Clean up SimpleDiagnostic inheritance (#1004)

This commit is contained in:
Jon Meow
2022-01-07 11:01:01 -08:00
committed by GitHub
parent b7df523dc8
commit cab5bb0158
6 changed files with 77 additions and 59 deletions
+30 -7
View File
@@ -68,6 +68,33 @@ class DiagnosticLocationTranslator {
-> Diagnostic::Location = 0;
};
// CRTP base class for diagnostics. `DiagnosticEmitter` requires `ShortName` and
// `Format`; `Message` is used by the default `Format` implementation. A simple
// child will look like:
//
// struct MySimpleError : DiagnosticBase<MyError> {
// static constexpr llvm::StringLiteral ShortName = "short-name";
// static constexpr llvm::StringLiteral Message = "A message.";
// };
//
// emitter.EmitError<MySimpleError>(location);
//
// A complex child may provide an alternate `Format` implementation:
//
// struct MyComplexError : DiagnosticBase<MyComplexError> {
// static constexpr llvm::StringLiteral ShortName = "short-name";
//
// auto Format() -> std::string { return llvm::formatv("See {0}.", ref); }
//
// std::string ref;
// };
//
// emitter.EmitError<MyComplexError>(location, {.ref = "ref"; });
template <typename Derived>
struct DiagnosticBase {
static auto Format() -> std::string { return Derived::Message.str(); }
};
// Manages the creation of reports, the testing if diagnostics are enabled, and
// the collection of reports.
//
@@ -88,7 +115,9 @@ class DiagnosticEmitter {
~DiagnosticEmitter() = default;
// Emits an error unconditionally.
template <typename DiagnosticT>
template <typename DiagnosticT,
typename = std::enable_if_t<
std::is_base_of_v<DiagnosticBase<DiagnosticT>, DiagnosticT>>>
auto EmitError(LocationT location, DiagnosticT diag) -> void {
// TODO: Encode the diagnostic kind in the Diagnostic object rather than
// hardcoding an "error: " prefix.
@@ -143,12 +172,6 @@ inline auto ConsoleDiagnosticConsumer() -> DiagnosticConsumer& {
return *consumer;
}
// CRTP base class for diagnostics with no substitutions.
template <typename Derived>
struct SimpleDiagnostic {
static auto Format() -> std::string { return Derived::Message.str(); }
};
// Diagnostic consumer adaptor that tracks whether any errors have been
// produced.
class ErrorTrackingDiagnosticConsumer : public DiagnosticConsumer {
@@ -14,7 +14,7 @@
namespace Carbon::Testing {
namespace {
struct FakeDiagnostic {
struct FakeDiagnostic : DiagnosticBase<FakeDiagnostic> {
static constexpr llvm::StringLiteral ShortName = "fake-diagnostic";
// TODO: consider ways to put the Message into `format` to allow dynamic
// selection of the message.
+8 -8
View File
@@ -14,13 +14,13 @@
namespace Carbon {
namespace {
struct EmptyDigitSequence : SimpleDiagnostic<EmptyDigitSequence> {
struct EmptyDigitSequence : DiagnosticBase<EmptyDigitSequence> {
static constexpr llvm::StringLiteral ShortName = "syntax-invalid-number";
static constexpr llvm::StringLiteral Message =
"Empty digit sequence in numeric literal.";
};
struct InvalidDigit {
struct InvalidDigit : DiagnosticBase<InvalidDigit> {
static constexpr llvm::StringLiteral ShortName = "syntax-invalid-number";
auto Format() -> std::string {
@@ -35,13 +35,13 @@ struct InvalidDigit {
int radix;
};
struct InvalidDigitSeparator : SimpleDiagnostic<InvalidDigitSeparator> {
struct InvalidDigitSeparator : DiagnosticBase<InvalidDigitSeparator> {
static constexpr llvm::StringLiteral ShortName = "syntax-invalid-number";
static constexpr llvm::StringLiteral Message =
"Misplaced digit separator in numeric literal.";
};
struct IrregularDigitSeparators {
struct IrregularDigitSeparators : DiagnosticBase<IrregularDigitSeparators> {
static constexpr llvm::StringLiteral ShortName =
"syntax-irregular-digit-separators";
@@ -58,19 +58,19 @@ struct IrregularDigitSeparators {
int radix;
};
struct UnknownBaseSpecifier : SimpleDiagnostic<UnknownBaseSpecifier> {
struct UnknownBaseSpecifier : DiagnosticBase<UnknownBaseSpecifier> {
static constexpr llvm::StringLiteral ShortName = "syntax-invalid-number";
static constexpr llvm::StringLiteral Message =
"Unknown base specifier in numeric literal.";
};
struct BinaryRealLiteral : SimpleDiagnostic<BinaryRealLiteral> {
struct BinaryRealLiteral : DiagnosticBase<BinaryRealLiteral> {
static constexpr llvm::StringLiteral ShortName = "syntax-invalid-number";
static constexpr llvm::StringLiteral Message =
"Binary real number literals are not supported.";
};
struct WrongRealLiteralExponent {
struct WrongRealLiteralExponent : DiagnosticBase<WrongRealLiteralExponent> {
static constexpr llvm::StringLiteral ShortName = "syntax-invalid-number";
auto Format() -> std::string {
@@ -81,7 +81,7 @@ struct WrongRealLiteralExponent {
char expected;
};
struct TooManyDigits {
struct TooManyDigits : DiagnosticBase<TooManyDigits> {
static constexpr llvm::StringLiteral ShortName = "syntax-invalid-number";
auto Format() -> std::string {
+11 -11
View File
@@ -17,27 +17,27 @@ namespace Carbon {
using LexerDiagnosticEmitter = DiagnosticEmitter<const char*>;
struct ContentBeforeStringTerminator
: SimpleDiagnostic<ContentBeforeStringTerminator> {
: DiagnosticBase<ContentBeforeStringTerminator> {
static constexpr llvm::StringLiteral ShortName = "syntax-invalid-string";
static constexpr llvm::StringLiteral Message =
"Only whitespace is permitted before the closing `\"\"\"` of a "
"multi-line string.";
};
struct UnicodeEscapeTooLarge : SimpleDiagnostic<UnicodeEscapeTooLarge> {
struct UnicodeEscapeTooLarge : DiagnosticBase<UnicodeEscapeTooLarge> {
static constexpr llvm::StringLiteral ShortName = "syntax-invalid-string";
static constexpr llvm::StringLiteral Message =
"Code point specified by `\\u{...}` escape is greater than 0x10FFFF.";
};
struct UnicodeEscapeSurrogate : SimpleDiagnostic<UnicodeEscapeSurrogate> {
struct UnicodeEscapeSurrogate : DiagnosticBase<UnicodeEscapeSurrogate> {
static constexpr llvm::StringLiteral ShortName = "syntax-invalid-string";
static constexpr llvm::StringLiteral Message =
"Code point specified by `\\u{...}` escape is a surrogate character.";
};
struct UnicodeEscapeMissingBracedDigits
: SimpleDiagnostic<UnicodeEscapeMissingBracedDigits> {
: DiagnosticBase<UnicodeEscapeMissingBracedDigits> {
static constexpr llvm::StringLiteral ShortName = "syntax-invalid-string";
static constexpr llvm::StringLiteral Message =
"Escape sequence `\\u` must be followed by a braced sequence of "
@@ -45,30 +45,30 @@ struct UnicodeEscapeMissingBracedDigits
};
struct HexadecimalEscapeMissingDigits
: SimpleDiagnostic<HexadecimalEscapeMissingDigits> {
: DiagnosticBase<HexadecimalEscapeMissingDigits> {
static constexpr llvm::StringLiteral ShortName = "syntax-invalid-string";
static constexpr llvm::StringLiteral Message =
"Escape sequence `\\x` must be followed by two "
"uppercase hexadecimal digits, for example `\\x0F`.";
};
struct DecimalEscapeSequence : SimpleDiagnostic<DecimalEscapeSequence> {
struct DecimalEscapeSequence : DiagnosticBase<DecimalEscapeSequence> {
static constexpr llvm::StringLiteral ShortName = "syntax-invalid-string";
static constexpr llvm::StringLiteral Message =
"Decimal digit follows `\\0` escape sequence. Use `\\x00` instead of "
"`\\0` if the next character is a digit.";
};
struct UnknownEscapeSequence {
struct UnknownEscapeSequence : DiagnosticBase<UnknownEscapeSequence> {
static constexpr llvm::StringLiteral ShortName = "syntax-invalid-string";
static constexpr const char* Message = "Unrecognized escape sequence `{0}`.";
char first;
auto Format() -> std::string { return llvm::formatv(Message, first).str(); }
char first;
};
struct MismatchedIndentInString : SimpleDiagnostic<MismatchedIndentInString> {
struct MismatchedIndentInString : DiagnosticBase<MismatchedIndentInString> {
static constexpr llvm::StringLiteral ShortName = "syntax-invalid-string";
static constexpr llvm::StringLiteral Message =
"Indentation does not match that of the closing \"\"\" in multi-line "
@@ -76,7 +76,7 @@ struct MismatchedIndentInString : SimpleDiagnostic<MismatchedIndentInString> {
};
struct InvalidHorizontalWhitespaceInString
: SimpleDiagnostic<InvalidHorizontalWhitespaceInString> {
: DiagnosticBase<InvalidHorizontalWhitespaceInString> {
static constexpr llvm::StringLiteral ShortName = "syntax-invalid-string";
static constexpr llvm::StringLiteral Message =
"Whitespace other than plain space must be expressed with an escape "
+5 -5
View File
@@ -25,32 +25,32 @@
namespace Carbon {
struct TrailingComment : SimpleDiagnostic<TrailingComment> {
struct TrailingComment : DiagnosticBase<TrailingComment> {
static constexpr llvm::StringLiteral ShortName = "syntax-comments";
static constexpr llvm::StringLiteral Message =
"Trailing comments are not permitted.";
};
struct NoWhitespaceAfterCommentIntroducer
: SimpleDiagnostic<NoWhitespaceAfterCommentIntroducer> {
: DiagnosticBase<NoWhitespaceAfterCommentIntroducer> {
static constexpr llvm::StringLiteral ShortName = "syntax-comments";
static constexpr llvm::StringLiteral Message =
"Whitespace is required after '//'.";
};
struct UnmatchedClosing : SimpleDiagnostic<UnmatchedClosing> {
struct UnmatchedClosing : DiagnosticBase<UnmatchedClosing> {
static constexpr llvm::StringLiteral ShortName = "syntax-balanced-delimiters";
static constexpr llvm::StringLiteral Message =
"Closing symbol without a corresponding opening symbol.";
};
struct MismatchedClosing : SimpleDiagnostic<MismatchedClosing> {
struct MismatchedClosing : DiagnosticBase<MismatchedClosing> {
static constexpr llvm::StringLiteral ShortName = "syntax-balanced-delimiters";
static constexpr llvm::StringLiteral Message =
"Closing symbol does not match most recent opening symbol.";
};
struct UnrecognizedCharacters : SimpleDiagnostic<UnrecognizedCharacters> {
struct UnrecognizedCharacters : DiagnosticBase<UnrecognizedCharacters> {
static constexpr llvm::StringLiteral ShortName =
"syntax-unrecognized-characters";
static constexpr llvm::StringLiteral Message =
+22 -27
View File
@@ -17,10 +17,10 @@
namespace Carbon {
struct StackLimitExceeded {
struct StackLimitExceeded : DiagnosticBase<StackLimitExceeded> {
static constexpr llvm::StringLiteral ShortName = "syntax-error";
auto Format() -> std::string {
static auto Format() -> std::string {
return llvm::formatv("Exceeded recursion limit ({0})",
ParseTree::StackDepthLimit);
}
@@ -55,46 +55,43 @@ class ParseTree::Parser::ScopedStackStep {
return (error_return_expr); \
}
struct UnexpectedTokenInCodeBlock
: SimpleDiagnostic<UnexpectedTokenInCodeBlock> {
struct UnexpectedTokenInCodeBlock : DiagnosticBase<UnexpectedTokenInCodeBlock> {
static constexpr llvm::StringLiteral ShortName = "syntax-error";
static constexpr llvm::StringLiteral Message =
"Unexpected token in code block.";
};
struct ExpectedFunctionName : SimpleDiagnostic<ExpectedFunctionName> {
struct ExpectedFunctionName : DiagnosticBase<ExpectedFunctionName> {
static constexpr llvm::StringLiteral ShortName = "syntax-error";
static constexpr llvm::StringLiteral Message =
"Expected function name after `fn` keyword.";
};
struct ExpectedFunctionParams : SimpleDiagnostic<ExpectedFunctionParams> {
struct ExpectedFunctionParams : DiagnosticBase<ExpectedFunctionParams> {
static constexpr llvm::StringLiteral ShortName = "syntax-error";
static constexpr llvm::StringLiteral Message =
"Expected `(` after function name.";
};
struct ExpectedFunctionBodyOrSemi
: SimpleDiagnostic<ExpectedFunctionBodyOrSemi> {
struct ExpectedFunctionBodyOrSemi : DiagnosticBase<ExpectedFunctionBodyOrSemi> {
static constexpr llvm::StringLiteral ShortName = "syntax-error";
static constexpr llvm::StringLiteral Message =
"Expected function definition or `;` after function declaration.";
};
struct ExpectedVariableName : SimpleDiagnostic<ExpectedVariableName> {
struct ExpectedVariableName : DiagnosticBase<ExpectedVariableName> {
static constexpr llvm::StringLiteral ShortName = "syntax-error";
static constexpr llvm::StringLiteral Message =
"Expected pattern in `var` declaration.";
};
struct ExpectedParameterName : SimpleDiagnostic<ExpectedParameterName> {
struct ExpectedParameterName : DiagnosticBase<ExpectedParameterName> {
static constexpr llvm::StringLiteral ShortName = "syntax-error";
static constexpr llvm::StringLiteral Message =
"Expected parameter declaration.";
};
struct ExpectedStructLiteralField
: SimpleDiagnostic<ExpectedStructLiteralField> {
struct ExpectedStructLiteralField : DiagnosticBase<ExpectedStructLiteralField> {
static constexpr llvm::StringLiteral ShortName = "syntax-error";
auto Format() -> std::string {
@@ -116,23 +113,23 @@ struct ExpectedStructLiteralField
bool can_be_value;
};
struct UnrecognizedDeclaration : SimpleDiagnostic<UnrecognizedDeclaration> {
struct UnrecognizedDeclaration : DiagnosticBase<UnrecognizedDeclaration> {
static constexpr llvm::StringLiteral ShortName = "syntax-error";
static constexpr llvm::StringLiteral Message =
"Unrecognized declaration introducer.";
};
struct ExpectedCodeBlock : SimpleDiagnostic<ExpectedCodeBlock> {
struct ExpectedCodeBlock : DiagnosticBase<ExpectedCodeBlock> {
static constexpr llvm::StringLiteral ShortName = "syntax-error";
static constexpr llvm::StringLiteral Message = "Expected braced code block.";
};
struct ExpectedExpression : SimpleDiagnostic<ExpectedExpression> {
struct ExpectedExpression : DiagnosticBase<ExpectedExpression> {
static constexpr llvm::StringLiteral ShortName = "syntax-error";
static constexpr llvm::StringLiteral Message = "Expected expression.";
};
struct ExpectedParenAfter : SimpleDiagnostic<ExpectedParenAfter> {
struct ExpectedParenAfter : DiagnosticBase<ExpectedParenAfter> {
static constexpr llvm::StringLiteral ShortName = "syntax-error";
static constexpr const char* Message = "Expected `(` after `{0}`.";
@@ -143,7 +140,7 @@ struct ExpectedParenAfter : SimpleDiagnostic<ExpectedParenAfter> {
TokenKind introducer;
};
struct ExpectedCloseParen : SimpleDiagnostic<ExpectedCloseParen> {
struct ExpectedCloseParen : DiagnosticBase<ExpectedCloseParen> {
static constexpr llvm::StringLiteral ShortName = "syntax-error";
static constexpr llvm::StringLiteral Message =
"Unexpected tokens before `)`.";
@@ -153,13 +150,13 @@ struct ExpectedCloseParen : SimpleDiagnostic<ExpectedCloseParen> {
};
struct ExpectedSemiAfterExpression
: SimpleDiagnostic<ExpectedSemiAfterExpression> {
: DiagnosticBase<ExpectedSemiAfterExpression> {
static constexpr llvm::StringLiteral ShortName = "syntax-error";
static constexpr llvm::StringLiteral Message =
"Expected `;` after expression.";
};
struct ExpectedSemiAfter : SimpleDiagnostic<ExpectedSemiAfter> {
struct ExpectedSemiAfter : DiagnosticBase<ExpectedSemiAfter> {
static constexpr llvm::StringLiteral ShortName = "syntax-error";
static constexpr const char* Message = "Expected `;` after `{0}`.";
@@ -170,15 +167,14 @@ struct ExpectedSemiAfter : SimpleDiagnostic<ExpectedSemiAfter> {
TokenKind preceding;
};
struct ExpectedIdentifierAfterDot
: SimpleDiagnostic<ExpectedIdentifierAfterDot> {
struct ExpectedIdentifierAfterDot : DiagnosticBase<ExpectedIdentifierAfterDot> {
static constexpr llvm::StringLiteral ShortName = "syntax-error";
static constexpr llvm::StringLiteral Message =
"Expected identifier after `.`.";
};
struct UnexpectedTokenAfterListElement
: SimpleDiagnostic<UnexpectedTokenAfterListElement> {
: DiagnosticBase<UnexpectedTokenAfterListElement> {
static constexpr llvm::StringLiteral ShortName = "syntax-error";
static constexpr const char* Message = "Expected `,` or `{0}`.";
@@ -190,7 +186,7 @@ struct UnexpectedTokenAfterListElement
};
struct BinaryOperatorRequiresWhitespace
: SimpleDiagnostic<BinaryOperatorRequiresWhitespace> {
: DiagnosticBase<BinaryOperatorRequiresWhitespace> {
static constexpr llvm::StringLiteral ShortName = "syntax-error";
static constexpr const char* Message =
"Whitespace missing {0} binary operator.";
@@ -209,8 +205,7 @@ struct BinaryOperatorRequiresWhitespace
bool has_trailing_space;
};
struct UnaryOperatorHasWhitespace
: SimpleDiagnostic<UnaryOperatorHasWhitespace> {
struct UnaryOperatorHasWhitespace : DiagnosticBase<UnaryOperatorHasWhitespace> {
static constexpr llvm::StringLiteral ShortName = "syntax-error";
static constexpr const char* Message =
"Whitespace is not allowed {0} this unary operator.";
@@ -223,7 +218,7 @@ struct UnaryOperatorHasWhitespace
};
struct UnaryOperatorRequiresWhitespace
: SimpleDiagnostic<UnaryOperatorRequiresWhitespace> {
: DiagnosticBase<UnaryOperatorRequiresWhitespace> {
static constexpr llvm::StringLiteral ShortName = "syntax-error";
static constexpr const char* Message =
"Whitespace is required {0} this unary operator.";
@@ -236,7 +231,7 @@ struct UnaryOperatorRequiresWhitespace
};
struct OperatorRequiresParentheses
: SimpleDiagnostic<OperatorRequiresParentheses> {
: DiagnosticBase<OperatorRequiresParentheses> {
static constexpr llvm::StringLiteral ShortName = "syntax-error";
static constexpr llvm::StringLiteral Message =
"Parentheses are required to disambiguate operator precedence.";