blob: 05c637e39af2eedf438daa5b4ec71c21b27ff26e [file]
// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
/// This file contains code to generate scanner and parser message
/// based on the information in pkg/front_end/messages.yaml.
///
/// For each message in messages.yaml that contains an 'index:' field,
/// this tool generates an error with the name specified by the 'analyzerCode:'
/// field and an entry in the fastaAnalyzerErrorList for that generated error.
/// The text in the 'analyzerCode:' field must contain the name of the class
/// containing the error and the name of the error separated by a `.`
/// (e.g. ParserErrorCode.EQUALITY_CANNOT_BE_EQUALITY_OPERAND).
///
/// It is expected that 'dart pkg/front_end/tool/generate_messages.dart'
/// has already been successfully run.
library;
import 'dart:convert';
import 'package:analyzer_testing/package_root.dart' as pkg_root;
import 'package:analyzer_utilities/analyzer_messages.dart';
import 'package:analyzer_utilities/located_error.dart';
import 'package:analyzer_utilities/messages.dart';
import 'package:analyzer_utilities/tools.dart';
Future<void> main() async {
await GeneratedContent.generateAll(pkg_root.packageRoot, allTargets);
}
/// A list of all targets generated by this code generator.
final List<GeneratedContent> allTargets = _analyzerGeneratedFiles();
/// Generates a list of [GeneratedContent] objects describing all the analyzer
/// files that need to be generated.
List<GeneratedContent> _analyzerGeneratedFiles() {
return [
GeneratedFile('analyzer/lib/src/diagnostic/diagnostic_code_values.g.dart', (
pkgRoot,
) async {
var codeGenerator = _DiagnosticCodeValuesGenerator();
codeGenerator.generate();
return codeGenerator.out.toString();
}),
for (var package in AnalyzerDiagnosticPackage.values)
GeneratedFile(
'${package.dirName}/lib/${package.diagnosticPathPart}.g.dart',
(pkgRoot) async {
var codeGenerator = _AnalyzerDiagnosticGenerator(
package: package,
parentLibrary:
'package:${package.dirName}/${package.diagnosticPathPart}.dart',
);
codeGenerator.generate();
return codeGenerator.out.toString();
},
),
];
}
/// Code generator for files containing analyzer diagnostics as top level
/// constants.
class _AnalyzerDiagnosticGenerator {
/// The package into which diagnostic will be generated.
final AnalyzerDiagnosticPackage package;
/// The Uri of the library that the generated file will be a part of.
final String parentLibrary;
final StringBuffer out = StringBuffer('''
// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// THIS FILE IS GENERATED. DO NOT EDIT.
//
// Instead modify 'pkg/analyzer/messages.yaml' and run
// 'dart run pkg/analyzer/tool/messages/generate.dart' to update.
''');
_AnalyzerDiagnosticGenerator({
required this.package,
required this.parentLibrary,
});
void generate() {
package.writeIgnoresTo(out);
out.writeln();
out.write('''
part of ${json.encode(parentLibrary)};
''');
out.writeln();
var memberAccumulator = MemberAccumulator();
for (var message in diagnosticTables.activeMessagesByPackage[package]!) {
LocatedError.wrap(span: message.keySpan, () {
message.toAnalyzerCode(memberAccumulator: memberAccumulator);
});
}
memberAccumulator.writeTo(out);
}
}
class _DiagnosticCodeValuesGenerator {
final StringBuffer out = StringBuffer('''
// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// THIS FILE IS GENERATED. DO NOT EDIT.
//
// Instead modify 'pkg/analyzer/messages.yaml' and run
// 'dart run pkg/analyzer/tool/messages/generate.dart' to update.
''');
void generate() {
AnalyzerDiagnosticPackage.analyzer.writeIgnoresTo(out);
out.writeln();
out.writeln(r'''
part of 'diagnostic_code_values.dart';
''');
out.writeln();
out.writeln(
"@AnalyzerPublicApi(message: 'exported by lib/error/error.dart')",
);
out.writeln('const List<DiagnosticCode> diagnosticCodeValues = [');
for (var message
in diagnosticTables.activeMessagesByPackage[AnalyzerDiagnosticPackage
.analyzer]!) {
out.writeln(' ${message.analyzerCode.analyzerCodeReference},');
}
out.writeln('];');
out.writeln();
_generateSharedAnalyzerCodeList();
out.writeln(
"@AnalyzerPublicApi(message: 'exported by lib/error/error.dart')",
);
out.writeln('@Deprecated("Use \'diagnosticCodeValues\' instead")');
out.writeln(
'List<DiagnosticCode> get errorCodeValues => diagnosticCodeValues;',
);
}
void _generateSharedAnalyzerCodeList() {
out.writeln('final sharedAnalyzerCodes = <DiagnosticCode>[');
for (var entry in diagnosticTables.sortedSharedDiagnostics) {
out.writeln('${entry.analyzerCode.analyzerCodeReference},');
}
out.writeln('];');
}
}