32 int num_inputs,
int num_intermediate_inputs,
33 const std::vector<LineMapping>& line_map,
34 int library_line_count)
35 : tokens(tokens), mode(mode), num_inputs(num_inputs),
36 num_intermediate_inputs(num_intermediate_inputs), line_map(line_map),
37 library_line_count(library_line_count) {}
45 auto parse_result = parser.
parse();
46 ast = std::move(parse_result.ast);
48 std::ranges::transform(parse_result.errors, std::back_inserter(diagnostics),
49 [](
const auto& error) {
50 return Diagnostic(DiagnosticSeverity::Error,
51 error.message, error.range);
58 semantic_analyzer = std::make_unique<SemanticAnalyzer>(
59 mode, num_inputs, num_intermediate_inputs, library_line_count);
60 semantic_analyzer->analyze(ast.get());
62 const auto& semantic_diagnostics = semantic_analyzer->getDiagnostics();
63 diagnostics.insert(diagnostics.end(), semantic_diagnostics.begin(),
64 semantic_diagnostics.end());
92 if (diagnostics.empty()) {
98 int warning_count = 0;
100 for (
const auto& diag : diagnostics) {
107 if (!result.empty()) {
110 std::string severity_name = std::string(
enum_name(diag.severity));
113 auto it = std::ranges::find_if(line_map, [&](
const auto& m) {
114 return m.preprocessed_line == diag.range.start.line;
116 if (it != line_map.end()) {
120 Range range = diag.range;
121 std::string message = diag.message;
123 if (mapping !=
nullptr) {
128 std::string expansion_trace;
129 std::vector<const MacroExpansion*> containing_expansions;
131 for (
const auto& expansion : mapping->
expansions) {
132 if (diag.range.start.column + 1 >=
133 expansion.preprocessed_start_column &&
134 diag.range.end.column <
135 expansion.preprocessed_end_column) {
136 containing_expansions.push_back(&expansion);
140 std::ranges::sort(containing_expansions,
141 [](
const auto* a,
const auto* b) {
142 return (a->preprocessed_end_column -
143 a->preprocessed_start_column) <
144 (b->preprocessed_end_column -
145 b->preprocessed_start_column);
148 for (
const auto* expansion : containing_expansions) {
149 expansion_trace += std::format(
150 "\n note: in expansion of macro '{}' from {}:{}",
152 expansion->original_column);
154 message += expansion_trace;
158 result += std::format(
"{} - {}: {}", range.
to_string(), severity_name,
163 if (error_count > 0 && warning_count > 0) {
164 summary = std::format(
"\nFound {} error(s) and {} warning(s).",
165 error_count, warning_count);
166 }
else if (error_count > 0) {
167 summary = std::format(
"\nFound {} error(s).", error_count);
168 }
else if (warning_count > 0) {
169 summary = std::format(
"\nFound {} warning(s).", warning_count);