[messages] Parse type from messages.yaml.
Changes the logic for parsing analyzer-style `messages.yaml` files so that an optional `type:` entry is accepted. When present, the type will be checked against the type inferred from the diagnostic code's class (`CompileTimeErrorCode` has type `compileTimeError`, `StaticWarningCode` has type `staticWarning`, etc). In a follow-up CL I will add these `type:` entries, and change the code generation logic to use them instead of inferring the type from the diagnostic code's class. This will pave the way for removing the notion of diagnostic code class entirely. Change-Id: I6a6a6964d58f06ea6573702f9afcc61b5370eda8 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/464242 Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
This commit is contained in:
@@ -15,7 +15,8 @@ import 'package:analyzer_utilities/located_error.dart';
|
||||
import 'package:analyzer_utilities/messages.dart';
|
||||
import 'package:analyzer_utilities/tools.dart';
|
||||
import 'package:path/path.dart';
|
||||
import 'package:yaml/yaml.dart' show YamlMap, YamlScalar, loadYamlNode;
|
||||
import 'package:yaml/yaml.dart'
|
||||
show YamlMap, YamlScalar, loadYamlNode, YamlNode;
|
||||
|
||||
/// Base diagnostic classes used for analyzer messages.
|
||||
const analyzerBaseClasses = DiagnosticBaseClasses(
|
||||
@@ -386,6 +387,10 @@ enum AnalyzerDiagnosticType {
|
||||
syntacticError,
|
||||
todo;
|
||||
|
||||
static final Map<String, AnalyzerDiagnosticType> _stringToValue = {
|
||||
for (var value in values) value.name: value,
|
||||
};
|
||||
|
||||
/// Base classes used for messages of this type.
|
||||
final DiagnosticBaseClasses baseClasses;
|
||||
|
||||
@@ -393,6 +398,8 @@ enum AnalyzerDiagnosticType {
|
||||
|
||||
/// The representation of this type in analyzer source code.
|
||||
String get code => 'DiagnosticType.${name.toSnakeCase().toUpperCase()}';
|
||||
|
||||
static AnalyzerDiagnosticType? fromString(String s) => _stringToValue[s];
|
||||
}
|
||||
|
||||
/// In-memory representation of diagnostic information obtained from the
|
||||
@@ -407,6 +414,9 @@ class AnalyzerMessage extends Message with MessageWithAnalyzerCode {
|
||||
@override
|
||||
final AnalyzerDiagnosticPackage package;
|
||||
|
||||
@override
|
||||
final AnalyzerDiagnosticType? type;
|
||||
|
||||
factory AnalyzerMessage(
|
||||
MessageYaml messageYaml, {
|
||||
required AnalyzerCode analyzerCode,
|
||||
@@ -437,6 +447,11 @@ class AnalyzerMessage extends Message with MessageWithAnalyzerCode {
|
||||
required bool allowLinterKeys,
|
||||
required this.package,
|
||||
}) : hasPublishedDocs = messageYaml.getBool('hasPublishedDocs'),
|
||||
type = messageYaml.get(
|
||||
'type',
|
||||
decode: MessageWithAnalyzerCode.decodeType,
|
||||
ifAbsent: () => null,
|
||||
),
|
||||
super(messageYaml) {
|
||||
// Ignore extra keys related to analyzer example-based tests.
|
||||
messageYaml.allowExtraKeys({'experiment'});
|
||||
@@ -580,6 +595,10 @@ 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;
|
||||
|
||||
void outputConstantHeader(StringSink out) {
|
||||
out.write(toAnalyzerComments(indent: ' '));
|
||||
if (deprecatedMessage != null) {
|
||||
@@ -712,4 +731,11 @@ LocatableDiagnostic $withArgumentsName({$withArgumentsParams}) {
|
||||
// But we also need to escape `$`.
|
||||
return jsonEncoded.replaceAll(r'$', r'\$');
|
||||
}
|
||||
|
||||
static AnalyzerDiagnosticType decodeType(YamlNode node) => switch (node) {
|
||||
YamlScalar(:String value) =>
|
||||
AnalyzerDiagnosticType.fromString(value) ??
|
||||
(throw 'Unknown analyzer diagnostic type'),
|
||||
_ => throw 'Must be a bool',
|
||||
};
|
||||
}
|
||||
|
||||
@@ -450,6 +450,15 @@ class DiagnosticTables {
|
||||
[])
|
||||
.add(message);
|
||||
var package = message.package;
|
||||
var type = message.type;
|
||||
if (type != null && analyzerCode.diagnosticClass.type != type) {
|
||||
throw LocatedError(
|
||||
'Diagnostic type is ${type.name}, but its diagnostic class '
|
||||
'(${analyzerCode.diagnosticClass.name}) implies a type of '
|
||||
'${analyzerCode.diagnosticClass.type.name}',
|
||||
span: message.keySpan,
|
||||
);
|
||||
}
|
||||
if (!message.isRemoved && message is! AliasMessage) {
|
||||
(activeMessagesByPackage[package] ??= []).add(message);
|
||||
}
|
||||
@@ -925,12 +934,20 @@ class SharedMessage extends CfeStyleMessage with MessageWithAnalyzerCode {
|
||||
@override
|
||||
final bool hasPublishedDocs;
|
||||
|
||||
@override
|
||||
final AnalyzerDiagnosticType? type;
|
||||
|
||||
SharedMessage(super.messageYaml)
|
||||
: analyzerCode = messageYaml.get(
|
||||
'analyzerCode',
|
||||
decode: _decodeAnalyzerCode,
|
||||
),
|
||||
hasPublishedDocs = messageYaml.getBool('hasPublishedDocs');
|
||||
hasPublishedDocs = messageYaml.getBool('hasPublishedDocs'),
|
||||
type = messageYaml.get(
|
||||
'type',
|
||||
decode: MessageWithAnalyzerCode.decodeType,
|
||||
ifAbsent: () => null,
|
||||
);
|
||||
|
||||
@override
|
||||
AnalyzerDiagnosticPackage get package => AnalyzerDiagnosticPackage.analyzer;
|
||||
|
||||
Reference in New Issue
Block a user