// 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 main() async { await GeneratedContent.generateAll(pkg_root.packageRoot, allTargets); } /// A list of all targets generated by this code generator. final List allTargets = _analyzerGeneratedFiles(); /// Generates a list of [GeneratedContent] objects describing all the analyzer /// files that need to be generated. List _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 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 get errorCodeValues => diagnosticCodeValues;', ); } void _generateSharedAnalyzerCodeList() { out.writeln('final sharedAnalyzerCodes = ['); for (var entry in diagnosticTables.sortedSharedDiagnostics) { out.writeln('${entry.analyzerCode.analyzerCodeReference},'); } out.writeln('];'); } }