mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-05 09:11:05 +01:00
At present, we typically define a DiagnosticConverter, then store an instance of it and a DiagnosticEmitter that wraps it. This is relatively minor in general, but I've been trying to create more self-contained DiagnosticEmitter classes (which hold their own DiagnosticConverter, similar to NullDiagnosticEmitter), and there it just gets in the way. Since we don't reuse DiagnosticConverter instances, this combines the definition into DiagnosticEmitter. Mainly this means we don't have a separate object in play, and less to carry around. The most impact is probably to SemIRDiagnosticConverter, which was also the most complex. Now `SemIRLocDiagnosticEmitter`, this gets some different construction flow. Note in the PR I've split the file rename to its own commit, to try to help delta views. However, the most substantial parts of the refactoring are split into #4876, which this depends upon.
61 lines
2.2 KiB
C++
61 lines
2.2 KiB
C++
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
|
|
// Exceptions. See /LICENSE for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
|
|
#ifndef CARBON_TOOLCHAIN_LEX_TEST_HELPERS_H_
|
|
#define CARBON_TOOLCHAIN_LEX_TEST_HELPERS_H_
|
|
|
|
#include <gmock/gmock.h>
|
|
|
|
#include <array>
|
|
|
|
#include "common/check.h"
|
|
#include "common/string_helpers.h"
|
|
#include "toolchain/diagnostics/diagnostic_emitter.h"
|
|
|
|
namespace Carbon::Testing {
|
|
|
|
// A diagnostic converter for tests that lex a single token. Produces
|
|
// locations such as "`12.5`:1:3" to refer to the third character in the token.
|
|
class SingleTokenDiagnosticEmitter : public DiagnosticEmitter<const char*> {
|
|
public:
|
|
// Form a converter for a given token. The string provided here must refer
|
|
// to the same character array that we are going to lex.
|
|
explicit SingleTokenDiagnosticEmitter(DiagnosticConsumer* consumer,
|
|
llvm::StringRef token)
|
|
: DiagnosticEmitter(consumer), token_(token) {}
|
|
|
|
protected:
|
|
// Implements `DiagnosticConverter::ConvertLoc`.
|
|
auto ConvertLoc(const char* pos, ContextFnT /*context_fn*/) const
|
|
-> ConvertedDiagnosticLoc override {
|
|
CARBON_CHECK(StringRefContainsPointer(token_, pos),
|
|
"invalid diagnostic location");
|
|
llvm::StringRef prefix = token_.take_front(pos - token_.begin());
|
|
auto [before_last_newline, this_line] = prefix.rsplit('\n');
|
|
if (before_last_newline.size() == prefix.size()) {
|
|
// On first line.
|
|
return {.loc = {.line_number = 1,
|
|
.column_number =
|
|
static_cast<int32_t>(pos - token_.begin() + 1)},
|
|
.last_byte_offset = -1};
|
|
} else {
|
|
// On second or subsequent lines. Note that the line number here is 2
|
|
// more than the number of newlines because `rsplit` removed one newline
|
|
// and `line_number` is 1-based.
|
|
return {
|
|
.loc = {.line_number =
|
|
static_cast<int32_t>(before_last_newline.count('\n') + 2),
|
|
.column_number = static_cast<int32_t>(this_line.size() + 1)},
|
|
.last_byte_offset = -1};
|
|
}
|
|
}
|
|
|
|
private:
|
|
llvm::StringRef token_;
|
|
};
|
|
|
|
} // namespace Carbon::Testing
|
|
|
|
#endif // CARBON_TOOLCHAIN_LEX_TEST_HELPERS_H_
|