[messages] Consume types from messages.yaml files.

Now that all diagnostic codes in analyzer-style `messages.yaml` files
have a `type:` entry, it can safely be used to determine the
diagnostic's type. This replaces the old logic that inferred
diagnostic types from the diagnostic's class name (diagnostics under
the heading `CompileTimeErrorCode` have type `compileTimeError`, those
under `StaticWarningCode` have type `staticWarning`, etc).

This paves the way for removing the notion of diagnostic code class
entirely.

Change-Id: I6a6a69646fdcaccaef6f8c32a1ebf303a54548d8
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/464283
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
This commit is contained in:
Paul Berry
2025-11-25 14:16:01 -08:00
committed by Commit Queue
parent c8ab18f13e
commit d48e7dc620
3 changed files with 30 additions and 13 deletions
@@ -371,7 +371,7 @@ class DocumentationValidator {
}
for (int i = 0; i < exampleSnippets.length; i++) {
_SnippetData snippet = exampleSnippets[i];
if (message.analyzerCode.diagnosticClass == linterLintCodeInfo) {
if (message.type == AnalyzerDiagnosticType.lint) {
snippet.lintCode = codeName;
}
await _validateSnippet('example', i, snippet);
@@ -386,7 +386,7 @@ class DocumentationValidator {
if (firstExample != null) {
snippet.auxiliaryFiles.addAll(firstExample.auxiliaryFiles);
}
if (message.analyzerCode.diagnosticClass == linterLintCodeInfo) {
if (message.type == AnalyzerDiagnosticType.lint) {
snippet.lintCode = codeName;
}
await _validateSnippet('fixes', i, snippet);
@@ -311,15 +311,24 @@ enum AnalyzerDiagnosticPackage {
analyzer(
diagnosticPathPart: 'src/diagnostic/diagnostic',
dirName: 'analyzer',
permittedTypes: {
.compileTimeError,
.hint,
.staticWarning,
.syntacticError,
.todo,
},
),
analysisServer(
diagnosticPathPart: 'src/diagnostic',
dirName: 'analysis_server',
permittedTypes: {.compileTimeError},
shouldIgnorePreferSingleQuotes: true,
),
linter(
diagnosticPathPart: 'src/diagnostic',
dirName: 'linter',
permittedTypes: {.lint},
shouldIgnorePreferExpressionFunctionBodies: true,
shouldIgnorePreferSingleQuotes: true,
);
@@ -335,6 +344,9 @@ enum AnalyzerDiagnosticPackage {
/// file will be `pkg/linter/lib/src/diagnostic/diagnostic.g.dart`.
final String diagnosticPathPart;
/// The set of [AnalyzerDiagnosticType]s that may be used in this package.
final Set<AnalyzerDiagnosticType> permittedTypes;
/// Whether code generated in this package needs an "ignore" comment to ignore
/// the `prefer_expression_function_bodies` lint.
final bool shouldIgnorePreferExpressionFunctionBodies;
@@ -346,6 +358,7 @@ enum AnalyzerDiagnosticPackage {
const AnalyzerDiagnosticPackage({
required this.diagnosticPathPart,
required this.dirName,
required this.permittedTypes,
this.shouldIgnorePreferExpressionFunctionBodies = false,
this.shouldIgnorePreferSingleQuotes = false,
});
@@ -415,7 +428,7 @@ class AnalyzerMessage extends Message with MessageWithAnalyzerCode {
final AnalyzerDiagnosticPackage package;
@override
final AnalyzerDiagnosticType? type;
final AnalyzerDiagnosticType type;
factory AnalyzerMessage(
MessageYaml messageYaml, {
@@ -450,7 +463,6 @@ class AnalyzerMessage extends Message with MessageWithAnalyzerCode {
type = messageYaml.get(
'type',
decode: MessageWithAnalyzerCode.decodeType,
ifAbsent: () => null,
),
super(messageYaml) {
// Ignore extra keys related to analyzer example-based tests.
@@ -545,7 +557,7 @@ mixin MessageWithAnalyzerCode on Message {
(value) =>
value != null && value.any((part) => part is TemplateParameterPart),
);
var baseClasses = analyzerCode.diagnosticClass.type.baseClasses;
var baseClasses = type.baseClasses;
if (parameters.isNotEmpty && !usesParameters) {
throw 'Error code declares parameters using a `parameters` entry, but '
"doesn't use them";
@@ -595,9 +607,8 @@ mixin MessageWithAnalyzerCode on Message {
/// The package into which this error code will be generated.
AnalyzerDiagnosticPackage get package;
/// The type of this diagnostic, if present in `messages.yaml`. Otherwise
/// `null`.
AnalyzerDiagnosticType? get type;
/// The type of this diagnostic.
AnalyzerDiagnosticType get type;
void outputConstantHeader(StringSink out) {
out.write(toAnalyzerComments(indent: ' '));
@@ -617,7 +628,7 @@ mixin MessageWithAnalyzerCode on Message {
var diagnosticCode = analyzerCode.snakeCaseName;
var correctionMessage = this.correctionMessage;
String? withArgumentsName;
var baseClasses = analyzerCode.diagnosticClass.type.baseClasses;
var baseClasses = type.baseClasses;
var ConstantStyle(:concreteClassName, :staticType) = constantStyle;
if (constantStyle case WithArgumentsConstantStyle(
:var withArgumentsParams,
@@ -662,7 +673,7 @@ LocatableDiagnostic $withArgumentsName({$withArgumentsParams}) {
constant.writeln('isUnresolvedIdentifier:true,');
}
if (baseClasses.requiresTypeArgument) {
constant.writeln('type: ${diagnosticClassInfo.type.code},');
constant.writeln('type: ${type.code},');
}
String uniqueName = analyzerCode.toString().replaceFirst(
'LinterLintCode.',
+9 -3
View File
@@ -451,7 +451,7 @@ class DiagnosticTables {
.add(message);
var package = message.package;
var type = message.type;
if (type != null && analyzerCode.diagnosticClass.type != type) {
if (analyzerCode.diagnosticClass.type != type) {
throw LocatedError(
'Diagnostic type is ${type.name}, but its diagnostic class '
'(${analyzerCode.diagnosticClass.name}) implies a type of '
@@ -459,6 +459,13 @@ class DiagnosticTables {
span: message.keySpan,
);
}
if (!package.permittedTypes.contains(type)) {
throw LocatedError(
'Diagnostic type is ${type.name}, which may not be used in '
'package:${package.dirName}',
span: message.keySpan,
);
}
if (!message.isRemoved && message is! AliasMessage) {
(activeMessagesByPackage[package] ??= []).add(message);
}
@@ -935,7 +942,7 @@ class SharedMessage extends CfeStyleMessage with MessageWithAnalyzerCode {
final bool hasPublishedDocs;
@override
final AnalyzerDiagnosticType? type;
final AnalyzerDiagnosticType type;
SharedMessage(super.messageYaml)
: analyzerCode = messageYaml.get(
@@ -946,7 +953,6 @@ class SharedMessage extends CfeStyleMessage with MessageWithAnalyzerCode {
type = messageYaml.get(
'type',
decode: MessageWithAnalyzerCode.decodeType,
ifAbsent: () => null,
);
@override