Improve diagnostic interface
This commit is contained in:
commit
6b55a13a83
5 changed files with 72 additions and 56 deletions
|
|
@ -5,6 +5,7 @@
|
||||||
#ifndef CPPAST_DIAGNOSTIC_HPP_INCLUDED
|
#ifndef CPPAST_DIAGNOSTIC_HPP_INCLUDED
|
||||||
#define CPPAST_DIAGNOSTIC_HPP_INCLUDED
|
#define CPPAST_DIAGNOSTIC_HPP_INCLUDED
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include <type_safe/optional.hpp>
|
#include <type_safe/optional.hpp>
|
||||||
|
|
@ -17,30 +18,33 @@ namespace cppast
|
||||||
{
|
{
|
||||||
type_safe::optional<std::string> entity;
|
type_safe::optional<std::string> entity;
|
||||||
type_safe::optional<std::string> file;
|
type_safe::optional<std::string> file;
|
||||||
type_safe::optional<unsigned> line;
|
type_safe::optional<unsigned> line, column;
|
||||||
|
|
||||||
/// \returns A source location where all information is available.
|
/// \returns A source location where all information is available.
|
||||||
static source_location make(std::string entity, std::string file, unsigned line)
|
static source_location make(std::string entity, std::string file, unsigned line,
|
||||||
|
unsigned column)
|
||||||
{
|
{
|
||||||
return {std::move(entity), std::move(file), line};
|
return {std::move(entity), std::move(file), line, column};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \returns A source location where only file and line information is available.
|
/// \returns A source location where only file information is available.
|
||||||
static source_location make_file(std::string file, unsigned line)
|
static source_location make_file(std::string file,
|
||||||
|
type_safe::optional<unsigned> line = type_safe::nullopt,
|
||||||
|
type_safe::optional<unsigned> column = type_safe::nullopt)
|
||||||
{
|
{
|
||||||
return {type_safe::nullopt, std::move(file), line};
|
return {type_safe::nullopt, std::move(file), line, column};
|
||||||
}
|
|
||||||
|
|
||||||
/// \returns A source location where only the file is available.
|
|
||||||
static source_location make_file(std::string file)
|
|
||||||
{
|
|
||||||
return {type_safe::nullopt, std::move(file), type_safe::nullopt};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \returns A source location where only the entity name is available.
|
/// \returns A source location where only the entity name is available.
|
||||||
static source_location make_entity(std::string entity)
|
static source_location make_entity(std::string entity)
|
||||||
{
|
{
|
||||||
return {std::move(entity), type_safe::nullopt, type_safe::nullopt};
|
return {std::move(entity), type_safe::nullopt, type_safe::nullopt, type_safe::nullopt};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \returns A source location where no information is avilable.
|
||||||
|
static source_location make_unknown()
|
||||||
|
{
|
||||||
|
return {type_safe::nullopt, type_safe::nullopt, type_safe::nullopt, type_safe::nullopt};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \returns A possible string representation of the source location.
|
/// \returns A possible string representation of the source location.
|
||||||
|
|
@ -51,8 +55,17 @@ namespace cppast
|
||||||
if (file)
|
if (file)
|
||||||
{
|
{
|
||||||
result += file.value() + ":";
|
result += file.value() + ":";
|
||||||
|
|
||||||
if (line)
|
if (line)
|
||||||
result += std::to_string(line.value()) + ":";
|
{
|
||||||
|
result += std::to_string(line.value());
|
||||||
|
|
||||||
|
if (column)
|
||||||
|
result += "," + std::to_string(column.value());
|
||||||
|
|
||||||
|
result += ":";
|
||||||
|
}
|
||||||
|
|
||||||
if (entity)
|
if (entity)
|
||||||
result += " (" + entity.value() + "):";
|
result += " (" + entity.value() + "):";
|
||||||
}
|
}
|
||||||
|
|
@ -100,6 +113,27 @@ namespace cppast
|
||||||
source_location location;
|
source_location location;
|
||||||
cppast::severity severity;
|
cppast::severity severity;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
template <typename... Args>
|
||||||
|
std::string format(Args&&... args)
|
||||||
|
{
|
||||||
|
std::ostringstream stream;
|
||||||
|
int dummy[] = {(stream << std::forward<Args>(args), 0)...};
|
||||||
|
(void)dummy;
|
||||||
|
return stream.str();
|
||||||
|
}
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
/// Creates a diagnostic.
|
||||||
|
/// \returns A diagnostic with the specified severity and location.
|
||||||
|
/// The message is created by streaming each argument in order to a [std::ostringstream]().
|
||||||
|
template <typename... Args>
|
||||||
|
diagnostic format_diagnostic(severity sev, source_location loc, Args&&... args)
|
||||||
|
{
|
||||||
|
return {detail::format(std::forward<Args>(args)...), std::move(loc), sev};
|
||||||
|
}
|
||||||
} // namespace cppast
|
} // namespace cppast
|
||||||
|
|
||||||
#endif // CPPAST_DIAGNOSTIC_HPP_INCLUDED
|
#endif // CPPAST_DIAGNOSTIC_HPP_INCLUDED
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,6 @@
|
||||||
#define CPPAST_PARSE_ERROR_HPP_INCLUDED
|
#define CPPAST_PARSE_ERROR_HPP_INCLUDED
|
||||||
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <sstream>
|
|
||||||
|
|
||||||
#include <debug_assert.hpp>
|
#include <debug_assert.hpp>
|
||||||
#include <cppast/diagnostic.hpp>
|
#include <cppast/diagnostic.hpp>
|
||||||
|
|
@ -78,15 +77,6 @@ namespace cppast
|
||||||
throw parse_error(type, std::move(message));
|
throw parse_error(type, std::move(message));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename... Args>
|
|
||||||
std::string format(Args&&... args)
|
|
||||||
{
|
|
||||||
std::ostringstream stream;
|
|
||||||
int dummy[] = {(stream << std::forward<Args>(args), 0)...};
|
|
||||||
(void)dummy;
|
|
||||||
return stream.str();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} // namespace cppast::detail
|
} // namespace cppast::detail
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -113,11 +113,10 @@ std::unique_ptr<cpp_entity> detail::parse_entity(const detail::parse_context& co
|
||||||
{
|
{
|
||||||
if (context.logger->is_verbose())
|
if (context.logger->is_verbose())
|
||||||
{
|
{
|
||||||
auto message = detail::format("parsing cursor of type '",
|
|
||||||
detail::get_cursor_kind_spelling(cur).c_str(), "'");
|
|
||||||
context.logger->log("libclang parser",
|
context.logger->log("libclang parser",
|
||||||
diagnostic{std::move(message), detail::make_location(cur),
|
format_diagnostic(severity::debug, detail::make_location(cur),
|
||||||
severity::debug});
|
"parsing cursor of type '",
|
||||||
|
detail::get_cursor_kind_spelling(cur).c_str(), "'"));
|
||||||
}
|
}
|
||||||
|
|
||||||
auto kind = clang_getCursorKind(cur);
|
auto kind = clang_getCursorKind(cur);
|
||||||
|
|
@ -211,8 +210,9 @@ std::unique_ptr<cpp_entity> detail::parse_entity(const detail::parse_context& co
|
||||||
auto msg = detail::format("unhandled cursor of kind '",
|
auto msg = detail::format("unhandled cursor of kind '",
|
||||||
detail::get_cursor_kind_spelling(cur).c_str(), "'");
|
detail::get_cursor_kind_spelling(cur).c_str(), "'");
|
||||||
context.logger->log("libclang parser",
|
context.logger->log("libclang parser",
|
||||||
diagnostic{std::move(msg), detail::make_location(cur),
|
format_diagnostic(severity::warning, detail::make_location(cur),
|
||||||
severity::warning});
|
"unhandled cursor of kind '",
|
||||||
|
detail::get_cursor_kind_spelling(cur).c_str(), "'"));
|
||||||
|
|
||||||
// build unexposed entity
|
// build unexposed entity
|
||||||
auto name = detail::get_cursor_name(cur);
|
auto name = detail::get_cursor_name(cur);
|
||||||
|
|
|
||||||
|
|
@ -102,7 +102,7 @@ namespace
|
||||||
DEBUG_ASSERT(*ptr == ':', detail::assert_handler{});
|
DEBUG_ASSERT(*ptr == ':', detail::assert_handler{});
|
||||||
++ptr;
|
++ptr;
|
||||||
|
|
||||||
return {type_safe::nullopt, std::move(filename), std::move(line)};
|
return {type_safe::nullopt, std::move(filename), std::move(line), type_safe::nullopt};
|
||||||
}
|
}
|
||||||
|
|
||||||
severity parse_severity(const char*& ptr)
|
severity parse_severity(const char*& ptr)
|
||||||
|
|
@ -708,13 +708,10 @@ detail::preprocessor_output detail::preprocess(const libclang_compile_config& co
|
||||||
else if (auto macro = parse_macro(p, result, file_depth == 0u))
|
else if (auto macro = parse_macro(p, result, file_depth == 0u))
|
||||||
{
|
{
|
||||||
if (logger.is_verbose())
|
if (logger.is_verbose())
|
||||||
{
|
|
||||||
auto message = detail::format("parsing macro '", macro->name(), "'");
|
|
||||||
logger.log("preprocessor",
|
logger.log("preprocessor",
|
||||||
diagnostic{std::move(message),
|
format_diagnostic(severity::debug,
|
||||||
source_location::make_file(path, p.cur_line()),
|
source_location::make_file(path, p.cur_line()),
|
||||||
severity::debug});
|
"parsing macro '", macro->name(), "'"));
|
||||||
}
|
|
||||||
|
|
||||||
result.macros.push_back({std::move(macro), p.cur_line()});
|
result.macros.push_back({std::move(macro), p.cur_line()});
|
||||||
}
|
}
|
||||||
|
|
@ -723,13 +720,11 @@ detail::preprocessor_output detail::preprocess(const libclang_compile_config& co
|
||||||
if (file_depth == 0u)
|
if (file_depth == 0u)
|
||||||
{
|
{
|
||||||
if (logger.is_verbose())
|
if (logger.is_verbose())
|
||||||
{
|
|
||||||
auto message = detail::format("undefining macro '", undef.value(), "'");
|
|
||||||
logger.log("preprocessor",
|
logger.log("preprocessor",
|
||||||
diagnostic{std::move(message),
|
format_diagnostic(severity::debug,
|
||||||
source_location::make_file(path, p.cur_line()),
|
source_location::make_file(path, p.cur_line()),
|
||||||
severity::debug});
|
"undefining macro '", undef.value(), "'"));
|
||||||
}
|
|
||||||
result.macros.erase(std::remove_if(result.macros.begin(), result.macros.end(),
|
result.macros.erase(std::remove_if(result.macros.begin(), result.macros.end(),
|
||||||
[&](const pp_macro& e) {
|
[&](const pp_macro& e) {
|
||||||
return e.macro->name() == undef.value();
|
return e.macro->name() == undef.value();
|
||||||
|
|
@ -740,14 +735,12 @@ detail::preprocessor_output detail::preprocess(const libclang_compile_config& co
|
||||||
else if (auto include = parse_include(p, file_depth == 0u))
|
else if (auto include = parse_include(p, file_depth == 0u))
|
||||||
{
|
{
|
||||||
if (logger.is_verbose())
|
if (logger.is_verbose())
|
||||||
{
|
|
||||||
auto message =
|
|
||||||
detail::format("parsing include '", include.value().file.name(), "'");
|
|
||||||
logger.log("preprocessor",
|
logger.log("preprocessor",
|
||||||
diagnostic{std::move(message),
|
format_diagnostic(severity::debug,
|
||||||
source_location::make_file(path, p.cur_line()),
|
source_location::make_file(path, p.cur_line()),
|
||||||
severity::debug});
|
"parsing include '", include.value().file.name(),
|
||||||
}
|
"'"));
|
||||||
|
|
||||||
result.includes.push_back(std::move(include.value()));
|
result.includes.push_back(std::move(include.value()));
|
||||||
}
|
}
|
||||||
else if (bump_pragma(p))
|
else if (bump_pragma(p))
|
||||||
|
|
|
||||||
|
|
@ -552,12 +552,11 @@ namespace
|
||||||
case CXType_OCLQueue:
|
case CXType_OCLQueue:
|
||||||
case CXType_OCLReserveID:
|
case CXType_OCLReserveID:
|
||||||
#endif
|
#endif
|
||||||
{
|
context.logger->log("libclang parser",
|
||||||
auto msg = detail::format("unexpected type of kind '",
|
format_diagnostic(severity::warning, detail::make_location(type),
|
||||||
detail::get_type_kind_spelling(type).c_str(), "'");
|
"unexpected type of kind '",
|
||||||
auto location = detail::make_location(type);
|
detail::get_type_kind_spelling(type).c_str(),
|
||||||
context.logger->log("libclang parser", diagnostic{msg, location, severity::warning});
|
"'"));
|
||||||
}
|
|
||||||
// fallthrough
|
// fallthrough
|
||||||
case CXType_Dependent: // seems to have something to do with expressions, just ignore that (for now?)
|
case CXType_Dependent: // seems to have something to do with expressions, just ignore that (for now?)
|
||||||
case CXType_Unexposed:
|
case CXType_Unexposed:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue