From 1309dffc0acb01f6a21bb629d5a1a50dcfb91cbb Mon Sep 17 00:00:00 2001 From: Konstantin Shcheglov Date: Thu, 7 May 2026 13:54:59 -0700 Subject: [PATCH] CQ. Move analyzer diagnostics back into analyzer. Move the analyzer-only Diagnostic, DiagnosticMessage, Severity, and locatable diagnostic helper types out of _fe_analyzer_shared and into package:analyzer. I paln to make changes outlined in https://github.com/dart-lang/sdk/issues/63311 and chat discussion. Keeping these classes in the analyzer simplifies the migration and avoids introducing a shared abstraction before there is a concrete need for one. If we decide later need to have a shared abstraction, we can always extract one at that point. With coding agents internal code motion is cheap. Update analyzer, analysis server plugin, analyzer plugin, linter, and scanner call sites to import the moved APIs from analyzer libraries, and refresh API baselines to reflect the new public owner. Change-Id: Ie0ef0f01c6e4be7ebaac25619ac3e3fe991a44d9 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/501000 Reviewed-by: Samuel Rawlins Reviewed-by: Paul Berry Commit-Queue: Konstantin Shcheglov --- .../lib/src/base/diagnostic_message.dart | 90 ---- .../lib/src/base/errors.dart | 403 ------------------ pkg/_fe_analyzer_shared/pubspec.yaml | 1 - pkg/analysis_server/lib/src/diagnostic.dart | 1 + pkg/analysis_server_plugin/api.txt | 3 +- pkg/analyzer/lib/diagnostic/diagnostic.dart | 178 +++++++- pkg/analyzer/lib/error/error.dart | 1 + pkg/analyzer/lib/error/listener.dart | 1 - .../lib/src/dart/analysis/driver.dart | 3 +- .../lib/src/dart/constant/evaluation.dart | 3 +- .../lib/src/dart/element/extensions.dart | 3 +- .../lib/src/dart/error/lint_codes.dart | 3 +- .../lib/src/dart/error/todo_codes.dart | 4 +- .../dart/resolver/named_type_resolver.dart | 4 +- .../lib/src/dart/scanner/scanner.dart | 3 +- .../dart/scanner/translate_error_token.dart | 5 +- .../src/dart/type_instantiation_target.dart | 13 +- .../lib/src/diagnostic/diagnostic.dart | 310 +++++++++++++- .../src/diagnostic/diagnostic_factory.dart | 42 +- .../src/diagnostic/diagnostic_message.dart | 6 - .../error/base_or_final_type_verifier.dart | 4 +- pkg/analyzer/lib/src/error/codes.dart | 2 - pkg/analyzer/lib/src/error/listener.dart | 8 +- .../src/error/type_arguments_verifier.dart | 4 +- .../lib/src/fasta/error_converter.dart | 3 +- .../lib/src/generated/error_verifier.dart | 4 +- pkg/analyzer/lib/src/generated/resolver.dart | 4 +- .../lib/src/utilities/extensions/element.dart | 3 +- pkg/analyzer_plugin/api.txt | 7 +- .../utilities/analyzer_converter_test.dart | 7 +- pkg/analyzer_testing/api.txt | 3 +- pkg/front_end/test/scanner_cfe_test.dart | 2 +- .../test/scanner_replacement_test.dart | 2 +- .../lib/src/rules/prefer_final_locals.dart | 4 +- 34 files changed, 563 insertions(+), 571 deletions(-) delete mode 100644 pkg/_fe_analyzer_shared/lib/src/base/diagnostic_message.dart delete mode 100644 pkg/analyzer/lib/src/diagnostic/diagnostic_message.dart diff --git a/pkg/_fe_analyzer_shared/lib/src/base/diagnostic_message.dart b/pkg/_fe_analyzer_shared/lib/src/base/diagnostic_message.dart deleted file mode 100644 index d9f5a875e60..00000000000 --- a/pkg/_fe_analyzer_shared/lib/src/base/diagnostic_message.dart +++ /dev/null @@ -1,90 +0,0 @@ -// 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. - -import 'package:_fe_analyzer_shared/src/base/analyzer_public_api.dart'; -import 'package:_fe_analyzer_shared/src/base/errors.dart'; - -/// A single message associated with a [Diagnostic], consisting of the text of -/// the message and the location associated with it. -/// -/// Clients may not extend, implement or mix-in this class. -@AnalyzerPublicApi( - message: 'Exported by package:analyzer/diagnostic/diagnostic.dart', -) -abstract class DiagnosticMessage { - /// The absolute and normalized path of the file associated with this message. - String get filePath; - - /// The length of the source range associated with this message. - int get length; - - /// The zero-based offset from the start of the file to the beginning of the - /// source range associated with this message. - int get offset; - - /// The URL containing documentation about this diagnostic message, if any. - /// - /// Note: this should not be confused with the location in the user's code - /// where the error was reported; that information can be obtained from - /// [filePath], [length], and [offset]. - String? get url; - - /// Gets the text of the message. - /// - /// If [includeUrl] is `true`, and this diagnostic message has an associated - /// URL, it is included in the returned value in a human-readable way. - /// Clients that wish to present URLs as simple text can do this. If - /// [includeUrl] is `false`, no URL is included in the returned value. - /// Clients that have a special mechanism for presenting URLs (e.g. as a - /// clickable link) should do this and then consult the [url] getter to access - /// the URL. - String messageText({required bool includeUrl}); -} - -/// A concrete implementation of a diagnostic message. -class DiagnosticMessageImpl implements DiagnosticMessage { - @override - final String filePath; - - @override - final int length; - - final String _message; - - @override - final int offset; - - @override - final String? url; - - /// Initialize a newly created message to represent a [message] reported in - /// the file at the given [filePath] at the given [offset] and with the given - /// [length]. - DiagnosticMessageImpl({ - required this.filePath, - required this.length, - required String message, - required this.offset, - required this.url, - }) : _message = message; - - @override - String messageText({required bool includeUrl}) { - if (includeUrl && url != null) { - StringBuffer result = new StringBuffer(_message); - if (!_message.endsWith('.')) { - result.write('.'); - } - result.write(' See $url'); - return result.toString(); - } - return _message; - } -} - -/// An indication of the severity of a [Diagnostic]. -@AnalyzerPublicApi( - message: 'exported by package:analyzer/diagnostic/diagnostic.dart', -) -enum Severity { error, warning, info } diff --git a/pkg/_fe_analyzer_shared/lib/src/base/errors.dart b/pkg/_fe_analyzer_shared/lib/src/base/errors.dart index 0730045233c..91315d148ca 100644 --- a/pkg/_fe_analyzer_shared/lib/src/base/errors.dart +++ b/pkg/_fe_analyzer_shared/lib/src/base/errors.dart @@ -8,12 +8,7 @@ library; import 'dart:math'; import 'package:_fe_analyzer_shared/src/base/analyzer_public_api.dart'; -import 'package:_fe_analyzer_shared/src/base/diagnostic_message.dart'; -import 'package:_fe_analyzer_shared/src/base/source.dart'; -import 'package:_fe_analyzer_shared/src/base/source_range.dart'; -import 'package:_fe_analyzer_shared/src/base/syntactic_entity.dart'; import 'package:_fe_analyzer_shared/src/scanner/characters.dart'; -import 'package:source_span/source_span.dart'; import 'customized_codes.dart'; @@ -76,175 +71,6 @@ String formatList(String pattern, List? arguments) { return buffer.join(); } -/// A diagnostic, as defined by the [Diagnostic Design Guidelines][guidelines]: -/// -/// > An indication of a specific problem at a specific location within the -/// > source code being processed by a development tool. -/// -/// Clients may not extend, implement or mix-in this class. -/// -/// [guidelines]: https://github.com/dart-lang/sdk/blob/main/pkg/analyzer/doc/implementation/diagnostics.md -@AnalyzerPublicApi( - message: 'Exported by package:analyzer/diagnostic/diagnostic.dart', -) -class Diagnostic { - /// The diagnostic code associated with the diagnostic. - final DiagnosticCode diagnosticCode; - - /// A list of messages that provide context for understanding the problem - /// being reported. The list will be empty if there are no such messages. - final List contextMessages; - - /// A description of how to fix the problem, or `null` if there is no such - /// description. - final String? correctionMessage; - - /// A message describing what is wrong and why. - final DiagnosticMessage problemMessage; - - /// The source in which the diagnostic occurred, or `null` if unknown. - final Source source; - - Diagnostic.forValues({ - required this.source, - required int offset, - required int length, - required this.diagnosticCode, - required String message, - this.correctionMessage, - this.contextMessages = const [], - }) : problemMessage = new DiagnosticMessageImpl( - filePath: source.fullName, - length: length, - message: message, - offset: offset, - url: null, - ); - - /// Initialize a newly created diagnostic. - /// - /// The diagnostic is associated with the given [source] and is located at the - /// given [offset] with the given [length]. The diagnostic will have the given - /// [diagnosticCode] and the list of [arguments] will be used to complete the - /// message and correction. If any [contextMessages] are provided, they will - /// be recorded with the diagnostic. - factory Diagnostic.tmp({ - required Source source, - required int offset, - required int length, - required DiagnosticCode diagnosticCode, - List arguments = const [], - List contextMessages = const [], - }) { - assert( - arguments.length == diagnosticCode.numParameters, - 'Message $diagnosticCode requires ${diagnosticCode.numParameters} ' - 'argument${diagnosticCode.numParameters == 1 ? '' : 's'}, but ' - '${arguments.length} ' - 'argument${arguments.length == 1 ? ' was' : 's were'} ' - 'provided', - ); - String message = formatList(diagnosticCode.problemMessage, arguments); - String? correctionTemplate = diagnosticCode.correctionMessage; - String? correctionMessage; - if (correctionTemplate != null) { - correctionMessage = formatList(correctionTemplate, arguments); - } - - return new Diagnostic.forValues( - source: source, - offset: offset, - length: length, - diagnosticCode: diagnosticCode, - message: message, - correctionMessage: correctionMessage, - contextMessages: contextMessages, - ); - } - - /// The template used to create the correction to be displayed for this - /// diagnostic, or `null` if there is no correction information for this - /// error. The correction should indicate how the user can fix the error. - @Deprecated("Use 'correctionMessage' instead.") - String? get correction => correctionMessage; - - @Deprecated("Use 'diagnosticCode' instead") - DiagnosticCode get errorCode => diagnosticCode; - - @override - int get hashCode { - int hashCode = offset; - hashCode ^= message.hashCode; - hashCode ^= source.hashCode; - return hashCode; - } - - /// The number of characters from the offset to the end of the source which - /// encompasses the compilation error. - int get length => problemMessage.length; - - /// The message to be displayed for this diagnostic. - /// - /// The message indicates what is wrong and why it is wrong. - String get message => problemMessage.messageText(includeUrl: true); - - /// The character offset from the beginning of the source (zero based) where - /// the diagnostic occurred. - int get offset => problemMessage.offset; - - Severity get severity { - switch (diagnosticCode.severity) { - case DiagnosticSeverity.ERROR: - return Severity.error; - case DiagnosticSeverity.WARNING: - return Severity.warning; - case DiagnosticSeverity.INFO: - return Severity.info; - default: - throw new StateError('Invalid severity: ${diagnosticCode.severity}'); - } - } - - @override - bool operator ==(Object other) { - if (identical(other, this)) { - return true; - } - // prepare the other Diagnostic. - if (other is Diagnostic) { - // Quick checks. - if (!identical(diagnosticCode, other.diagnosticCode)) { - return false; - } - if (offset != other.offset || length != other.length) { - return false; - } - // Deep checks. - if (message != other.message) { - return false; - } - if (source != other.source) { - return false; - } - return true; - } - return false; - } - - @override - String toString() { - StringBuffer buffer = new StringBuffer(); - buffer.write(source.fullName); - buffer.write("("); - buffer.write(offset); - buffer.write(".."); - buffer.write(offset + length - 1); - buffer.write("): "); - buffer.write(message); - return buffer.toString(); - } -} - /// An error code associated with an `AnalysisError`. /// /// Generally, messages should follow the [Guide for Writing @@ -376,23 +202,6 @@ abstract class DiagnosticCodeImpl extends DiagnosticCode { DiagnosticSeverity get severity => type.severity; } -/// Private subtype of [DiagnosticCode] that supports runtime checking of -/// parameter types. -class DiagnosticCodeWithExpectedTypes extends DiagnosticCodeImpl { - final List? expectedTypes; - - const DiagnosticCodeWithExpectedTypes({ - super.correctionMessage, - super.hasPublishedDocs = false, - super.isUnresolvedIdentifier = false, - required super.name, - required super.problemMessage, - required super.type, - required super.uniqueName, - this.expectedTypes, - }); -} - /// The severity of an [DiagnosticCode]. @AnalyzerPublicApi(message: 'exported by package:analyzer/error/error.dart') class DiagnosticSeverity implements Comparable { @@ -565,215 +374,3 @@ class DiagnosticType implements Comparable { @override String toString() => name; } - -/// Common functionality for [DiagnosticCode]-derived classes that represent -/// errors that take arguments. -/// -/// This class provides a [withArguments] getter, which can be used to supply -/// arguments and produce a [LocatableDiagnostic]. -/// -/// Note: the type argument `T` should be instantiated with a function type. But -/// it is typed as `extends Object` in order to reduce the risk of accidental -/// dynamic invocation of [withArguments]. -class DiagnosticWithArguments - extends DiagnosticCodeWithExpectedTypes { - /// Function accepting named arguments and returning [LocatableDiagnostic]. - /// - /// The value returned by this function can - /// be associated with a location in the source code using the - /// [LocatableDiagnostic.at] method, and then the result can be passed to - /// [DiagnosticReporter.reportError]. - final T withArguments; - - const DiagnosticWithArguments({ - required super.name, - required super.problemMessage, - super.correctionMessage, - super.hasPublishedDocs = false, - super.isUnresolvedIdentifier = false, - required super.type, - required super.uniqueName, - required super.expectedTypes, - required this.withArguments, - }); -} - -/// Common functionality for [DiagnosticCode]-derived classes that represent -/// errors that do not take arguments. -/// -/// This class implements [LocatableDiagnostic], which means that instances can -/// be associated with a location in the source code using the [at] method, and -/// then the result can be passed to [DiagnosticReporter.reportError]. -base mixin DiagnosticWithoutArguments on DiagnosticCodeImpl - implements LocatableDiagnostic { - @override - List get arguments => const []; - - @override - DiagnosticCode get code => this; - - @override - Iterable get contextMessages => const []; - - @override - LocatedDiagnostic at(SyntacticEntity node) => - atOffset(offset: node.offset, length: node.length); - - @override - LocatedDiagnostic atOffset({required int offset, required int length}) => - new LocatedDiagnostic(this, offset, length); - - @override - LocatedDiagnostic atSourceRange(SourceRange sourceRange) => - atOffset(offset: sourceRange.offset, length: sourceRange.length); - - @override - LocatedDiagnostic atSourceSpan(SourceSpan span) => - atOffset(offset: span.start.offset, length: span.length); - - @override - LocatableDiagnostic withContextMessages( - Iterable messages, - ) => new LocatableDiagnosticImpl( - code, - arguments, - contextMessages: [...messages], - ); -} - -/// Concrete implementation of [DiagnosticWithoutArguments], used for diagnostic -/// messages that don't take any arguments. -/// -/// This needs to be a separate class from [DiagnosticWithoutArguments] because -/// [DiagnosticWithoutArguments] is a mixin. -final class DiagnosticWithoutArgumentsImpl - extends DiagnosticCodeWithExpectedTypes - with DiagnosticWithoutArguments { - const DiagnosticWithoutArgumentsImpl({ - required super.name, - required super.problemMessage, - super.correctionMessage, - super.hasPublishedDocs = false, - super.isUnresolvedIdentifier = false, - required super.type, - required super.uniqueName, - super.expectedTypes, - }); -} - -/// Expected type of a diagnostic code's parameter. -enum ExpectedType { element, int, name, object, string, token, type, uri } - -/// Interface for a diagnostic that does not have any unfilled template -/// parameters, and hence is ready to be associated with a location in the -/// source code. -/// -/// This could either be the result of calling `withArguments` on a diagnostic -/// code that requires arguments, or it could be a diagnostic code that doesn't -/// require arguments. -abstract final class LocatableDiagnostic { - /// The arguments that were applied to the diagnostic, or the empty list if - /// [code] doesn't accept any arguments. - List get arguments; - - /// The [DiagnosticCode] associated with the diagnostic. - DiagnosticCode get code; - - /// The context messages that were applied to the diagnostic. - Iterable get contextMessages; - - /// Converts this diagnostic to a [LocatedDiagnostic] by applying it to a - /// syntactic entity in the source code. - /// - /// The result may be passed to [DiagnosticReporter.reportError]. - LocatedDiagnostic at(SyntacticEntity node); - - /// Converts this diagnostic to a [LocatedDiagnostic] by applying it to a - /// location in the source code. - /// - /// The result may be passed to [DiagnosticReporter.reportError]. - LocatedDiagnostic atOffset({required int offset, required int length}); - - /// Converts this diagnostic to a [LocatedDiagnostic] by applying it to a - /// location in the source code. - /// - /// The result may be passed to [DiagnosticReporter.reportError]. - LocatedDiagnostic atSourceRange(SourceRange sourceRange); - - /// Converts this diagnostic to a [LocatedDiagnostic] by applying it to a - /// location in the source code. - /// - /// The result may be passed to [DiagnosticReporter.reportError]. - LocatedDiagnostic atSourceSpan(SourceSpan span); - - /// Attaches context messages to this diagnostic. - /// - /// The return value is a fresh instance of [LocatableDiagnostic]. This allows - /// for a literate style of error reporting, e.g.: - /// ```dart - /// // For an diagnostic code that doesn't take arguments: - /// diagnosticReporter.reportError( - /// diagnosticCode.withContextMessages(messages).at(astNode)); - /// - /// // For a diagnostic code that does take arguments: - /// diagnosticReporter.reportError( - /// diagnosticCode - /// .withArguments(...) - /// .withContextMessages(messages) - /// .at(astNode)); - /// ``` - LocatableDiagnostic withContextMessages(Iterable messages); -} - -/// Concrete implementation of [LocatableDiagnostic]. -final class LocatableDiagnosticImpl implements LocatableDiagnostic { - @override - final DiagnosticCode code; - - @override - final List arguments; - - @override - final Iterable contextMessages; - - LocatableDiagnosticImpl( - this.code, - this.arguments, { - this.contextMessages = const [], - }); - - @override - LocatedDiagnostic at(SyntacticEntity node) => - atOffset(offset: node.offset, length: node.length); - - @override - LocatedDiagnostic atOffset({required int offset, required int length}) => - new LocatedDiagnostic(this, offset, length); - - @override - LocatedDiagnostic atSourceRange(SourceRange sourceRange) => - atOffset(offset: sourceRange.offset, length: sourceRange.length); - - @override - LocatedDiagnostic atSourceSpan(SourceSpan span) => - atOffset(offset: span.start.offset, length: span.length); - - @override - LocatableDiagnostic withContextMessages( - Iterable messages, - ) => new LocatableDiagnosticImpl( - code, - arguments, - contextMessages: [...contextMessages, ...messages], - ); -} - -/// A diagnostic that does not have any unfilled template parameters, and has -/// been associated with a location in the source code. -final class LocatedDiagnostic { - final LocatableDiagnostic locatableDiagnostic; - final int offset; - final int length; - - LocatedDiagnostic(this.locatableDiagnostic, this.offset, this.length); -} diff --git a/pkg/_fe_analyzer_shared/pubspec.yaml b/pkg/_fe_analyzer_shared/pubspec.yaml index dc8d868005e..1b06f3982b6 100644 --- a/pkg/_fe_analyzer_shared/pubspec.yaml +++ b/pkg/_fe_analyzer_shared/pubspec.yaml @@ -12,7 +12,6 @@ resolution: workspace dependencies: meta: ^1.9.0 - source_span: ^1.10.0 # We use 'any' version constraints here as we get our package versions from # the dart-lang/sdk repo's DEPS file. Note that this is a special case; the diff --git a/pkg/analysis_server/lib/src/diagnostic.dart b/pkg/analysis_server/lib/src/diagnostic.dart index c72add3a499..04a679071bf 100644 --- a/pkg/analysis_server/lib/src/diagnostic.dart +++ b/pkg/analysis_server/lib/src/diagnostic.dart @@ -3,6 +3,7 @@ // BSD-style license that can be found in the LICENSE file. import 'package:_fe_analyzer_shared/src/base/errors.dart'; +import 'package:analyzer/src/diagnostic/diagnostic.dart'; import 'diagnostic.dart' as diag; diff --git a/pkg/analysis_server_plugin/api.txt b/pkg/analysis_server_plugin/api.txt index f5b4f4614e1..d6e86e2f688 100644 --- a/pkg/analysis_server_plugin/api.txt +++ b/pkg/analysis_server_plugin/api.txt @@ -161,7 +161,6 @@ dart:core: bool (referenced) int (referenced) package:_fe_analyzer_shared/src/base/errors.dart: - Diagnostic (referenced) DiagnosticCode (referenced) package:_fe_analyzer_shared/src/base/source_range.dart: SourceRange (referenced) @@ -193,6 +192,8 @@ package:analyzer/dart/element/type_provider.dart: TypeProvider (referenced) package:analyzer/dart/element/type_system.dart: TypeSystem (referenced) +package:analyzer/diagnostic/diagnostic.dart: + Diagnostic (referenced) package:analyzer/instrumentation/service.dart: InstrumentationService (referenced) package:analyzer/src/dart/ast/ast.dart: diff --git a/pkg/analyzer/lib/diagnostic/diagnostic.dart b/pkg/analyzer/lib/diagnostic/diagnostic.dart index 4e9fc92e10e..4c1b8b81b51 100644 --- a/pkg/analyzer/lib/diagnostic/diagnostic.dart +++ b/pkg/analyzer/lib/diagnostic/diagnostic.dart @@ -2,6 +2,178 @@ // 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. -export 'package:_fe_analyzer_shared/src/base/diagnostic_message.dart' - show DiagnosticMessage, Severity; -export 'package:_fe_analyzer_shared/src/base/errors.dart' show Diagnostic; +import 'package:_fe_analyzer_shared/src/base/errors.dart'; +import 'package:analyzer/source/source.dart'; +import 'package:analyzer/src/diagnostic/diagnostic.dart' + show DiagnosticMessage, DiagnosticMessageImpl; + +export 'package:analyzer/src/diagnostic/diagnostic.dart' show DiagnosticMessage; + +/// A diagnostic, as defined by the [Diagnostic Design Guidelines][guidelines]: +/// +/// > An indication of a specific problem at a specific location within the +/// > source code being processed by a development tool. +/// +/// Clients may not extend, implement or mix-in this class. +/// +/// [guidelines]: https://github.com/dart-lang/sdk/blob/main/pkg/analyzer/doc/implementation/diagnostics.md +class Diagnostic { + /// The diagnostic code associated with the diagnostic. + final DiagnosticCode diagnosticCode; + + /// A list of messages that provide context for understanding the problem + /// being reported. The list will be empty if there are no such messages. + final List contextMessages; + + /// A description of how to fix the problem, or `null` if there is no such + /// description. + final String? correctionMessage; + + /// A message describing what is wrong and why. + final DiagnosticMessage problemMessage; + + /// The source in which the diagnostic occurred, or `null` if unknown. + final Source source; + + Diagnostic.forValues({ + required this.source, + required int offset, + required int length, + required this.diagnosticCode, + required String message, + this.correctionMessage, + this.contextMessages = const [], + }) : problemMessage = DiagnosticMessageImpl( + filePath: source.fullName, + length: length, + message: message, + offset: offset, + url: null, + ); + + /// Initialize a newly created diagnostic. + /// + /// The diagnostic is associated with the given [source] and is located at the + /// given [offset] with the given [length]. The diagnostic will have the given + /// [diagnosticCode] and the list of [arguments] will be used to complete the + /// message and correction. If any [contextMessages] are provided, they will + /// be recorded with the diagnostic. + factory Diagnostic.tmp({ + required Source source, + required int offset, + required int length, + required DiagnosticCode diagnosticCode, + List arguments = const [], + List contextMessages = const [], + }) { + assert( + arguments.length == diagnosticCode.numParameters, + 'Message $diagnosticCode requires ${diagnosticCode.numParameters} ' + 'argument${diagnosticCode.numParameters == 1 ? '' : 's'}, but ' + '${arguments.length} ' + 'argument${arguments.length == 1 ? ' was' : 's were'} ' + 'provided', + ); + String message = formatList(diagnosticCode.problemMessage, arguments); + String? correctionTemplate = diagnosticCode.correctionMessage; + String? correctionMessage; + if (correctionTemplate != null) { + correctionMessage = formatList(correctionTemplate, arguments); + } + + return Diagnostic.forValues( + source: source, + offset: offset, + length: length, + diagnosticCode: diagnosticCode, + message: message, + correctionMessage: correctionMessage, + contextMessages: contextMessages, + ); + } + + /// The template used to create the correction to be displayed for this + /// diagnostic, or `null` if there is no correction information for this + /// error. The correction should indicate how the user can fix the error. + @Deprecated("Use 'correctionMessage' instead.") + String? get correction => correctionMessage; + + @Deprecated("Use 'diagnosticCode' instead") + DiagnosticCode get errorCode => diagnosticCode; + + @override + int get hashCode { + int hashCode = offset; + hashCode ^= message.hashCode; + hashCode ^= source.hashCode; + return hashCode; + } + + /// The number of characters from the offset to the end of the source which + /// encompasses the compilation error. + int get length => problemMessage.length; + + /// The message to be displayed for this diagnostic. + /// + /// The message indicates what is wrong and why it is wrong. + String get message => problemMessage.messageText(includeUrl: true); + + /// The character offset from the beginning of the source (zero based) where + /// the diagnostic occurred. + int get offset => problemMessage.offset; + + Severity get severity { + switch (diagnosticCode.severity) { + case DiagnosticSeverity.ERROR: + return Severity.error; + case DiagnosticSeverity.WARNING: + return Severity.warning; + case DiagnosticSeverity.INFO: + return Severity.info; + default: + throw StateError('Invalid severity: ${diagnosticCode.severity}'); + } + } + + @override + bool operator ==(Object other) { + if (identical(other, this)) { + return true; + } + // prepare the other Diagnostic. + if (other is Diagnostic) { + // Quick checks. + if (!identical(diagnosticCode, other.diagnosticCode)) { + return false; + } + if (offset != other.offset || length != other.length) { + return false; + } + // Deep checks. + if (message != other.message) { + return false; + } + if (source != other.source) { + return false; + } + return true; + } + return false; + } + + @override + String toString() { + StringBuffer buffer = StringBuffer(); + buffer.write(source.fullName); + buffer.write("("); + buffer.write(offset); + buffer.write(".."); + buffer.write(offset + length - 1); + buffer.write("): "); + buffer.write(message); + return buffer.toString(); + } +} + +/// An indication of the severity of a [Diagnostic]. +enum Severity { error, warning, info } diff --git a/pkg/analyzer/lib/error/error.dart b/pkg/analyzer/lib/error/error.dart index 9433fb0e442..6fb2866a2af 100644 --- a/pkg/analyzer/lib/error/error.dart +++ b/pkg/analyzer/lib/error/error.dart @@ -8,6 +8,7 @@ library; import 'dart:collection'; import 'package:_fe_analyzer_shared/src/base/errors.dart'; +import 'package:analyzer/diagnostic/diagnostic.dart'; import 'package:analyzer/src/diagnostic/diagnostic_code_values.dart'; export 'package:_fe_analyzer_shared/src/base/errors.dart' diff --git a/pkg/analyzer/lib/error/listener.dart b/pkg/analyzer/lib/error/listener.dart index 64737186ff5..586f3a86d6d 100644 --- a/pkg/analyzer/lib/error/listener.dart +++ b/pkg/analyzer/lib/error/listener.dart @@ -2,7 +2,6 @@ // 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. -import 'package:_fe_analyzer_shared/src/base/errors.dart'; import 'package:analyzer/diagnostic/diagnostic.dart'; import 'package:analyzer/src/error/listener.dart'; diff --git a/pkg/analyzer/lib/src/dart/analysis/driver.dart b/pkg/analyzer/lib/src/dart/analysis/driver.dart index 59c337f971e..75de5a6c0e0 100644 --- a/pkg/analyzer/lib/src/dart/analysis/driver.dart +++ b/pkg/analyzer/lib/src/dart/analysis/driver.dart @@ -39,7 +39,8 @@ import 'package:analyzer/src/dart/ast/ast.dart'; import 'package:analyzer/src/dart/element/element.dart'; import 'package:analyzer/src/dart/resolver/flow_analysis_visitor.dart'; import 'package:analyzer/src/dartdoc/dartdoc_directive_info.dart'; -import 'package:analyzer/src/diagnostic/diagnostic_message.dart'; +import 'package:analyzer/src/diagnostic/diagnostic.dart' + show DiagnosticMessageImpl; import 'package:analyzer/src/exception/exception.dart'; import 'package:analyzer/src/fine/manifest_id.dart'; import 'package:analyzer/src/fine/requirements.dart'; diff --git a/pkg/analyzer/lib/src/dart/constant/evaluation.dart b/pkg/analyzer/lib/src/dart/constant/evaluation.dart index 9106ac3a9c3..6f551e15340 100644 --- a/pkg/analyzer/lib/src/dart/constant/evaluation.dart +++ b/pkg/analyzer/lib/src/dart/constant/evaluation.dart @@ -28,8 +28,9 @@ import 'package:analyzer/src/dart/element/type_algebra.dart'; import 'package:analyzer/src/dart/element/type_provider.dart'; import 'package:analyzer/src/dart/element/type_system.dart' show TypeSystemImpl; import 'package:analyzer/src/dart/type_instantiation_target.dart'; +import 'package:analyzer/src/diagnostic/diagnostic.dart' + show DiagnosticMessageImpl; import 'package:analyzer/src/diagnostic/diagnostic.dart' as diag; -import 'package:analyzer/src/diagnostic/diagnostic_message.dart'; import 'package:analyzer/src/error/listener.dart'; import 'package:analyzer/src/generated/engine.dart'; import 'package:analyzer/src/generated/java_core.dart'; diff --git a/pkg/analyzer/lib/src/dart/element/extensions.dart b/pkg/analyzer/lib/src/dart/element/extensions.dart index c0203fbd468..7a13a1e65a3 100644 --- a/pkg/analyzer/lib/src/dart/element/extensions.dart +++ b/pkg/analyzer/lib/src/dart/element/extensions.dart @@ -10,7 +10,8 @@ import 'package:analyzer/source/source.dart'; import 'package:analyzer/source/source_range.dart'; import 'package:analyzer/src/dart/element/element.dart'; import 'package:analyzer/src/dart/element/type.dart'; -import 'package:analyzer/src/diagnostic/diagnostic_message.dart'; +import 'package:analyzer/src/diagnostic/diagnostic.dart' + show DiagnosticMessageImpl; import 'package:analyzer/src/generated/utilities_dart.dart'; import 'package:meta/meta_meta.dart'; diff --git a/pkg/analyzer/lib/src/dart/error/lint_codes.dart b/pkg/analyzer/lib/src/dart/error/lint_codes.dart index 370f3fe3f9b..4e6cc0f7048 100644 --- a/pkg/analyzer/lib/src/dart/error/lint_codes.dart +++ b/pkg/analyzer/lib/src/dart/error/lint_codes.dart @@ -8,8 +8,9 @@ library; import 'package:_fe_analyzer_shared/src/base/analyzer_public_api.dart'; import 'package:_fe_analyzer_shared/src/base/errors.dart'; +import 'package:analyzer/src/diagnostic/diagnostic.dart'; -export 'package:_fe_analyzer_shared/src/base/errors.dart' +export 'package:analyzer/src/diagnostic/diagnostic.dart' show DiagnosticWithArguments, DiagnosticWithoutArguments, diff --git a/pkg/analyzer/lib/src/dart/error/todo_codes.dart b/pkg/analyzer/lib/src/dart/error/todo_codes.dart index 9e2cf4b84bb..bae0ac541b0 100644 --- a/pkg/analyzer/lib/src/dart/error/todo_codes.dart +++ b/pkg/analyzer/lib/src/dart/error/todo_codes.dart @@ -6,8 +6,8 @@ import 'package:_fe_analyzer_shared/src/base/errors.dart'; import 'package:analyzer/src/diagnostic/diagnostic.dart' as diag; typedef TodoDiagnosticCode = - DiagnosticWithArguments< - LocatableDiagnostic Function({required String message}) + diag.DiagnosticWithArguments< + diag.LocatableDiagnostic Function({required String message}) >; /// Static helper methods and properties for working with [DiagnosticType.TODO] diff --git a/pkg/analyzer/lib/src/dart/resolver/named_type_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/named_type_resolver.dart index 4165e470d41..ee15fd27bd0 100644 --- a/pkg/analyzer/lib/src/dart/resolver/named_type_resolver.dart +++ b/pkg/analyzer/lib/src/dart/resolver/named_type_resolver.dart @@ -14,13 +14,13 @@ import 'package:analyzer/src/dart/element/element.dart'; import 'package:analyzer/src/dart/element/type.dart'; import 'package:analyzer/src/dart/element/type_constraint_gatherer.dart'; import 'package:analyzer/src/dart/element/type_system.dart'; -import 'package:analyzer/src/dart/error/lint_codes.dart'; import 'package:analyzer/src/dart/resolver/flow_analysis_visitor.dart'; import 'package:analyzer/src/dart/resolver/scope_context.dart'; import 'package:analyzer/src/dart/type_instantiation_target.dart'; +import 'package:analyzer/src/diagnostic/diagnostic.dart' + show DiagnosticMessageImpl, LocatableDiagnostic; import 'package:analyzer/src/diagnostic/diagnostic.dart' as diag; import 'package:analyzer/src/diagnostic/diagnostic_factory.dart'; -import 'package:analyzer/src/diagnostic/diagnostic_message.dart'; import 'package:analyzer/src/error/listener.dart'; import 'package:analyzer/src/generated/scope_helpers.dart'; diff --git a/pkg/analyzer/lib/src/dart/scanner/scanner.dart b/pkg/analyzer/lib/src/dart/scanner/scanner.dart index ecfa1a8bc3b..ec0c64d0849 100644 --- a/pkg/analyzer/lib/src/dart/scanner/scanner.dart +++ b/pkg/analyzer/lib/src/dart/scanner/scanner.dart @@ -4,7 +4,6 @@ import 'dart:typed_data'; -import 'package:_fe_analyzer_shared/src/base/errors.dart'; import 'package:_fe_analyzer_shared/src/parser/experimental_features.dart'; import 'package:_fe_analyzer_shared/src/scanner/scanner.dart' as fasta; import 'package:_fe_analyzer_shared/src/scanner/token.dart' show Token; @@ -34,7 +33,7 @@ class Scanner { final String _inputText; /// The callback to report diagnostics. - final void Function(LocatedDiagnostic) reportError; + final void Function(diag.LocatedDiagnostic) reportError; /// If the file has [fasta.LanguageVersionToken], it is allowed to use the /// language version greater than the one specified in the package config. diff --git a/pkg/analyzer/lib/src/dart/scanner/translate_error_token.dart b/pkg/analyzer/lib/src/dart/scanner/translate_error_token.dart index c05056a5c4b..2f59bd044f8 100644 --- a/pkg/analyzer/lib/src/dart/scanner/translate_error_token.dart +++ b/pkg/analyzer/lib/src/dart/scanner/translate_error_token.dart @@ -2,7 +2,6 @@ // 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. -import 'package:_fe_analyzer_shared/src/base/errors.dart'; import 'package:_fe_analyzer_shared/src/messages/codes.dart'; import 'package:_fe_analyzer_shared/src/messages/diagnostic.dart' as fe_diag; import 'package:_fe_analyzer_shared/src/messages/diagnostic.dart'; @@ -18,7 +17,7 @@ void translateErrorToken(ErrorToken token, ReportError reportError) { int charOffset = token.charOffset; // TODO(paulberry): why is endOffset sometimes null? int endOffset = token.endOffset ?? charOffset; - void makeError(LocatableDiagnostic locatableDiagnostic) { + void makeError(diag.LocatableDiagnostic locatableDiagnostic) { if (_isAtEnd(token, charOffset)) { // Analyzer never generates an error message past the end of the input, // since such an error would not be visible in an editor. @@ -129,4 +128,4 @@ bool _isAtEnd(Token token, int charOffset) { /// Used to report a scan error. /// The [locatedDiagnostic] contains the error code, arguments, and the location /// of the error. -typedef ReportError = void Function(LocatedDiagnostic locatedDiagnostic); +typedef ReportError = void Function(diag.LocatedDiagnostic locatedDiagnostic); diff --git a/pkg/analyzer/lib/src/dart/type_instantiation_target.dart b/pkg/analyzer/lib/src/dart/type_instantiation_target.dart index 423fc791f5a..caa43126e63 100644 --- a/pkg/analyzer/lib/src/dart/type_instantiation_target.dart +++ b/pkg/analyzer/lib/src/dart/type_instantiation_target.dart @@ -6,7 +6,6 @@ // currently contains some classes called `TypeInstantiationTarget...` and some // called `InvocationTarget...`. -import 'package:_fe_analyzer_shared/src/base/errors.dart'; import 'package:analyzer/dart/element/element.dart'; import 'package:analyzer/dart/element/type.dart'; import 'package:analyzer/src/dart/element/element.dart'; @@ -30,7 +29,7 @@ class InvocationTargetConstructorElement InvocationTargetConstructorElement(super.element, this.rawType); @override - LocatableDiagnostic wrongNumberOfTypeArgumentsError({ + diag.LocatableDiagnostic wrongNumberOfTypeArgumentsError({ required int typeParameterCount, required int typeArgumentCount, }) { @@ -68,7 +67,7 @@ class InvocationTargetExecutableElement extends TypeInstantiationTargetElement element.type as FunctionTypeImpl; @override - LocatableDiagnostic wrongNumberOfTypeArgumentsError({ + diag.LocatableDiagnostic wrongNumberOfTypeArgumentsError({ required int typeParameterCount, required int typeArgumentCount, }) { @@ -102,7 +101,7 @@ class InvocationTargetExtensionOverride extends InvocationTarget { FunctionTypeImpl get rawType => type; @override - LocatableDiagnostic wrongNumberOfTypeArgumentsError({ + diag.LocatableDiagnostic wrongNumberOfTypeArgumentsError({ required int typeParameterCount, required int typeArgumentCount, }) { @@ -132,7 +131,7 @@ class InvocationTargetFunctionTypedExpression extends InvocationTarget { FunctionTypeImpl get rawType => type; @override - LocatableDiagnostic wrongNumberOfTypeArgumentsError({ + diag.LocatableDiagnostic wrongNumberOfTypeArgumentsError({ required int typeParameterCount, required int typeArgumentCount, }) { @@ -160,7 +159,7 @@ sealed class TypeInstantiationTarget { /// Creates the appropriate diagnostic message when the wrong number of type /// arguments is applied. - LocatableDiagnostic wrongNumberOfTypeArgumentsError({ + diag.LocatableDiagnostic wrongNumberOfTypeArgumentsError({ required int typeParameterCount, required int typeArgumentCount, }); @@ -215,7 +214,7 @@ sealed class TypeInstantiationTargetTypeDefiningElement const TypeInstantiationTargetTypeDefiningElement(); @override - LocatableDiagnostic wrongNumberOfTypeArgumentsError({ + diag.LocatableDiagnostic wrongNumberOfTypeArgumentsError({ required int typeParameterCount, required int typeArgumentCount, }) { diff --git a/pkg/analyzer/lib/src/diagnostic/diagnostic.dart b/pkg/analyzer/lib/src/diagnostic/diagnostic.dart index 92c64753094..45ce4ddcbe4 100644 --- a/pkg/analyzer/lib/src/diagnostic/diagnostic.dart +++ b/pkg/analyzer/lib/src/diagnostic/diagnostic.dart @@ -2,12 +2,320 @@ // 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. -/// @docImport 'package:analyzer/src/error/inference_error.dart'; +/// @docImport 'package:analyzer/diagnostic/diagnostic.dart'; +/// @docImport 'package:analyzer/error/listener.dart'; library; +import 'package:_fe_analyzer_shared/src/base/analyzer_public_api.dart'; import 'package:_fe_analyzer_shared/src/base/errors.dart'; +import 'package:analyzer/dart/ast/syntactic_entity.dart'; import 'package:analyzer/dart/element/element.dart'; import 'package:analyzer/dart/element/type.dart'; +import 'package:analyzer/source/source_range.dart'; import 'package:analyzer/src/diagnostic/diagnostic.dart' as diag; +import 'package:source_span/source_span.dart'; part 'package:analyzer/src/diagnostic/diagnostic.g.dart'; + +/// Private subtype of [DiagnosticCode] that supports runtime checking of +/// parameter types. +class DiagnosticCodeWithExpectedTypes extends DiagnosticCodeImpl { + final List? expectedTypes; + + const DiagnosticCodeWithExpectedTypes({ + super.correctionMessage, + super.hasPublishedDocs = false, + super.isUnresolvedIdentifier = false, + required super.name, + required super.problemMessage, + required super.type, + required super.uniqueName, + this.expectedTypes, + }); +} + +/// A single message associated with a [Diagnostic], consisting of the text of +/// the message and the location associated with it. +/// +/// Clients may not extend, implement or mix-in this class. +@AnalyzerPublicApi( + message: 'Exported by package:analyzer/diagnostic/diagnostic.dart', +) +abstract class DiagnosticMessage { + /// The absolute and normalized path of the file associated with this message. + String get filePath; + + /// The length of the source range associated with this message. + int get length; + + /// The zero-based offset from the start of the file to the beginning of the + /// source range associated with this message. + int get offset; + + /// The URL containing documentation about this diagnostic message, if any. + /// + /// Note: this should not be confused with the location in the user's code + /// where the error was reported; that information can be obtained from + /// [filePath], [length], and [offset]. + String? get url; + + /// Gets the text of the message. + /// + /// If [includeUrl] is `true`, and this diagnostic message has an associated + /// URL, it is included in the returned value in a human-readable way. + /// Clients that wish to present URLs as simple text can do this. If + /// [includeUrl] is `false`, no URL is included in the returned value. + /// Clients that have a special mechanism for presenting URLs (e.g. as a + /// clickable link) should do this and then consult the [url] getter to access + /// the URL. + String messageText({required bool includeUrl}); +} + +/// A concrete implementation of a diagnostic message. +class DiagnosticMessageImpl implements DiagnosticMessage { + @override + final String filePath; + + @override + final int length; + + final String _message; + + @override + final int offset; + + @override + final String? url; + + /// Initialize a newly created message to represent a [message] reported in + /// the file at the given [filePath] at the given [offset] and with the given + /// [length]. + DiagnosticMessageImpl({ + required this.filePath, + required this.length, + required String message, + required this.offset, + required this.url, + }) : _message = message; + + @override + String messageText({required bool includeUrl}) { + if (includeUrl && url != null) { + var result = StringBuffer(_message); + if (!_message.endsWith('.')) { + result.write('.'); + } + result.write(' See $url'); + return result.toString(); + } + return _message; + } +} + +/// Common functionality for [DiagnosticCode]-derived classes that represent +/// errors that take arguments. +/// +/// This class provides a [withArguments] getter, which can be used to supply +/// arguments and produce a [LocatableDiagnostic]. +/// +/// Note: the type argument `T` should be instantiated with a function type. But +/// it is typed as `extends Object` in order to reduce the risk of accidental +/// dynamic invocation of [withArguments]. +class DiagnosticWithArguments + extends DiagnosticCodeWithExpectedTypes { + /// Function accepting named arguments and returning [LocatableDiagnostic]. + /// + /// The value returned by this function can + /// be associated with a location in the source code using the + /// [LocatableDiagnostic.at] method, and then the result can be passed to + /// [DiagnosticReporter.reportError]. + final T withArguments; + + const DiagnosticWithArguments({ + required super.name, + required super.problemMessage, + super.correctionMessage, + super.hasPublishedDocs = false, + super.isUnresolvedIdentifier = false, + required super.type, + required super.uniqueName, + required super.expectedTypes, + required this.withArguments, + }); +} + +/// Common functionality for [DiagnosticCode]-derived classes that represent +/// errors that do not take arguments. +/// +/// This class implements [LocatableDiagnostic], which means that instances can +/// be associated with a location in the source code using the [at] method, and +/// then the result can be passed to [DiagnosticReporter.reportError]. +base mixin DiagnosticWithoutArguments on DiagnosticCodeImpl + implements LocatableDiagnostic { + @override + List get arguments => const []; + + @override + DiagnosticCode get code => this; + + @override + Iterable get contextMessages => const []; + + @override + LocatedDiagnostic at(SyntacticEntity node) => + atOffset(offset: node.offset, length: node.length); + + @override + LocatedDiagnostic atOffset({required int offset, required int length}) => + LocatedDiagnostic(this, offset, length); + + @override + LocatedDiagnostic atSourceRange(SourceRange sourceRange) => + atOffset(offset: sourceRange.offset, length: sourceRange.length); + + @override + LocatedDiagnostic atSourceSpan(SourceSpan span) => + atOffset(offset: span.start.offset, length: span.length); + + @override + LocatableDiagnostic withContextMessages( + Iterable messages, + ) => LocatableDiagnosticImpl(code, arguments, contextMessages: [...messages]); +} + +/// Concrete implementation of [DiagnosticWithoutArguments], used for diagnostic +/// messages that don't take any arguments. +/// +/// This needs to be a separate class from [DiagnosticWithoutArguments] because +/// [DiagnosticWithoutArguments] is a mixin. +final class DiagnosticWithoutArgumentsImpl + extends DiagnosticCodeWithExpectedTypes + with DiagnosticWithoutArguments { + const DiagnosticWithoutArgumentsImpl({ + required super.name, + required super.problemMessage, + super.correctionMessage, + super.hasPublishedDocs = false, + super.isUnresolvedIdentifier = false, + required super.type, + required super.uniqueName, + super.expectedTypes, + }); +} + +/// Expected type of a diagnostic code's parameter. +enum ExpectedType { element, int, name, object, string, token, type, uri } + +/// Interface for a diagnostic that does not have any unfilled template +/// parameters, and hence is ready to be associated with a location in the +/// source code. +/// +/// This could either be the result of calling `withArguments` on a diagnostic +/// code that requires arguments, or it could be a diagnostic code that doesn't +/// require arguments. +abstract final class LocatableDiagnostic { + /// The arguments that were applied to the diagnostic, or the empty list if + /// [code] doesn't accept any arguments. + List get arguments; + + /// The [DiagnosticCode] associated with the diagnostic. + DiagnosticCode get code; + + /// The context messages that were applied to the diagnostic. + Iterable get contextMessages; + + /// Converts this diagnostic to a [LocatedDiagnostic] by applying it to a + /// syntactic entity in the source code. + /// + /// The result may be passed to [DiagnosticReporter.reportError]. + LocatedDiagnostic at(SyntacticEntity node); + + /// Converts this diagnostic to a [LocatedDiagnostic] by applying it to a + /// location in the source code. + /// + /// The result may be passed to [DiagnosticReporter.reportError]. + LocatedDiagnostic atOffset({required int offset, required int length}); + + /// Converts this diagnostic to a [LocatedDiagnostic] by applying it to a + /// location in the source code. + /// + /// The result may be passed to [DiagnosticReporter.reportError]. + LocatedDiagnostic atSourceRange(SourceRange sourceRange); + + /// Converts this diagnostic to a [LocatedDiagnostic] by applying it to a + /// location in the source code. + /// + /// The result may be passed to [DiagnosticReporter.reportError]. + LocatedDiagnostic atSourceSpan(SourceSpan span); + + /// Attaches context messages to this diagnostic. + /// + /// The return value is a fresh instance of [LocatableDiagnostic]. This allows + /// for a literate style of error reporting, e.g.: + /// ```dart + /// // For an diagnostic code that doesn't take arguments: + /// diagnosticReporter.reportError( + /// diagnosticCode.withContextMessages(messages).at(astNode)); + /// + /// // For a diagnostic code that does take arguments: + /// diagnosticReporter.reportError( + /// diagnosticCode + /// .withArguments(...) + /// .withContextMessages(messages) + /// .at(astNode)); + /// ``` + LocatableDiagnostic withContextMessages(Iterable messages); +} + +/// Concrete implementation of [LocatableDiagnostic]. +final class LocatableDiagnosticImpl implements LocatableDiagnostic { + @override + final DiagnosticCode code; + + @override + final List arguments; + + @override + final Iterable contextMessages; + + LocatableDiagnosticImpl( + this.code, + this.arguments, { + this.contextMessages = const [], + }); + + @override + LocatedDiagnostic at(SyntacticEntity node) => + atOffset(offset: node.offset, length: node.length); + + @override + LocatedDiagnostic atOffset({required int offset, required int length}) => + LocatedDiagnostic(this, offset, length); + + @override + LocatedDiagnostic atSourceRange(SourceRange sourceRange) => + atOffset(offset: sourceRange.offset, length: sourceRange.length); + + @override + LocatedDiagnostic atSourceSpan(SourceSpan span) => + atOffset(offset: span.start.offset, length: span.length); + + @override + LocatableDiagnostic withContextMessages( + Iterable messages, + ) => LocatableDiagnosticImpl( + code, + arguments, + contextMessages: [...contextMessages, ...messages], + ); +} + +/// A diagnostic that does not have any unfilled template parameters, and has +/// been associated with a location in the source code. +final class LocatedDiagnostic { + final LocatableDiagnostic locatableDiagnostic; + final int offset; + final int length; + + LocatedDiagnostic(this.locatableDiagnostic, this.offset, this.length); +} diff --git a/pkg/analyzer/lib/src/diagnostic/diagnostic_factory.dart b/pkg/analyzer/lib/src/diagnostic/diagnostic_factory.dart index 2402c06fada..92b53045109 100644 --- a/pkg/analyzer/lib/src/diagnostic/diagnostic_factory.dart +++ b/pkg/analyzer/lib/src/diagnostic/diagnostic_factory.dart @@ -2,7 +2,6 @@ // 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. -import 'package:_fe_analyzer_shared/src/base/errors.dart'; import 'package:analyzer/dart/ast/syntactic_entity.dart'; import 'package:analyzer/dart/ast/token.dart'; import 'package:analyzer/dart/element/element.dart'; @@ -10,14 +9,15 @@ import 'package:analyzer/dart/element/type.dart'; import 'package:analyzer/source/source.dart'; import 'package:analyzer/src/dart/ast/ast.dart'; import 'package:analyzer/src/dart/element/element.dart'; +import 'package:analyzer/src/diagnostic/diagnostic.dart' + show DiagnosticMessageImpl; import 'package:analyzer/src/diagnostic/diagnostic.dart' as diag; -import 'package:analyzer/src/diagnostic/diagnostic_message.dart'; import 'package:analyzer/src/utilities/extensions/string.dart'; import 'package:yaml/yaml.dart'; typedef InvalidOverrideDiagnosticCode = - DiagnosticWithArguments< - LocatableDiagnostic Function({ + diag.DiagnosticWithArguments< + diag.LocatableDiagnostic Function({ required String memberName, required String declaringInterfaceName, required DartType typeInDeclaringInterface, @@ -33,7 +33,7 @@ class DiagnosticFactory { /// Return a diagnostic indicating that [duplicate] uses the same [variable] /// as a previous [original] node in a pattern assignment. - LocatedDiagnostic duplicateAssignmentPatternVariable({ + diag.LocatedDiagnostic duplicateAssignmentPatternVariable({ required Source source, required PromotableElementImpl variable, required AssignedVariablePatternImpl original, @@ -55,8 +55,8 @@ class DiagnosticFactory { /// Return a diagnostic indicating that [duplicateFragment] reuses a name /// already used by [originalElement]. - LocatedDiagnostic duplicateDefinition( - LocatableDiagnostic locatableDiagnostic, + diag.LocatedDiagnostic duplicateDefinition( + diag.LocatableDiagnostic locatableDiagnostic, FragmentImpl duplicateFragment, ElementImpl originalElement, ) { @@ -81,9 +81,9 @@ class DiagnosticFactory { /// Return a diagnostic indicating that [duplicateNode] reuses a name /// already used by [originalNode]. - LocatedDiagnostic duplicateDefinitionForNodes( + diag.LocatedDiagnostic duplicateDefinitionForNodes( Source source, - LocatableDiagnostic locatableDiagnostic, + diag.LocatableDiagnostic locatableDiagnostic, SyntacticEntity duplicateNode, SyntacticEntity originalNode, ) { @@ -102,7 +102,7 @@ class DiagnosticFactory { /// Return a diagnostic indicating that [duplicateField] reuses a name /// already used by [originalField]. - LocatedDiagnostic duplicateFieldDefinitionInLiteral( + diag.LocatedDiagnostic duplicateFieldDefinitionInLiteral( Source source, RecordLiteralNamedField duplicateField, RecordLiteralNamedField originalField, @@ -128,7 +128,7 @@ class DiagnosticFactory { /// /// This method requires that both the [duplicateField] and [originalField] /// have a non-null `name`. - LocatedDiagnostic duplicateFieldDefinitionInType( + diag.LocatedDiagnostic duplicateFieldDefinitionInType( Source source, RecordTypeAnnotationField duplicateField, RecordTypeAnnotationField originalField, @@ -151,7 +151,7 @@ class DiagnosticFactory { /// Return a diagnostic indicating that [duplicateField] reuses a name /// already used by [originalField]. - LocatedDiagnostic duplicatePatternField({ + diag.LocatedDiagnostic duplicatePatternField({ required Source source, required String name, required PatternField duplicateField, @@ -177,7 +177,7 @@ class DiagnosticFactory { /// Return a diagnostic indicating that [duplicateElement] reuses a name /// already used by [originalElement]. - LocatedDiagnostic duplicateRestElementInPattern({ + diag.LocatedDiagnostic duplicateRestElementInPattern({ required Source source, required RestPatternElement originalElement, required RestPatternElement duplicateElement, @@ -197,7 +197,7 @@ class DiagnosticFactory { /// Return a diagnostic indicating that the [duplicateElement] (in a constant /// set) is a duplicate of the [originalElement]. - LocatedDiagnostic equalElementsInConstSet( + diag.LocatedDiagnostic equalElementsInConstSet( Source source, Expression duplicateElement, Expression originalElement, @@ -217,7 +217,7 @@ class DiagnosticFactory { /// Return a diagnostic indicating that the [duplicateKey] (in a constant map) /// is a duplicate of the [originalKey]. - LocatedDiagnostic equalKeysInConstMap( + diag.LocatedDiagnostic equalKeysInConstMap( Source source, Expression duplicateKey, Expression originalKey, @@ -237,7 +237,7 @@ class DiagnosticFactory { /// Return a diagnostic indicating that the [duplicateKey] (in a map pattern) /// is a duplicate of the [originalKey]. - LocatedDiagnostic equalKeysInMapPattern( + diag.LocatedDiagnostic equalKeysInMapPattern( Source source, Expression duplicateKey, Expression originalKey, @@ -255,7 +255,7 @@ class DiagnosticFactory { .at(duplicateKey); } - LocatedDiagnostic incompatibleLint({ + diag.LocatedDiagnostic incompatibleLint({ required Source source, required YamlScalar reference, required Map incompatibleRules, @@ -286,7 +286,7 @@ class DiagnosticFactory { /// Returns a diagnostic indicating that incompatible rules were found between /// the current list and one or more of the included files. - LocatedDiagnostic incompatibleLintFiles({ + diag.LocatedDiagnostic incompatibleLintFiles({ required Source source, required YamlScalar reference, required Map incompatibleRules, @@ -318,7 +318,7 @@ class DiagnosticFactory { /// Returns a diagnostic indicating that incompatible rules were found between /// the included files. - LocatedDiagnostic incompatibleLintIncluded({ + diag.LocatedDiagnostic incompatibleLintIncluded({ required Source source, required YamlScalar reference, required Map incompatibleRules, @@ -353,7 +353,7 @@ class DiagnosticFactory { /// Return a diagnostic indicating that [member] is not a correct override of /// [superMember]. - LocatedDiagnostic invalidOverride( + diag.LocatedDiagnostic invalidOverride( Source source, InvalidOverrideDiagnosticCode code, SyntacticEntity errorNode, @@ -403,7 +403,7 @@ class DiagnosticFactory { /// Return a diagnostic indicating that the given [nameToken] was referenced /// before it was declared. - LocatedDiagnostic referencedBeforeDeclaration( + diag.LocatedDiagnostic referencedBeforeDeclaration( Source source, { required Token nameToken, required Element element2, diff --git a/pkg/analyzer/lib/src/diagnostic/diagnostic_message.dart b/pkg/analyzer/lib/src/diagnostic/diagnostic_message.dart deleted file mode 100644 index d7957cccb87..00000000000 --- a/pkg/analyzer/lib/src/diagnostic/diagnostic_message.dart +++ /dev/null @@ -1,6 +0,0 @@ -// Copyright (c) 2019, 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. - -export 'package:_fe_analyzer_shared/src/base/diagnostic_message.dart' - show DiagnosticMessageImpl; diff --git a/pkg/analyzer/lib/src/error/base_or_final_type_verifier.dart b/pkg/analyzer/lib/src/error/base_or_final_type_verifier.dart index 22475eda64c..95cbae4c78f 100644 --- a/pkg/analyzer/lib/src/error/base_or_final_type_verifier.dart +++ b/pkg/analyzer/lib/src/error/base_or_final_type_verifier.dart @@ -6,12 +6,12 @@ import 'package:analyzer/dart/analysis/features.dart'; import 'package:analyzer/dart/ast/ast.dart'; import 'package:analyzer/dart/element/element.dart'; import 'package:analyzer/dart/element/type.dart'; -import 'package:analyzer/diagnostic/diagnostic.dart'; import 'package:analyzer/source/source.dart'; import 'package:analyzer/src/dart/element/element.dart'; import 'package:analyzer/src/dart/element/extensions.dart'; +import 'package:analyzer/src/diagnostic/diagnostic.dart' + show DiagnosticMessage, DiagnosticMessageImpl; import 'package:analyzer/src/diagnostic/diagnostic.dart' as diag; -import 'package:analyzer/src/diagnostic/diagnostic_message.dart'; import 'package:analyzer/src/error/listener.dart'; /// Helper for verifying that subelements of a base or final element must be diff --git a/pkg/analyzer/lib/src/error/codes.dart b/pkg/analyzer/lib/src/error/codes.dart index 5d85c483a58..b9b85f3a03a 100644 --- a/pkg/analyzer/lib/src/error/codes.dart +++ b/pkg/analyzer/lib/src/error/codes.dart @@ -2,7 +2,5 @@ // 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. -export 'package:_fe_analyzer_shared/src/base/errors.dart' - show LocatableDiagnosticImpl; export 'package:analyzer/src/dart/error/lint_codes.dart'; export 'package:analyzer/src/dart/error/todo_codes.dart'; diff --git a/pkg/analyzer/lib/src/error/listener.dart b/pkg/analyzer/lib/src/error/listener.dart index 890de75dbeb..95ed077eff5 100644 --- a/pkg/analyzer/lib/src/error/listener.dart +++ b/pkg/analyzer/lib/src/error/listener.dart @@ -17,7 +17,13 @@ import 'package:analyzer/src/dart/ast/extensions.dart'; import 'package:analyzer/src/dart/element/element.dart'; import 'package:analyzer/src/dart/element/extensions.dart'; import 'package:analyzer/src/dart/element/type.dart'; -import 'package:analyzer/src/diagnostic/diagnostic_message.dart'; +import 'package:analyzer/src/diagnostic/diagnostic.dart' + show + DiagnosticCodeWithExpectedTypes, + DiagnosticMessage, + DiagnosticMessageImpl, + ExpectedType, + LocatedDiagnostic; import 'package:analyzer/src/utilities/extensions/collection.dart'; import 'package:meta/meta.dart'; import 'package:source_span/source_span.dart'; diff --git a/pkg/analyzer/lib/src/error/type_arguments_verifier.dart b/pkg/analyzer/lib/src/error/type_arguments_verifier.dart index 887c30f9645..7f2a409176c 100644 --- a/pkg/analyzer/lib/src/error/type_arguments_verifier.dart +++ b/pkg/analyzer/lib/src/error/type_arguments_verifier.dart @@ -8,15 +8,15 @@ import 'package:analyzer/dart/analysis/analysis_options.dart'; import 'package:analyzer/dart/analysis/features.dart'; import 'package:analyzer/dart/element/element.dart'; import 'package:analyzer/dart/element/type.dart'; -import 'package:analyzer/diagnostic/diagnostic.dart'; import 'package:analyzer/src/dart/ast/ast.dart'; import 'package:analyzer/src/dart/ast/extensions.dart'; import 'package:analyzer/src/dart/element/element.dart'; import 'package:analyzer/src/dart/element/type.dart'; import 'package:analyzer/src/dart/element/type_algebra.dart'; import 'package:analyzer/src/dart/element/type_system.dart'; +import 'package:analyzer/src/diagnostic/diagnostic.dart' + show DiagnosticMessage, DiagnosticMessageImpl; import 'package:analyzer/src/diagnostic/diagnostic.dart' as diag; -import 'package:analyzer/src/diagnostic/diagnostic_message.dart'; import 'package:analyzer/src/error/codes.dart'; import 'package:analyzer/src/error/listener.dart'; diff --git a/pkg/analyzer/lib/src/fasta/error_converter.dart b/pkg/analyzer/lib/src/fasta/error_converter.dart index f73ea6e3e4d..f4b3b20d8cb 100644 --- a/pkg/analyzer/lib/src/fasta/error_converter.dart +++ b/pkg/analyzer/lib/src/fasta/error_converter.dart @@ -6,6 +6,7 @@ import 'package:_fe_analyzer_shared/src/base/errors.dart'; import 'package:_fe_analyzer_shared/src/messages/codes.dart' show Code, Message; import 'package:_fe_analyzer_shared/src/messages/diagnostic.dart'; import 'package:analyzer/dart/ast/token.dart' show Token; +import 'package:analyzer/diagnostic/diagnostic.dart'; import 'package:analyzer/src/diagnostic/diagnostic.dart' as diag; import 'package:analyzer/src/diagnostic/diagnostic_code_values.dart'; import 'package:analyzer/src/error/listener.dart'; @@ -378,7 +379,7 @@ class FastaErrorReporter { reportByCode(code.pseudoSharedCode, offset, length, message); } - void reportScannerError(LocatedDiagnostic locatedDiagnostic) { + void reportScannerError(diag.LocatedDiagnostic locatedDiagnostic) { diagnosticReporter?.report(locatedDiagnostic); } diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart index 3a0badc8d20..6c875061200 100644 --- a/pkg/analyzer/lib/src/generated/error_verifier.dart +++ b/pkg/analyzer/lib/src/generated/error_verifier.dart @@ -15,7 +15,6 @@ import 'package:analyzer/dart/ast/token.dart'; import 'package:analyzer/dart/ast/visitor.dart'; import 'package:analyzer/dart/element/element.dart'; import 'package:analyzer/dart/element/type.dart'; -import 'package:analyzer/diagnostic/diagnostic.dart'; import 'package:analyzer/source/source_range.dart'; import 'package:analyzer/src/dart/analysis/analysis_options.dart'; import 'package:analyzer/src/dart/analysis/file_state.dart'; @@ -32,9 +31,10 @@ import 'package:analyzer/src/dart/element/type_system.dart'; import 'package:analyzer/src/dart/element/well_bounded.dart'; import 'package:analyzer/src/dart/resolver/flow_analysis_visitor.dart'; import 'package:analyzer/src/dart/resolver/scope.dart'; +import 'package:analyzer/src/diagnostic/diagnostic.dart' + show DiagnosticMessage, DiagnosticMessageImpl; import 'package:analyzer/src/diagnostic/diagnostic.dart' as diag; import 'package:analyzer/src/diagnostic/diagnostic_factory.dart'; -import 'package:analyzer/src/diagnostic/diagnostic_message.dart'; import 'package:analyzer/src/error/codes.dart'; import 'package:analyzer/src/error/const_argument_verifier.dart'; import 'package:analyzer/src/error/constructor_fields_verifier.dart'; diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart index c331922079e..b741b531d08 100644 --- a/pkg/analyzer/lib/src/generated/resolver.dart +++ b/pkg/analyzer/lib/src/generated/resolver.dart @@ -24,7 +24,6 @@ import 'package:analyzer/dart/element/element.dart'; import 'package:analyzer/dart/element/scope.dart'; import 'package:analyzer/dart/element/type.dart'; import 'package:analyzer/dart/element/type_provider.dart'; -import 'package:analyzer/diagnostic/diagnostic.dart'; import 'package:analyzer/error/listener.dart'; import 'package:analyzer/source/source.dart'; import 'package:analyzer/src/dart/ast/ast.dart'; @@ -67,8 +66,9 @@ import 'package:analyzer/src/dart/resolver/typed_literal_resolver.dart'; import 'package:analyzer/src/dart/resolver/variable_declaration_resolver.dart'; import 'package:analyzer/src/dart/resolver/yield_statement_resolver.dart'; import 'package:analyzer/src/dart/type_instantiation_target.dart'; +import 'package:analyzer/src/diagnostic/diagnostic.dart' + show DiagnosticMessage, DiagnosticMessageImpl; import 'package:analyzer/src/diagnostic/diagnostic.dart' as diag; -import 'package:analyzer/src/diagnostic/diagnostic_message.dart'; import 'package:analyzer/src/error/base_or_final_type_verifier.dart'; import 'package:analyzer/src/error/bool_expression_verifier.dart'; import 'package:analyzer/src/error/codes.dart'; diff --git a/pkg/analyzer/lib/src/utilities/extensions/element.dart b/pkg/analyzer/lib/src/utilities/extensions/element.dart index ef5b0c76125..abadc809e28 100644 --- a/pkg/analyzer/lib/src/utilities/extensions/element.dart +++ b/pkg/analyzer/lib/src/utilities/extensions/element.dart @@ -8,7 +8,8 @@ import 'package:analyzer/dart/element/type.dart'; import 'package:analyzer/src/dart/element/element.dart'; import 'package:analyzer/src/dart/element/member.dart'; import 'package:analyzer/src/dart/element/type.dart'; -import 'package:analyzer/src/diagnostic/diagnostic_message.dart'; +import 'package:analyzer/src/diagnostic/diagnostic.dart' + show DiagnosticMessageImpl; import 'package:meta/meta.dart'; class MockLibraryImportElement implements Element { diff --git a/pkg/analyzer_plugin/api.txt b/pkg/analyzer_plugin/api.txt index 676d69db401..49b7c3ba1df 100644 --- a/pkg/analyzer_plugin/api.txt +++ b/pkg/analyzer_plugin/api.txt @@ -2103,10 +2103,7 @@ dart:core: int (referenced) dart:isolate: SendPort (referenced) -package:_fe_analyzer_shared/src/base/diagnostic_message.dart: - DiagnosticMessage@2 (referenced) package:_fe_analyzer_shared/src/base/errors.dart: - Diagnostic (referenced) DiagnosticSeverity (referenced) DiagnosticType (referenced) package:_fe_analyzer_shared/src/base/source_range.dart: @@ -2143,6 +2140,8 @@ package:analyzer/dart/element/type_provider.dart: TypeProvider (referenced) package:analyzer/dart/element/type_system.dart: TypeSystem (referenced) +package:analyzer/diagnostic/diagnostic.dart: + Diagnostic (referenced) package:analyzer/file_system/file_system.dart: Folder (referenced) ResourceProvider (referenced) @@ -2162,5 +2161,7 @@ package:analyzer/src/dart/ast/ast.dart: FunctionBody (referenced) NodeList (referenced) TypeAnnotation (referenced) +package:analyzer/src/diagnostic/diagnostic.dart: + DiagnosticMessage@2 (referenced) package:pub_semver/src/version.dart: Version (referenced) diff --git a/pkg/analyzer_plugin/test/utilities/analyzer_converter_test.dart b/pkg/analyzer_plugin/test/utilities/analyzer_converter_test.dart index 27944796503..087433df1c3 100644 --- a/pkg/analyzer_plugin/test/utilities/analyzer_converter_test.dart +++ b/pkg/analyzer_plugin/test/utilities/analyzer_converter_test.dart @@ -9,8 +9,9 @@ import 'package:analyzer/source/error_processor.dart' as analyzer; import 'package:analyzer/source/line_info.dart' as analyzer; import 'package:analyzer/src/dart/analysis/analysis_options.dart' as analyzer; import 'package:analyzer/src/dart/element/element.dart' as analyzer; +import 'package:analyzer/src/diagnostic/diagnostic.dart' + show DiagnosticMessageImpl; import 'package:analyzer/src/diagnostic/diagnostic.dart' as diag; -import 'package:analyzer/src/diagnostic/diagnostic_message.dart' as analyzer; import 'package:analyzer_plugin/protocol/protocol_common.dart' as plugin; import 'package:analyzer_plugin/utilities/analyzer_converter.dart'; import 'package:test/test.dart'; @@ -58,14 +59,14 @@ class AnalyzerConverterTest extends AbstractSingleUnitTest { int offset, { String? contextMessage, }) async { - var contextMessages = []; + var contextMessages = []; await resolveTestCode(''); var testSource = result.unit.declaredFragment!.source; if (contextMessage != null) { contextMessages.add( - analyzer.DiagnosticMessageImpl( + DiagnosticMessageImpl( filePath: testSource.fullName, offset: 53, length: 7, diff --git a/pkg/analyzer_testing/api.txt b/pkg/analyzer_testing/api.txt index 6e92e0064be..34d015feffc 100644 --- a/pkg/analyzer_testing/api.txt +++ b/pkg/analyzer_testing/api.txt @@ -97,8 +97,9 @@ dart:core: bool (referenced) int (referenced) package:_fe_analyzer_shared/src/base/errors.dart: - Diagnostic (referenced) DiagnosticCode (referenced) +package:analyzer/diagnostic/diagnostic.dart: + Diagnostic (referenced) package:analyzer/file_system/file_system.dart: File (referenced) Folder (referenced) diff --git a/pkg/front_end/test/scanner_cfe_test.dart b/pkg/front_end/test/scanner_cfe_test.dart index 1f1f0b9f131..c4b37d9689d 100644 --- a/pkg/front_end/test/scanner_cfe_test.dart +++ b/pkg/front_end/test/scanner_cfe_test.dart @@ -5,7 +5,6 @@ import 'dart:convert'; import 'dart:typed_data' show Uint8List; -import 'package:_fe_analyzer_shared/src/base/errors.dart'; import 'package:_fe_analyzer_shared/src/scanner/error_token.dart'; import 'package:_fe_analyzer_shared/src/scanner/scanner.dart' as usedForFuzzTesting; @@ -13,6 +12,7 @@ import 'package:_fe_analyzer_shared/src/scanner/scanner.dart'; import 'package:_fe_analyzer_shared/src/scanner/token.dart'; import 'package:_fe_analyzer_shared/src/scanner/token_constants.dart'; import 'package:analyzer/src/dart/scanner/translate_error_token.dart'; +import 'package:analyzer/src/diagnostic/diagnostic.dart' show LocatedDiagnostic; import 'package:analyzer/src/diagnostic/diagnostic.dart' as diag; import 'package:front_end/src/codes/diagnostic.dart' as fe_diag; import 'package:test/test.dart'; diff --git a/pkg/front_end/test/scanner_replacement_test.dart b/pkg/front_end/test/scanner_replacement_test.dart index 82999e3c4e2..7693a92b7c5 100644 --- a/pkg/front_end/test/scanner_replacement_test.dart +++ b/pkg/front_end/test/scanner_replacement_test.dart @@ -2,12 +2,12 @@ // 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. -import 'package:_fe_analyzer_shared/src/base/errors.dart'; import 'package:_fe_analyzer_shared/src/scanner/error_token.dart'; import 'package:_fe_analyzer_shared/src/scanner/scanner.dart'; import 'package:_fe_analyzer_shared/src/scanner/token.dart'; import 'package:analyzer/src/dart/scanner/translate_error_token.dart' show translateErrorToken; +import 'package:analyzer/src/diagnostic/diagnostic.dart' show LocatedDiagnostic; import 'package:analyzer/src/diagnostic/diagnostic.dart' as diag; import 'package:test/test.dart'; import 'package:test_reflective_loader/test_reflective_loader.dart'; diff --git a/pkg/linter/lib/src/rules/prefer_final_locals.dart b/pkg/linter/lib/src/rules/prefer_final_locals.dart index be004bd3bb6..e56d83f7bb1 100644 --- a/pkg/linter/lib/src/rules/prefer_final_locals.dart +++ b/pkg/linter/lib/src/rules/prefer_final_locals.dart @@ -8,10 +8,10 @@ import 'package:analyzer/analysis_rule/rule_visitor_registry.dart'; import 'package:analyzer/dart/ast/ast.dart'; import 'package:analyzer/dart/ast/visitor.dart'; import 'package:analyzer/dart/element/element.dart'; -import 'package:analyzer/diagnostic/diagnostic.dart'; import 'package:analyzer/error/error.dart'; import 'package:analyzer/src/dart/element/extensions.dart'; // ignore: implementation_imports -import 'package:analyzer/src/diagnostic/diagnostic_message.dart'; // ignore: implementation_imports +import 'package:analyzer/src/diagnostic/diagnostic.dart' // ignore: implementation_imports + show DiagnosticMessage, DiagnosticMessageImpl; import '../analyzer.dart'; import '../diagnostic.dart' as diag;