From e1c76b280528ad05ac58b29fd543e5b30622ed1f Mon Sep 17 00:00:00 2001 From: Parker Lougheed Date: Mon, 18 Nov 2024 15:29:08 +0000 Subject: [PATCH 1/8] [linter] Mark latest diagnostic docs as published Closes https://github.com/dart-lang/sdk/issues/56882 Change-Id: Id41adea71251731b638aa21e23a452a1dc19ed51 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/395860 Reviewed-by: Brian Wilkerson Commit-Queue: Brian Wilkerson Reviewed-by: Samuel Rawlins --- pkg/linter/lib/src/lint_codes.g.dart | 5 +++++ pkg/linter/messages.yaml | 10 +++++----- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/pkg/linter/lib/src/lint_codes.g.dart b/pkg/linter/lib/src/lint_codes.g.dart index 08167820e906..dff1dbf7d094 100644 --- a/pkg/linter/lib/src/lint_codes.g.dart +++ b/pkg/linter/lib/src/lint_codes.g.dart @@ -722,6 +722,7 @@ class LinterLintCode extends LintCode { correctionMessage: "Try using conversion methods from 'dart:js_interop' to convert " "between Dart types and JS interop types.", + hasPublishedDocs: true, uniqueName: 'invalid_runtime_check_with_js_interop_types_dart_as_js', ); @@ -807,6 +808,7 @@ class LinterLintCode extends LintCode { LintNames.library_annotations, "This annotation should be attached to a library directive.", correctionMessage: "Try attaching the annotation to a library directive.", + hasPublishedDocs: true, ); static const LintCode library_names = LinterLintCode( @@ -1550,6 +1552,7 @@ class LinterLintCode extends LintCode { correctionMessage: "Try using backticks around the content with angle brackets, or try " "replacing `<` with `<` and `>` with `>`.", + hasPublishedDocs: true, ); static const LintCode unnecessary_await_in_return = LinterLintCode( @@ -1632,6 +1635,7 @@ class LinterLintCode extends LintCode { LintNames.unnecessary_library_name, "Library names are not necessary.", correctionMessage: "Remove the library name.", + hasPublishedDocs: true, ); static const LintCode unnecessary_new = LinterLintCode( @@ -1938,6 +1942,7 @@ class LinterLintCode extends LintCode { correctionMessage: "Try using truncating division, '~/', instead of regular division " "('/') followed by 'toInt()'.", + hasPublishedDocs: true, ); static const LintCode valid_regexps = LinterLintCode( diff --git a/pkg/linter/messages.yaml b/pkg/linter/messages.yaml index be4d0fa5c4c2..7e7b5b8d58ff 100644 --- a/pkg/linter/messages.yaml +++ b/pkg/linter/messages.yaml @@ -4979,7 +4979,7 @@ LintCode: correctionMessage: "Try using conversion methods from 'dart:js_interop' to convert between Dart types and JS interop types." addedIn: "3.5" categories: [errorProne, web] - hasPublishedDocs: false + hasPublishedDocs: true documentation: |- #### Description @@ -5415,7 +5415,7 @@ LintCode: correctionMessage: "Try attaching the annotation to a library directive." addedIn: "2.19" categories: [style] - hasPublishedDocs: false + hasPublishedDocs: true documentation: |- #### Description @@ -11261,7 +11261,7 @@ LintCode: correctionMessage: "Try using backticks around the content with angle brackets, or try replacing `<` with `<` and `>` with `>`." addedIn: "3.5" categories: [errorProne] - hasPublishedDocs: false + hasPublishedDocs: true documentation: |- #### Description @@ -11906,7 +11906,7 @@ LintCode: correctionMessage: "Remove the library name." addedIn: "3.4" categories: [brevity, languageFeatureUsage, style] - hasPublishedDocs: false + hasPublishedDocs: true documentation: |- #### Description @@ -14253,7 +14253,7 @@ LintCode: correctionMessage: "Try using truncating division, '~/', instead of regular division ('/') followed by 'toInt()'." addedIn: "3.6" categories: [languageFeatureUsage] - hasPublishedDocs: false + hasPublishedDocs: true documentation: |- #### Description From 58f9beb6d4ec9e93430454bb96c0b8f068d0b0bc Mon Sep 17 00:00:00 2001 From: Paul Berry Date: Mon, 18 Nov 2024 15:46:17 +0000 Subject: [PATCH 2/8] [mini_types] Add a `Type.substitute` method. This method will be used by a follow-up CL that adds support for generic functions, since the implementation of `==` and `hashCode` for generic functions needs to perform substitutions in order to recognize that alpha-equivalent types (such as `T Function()` and `U Function`) are equal. Change-Id: If641c4d0ae48708abf3701853014dc52dfc559c5 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/395684 Reviewed-by: Chloe Stefantsova Commit-Queue: Paul Berry --- pkg/_fe_analyzer_shared/test/mini_types.dart | 123 ++++++++++++++++-- .../test/mini_types_test.dart | 57 ++++++++ 2 files changed, 172 insertions(+), 8 deletions(-) diff --git a/pkg/_fe_analyzer_shared/test/mini_types.dart b/pkg/_fe_analyzer_shared/test/mini_types.dart index ba4e7b7fdeec..4259e4cf6a70 100644 --- a/pkg/_fe_analyzer_shared/test/mini_types.dart +++ b/pkg/_fe_analyzer_shared/test/mini_types.dart @@ -130,6 +130,24 @@ class FunctionType extends Type nullabilitySuffix: nullabilitySuffix); } + @override + FunctionType? substitute(Map substitution) { + var newReturnType = returnType.substitute(substitution); + var newPositionalParameters = positionalParameters.substitute(substitution); + var newNamedParameters = namedParameters.substitute(substitution); + if (newReturnType == null && + newPositionalParameters == null && + newNamedParameters == null) { + return null; + } else { + return FunctionType(newReturnType ?? returnType, + newPositionalParameters ?? positionalParameters, + requiredPositionalParameterCount: requiredPositionalParameterCount, + namedParameters: newNamedParameters ?? namedParameters, + nullabilitySuffix: nullabilitySuffix); + } + } + @override Type withNullability(NullabilitySuffix suffix) => FunctionType(returnType, positionalParameters, @@ -179,6 +197,13 @@ class FutureOrType extends PrimaryType { return FutureOrType(newArg, nullabilitySuffix: nullabilitySuffix); } + @override + Type? substitute(Map substitution) { + var newArg = typeArgument.substitute(substitution); + if (newArg == null) return null; + return FutureOrType(newArg, nullabilitySuffix: nullabilitySuffix); + } + @override Type withNullability(NullabilitySuffix suffix) => FutureOrType(typeArgument, nullabilitySuffix: suffix); @@ -204,7 +229,9 @@ class InvalidType extends _SpecialSimpleType /// A named parameter of a function type. class NamedFunctionParameter - implements SharedNamedFunctionParameterStructure { + implements + SharedNamedFunctionParameterStructure, + _Substitutable { @override final String name; @@ -227,11 +254,20 @@ class NamedFunctionParameter type == other.type && isRequired == other.isRequired; + @override + NamedFunctionParameter? substitute(Map substitution) { + var newType = type.substitute(substitution); + if (newType == null) return null; + return NamedFunctionParameter( + isRequired: isRequired, name: name, type: newType); + } + @override String toString() => [if (isRequired) 'required', type, name].join(' '); } -class NamedType implements SharedNamedTypeStructure { +class NamedType + implements SharedNamedTypeStructure, _Substitutable { @override final String name; @@ -246,6 +282,13 @@ class NamedType implements SharedNamedTypeStructure { @override bool operator ==(Object other) => other is NamedType && name == other.name && type == other.type; + + @override + NamedType? substitute(Map substitution) { + var newType = type.substitute(substitution); + if (newType == null) return null; + return NamedType(name: name, type: newType); + } } /// Representation of the type `Never` suitable for unit testing of code in the @@ -348,6 +391,14 @@ class PrimaryType extends Type { args: newArgs, nullabilitySuffix: nullabilitySuffix); } + @override + Type? substitute(Map substitution) { + var newArgs = args.substitute(substitution); + if (newArgs == null) return null; + return PrimaryType._(nameInfo, + args: newArgs, nullabilitySuffix: nullabilitySuffix); + } + @override Type withNullability(NullabilitySuffix suffix) => PrimaryType._(nameInfo, args: args, nullabilitySuffix: suffix); @@ -439,6 +490,17 @@ class RecordType extends Type implements SharedRecordTypeStructure { ); } + @override + Type? substitute(Map substitution) { + var newPositionalTypes = positionalTypes.substitute(substitution); + var newNamedTypes = namedTypes.substitute(substitution); + if (newPositionalTypes == null && newNamedTypes == null) return null; + return RecordType( + positionalTypes: newPositionalTypes ?? positionalTypes, + namedTypes: newNamedTypes ?? namedTypes, + nullabilitySuffix: nullabilitySuffix); + } + @override Type withNullability(NullabilitySuffix suffix) => RecordType( positionalTypes: positionalTypes, @@ -502,7 +564,7 @@ class SpecialTypeName extends TypeNameInfo { /// Representation of a type suitable for unit testing of code in the /// `_fe_analyzer_shared` package. -abstract class Type implements SharedTypeStructure { +abstract class Type implements SharedTypeStructure, _Substitutable { @override final NullabilitySuffix nullabilitySuffix; @@ -582,11 +644,11 @@ sealed class TypeNameInfo { /// An assertion in the [PrimaryType] constructor verifies this. /// /// This ensures that the methods [Type.closureWithRespectToUnknown], - /// [Type.recursivelyDemote], and [Type.withNullability] (which create new - /// instances of [Type] based on old ones) create the appropriate subtype of - /// [Type]. It also ensures that when [Type] objects are directly constructed - /// (as they are in this file and in `mini_ast.dart`), the appropriate subtype - /// of [Type] is used. + /// [Type.recursivelyDemote], [Type.substitute], and [Type.withNullability] + /// (which create new instances of [Type] based on old ones) create the + /// appropriate subtype of [Type]. It also ensures that when [Type] objects + /// are directly constructed (as they are in this file and in + /// `mini_ast.dart`), the appropriate subtype of [Type] is used. final core.Type _expectedRuntimeType; TypeNameInfo(this.name, {required core.Type expectedRuntimeType}) @@ -674,6 +736,10 @@ class TypeParameterType extends Type { } } + @override + Type? substitute(Map substitution) => + substitution[typeParameter]; + @override Type withNullability(NullabilitySuffix suffix) => TypeParameterType(typeParameter, @@ -1411,6 +1477,9 @@ class UnknownType extends Type implements SharedUnknownTypeStructure { @override Type? recursivelyDemote({required bool covariant}) => null; + @override + Type? substitute(Map substitution) => null; + @override Type withNullability(NullabilitySuffix suffix) => UnknownType(nullabilitySuffix: suffix); @@ -1448,6 +1517,22 @@ abstract class _SpecialSimpleType extends PrimaryType { @override Type? recursivelyDemote({required bool covariant}) => null; + + @override + Type? substitute(Map substitution) => null; +} + +/// Interface for [Type] and the data structures that comprise it, allowing +/// type substitutions to be performed. +abstract class _Substitutable> { + /// If `this` contains any references to a [TypeParameter] matching one of the + /// keys in [substitution], returns a clone of `this` with those references + /// replaced by the corresponding value. Otherwise returns `null`. + /// + /// For example, if `t` is a reference to the [TypeParameter] object + /// representing `T`, then `Type('Map`).substitute({t: Type('int')})` + /// returns a [Type] object representing `Map`. + T? substitute(Map substitution); } class _TypeParser { @@ -1878,3 +1963,25 @@ extension on List { return newList; } } + +extension> on List { + /// Helper method for performing substitutions on the constituent parts of a + /// [Type] that are stored in lists. + /// + /// Calls [_Substitutable.substitute] on each element of the list; if all + /// those calls returned `null` (meaning no substitutions were done), returns + /// `null`. Otherwise returns a new [List] in which each element requiring + /// substitutions is replaced with the substitution result. + List? substitute(Map substitution) { + List? result; + for (int i = 0; i < length; i++) { + var oldListElement = this[i]; + var newType = oldListElement.substitute(substitution); + if (newType != null && result == null) { + result = sublist(0, i); + } + result?.add(newType ?? oldListElement); + } + return result; + } +} diff --git a/pkg/_fe_analyzer_shared/test/mini_types_test.dart b/pkg/_fe_analyzer_shared/test/mini_types_test.dart index b2ded6073ba8..9beffa77b8fc 100644 --- a/pkg/_fe_analyzer_shared/test/mini_types_test.dart +++ b/pkg/_fe_analyzer_shared/test/mini_types_test.dart @@ -1020,4 +1020,61 @@ main() { }); }); }); + + group('substitute:', () { + test('FunctionType', () { + expect(Type('int Function(int, {int i})').substitute({t: Type('String')}), + isNull); + expect(Type('T Function(int, {int i})').substitute({t: Type('String')}), + Type('String Function(int, {int i})')); + expect(Type('int Function(T, {int i})?').substitute({t: Type('String')}), + Type('int Function(String, {int i})?')); + expect(Type('int Function(int, {T i})').substitute({t: Type('String')}), + Type('int Function(int, {String i})')); + expect(Type('int Function(T, T)').substitute({t: Type('String')}), + Type('int Function(String, String)')); + expect(Type('int Function({T t1, T t2})').substitute({t: Type('String')}), + Type('int Function({String t1, String t2})')); + }); + + test('PrimaryType', () { + expect(Type('Map').substitute({t: Type('String')}), isNull); + expect(Type('Map').substitute({t: Type('String')}), + Type('Map')); + expect(Type('Map').substitute({t: Type('String')}), + Type('Map')); + expect(Type('Map').substitute({t: Type('String')}), + Type('Map')); + expect(Type('dynamic').substitute({t: Type('String')}), isNull); + expect(Type('error').substitute({t: Type('String')}), isNull); + expect(Type('Never').substitute({t: Type('String')}), isNull); + expect(Type('Null').substitute({t: Type('String')}), isNull); + expect(Type('void').substitute({t: Type('String')}), isNull); + expect(Type('FutureOr').substitute({t: Type('String')}), isNull); + expect(Type('FutureOr').substitute({t: Type('String')}), + Type('FutureOr')); + }); + + test('RecordType', () { + expect(Type('(int, {int i})').substitute({t: Type('String')}), isNull); + expect(Type('(T, {int i})?').substitute({t: Type('String')}), + Type('(String, {int i})?')); + expect(Type('(int, {T i})').substitute({t: Type('String')}), + Type('(int, {String i})')); + expect(Type('(T, T)').substitute({t: Type('String')}), + Type('(String, String)')); + expect(Type('({T t1, T t2})').substitute({t: Type('String')}), + Type('({String t1, String t2})')); + }); + + test('TypeParameterType', () { + expect(Type('T').substitute({u: Type('String')}), isNull); + expect(Type('T').substitute({t: Type('String')}), Type('String')); + expect(Type('T&Object').substitute({t: Type('String')}), Type('String')); + }); + + test('UnknownType', () { + expect(Type('_').substitute({t: Type('String')}), isNull); + }); + }); } From b80fdcb683918b7063bf55a9e253a906ee1ed9d6 Mon Sep 17 00:00:00 2001 From: Konstantin Shcheglov Date: Mon, 18 Nov 2024 16:56:39 +0000 Subject: [PATCH 3/8] Elements. Migrate ErrorDetectionHelpers. Change-Id: I50b08924a4be96210378a9ad56a9d671a030d5f9 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/395800 Reviewed-by: Brian Wilkerson Commit-Queue: Konstantin Shcheglov --- .../src/cider/local_library_contributor.dart | 4 +- .../completion/dart/candidate_suggestion.dart | 14 +++--- pkg/analyzer/analyzer_use_new_elements.txt | 1 - pkg/analyzer/lib/src/dart/ast/ast.dart | 4 +- .../lib/src/dart/element/element.dart | 7 ++- pkg/analyzer/lib/src/dart/element/member.dart | 4 +- .../resolver/property_element_resolver.dart | 10 +++++ .../generated/error_detection_helpers.dart | 43 ++++++++++++------- .../lib/src/generated/error_verifier.dart | 3 ++ pkg/analyzer/lib/src/generated/resolver.dart | 14 +++--- .../lib/src/utilities/extensions/element.dart | 26 +++++++++++ 11 files changed, 91 insertions(+), 39 deletions(-) diff --git a/pkg/analysis_server/lib/src/cider/local_library_contributor.dart b/pkg/analysis_server/lib/src/cider/local_library_contributor.dart index fced83e3dc01..6f998a641535 100644 --- a/pkg/analysis_server/lib/src/cider/local_library_contributor.dart +++ b/pkg/analysis_server/lib/src/cider/local_library_contributor.dart @@ -167,7 +167,7 @@ class LibraryElementSuggestionBuilder extends GeneralizingElementVisitor { if (element.isGetter) { if (variable is FieldElement) { builder.suggestField( - variable.asElement2 as FieldElement2, + variable.asElement2, inheritanceDistance: 0.0, ); } @@ -281,7 +281,7 @@ class LibraryElementSuggestionBuilder extends GeneralizingElementVisitor { } } else { builder.suggestStaticField( - field.asElement2 as FieldElement2, + field.asElement2, prefix: prefix, ); } diff --git a/pkg/analysis_server/lib/src/services/completion/dart/candidate_suggestion.dart b/pkg/analysis_server/lib/src/services/completion/dart/candidate_suggestion.dart index 47df06f72c7a..ebaf9c4b0e3e 100644 --- a/pkg/analysis_server/lib/src/services/completion/dart/candidate_suggestion.dart +++ b/pkg/analysis_server/lib/src/services/completion/dart/candidate_suggestion.dart @@ -1218,13 +1218,13 @@ extension SuggestionBuilderExtension on SuggestionBuilder { case EnumConstantSuggestion(): if (suggestion.includeEnumName) { suggestEnumConstant( - suggestion.element.asElement2 as FieldElement2, + suggestion.element.asElement2, suggestion.completion, relevance: relevance, ); } else { suggestField( - suggestion.element.asElement2 as FieldElement2, + suggestion.element.asElement2, inheritanceDistance: 0.0, relevance: relevance, ); @@ -1246,7 +1246,7 @@ extension SuggestionBuilderExtension on SuggestionBuilder { var fieldElement = suggestion.element; if (fieldElement.isEnumConstant) { suggestEnumConstant( - fieldElement.asElement2 as FieldElement2, + fieldElement.asElement2, suggestion.completion, relevance: relevance, ); @@ -1259,7 +1259,7 @@ extension SuggestionBuilderExtension on SuggestionBuilder { ? fieldElement.declaration.asElement2 : fieldElement.asElement2; suggestField( - field as FieldElement2, + field, inheritanceDistance: inheritanceDistance, relevance: relevance, ); @@ -1320,7 +1320,7 @@ extension SuggestionBuilderExtension on SuggestionBuilder { request.featureComputer, ); suggestMethod( - suggestion.element.asElement2 as MethodElement2, + suggestion.element.asElement2, kind: kind, inheritanceDistance: inheritanceDistance, relevance: relevance, @@ -1387,7 +1387,7 @@ extension SuggestionBuilderExtension on SuggestionBuilder { request.featureComputer, ); suggestSetStateMethod( - suggestion.element.asElement2 as MethodElement2, + suggestion.element.asElement2, kind: suggestion.kind, completion: suggestion.completion, displayText: suggestion.displayText, @@ -1397,7 +1397,7 @@ extension SuggestionBuilderExtension on SuggestionBuilder { ); case StaticFieldSuggestion(): suggestStaticField( - suggestion.element.asElement2 as FieldElement2, + suggestion.element.asElement2, prefix: suggestion.prefix, relevance: relevance, completion: suggestion.completion, diff --git a/pkg/analyzer/analyzer_use_new_elements.txt b/pkg/analyzer/analyzer_use_new_elements.txt index 83bb89df4e12..4094018ebc0c 100644 --- a/pkg/analyzer/analyzer_use_new_elements.txt +++ b/pkg/analyzer/analyzer_use_new_elements.txt @@ -112,7 +112,6 @@ lib/src/error/required_parameters_verifier.dart lib/src/error/unused_local_elements_verifier.dart lib/src/generated/element_resolver.dart lib/src/generated/element_walker.dart -lib/src/generated/error_detection_helpers.dart lib/src/generated/error_verifier.dart lib/src/generated/exhaustiveness.dart lib/src/generated/ffi_verifier.dart diff --git a/pkg/analyzer/lib/src/dart/ast/ast.dart b/pkg/analyzer/lib/src/dart/ast/ast.dart index d0adf8f98983..3ad643d3a3ff 100644 --- a/pkg/analyzer/lib/src/dart/ast/ast.dart +++ b/pkg/analyzer/lib/src/dart/ast/ast.dart @@ -1829,7 +1829,7 @@ final class BinaryExpressionImpl extends ExpressionImpl @experimental @override - MethodElement2? get element => staticElement?.asElement2 as MethodElement2?; + MethodElement2? get element => staticElement?.asElement2; @override Token get endToken => _rightOperand.endToken; @@ -10137,7 +10137,7 @@ final class IndexExpressionImpl extends ExpressionImpl @experimental @override - MethodElement2? get element => staticElement?.asElement2 as MethodElement2?; + MethodElement2? get element => staticElement?.asElement2; @override Token get endToken => rightBracket; diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart index 0e433a7c5e4f..c5d7ebf60a1c 100644 --- a/pkg/analyzer/lib/src/dart/element/element.dart +++ b/pkg/analyzer/lib/src/dart/element/element.dart @@ -3524,7 +3524,7 @@ class EnumElementImpl extends InterfaceElementImpl @override List get constants2 => - constants.map((e) => e.asElement2 as FieldElement2).toList(); + constants.map((e) => e.asElement2).toList(); @override EnumElementImpl2 get element { @@ -3583,7 +3583,7 @@ class EnumElementImpl2 extends InterfaceElementImpl2 @override List get constants2 => - constants.map((e) => e.asElement2 as FieldElement2).toList(); + constants.map((e) => e.asElement2).toList(); @override T? accept2(ElementVisitor2 visitor) { @@ -4048,8 +4048,7 @@ class ExtensionTypeElementImpl2 extends InterfaceElementImpl2 ConstructorElement2 get primaryConstructor2 => primaryConstructor.element; @override - FieldElement2 get representation2 => - representation.asElement2 as FieldElement2; + FieldElement2 get representation2 => representation.asElement2; @override T? accept2(ElementVisitor2 visitor) { diff --git a/pkg/analyzer/lib/src/dart/element/member.dart b/pkg/analyzer/lib/src/dart/element/member.dart index 008a018cb73e..ca7bdb03d6c6 100644 --- a/pkg/analyzer/lib/src/dart/element/member.dart +++ b/pkg/analyzer/lib/src/dart/element/member.dart @@ -589,7 +589,7 @@ class FieldMember extends VariableMember @override Source? get source => _declaration.source; - FieldElement2 get _element2 => declaration.asElement2 as FieldElement2; + FieldElement2 get _element2 => declaration.asElement2; @override T? accept(ElementVisitor visitor) => visitor.visitFieldElement(this); @@ -1000,7 +1000,7 @@ class MethodMember extends ExecutableMember Source get source => _declaration.source!; @override - MethodElement2 get _element2 => declaration.asElement2 as MethodElement2; + MethodElement2 get _element2 => declaration.asElement2; @override T? accept(ElementVisitor visitor) => visitor.visitMethodElement(this); diff --git a/pkg/analyzer/lib/src/dart/resolver/property_element_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/property_element_resolver.dart index a9893d590422..5caefd73c358 100644 --- a/pkg/analyzer/lib/src/dart/resolver/property_element_resolver.dart +++ b/pkg/analyzer/lib/src/dart/resolver/property_element_resolver.dart @@ -5,6 +5,7 @@ import 'package:_fe_analyzer_shared/src/flow_analysis/flow_analysis.dart'; import 'package:_fe_analyzer_shared/src/types/shared_type.dart'; import 'package:analyzer/dart/element/element.dart'; +import 'package:analyzer/dart/element/element2.dart'; import 'package:analyzer/dart/element/type.dart'; import 'package:analyzer/error/error.dart'; import 'package:analyzer/error/listener.dart'; @@ -23,6 +24,7 @@ import 'package:analyzer/src/error/codes.dart'; import 'package:analyzer/src/generated/resolver.dart'; import 'package:analyzer/src/generated/scope_helpers.dart'; import 'package:analyzer/src/generated/super_context.dart'; +import 'package:analyzer/src/utilities/extensions/element.dart'; class PropertyElementResolver with ScopeHelpers { final ResolverVisitor _resolver; @@ -944,7 +946,15 @@ class PropertyElementResolverResult { return readElementRequested ?? readElementRecovery; } + Element2? get readElement2 { + return readElement.asElement2; + } + Element? get writeElement { return writeElementRequested ?? writeElementRecovery; } + + Element2? get writeElement2 { + return writeElement.asElement2; + } } diff --git a/pkg/analyzer/lib/src/generated/error_detection_helpers.dart b/pkg/analyzer/lib/src/generated/error_detection_helpers.dart index fcf24281957c..b895fda7c810 100644 --- a/pkg/analyzer/lib/src/generated/error_detection_helpers.dart +++ b/pkg/analyzer/lib/src/generated/error_detection_helpers.dart @@ -6,16 +6,18 @@ import 'package:_fe_analyzer_shared/src/flow_analysis/flow_analysis.dart'; import 'package:_fe_analyzer_shared/src/types/shared_type.dart'; import 'package:analyzer/dart/ast/ast.dart'; import 'package:analyzer/dart/ast/syntactic_entity.dart'; -import 'package:analyzer/dart/element/element.dart'; +import 'package:analyzer/dart/element/element2.dart'; import 'package:analyzer/dart/element/nullability_suffix.dart'; import 'package:analyzer/dart/element/type.dart'; import 'package:analyzer/diagnostic/diagnostic.dart'; import 'package:analyzer/error/error.dart'; import 'package:analyzer/error/listener.dart'; import 'package:analyzer/src/dart/ast/extensions.dart'; +import 'package:analyzer/src/dart/element/inheritance_manager3.dart'; import 'package:analyzer/src/dart/element/type.dart'; import 'package:analyzer/src/dart/element/type_system.dart'; import 'package:analyzer/src/error/codes.dart'; +import 'package:analyzer/src/utilities/extensions/object.dart'; /// Methods useful in detecting errors. This mixin exists to allow code to be /// more easily shared between the two visitors that do the majority of error @@ -23,6 +25,8 @@ import 'package:analyzer/src/error/codes.dart'; mixin ErrorDetectionHelpers { ErrorReporter get errorReporter; + InheritanceManager3 get inheritance; + bool get strictCasts; TypeSystemImpl get typeSystem; @@ -61,7 +65,7 @@ mixin ErrorDetectionHelpers { whyNotPromoted}) { _checkForArgumentTypeNotAssignableForArgument( argument: argument is NamedExpression ? argument.expression : argument, - parameter: argument.staticParameterElement, + parameter: argument.correspondingParameter, promoteParameterToNullable: promoteParameterToNullable, whyNotPromoted: whyNotPromoted, ); @@ -166,7 +170,7 @@ mixin ErrorDetectionHelpers { /// See [CompileTimeErrorCode.CONST_FIELD_INITIALIZER_NOT_ASSIGNABLE], and /// [CompileTimeErrorCode.FIELD_INITIALIZER_NOT_ASSIGNABLE]. void checkForFieldInitializerNotAssignable( - ConstructorFieldInitializer initializer, FieldElement fieldElement, + ConstructorFieldInitializer initializer, FieldElement2 fieldElement, {required bool isConstConstructor, required Map, NonPromotionReason> Function()? whyNotPromoted}) { @@ -256,13 +260,13 @@ mixin ErrorDetectionHelpers { void checkIndexExpressionIndex( Expression index, { - required ExecutableElement? readElement, - required ExecutableElement? writeElement, + required ExecutableElement2? readElement, + required ExecutableElement2? writeElement, required Map, NonPromotionReason> Function()? whyNotPromoted, }) { - if (readElement is MethodElement) { - var parameters = readElement.parameters; + if (readElement is MethodElement2) { + var parameters = readElement.formalParameters; if (parameters.isNotEmpty) { _checkForArgumentTypeNotAssignableForArgument( argument: index, @@ -273,8 +277,8 @@ mixin ErrorDetectionHelpers { } } - if (writeElement is MethodElement) { - var parameters = writeElement.parameters; + if (writeElement is MethodElement2) { + var parameters = writeElement.formalParameters; if (parameters.isNotEmpty) { _checkForArgumentTypeNotAssignableForArgument( argument: index, @@ -309,7 +313,7 @@ mixin ErrorDetectionHelpers { /// > Let `e` be an expression whose static type is an interface type that has /// > a method named `call`. In the case where the context type for `e` /// > is a function type or the type `Function`, `e` is treated as `e.call`. - MethodElement? getImplicitCallMethod( + MethodElement2? getImplicitCallMethod( DartType type, DartType context, SyntacticEntity errorNode) { var visitedTypes = {type}; while (type is TypeParameterType) { @@ -326,8 +330,15 @@ mixin ErrorDetectionHelpers { if (typeSystem.acceptsFunctionType(context) && type is InterfaceType && type.nullabilitySuffix != NullabilitySuffix.question) { - return type.lookUpMethod2( - FunctionElement.CALL_METHOD_NAME, type.element.library); + return inheritance + .getMember3( + type, + Name.forLibrary( + type.element3.library2, + MethodElement2.CALL_METHOD_NAME, + ), + ) + .ifTypeOrNull(); } else { return null; } @@ -335,10 +346,10 @@ mixin ErrorDetectionHelpers { /// Return the variable element represented by the given [expression], or /// `null` if there is no such element. - VariableElement? getVariableElement(Expression? expression) { + VariableElement2? getVariableElement(Expression? expression) { if (expression is Identifier) { - var element = expression.staticElement; - if (element is VariableElement) { + var element = expression.element; + if (element is VariableElement2) { return element; } } @@ -347,7 +358,7 @@ mixin ErrorDetectionHelpers { void _checkForArgumentTypeNotAssignableForArgument({ required Expression argument, - required ParameterElement? parameter, + required FormalParameterElement? parameter, required bool promoteParameterToNullable, Map, NonPromotionReason> Function()? whyNotPromoted, diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart index 9f0bee54f820..5cc3405b1ba8 100644 --- a/pkg/analyzer/lib/src/generated/error_verifier.dart +++ b/pkg/analyzer/lib/src/generated/error_verifier.dart @@ -312,6 +312,9 @@ class ErrorVerifier extends RecursiveAstVisitor assert(_enclosingExecutable.element == null); } + @override + InheritanceManager3 get inheritance => _inheritanceManager; + @override bool get strictCasts => options.strictCasts; diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart index a986eb4f5623..a3e749c5a873 100644 --- a/pkg/analyzer/lib/src/generated/resolver.dart +++ b/pkg/analyzer/lib/src/generated/resolver.dart @@ -22,6 +22,7 @@ import 'package:analyzer/dart/ast/syntactic_entity.dart'; 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/element2.dart'; import 'package:analyzer/dart/element/scope.dart'; import 'package:analyzer/dart/element/type.dart'; import 'package:analyzer/dart/element/type_provider.dart'; @@ -86,6 +87,7 @@ import 'package:analyzer/src/generated/utilities_dart.dart'; import 'package:analyzer/src/generated/variable_type_provider.dart'; import 'package:analyzer/src/task/inference_error.dart'; import 'package:analyzer/src/util/ast_data_extractor.dart'; +import 'package:analyzer/src/utilities/extensions/element.dart'; import 'package:analyzer/src/utilities/extensions/object.dart'; /// Function determining which source files should have inference logging @@ -181,6 +183,7 @@ class ResolverVisitor extends ThrowingAstVisitor AugmentableElement? enclosingAugmentation; /// The manager for the inheritance mappings. + @override final InheritanceManager3 inheritance; /// The feature set that is enabled for the current unit. @@ -1452,8 +1455,9 @@ class ResolverVisitor extends ThrowingAstVisitor var whyNotPromoted = flowAnalysis.flow?.whyNotPromoted(node.index); checkIndexExpressionIndex( node.index, - readElement: hasRead ? result.readElement as ExecutableElement? : null, - writeElement: result.writeElement as ExecutableElement?, + readElement: + hasRead ? result.readElement2 as ExecutableElement2? : null, + writeElement: result.writeElement2 as ExecutableElement2?, whyNotPromoted: whyNotPromoted, ); @@ -2379,7 +2383,7 @@ class ResolverVisitor extends ThrowingAstVisitor var whyNotPromoted = flowAnalysis.flow?.whyNotPromoted(expression); if (fieldElement != null) { var enclosingConstructor = enclosingFunction as ConstructorElement; - checkForFieldInitializerNotAssignable(node, fieldElement, + checkForFieldInitializerNotAssignable(node, fieldElement.asElement2, isConstConstructor: enclosingConstructor.isConst, whyNotPromoted: whyNotPromoted); } @@ -3033,7 +3037,7 @@ class ResolverVisitor extends ThrowingAstVisitor var whyNotPromoted = flowAnalysis.flow?.whyNotPromoted(node.index); checkIndexExpressionIndex( node.index, - readElement: result.readElement as ExecutableElement?, + readElement: result.readElement2 as ExecutableElement2?, writeElement: null, whyNotPromoted: whyNotPromoted, ); @@ -4155,7 +4159,7 @@ class ResolverVisitor extends ThrowingAstVisitor var callReference = ImplicitCallReferenceImpl( expression: expression, - staticElement: callMethod, + staticElement: callMethod.asElement, typeArguments: null, typeArgumentTypes: typeArgumentTypes, ); diff --git a/pkg/analyzer/lib/src/utilities/extensions/element.dart b/pkg/analyzer/lib/src/utilities/extensions/element.dart index ecfad05b60cb..93c051be7220 100644 --- a/pkg/analyzer/lib/src/utilities/extensions/element.dart +++ b/pkg/analyzer/lib/src/utilities/extensions/element.dart @@ -228,6 +228,16 @@ extension ExecutableElementOrNullExtension on ExecutableElement? { } } +extension FieldElementExtension on FieldElement { + FieldElement2 get asElement2 { + return switch (this) { + FieldFragment(:var element) => element, + FieldMember member => member, + _ => throw UnsupportedError('Unsupported type: $runtimeType'), + }; + } +} + extension FormalParameterExtension on FormalParameterElement { void appendToWithoutDelimiters( StringBuffer buffer, { @@ -289,6 +299,22 @@ extension ListOfTypeParameterElementExtension on List { } } +extension MethodElement2Extension on MethodElement2 { + MethodElement get asElement { + return baseElement.firstFragment as MethodElement; + } +} + +extension MethodElementExtension on MethodElement { + MethodElement2 get asElement2 { + return switch (this) { + MethodFragment(:var element) => element, + MethodMember member => member, + _ => throw UnsupportedError('Unsupported type: $runtimeType'), + }; + } +} + extension ParameterElementExtension on ParameterElement { ParameterElementImpl get declarationImpl { return declaration as ParameterElementImpl; From 1293500b0ca55c3ec9445b6de7811be61e965b43 Mon Sep 17 00:00:00 2001 From: Konstantin Shcheglov Date: Mon, 18 Nov 2024 16:57:21 +0000 Subject: [PATCH 4/8] Elements. Migrate AssignmentVerifier. Change-Id: I45a3c4df63250c611f011d61023ed74485145b78 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/395780 Commit-Queue: Konstantin Shcheglov Reviewed-by: Brian Wilkerson --- .../custom/handler_editable_arguments.dart | 2 +- pkg/analyzer/analyzer_use_new_elements.txt | 1 - pkg/analyzer/lib/dart/element/element2.dart | 3 + .../lib/src/dart/element/element.dart | 2 +- pkg/analyzer/lib/src/dart/element/member.dart | 2 +- .../resolver/extension_member_resolver.dart | 7 +++ .../resolver/property_element_resolver.dart | 8 +-- .../src/dart/resolver/resolution_result.dart | 6 ++ .../lib/src/error/assignment_verifier.dart | 56 +++++++++++-------- 9 files changed, 57 insertions(+), 30 deletions(-) diff --git a/pkg/analysis_server/lib/src/lsp/handlers/custom/handler_editable_arguments.dart b/pkg/analysis_server/lib/src/lsp/handlers/custom/handler_editable_arguments.dart index 7f49281766a5..2baa03c36ea3 100644 --- a/pkg/analysis_server/lib/src/lsp/handlers/custom/handler_editable_arguments.dart +++ b/pkg/analysis_server/lib/src/lsp/handlers/custom/handler_editable_arguments.dart @@ -173,7 +173,7 @@ class EditableArgumentsHandler /// Returns the name of an enum constant prefixed with the enum name. String? _qualifiedEnumConstant(FieldElement2 enumConstant) { - var enumName = enumConstant.enclosingElement2?.name3; + var enumName = enumConstant.enclosingElement2.name3; var name = enumConstant.name3; return enumName != null && name != null ? '$enumName.$name' : null; } diff --git a/pkg/analyzer/analyzer_use_new_elements.txt b/pkg/analyzer/analyzer_use_new_elements.txt index 4094018ebc0c..3c2f6bb349e3 100644 --- a/pkg/analyzer/analyzer_use_new_elements.txt +++ b/pkg/analyzer/analyzer_use_new_elements.txt @@ -98,7 +98,6 @@ lib/src/dart/resolver/typed_literal_resolver.dart lib/src/dart/resolver/variable_declaration_resolver.dart lib/src/dart/resolver/yield_statement_resolver.dart lib/src/diagnostic/diagnostic_factory.dart -lib/src/error/assignment_verifier.dart lib/src/error/best_practices_verifier.dart lib/src/error/correct_override.dart lib/src/error/dead_code_verifier.dart diff --git a/pkg/analyzer/lib/dart/element/element2.dart b/pkg/analyzer/lib/dart/element/element2.dart index a6317e4ea1e1..3ce694313812 100644 --- a/pkg/analyzer/lib/dart/element/element2.dart +++ b/pkg/analyzer/lib/dart/element/element2.dart @@ -747,6 +747,9 @@ abstract class FieldElement2 implements PropertyInducingElement2 { @override FieldElement2 get baseElement; + @override + InstanceElement2 get enclosingElement2; + @override FieldFragment get firstFragment; diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart index c5d7ebf60a1c..a4b467f4d232 100644 --- a/pkg/analyzer/lib/src/dart/element/element.dart +++ b/pkg/analyzer/lib/src/dart/element/element.dart @@ -4189,7 +4189,7 @@ class FieldElementImpl2 extends PropertyInducingElementImpl2 FieldElement2 get baseElement => this; @override - Element2? get enclosingElement2 => + InstanceElement2 get enclosingElement2 => (firstFragment._enclosingElement3 as InstanceFragment).element; @override diff --git a/pkg/analyzer/lib/src/dart/element/member.dart b/pkg/analyzer/lib/src/dart/element/member.dart index ca7bdb03d6c6..e8cb1aeb79a0 100644 --- a/pkg/analyzer/lib/src/dart/element/member.dart +++ b/pkg/analyzer/lib/src/dart/element/member.dart @@ -502,7 +502,7 @@ class FieldMember extends VariableMember String get displayName => declaration.displayName; @override - Element2? get enclosingElement2 => _element2.enclosingElement2; + InstanceElement2 get enclosingElement2 => _element2.enclosingElement2; @override Element get enclosingElement3 => declaration.enclosingElement3; diff --git a/pkg/analyzer/lib/src/dart/resolver/extension_member_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/extension_member_resolver.dart index cf0ac3c6fe2b..9c3ee1d3e21f 100644 --- a/pkg/analyzer/lib/src/dart/resolver/extension_member_resolver.dart +++ b/pkg/analyzer/lib/src/dart/resolver/extension_member_resolver.dart @@ -5,6 +5,7 @@ import 'package:analyzer/dart/analysis/features.dart'; import 'package:analyzer/dart/ast/syntactic_entity.dart'; import 'package:analyzer/dart/element/element.dart'; +import 'package:analyzer/dart/element/element2.dart'; import 'package:analyzer/dart/element/type.dart'; import 'package:analyzer/dart/element/type_provider.dart'; import 'package:analyzer/error/listener.dart'; @@ -466,8 +467,14 @@ enum ExtensionResolutionError implements ExtensionResolutionResult { @override ExecutableElement? get getter => null; + @override + ExecutableElement2? get getter2 => null; + @override ExecutableElement? get setter => null; + + @override + ExecutableElement2? get setter2 => null; } /// The result of attempting to resolve an identifier to elements, where the diff --git a/pkg/analyzer/lib/src/dart/resolver/property_element_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/property_element_resolver.dart index 5caefd73c358..c0bc645805bb 100644 --- a/pkg/analyzer/lib/src/dart/resolver/property_element_resolver.dart +++ b/pkg/analyzer/lib/src/dart/resolver/property_element_resolver.dart @@ -287,8 +287,8 @@ class PropertyElementResolver with ScopeHelpers { AssignmentVerifier(errorReporter).verify( node: node, - requested: writeElementRequested, - recovery: writeElementRecovery, + requested: writeElementRequested.asElement2, + recovery: writeElementRecovery.asElement2, receiverType: null, ); } @@ -528,7 +528,7 @@ class PropertyElementResolver with ScopeHelpers { AssignmentVerifier(errorReporter).verify( node: propertyName, requested: null, - recovery: result.getter, + recovery: result.getter2, receiverType: targetType, ); } @@ -736,7 +736,7 @@ class PropertyElementResolver with ScopeHelpers { AssignmentVerifier(errorReporter).verify( node: propertyName, requested: null, - recovery: writeElementRecovery, + recovery: writeElementRecovery.asElement2, receiverType: typeReference.thisType, ); } diff --git a/pkg/analyzer/lib/src/dart/resolver/resolution_result.dart b/pkg/analyzer/lib/src/dart/resolver/resolution_result.dart index cd6cd3420030..3668ce345f73 100644 --- a/pkg/analyzer/lib/src/dart/resolver/resolution_result.dart +++ b/pkg/analyzer/lib/src/dart/resolver/resolution_result.dart @@ -3,7 +3,9 @@ // BSD-style license that can be found in the LICENSE file. import 'package:analyzer/dart/element/element.dart'; +import 'package:analyzer/dart/element/element2.dart'; import 'package:analyzer/dart/element/type.dart'; +import 'package:analyzer/src/utilities/extensions/element.dart'; /// The result of attempting to resolve an identifier to elements. class ResolutionResult extends SimpleResolutionResult { @@ -57,4 +59,8 @@ class SimpleResolutionResult { final ExecutableElement? setter; const SimpleResolutionResult({this.getter, this.setter}); + + ExecutableElement2? get getter2 => getter.asElement2; + + ExecutableElement2? get setter2 => setter.asElement2; } diff --git a/pkg/analyzer/lib/src/error/assignment_verifier.dart b/pkg/analyzer/lib/src/error/assignment_verifier.dart index 5268a5d2da78..dfad26aed0ec 100644 --- a/pkg/analyzer/lib/src/error/assignment_verifier.dart +++ b/pkg/analyzer/lib/src/error/assignment_verifier.dart @@ -3,7 +3,7 @@ // BSD-style license that can be found in the LICENSE file. import 'package:analyzer/dart/ast/ast.dart'; -import 'package:analyzer/dart/element/element.dart'; +import 'package:analyzer/dart/element/element2.dart'; import 'package:analyzer/dart/element/type.dart'; import 'package:analyzer/error/listener.dart'; import 'package:analyzer/src/dart/element/element.dart'; @@ -29,12 +29,12 @@ class AssignmentVerifier { /// [CompileTimeErrorCode.UNDEFINED_IDENTIFIER]. void verify({ required SimpleIdentifier node, - required Element? requested, - required Element? recovery, + required Element2? requested, + required Element2? recovery, required DartType? receiverType, }) { if (requested != null) { - if (requested is VariableElement) { + if (requested is VariableElement2) { if (requested.isConst) { _errorReporter.atNode( node, @@ -45,54 +45,66 @@ class AssignmentVerifier { return; } - if (recovery is DynamicElementImpl || - recovery is InterfaceElement || - recovery is TypeAliasElement || - recovery is TypeParameterElement) { + if (recovery is DynamicElementImpl2 || + recovery is InterfaceElement2 || + recovery is TypeAliasElement2 || + recovery is TypeParameterElement2) { _errorReporter.atNode( node, CompileTimeErrorCode.ASSIGNMENT_TO_TYPE, ); - } else if (recovery is FunctionElement) { + } else if (recovery is LocalFunctionElement || + recovery is TopLevelFunctionElement) { _errorReporter.atNode( node, CompileTimeErrorCode.ASSIGNMENT_TO_FUNCTION, ); - } else if (recovery is MethodElement) { + } else if (recovery is MethodElement2) { _errorReporter.atNode( node, CompileTimeErrorCode.ASSIGNMENT_TO_METHOD, ); - } else if (recovery is PrefixElement) { - _errorReporter.atNode( - node, - CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT, - arguments: [recovery.name], - ); - } else if (recovery is PropertyAccessorElement && recovery.isGetter) { - var variable = recovery.variable2; + } else if (recovery is PrefixElement2) { + if (recovery.name3 case var prefixName?) { + _errorReporter.atNode( + node, + CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT, + arguments: [prefixName], + ); + } + } else if (recovery is GetterElement) { + var variable = recovery.variable3; if (variable == null) { return; } + + var variableName = variable.name3; + if (variableName == null) { + return; + } + if (variable.isConst) { _errorReporter.atNode( node, CompileTimeErrorCode.ASSIGNMENT_TO_CONST, ); - } else if (variable is FieldElement && variable.isSynthetic) { + } else if (variable is FieldElement2 && variable.isSynthetic) { _errorReporter.atNode( node, CompileTimeErrorCode.ASSIGNMENT_TO_FINAL_NO_SETTER, - arguments: [variable.name, variable.enclosingElement3.displayName], + arguments: [ + variableName, + variable.enclosingElement2.displayName, + ], ); } else { _errorReporter.atNode( node, CompileTimeErrorCode.ASSIGNMENT_TO_FINAL, - arguments: [variable.name], + arguments: [variableName], ); } - } else if (recovery is MultiplyDefinedElementImpl) { + } else if (recovery is MultiplyDefinedElementImpl2) { // Will be reported in ErrorVerifier. } else { if (node.isSynthetic) { From 17a2f169266e42ea0ca91617990f906639b19726 Mon Sep 17 00:00:00 2001 From: Konstantin Shcheglov Date: Mon, 18 Nov 2024 17:36:50 +0000 Subject: [PATCH 5/8] Elements. Add PropertyAccessorElement2 and PropertyAccessorFragment. I found a number of places where we need to access `variable3`, so it might be convenient to have a common interface that provides it. Still, there are many places where we want to know that this is specifically `GetterElement`, to separate interfaces for them are also useful. Change-Id: Ib671dc3bdb9a04a022fd74921f8ccedcdba79643 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/395701 Commit-Queue: Konstantin Shcheglov Reviewed-by: Brian Wilkerson --- .../src/computer/computer_documentation.dart | 4 +- .../handler_document_color_presentation.dart | 3 +- .../completion/dart/feature_computer.dart | 15 +--- .../completion/dart/suggestion_builder.dart | 4 +- .../flutter_convert_to_stateless_widget.dart | 3 +- .../correction/dart/remove_unused.dart | 6 +- .../fix/data_driven/element_matcher.dart | 11 ++- .../lib/src/utilities/import_analyzer.dart | 23 ++---- pkg/analyzer/lib/dart/element/element2.dart | 73 ++++++++++++------- .../lib/src/dart/element/element.dart | 62 ++++++++-------- pkg/analyzer/lib/src/dart/element/member.dart | 2 +- .../src/error/must_call_super_verifier.dart | 6 +- .../lib/src/error/use_result_verifier.dart | 19 ++--- .../src/services/top_level_declarations.dart | 7 +- pkg/linter/lib/src/extensions.dart | 7 +- .../lib/src/rules/unnecessary_lambdas.dart | 3 +- .../lib/src/util/leak_detector_visitor.dart | 3 +- 17 files changed, 111 insertions(+), 140 deletions(-) diff --git a/pkg/analysis_server/lib/src/computer/computer_documentation.dart b/pkg/analysis_server/lib/src/computer/computer_documentation.dart index d4aaf6414a56..deb9c651b856 100644 --- a/pkg/analysis_server/lib/src/computer/computer_documentation.dart +++ b/pkg/analysis_server/lib/src/computer/computer_documentation.dart @@ -52,8 +52,8 @@ class DartDocumentationComputer { element, ...overridden.superElements, ...overridden.interfaceElements, - if (element case GetterElement(variable3: var variable?)) variable, - if (element case SetterElement(variable3: var variable?)) variable, + if (element case PropertyAccessorElement2(variable3: var variable?)) + variable, ]; for (var candidate in candidates) { if (candidate.documentationCommentOrNull != null) { diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_document_color_presentation.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_document_color_presentation.dart index 7f6a052c2841..5297baa463e3 100644 --- a/pkg/analysis_server/lib/src/lsp/handlers/handler_document_color_presentation.dart +++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_document_color_presentation.dart @@ -253,8 +253,7 @@ class DocumentColorPresentationHandler parent is PrefixedIdentifier ? parent.element : node.element; return switch (element) { - GetterElement(:var variable3) || SetterElement(:var variable3) => - variable3?.isConst ?? false, + PropertyAccessorElement2(:var variable3) => variable3?.isConst ?? false, VariableElement2() => element.isConst, _ => false, }; diff --git a/pkg/analysis_server/lib/src/services/completion/dart/feature_computer.dart b/pkg/analysis_server/lib/src/services/completion/dart/feature_computer.dart index e675878decb6..96b62e617717 100644 --- a/pkg/analysis_server/lib/src/services/completion/dart/feature_computer.dart +++ b/pkg/analysis_server/lib/src/services/completion/dart/feature_computer.dart @@ -257,13 +257,7 @@ class FeatureComputer { return protocol.ElementKind.CLASS; } else if (element is FieldElement2 && element.isEnumConstant) { return protocol.ElementKind.ENUM_CONSTANT; - } else if (element is GetterElement) { - var variable = element.variable3; - if (variable == null) { - return protocol.ElementKind.UNKNOWN; - } - element = variable; - } else if (element is SetterElement) { + } else if (element is PropertyAccessorElement2) { var variable = element.variable3; if (variable == null) { return protocol.ElementKind.UNKNOWN; @@ -467,12 +461,7 @@ class FeatureComputer { return 1.0; } else if (element is TopLevelVariableElement2 && element.isConst) { return 1.0; - } else if (element is GetterElement && element.isSynthetic) { - var variable = element.variable3; - if (variable != null && variable.isStatic && variable.isConst) { - return 1.0; - } - } else if (element is SetterElement && element.isSynthetic) { + } else if (element is PropertyAccessorElement2 && element.isSynthetic) { var variable = element.variable3; if (variable != null && variable.isStatic && variable.isConst) { return 1.0; diff --git a/pkg/analysis_server/lib/src/services/completion/dart/suggestion_builder.dart b/pkg/analysis_server/lib/src/services/completion/dart/suggestion_builder.dart index 4bc506affb94..58e9c986a3b0 100644 --- a/pkg/analysis_server/lib/src/services/completion/dart/suggestion_builder.dart +++ b/pkg/analysis_server/lib/src/services/completion/dart/suggestion_builder.dart @@ -1492,9 +1492,7 @@ class SuggestionBuilder { int? requiredParameterCount; bool? hasNamedParameters; CompletionDefaultArgumentList? defaultArgumentList; - if (element is ExecutableElement2 && - element is! GetterElement && - element is! SetterElement) { + if (element is ExecutableElement2 && element is! PropertyAccessorElement2) { parameterNames = element.formalParameters.map((parameter) { return parameter.displayName; diff --git a/pkg/analysis_server/lib/src/services/correction/dart/flutter_convert_to_stateless_widget.dart b/pkg/analysis_server/lib/src/services/correction/dart/flutter_convert_to_stateless_widget.dart index cc32a597cef2..e5a2935271eb 100644 --- a/pkg/analysis_server/lib/src/services/correction/dart/flutter_convert_to_stateless_widget.dart +++ b/pkg/analysis_server/lib/src/services/correction/dart/flutter_convert_to_stateless_widget.dart @@ -303,8 +303,7 @@ class _FieldFinder extends RecursiveAstVisitor { if (node.inSetterContext()) { var element = node.writeOrReadElement2; var field = switch (element) { - GetterElement(:var variable3) => variable3, - SetterElement(:var variable3) => variable3, + PropertyAccessorElement2(:var variable3) => variable3, _ => null, }; if (field is FieldElement2) { diff --git a/pkg/analysis_server/lib/src/services/correction/dart/remove_unused.dart b/pkg/analysis_server/lib/src/services/correction/dart/remove_unused.dart index 509789585062..9c884c687c5a 100644 --- a/pkg/analysis_server/lib/src/services/correction/dart/remove_unused.dart +++ b/pkg/analysis_server/lib/src/services/correction/dart/remove_unused.dart @@ -273,11 +273,7 @@ class _ElementReferenceCollector extends RecursiveAstVisitor { var staticElement = node.writeOrReadElement2; if (staticElement == element) { references.add(node); - } else if (staticElement is GetterElement) { - if (staticElement.variable3 == element) { - references.add(node); - } - } else if (staticElement is SetterElement) { + } else if (staticElement is PropertyAccessorElement2) { if (staticElement.variable3 == element) { references.add(node); } diff --git a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/element_matcher.dart b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/element_matcher.dart index 2a8ac6bce989..396bb9340e9b 100644 --- a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/element_matcher.dart +++ b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/element_matcher.dart @@ -7,13 +7,12 @@ import 'package:analysis_server/src/services/correction/fix/data_driven/element_ import 'package:analyzer/dart/ast/token.dart'; import 'package:analyzer/dart/element/element2.dart' show - LibraryElement2, - LibraryFragment, ExtensionElement2, - GetterElement, InterfaceElement2, + LibraryElement2, + LibraryFragment, PrefixElement2, - SetterElement; + PropertyAccessorElement2; import 'package:analyzer/dart/element/type.dart'; import 'package:analyzer/src/dart/ast/ast.dart'; @@ -546,8 +545,8 @@ class _MatcherBuilder { var element = node.element; // Add enclosing element to the matcher for non top level property // accessors when possible. - if (element is GetterElement || element is SetterElement) { - var enclosingElement = element?.enclosingElement2; + if (element is PropertyAccessorElement2) { + var enclosingElement = element.enclosingElement2; if (enclosingElement is! LibraryElement2) { _addMatcher( components: [node.name, (enclosingElement?.displayName)!], diff --git a/pkg/analysis_server/lib/src/utilities/import_analyzer.dart b/pkg/analysis_server/lib/src/utilities/import_analyzer.dart index 5f6b596cc07e..29a66310d3f1 100644 --- a/pkg/analysis_server/lib/src/utilities/import_analyzer.dart +++ b/pkg/analysis_server/lib/src/utilities/import_analyzer.dart @@ -121,23 +121,14 @@ class _ElementRecorder { int referenceOffset, LibraryImport? import, ) { - switch (referencedElement) { - case GetterElement(): - if (referencedElement.isSynthetic) { - var variable = referencedElement.variable3; - if (variable == null) { - return; - } - referencedElement = variable; - } - case SetterElement(): - if (referencedElement.isSynthetic) { - var variable = referencedElement.variable3; - if (variable == null) { - return; - } - referencedElement = variable; + if (referencedElement is PropertyAccessorElement2) { + if (referencedElement.isSynthetic) { + var variable = referencedElement.variable3; + if (variable == null) { + return; } + referencedElement = variable; + } } if (_isBeingMoved(referenceOffset)) { diff --git a/pkg/analyzer/lib/dart/element/element2.dart b/pkg/analyzer/lib/dart/element/element2.dart index 3ce694313812..231d0d767593 100644 --- a/pkg/analyzer/lib/dart/element/element2.dart +++ b/pkg/analyzer/lib/dart/element/element2.dart @@ -1071,7 +1071,7 @@ abstract class GenericFunctionTypeFragment implements FunctionTypedFragment { /// top-level variable or a field. Induced getters are synthetic. /// /// Clients may not extend, implement or mix-in this class. -abstract class GetterElement implements ExecutableElement2 { +abstract class GetterElement implements PropertyAccessorElement2 { @override GetterElement get baseElement; @@ -1081,18 +1081,12 @@ abstract class GetterElement implements ExecutableElement2 { @override GetterFragment get firstFragment; - - /// The field or top-level variable associated with this getter. - /// - /// If this getter was explicitly defined (is not synthetic) then the variable - /// associated with it will be synthetic. - PropertyInducingElement2? get variable3; } /// The portion of a [GetterElement] contributed by a single declaration. /// /// Clients may not extend, implement or mix-in this class. -abstract class GetterFragment implements ExecutableFragment { +abstract class GetterFragment implements PropertyAccessorFragment { /// The setter that corresponds to (has the same name as) this getter, or /// `null` if there is no corresponding setter. SetterFragment? get correspondingSetter2; @@ -1113,12 +1107,6 @@ abstract class GetterFragment implements ExecutableFragment { // but can't because the Impl class supports both getters and setters. // @override // GetterElement get element; - - /// The field or top-level variable associated with this getter. - /// - /// If this getter was explicitly defined (is not synthetic) then the variable - /// associated with it will be synthetic. - PropertyInducingFragment? get variable3; } /// An element whose instance members can refer to `this`. @@ -2077,6 +2065,47 @@ abstract class PromotableFragment implements VariableFragment { PromotableFragment? get previousFragment; } +/// A getter or a setter. +/// +/// Property accessors can either be defined explicitly or they can be induced +/// by either a top-level variable or a field. Induced property accessors are +/// synthetic. +/// +/// Clients may not extend, implement or mix-in this class. +abstract class PropertyAccessorElement2 implements ExecutableElement2 { + @override + PropertyAccessorElement2 get baseElement; + + @override + PropertyAccessorFragment get firstFragment; + + /// The field or top-level variable associated with this getter. + /// + /// If this getter was explicitly defined (is not synthetic) then the variable + /// associated with it will be synthetic. + PropertyInducingElement2? get variable3; +} + +/// The portion of a [GetterElement] contributed by a single declaration. +/// +/// Clients may not extend, implement or mix-in this class. +abstract class PropertyAccessorFragment implements ExecutableFragment { + @override + PropertyAccessorElement2 get element; + + @override + PropertyAccessorFragment? get nextFragment; + + @override + PropertyAccessorFragment? get previousFragment; + + /// The field or top-level variable associated with this property accessors. + /// + /// If this property accessor was explicitly defined (is not synthetic) then + /// the variable associated with it will be synthetic. + PropertyInducingFragment? get variable3; +} + /// A variable that has an associated getter and possibly a setter. Note that /// explicitly defined variables implicitly define a synthetic getter and that /// non-`final` explicitly defined variables implicitly define a synthetic @@ -2180,7 +2209,7 @@ abstract class PropertyInducingFragment /// top-level variable or a field. Induced setters are synthetic. /// /// Clients may not extend, implement or mix-in this class. -abstract class SetterElement implements ExecutableElement2 { +abstract class SetterElement implements PropertyAccessorElement2 { @override SetterElement get baseElement; @@ -2190,18 +2219,12 @@ abstract class SetterElement implements ExecutableElement2 { @override SetterFragment get firstFragment; - - /// The field or top-level variable associated with this setter. - /// - /// If this setter was explicitly defined (is not synthetic) then the variable - /// associated with it will be synthetic. - PropertyInducingElement2? get variable3; } /// The portion of a [SetterElement] contributed by a single declaration. /// /// Clients may not extend, implement or mix-in this class. -abstract class SetterFragment implements ExecutableFragment { +abstract class SetterFragment implements PropertyAccessorFragment { /// The getter that corresponds to (has the same name as) this setter, or /// `null` if there is no corresponding getter. GetterFragment? get correspondingGetter2; @@ -2222,12 +2245,6 @@ abstract class SetterFragment implements ExecutableFragment { // setters. // @override // SetterFragment? get previousFragment; - - /// The field or top-level variable associated with this setter. - /// - /// If this setter was explicitly defined (is not synthetic) then the variable - /// associated with it will be synthetic. - PropertyInducingFragment? get variable3; } /// A super formal parameter. diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart index a4b467f4d232..0360d91e1b3e 100644 --- a/pkg/analyzer/lib/src/dart/element/element.dart +++ b/pkg/analyzer/lib/src/dart/element/element.dart @@ -5153,7 +5153,7 @@ class GenericFunctionTypeElementImpl extends _ExistingElementImpl } } -class GetterElementImpl extends ExecutableElementImpl2 +class GetterElementImpl extends PropertyAccessorElementImpl2 with FragmentedExecutableElementMixin, FragmentedFunctionTypedElementMixin, @@ -5179,18 +5179,9 @@ class GetterElementImpl extends ExecutableElementImpl2 SetterElement? get correspondingSetter2 => firstFragment.correspondingSetter2?.element as SetterElement?; - @override - Element2? get enclosingElement2 => firstFragment.enclosingFragment?.element; - - @override - bool get isExternal => firstFragment.isExternal; - @override ElementKind get kind => ElementKind.GETTER; - @override - String? get name3 => firstFragment.name2; - @override Element2 get nonSynthetic2 { if (!isSynthetic) { @@ -5201,9 +5192,6 @@ class GetterElementImpl extends ExecutableElementImpl2 throw StateError('Synthetic getter has no variable'); } - @override - PropertyInducingElement2? get variable3 => firstFragment.variable2?.element; - @override T? accept2(ElementVisitor2 visitor) { return visitor.visitGetterElement(this); @@ -9185,7 +9173,11 @@ abstract class PromotableElementImpl2 extends VariableElementImpl2 /// A concrete implementation of a [PropertyAccessorElement]. class PropertyAccessorElementImpl extends ExecutableElementImpl with AugmentableElement - implements PropertyAccessorElement, GetterFragment, SetterFragment { + implements + PropertyAccessorElement, + PropertyAccessorFragment, + GetterFragment, + SetterFragment { @override String? name2; @@ -9198,7 +9190,7 @@ class PropertyAccessorElementImpl extends ExecutableElementImpl /// /// The element will always be an instance of either `GetterElement` or /// `SetterElement`. - ExecutableElement2? _element; + PropertyAccessorElementImpl2? _element; /// Initialize a newly created property accessor element to have the given /// [name] and [offset]. @@ -9258,7 +9250,7 @@ class PropertyAccessorElementImpl extends ExecutableElementImpl PropertyAccessorElement get declaration => this; @override - ExecutableElement2 get element { + PropertyAccessorElementImpl2 get element { if (_element != null) { return _element!; } @@ -9277,7 +9269,7 @@ class PropertyAccessorElementImpl extends ExecutableElementImpl } } - set element(ExecutableElement2 element) => _element = element; + set element(PropertyAccessorElementImpl2 element) => _element = element; @override Fragment? get enclosingFragment { @@ -9345,10 +9337,10 @@ class PropertyAccessorElementImpl extends ExecutableElementImpl } @override - ExecutableFragment? get nextFragment => augmentation; + PropertyAccessorFragment? get nextFragment => augmentation; @override - ExecutableFragment? get previousFragment => augmentationTarget; + PropertyAccessorFragment? get previousFragment => augmentationTarget; @override PropertyInducingElementImpl? get variable2 { @@ -9376,6 +9368,27 @@ class PropertyAccessorElementImpl extends ExecutableElementImpl } } +abstract class PropertyAccessorElementImpl2 extends ExecutableElementImpl2 + implements PropertyAccessorElement2 { + @override + PropertyAccessorElement2 get baseElement => this; + + @override + Element2? get enclosingElement2 => firstFragment.enclosingFragment?.element; + + @override + PropertyAccessorElementImpl get firstFragment; + + @override + bool get isExternal => firstFragment.isExternal; + + @override + String? get name3 => firstFragment.name2; + + @override + PropertyInducingElement2? get variable3 => firstFragment.variable2?.element; +} + /// Implicit getter for a [PropertyInducingElementImpl]. // Pre-existing name. // ignore: camel_case_types @@ -9703,7 +9716,7 @@ abstract class PropertyInducingElementTypeInference { DartType perform(); } -class SetterElementImpl extends ExecutableElementImpl2 +class SetterElementImpl extends PropertyAccessorElementImpl2 with FragmentedExecutableElementMixin, FragmentedFunctionTypedElementMixin, @@ -9732,15 +9745,9 @@ class SetterElementImpl extends ExecutableElementImpl2 @override Element2? get enclosingElement2 => firstFragment.enclosingFragment?.element; - @override - bool get isExternal => firstFragment.isExternal; - @override ElementKind get kind => ElementKind.SETTER; - @override - String? get name3 => firstFragment.name2; - @override Element2 get nonSynthetic2 { if (!isSynthetic) { @@ -9751,9 +9758,6 @@ class SetterElementImpl extends ExecutableElementImpl2 throw StateError('Synthetic setter has no variable'); } - @override - PropertyInducingElement2? get variable3 => firstFragment.variable2?.element; - @override T? accept2(ElementVisitor2 visitor) { return visitor.visitSetterElement(this); diff --git a/pkg/analyzer/lib/src/dart/element/member.dart b/pkg/analyzer/lib/src/dart/element/member.dart index e8cb1aeb79a0..26bfa9ca92ae 100644 --- a/pkg/analyzer/lib/src/dart/element/member.dart +++ b/pkg/analyzer/lib/src/dart/element/member.dart @@ -1240,7 +1240,7 @@ class ParameterMember extends VariableMember /// A property accessor element defined in a parameterized type where the values /// of the type parameters are known. abstract class PropertyAccessorMember extends ExecutableMember - implements PropertyAccessorElement { + implements PropertyAccessorElement, PropertyAccessorElement2 { factory PropertyAccessorMember( PropertyAccessorElement declaration, MapSubstitution augmentationSubstitution, diff --git a/pkg/analyzer/lib/src/error/must_call_super_verifier.dart b/pkg/analyzer/lib/src/error/must_call_super_verifier.dart index a28dbcf876ae..1f26f3943811 100644 --- a/pkg/analyzer/lib/src/error/must_call_super_verifier.dart +++ b/pkg/analyzer/lib/src/error/must_call_super_verifier.dart @@ -123,10 +123,8 @@ class MustCallSuperVerifier { if (member is MethodElement2 && member.metadata2.hasMustCallSuper) { return member; } - if (member is GetterElement && member.metadata2.hasMustCallSuper) { - return member; - } - if (member is SetterElement && member.metadata2.hasMustCallSuper) { + if (member is PropertyAccessorElement2 && + member.metadata2.hasMustCallSuper) { return member; } // TODO(srawlins): What about a field annotated with `@mustCallSuper`? diff --git a/pkg/analyzer/lib/src/error/use_result_verifier.dart b/pkg/analyzer/lib/src/error/use_result_verifier.dart index 6a7be34ddfc6..2456bb21cee0 100644 --- a/pkg/analyzer/lib/src/error/use_result_verifier.dart +++ b/pkg/analyzer/lib/src/error/use_result_verifier.dart @@ -176,20 +176,11 @@ class UseResultVerifier { static ElementAnnotation? _getUseResultMetadata(Element2 element) { // Implicit getters/setters. - if (element.isSynthetic) { - switch (element) { - case GetterElement getter: - if (getter.variable3 case var variable?) { - element = variable; - } else { - return null; - } - case SetterElement setter: - if (setter.variable3 case var variable?) { - element = variable; - } else { - return null; - } + if (element.isSynthetic && element is PropertyAccessorElement2) { + if (element.variable3 case var variable?) { + element = variable; + } else { + return null; } } diff --git a/pkg/analyzer/lib/src/services/top_level_declarations.dart b/pkg/analyzer/lib/src/services/top_level_declarations.dart index fa30c42731c0..ec6a75a48052 100644 --- a/pkg/analyzer/lib/src/services/top_level_declarations.dart +++ b/pkg/analyzer/lib/src/services/top_level_declarations.dart @@ -176,12 +176,7 @@ class TopLevelDeclarations { static Element2? _findElement2(LibraryElement2 libraryElement, String name) { var element = libraryElement.exportNamespace.get2(name) ?? libraryElement.exportNamespace.get2('$name='); - if (element is GetterElement) { - var variable = element.variable3; - if (variable != null) { - return variable; - } - } else if (element is SetterElement) { + if (element is PropertyAccessorElement2) { var variable = element.variable3; if (variable != null) { return variable; diff --git a/pkg/linter/lib/src/extensions.dart b/pkg/linter/lib/src/extensions.dart index 3dedfb31fbdd..1f943d9e7687 100644 --- a/pkg/linter/lib/src/extensions.dart +++ b/pkg/linter/lib/src/extensions.dart @@ -372,8 +372,7 @@ extension ElementExtension on Element { extension ElementExtension2 on Element2? { Element2? get canonicalElement2 => switch (this) { - GetterElement(:var variable3) => variable3, - SetterElement(:var variable3) => variable3, + PropertyAccessorElement2(:var variable3) => variable3, _ => this, }; @@ -549,11 +548,9 @@ extension InhertanceManager3Extension on InheritanceManager3 { switch (member) { case FieldElement2(): executable = member.getter2; - case GetterElement(): - executable = member; case MethodElement2(): executable = member; - case SetterElement(): + case PropertyAccessorElement2(): executable = member; } diff --git a/pkg/linter/lib/src/rules/unnecessary_lambdas.dart b/pkg/linter/lib/src/rules/unnecessary_lambdas.dart index fd621314a462..a4896194b679 100644 --- a/pkg/linter/lib/src/rules/unnecessary_lambdas.dart +++ b/pkg/linter/lib/src/rules/unnecessary_lambdas.dart @@ -234,8 +234,7 @@ extension on Expression? { extension on Element2? { /// Returns whether this is a `final` variable or property and not `late`. bool get isFinal => switch (this) { - GetterElement(:var isSynthetic, :var variable3?) || - SetterElement(:var isSynthetic, :var variable3?) => + PropertyAccessorElement2(:var isSynthetic, :var variable3?) => isSynthetic && variable3.isFinal && !variable3.isLate, VariableElement2(:var isLate, :var isFinal) => isFinal && !isLate, // TODO(pq): [element model] this preserves existing v1 semantics but looks fishy diff --git a/pkg/linter/lib/src/util/leak_detector_visitor.dart b/pkg/linter/lib/src/util/leak_detector_visitor.dart index 80f3d6cdedf5..6ae978f8553e 100644 --- a/pkg/linter/lib/src/util/leak_detector_visitor.dart +++ b/pkg/linter/lib/src/util/leak_detector_visitor.dart @@ -291,8 +291,7 @@ enum _VariableType { extension on Element2? { bool matches(VariableElement2? variable) => switch (this) { - GetterElement(:var variable3) => variable3 == variable, - SetterElement(:var variable3) => variable3 == variable, + PropertyAccessorElement2(:var variable3) => variable3 == variable, _ => false, }; } From 922847af5f2952de37e1ada214b9d4712fabaa94 Mon Sep 17 00:00:00 2001 From: Sam Rawlins Date: Mon, 18 Nov 2024 17:53:10 +0000 Subject: [PATCH 6/8] DAS plugins: Only analyze (and hence visit) .dart files In it's current form, the lint rules are given _every_ file in the context root, including things like CHANGELOG.md, YAML files, etc, and it tries to parse them as Dart source. Change-Id: I0bd5a682fa4f22b857520bb99e7a3d8990c93e37 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/396041 Commit-Queue: Samuel Rawlins Reviewed-by: Konstantin Shcheglov Auto-Submit: Samuel Rawlins Reviewed-by: Brian Wilkerson --- pkg/analysis_server_plugin/lib/src/plugin_server.dart | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/pkg/analysis_server_plugin/lib/src/plugin_server.dart b/pkg/analysis_server_plugin/lib/src/plugin_server.dart index 3002328077dc..1a8bf75449bc 100644 --- a/pkg/analysis_server_plugin/lib/src/plugin_server.dart +++ b/pkg/analysis_server_plugin/lib/src/plugin_server.dart @@ -29,6 +29,7 @@ import 'package:analyzer/src/dart/element/type_system.dart'; import 'package:analyzer/src/lint/linter.dart'; import 'package:analyzer/src/lint/linter_visitor.dart'; import 'package:analyzer/src/lint/registry.dart'; +import 'package:analyzer/src/util/file_paths.dart' as file_paths; import 'package:analyzer_plugin/channel/channel.dart'; import 'package:analyzer_plugin/protocol/protocol.dart'; import 'package:analyzer_plugin/protocol/protocol_common.dart' as protocol; @@ -190,7 +191,14 @@ class PluginServer { required AnalysisContextCollection contextCollection, }) async { await _forAnalysisContexts(contextCollection, (analysisContext) async { - var paths = analysisContext.contextRoot.analyzedFiles().toList(); + var paths = analysisContext.contextRoot + .analyzedFiles() + // TODO(srawlins): Enable analysis on other files, even if only + // YAML files for analysis options and pubspec analysis and quick + // fixes. + .where((p) => file_paths.isDart(_resourceProvider.pathContext, p)) + .toList(); + await _analyzeFiles( analysisContext: analysisContext, paths: paths, From ae0b50d62b520ef9c9cb7cdac017bd2547fe41a3 Mon Sep 17 00:00:00 2001 From: Paul Berry Date: Mon, 18 Nov 2024 18:27:11 +0000 Subject: [PATCH 7/8] [mini_types] Add a `Type.gatherUsedIdentifiers` method. This method will be used by a follow-up CL that adds support for generic functions, since the implementation of `==` and `hashCode` for generic functions needs to perform substitutions in order to recognize that alpha-equivalent types (such as `T Function()` and `U Function`) are equal, and those substitutions need to avoid name collisions with identifier names that already appear in the type. Change-Id: Ifd237a9842791f440e285d89e9d80b898e996411 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/395685 Reviewed-by: Samuel Rawlins Commit-Queue: Paul Berry --- pkg/_fe_analyzer_shared/test/mini_types.dart | 66 +++++++++++++++++++ .../test/mini_types_test.dart | 41 ++++++++++++ 2 files changed, 107 insertions(+) diff --git a/pkg/_fe_analyzer_shared/test/mini_types.dart b/pkg/_fe_analyzer_shared/test/mini_types.dart index 4259e4cf6a70..5fbc302847f7 100644 --- a/pkg/_fe_analyzer_shared/test/mini_types.dart +++ b/pkg/_fe_analyzer_shared/test/mini_types.dart @@ -111,6 +111,25 @@ class FunctionType extends Type nullabilitySuffix: nullabilitySuffix); } + @override + void gatherUsedIdentifiers(Set identifiers) { + returnType.gatherUsedIdentifiers(identifiers); + for (var positionalParameter in positionalParameters) { + positionalParameter.gatherUsedIdentifiers(identifiers); + } + for (var typeFormal in typeFormals) { + identifiers.add(typeFormal.name); + } + for (var namedParameter in namedParameters) { + // As explained in the documentation for `Type.gatherUsedIdentifiers`, + // to reduce the risk of confusion, this method is generous in which + // identifiers it reports. So report `namedParameter.name` even though + // it's not strictly necessary. + identifiers.add(namedParameter.name); + namedParameter.type.gatherUsedIdentifiers(identifiers); + } + } + @override Type? recursivelyDemote({required bool covariant}) { Type? newReturnType = returnType.recursivelyDemote(covariant: covariant); @@ -383,6 +402,14 @@ class PrimaryType extends Type { args: newArgs, nullabilitySuffix: nullabilitySuffix); } + @override + void gatherUsedIdentifiers(Set identifiers) { + identifiers.add(name); + for (var arg in args) { + arg.gatherUsedIdentifiers(identifiers); + } + } + @override Type? recursivelyDemote({required bool covariant}) { List? newArgs = args.recursivelyDemote(covariant: covariant); @@ -467,6 +494,21 @@ class RecordType extends Type implements SharedRecordTypeStructure { ); } + @override + void gatherUsedIdentifiers(Set identifiers) { + for (var type in positionalTypes) { + type.gatherUsedIdentifiers(identifiers); + } + for (var namedType in namedTypes) { + // As explained in the documentation for `Type.gatherUsedIdentifiers`, + // to reduce the risk of confusion, this method is generous in which + // identifiers it reports. So report `namedType.name` even though it's + // not strictly necessary. + identifiers.add(namedType.name); + namedType.type.gatherUsedIdentifiers(identifiers); + } + } + @override Type? recursivelyDemote({required bool covariant}) { List? newPositional; @@ -581,6 +623,21 @@ abstract class Type implements SharedTypeStructure, _Substitutable { /// `Never`). Type? closureWithRespectToUnknown({required bool covariant}); + /// Recursively visits `this`, gathering up all the identifiers that appear in + /// it, and adds them to the set [identifiers]. + /// + /// This method is intended to aid in choosing safe names for substitutions. + /// For example, it can be used to determine that in a type like + /// `T Function(U)`, it's not safe to rename the type variable `U` to `T`, + /// since that would conflict with an existing use of `T`. + /// + /// To lower the risk of confusion, it is generous in which identifiers it + /// reports. For example, in the type `void Function({T X})`, it reports + /// `X` as a used identifier. This is because even though it would technically + /// be safe to rename the type variable `T` to `X`, to do so would be result + /// in a confusing type. + void gatherUsedIdentifiers(Set identifiers); + @override String getDisplayString() => type; @@ -724,6 +781,12 @@ class TypeParameterType extends Type { promotion: newPromotion, nullabilitySuffix: nullabilitySuffix); } + @override + void gatherUsedIdentifiers(Set identifiers) { + identifiers.add(typeParameter.name); + promotion?.gatherUsedIdentifiers(identifiers); + } + @override Type? recursivelyDemote({required bool covariant}) { if (!covariant) { @@ -1474,6 +1537,9 @@ class UnknownType extends Type implements SharedUnknownTypeStructure { Type? closureWithRespectToUnknown({required bool covariant}) => covariant ? Type('Object?') : NeverType.instance; + @override + void gatherUsedIdentifiers(Set identifiers) {} + @override Type? recursivelyDemote({required bool covariant}) => null; diff --git a/pkg/_fe_analyzer_shared/test/mini_types_test.dart b/pkg/_fe_analyzer_shared/test/mini_types_test.dart index 9beffa77b8fc..cd8bdeeaa029 100644 --- a/pkg/_fe_analyzer_shared/test/mini_types_test.dart +++ b/pkg/_fe_analyzer_shared/test/mini_types_test.dart @@ -1021,6 +1021,47 @@ main() { }); }); + group('gatherUsedIdentifiers:', () { + Set queryUsedIdentifiers(Type t) { + var identifiers = {}; + t.gatherUsedIdentifiers(identifiers); + return identifiers; + } + + test('FunctionType', () { + expect(queryUsedIdentifiers(Type('int Function(String, {bool b})')), + unorderedEquals({'int', 'String', 'bool', 'b'})); + }); + + test('PrimaryType', () { + expect(queryUsedIdentifiers(Type('Map')), + unorderedEquals({'Map', 'String', 'int'})); + expect( + queryUsedIdentifiers(Type('dynamic')), unorderedEquals({'dynamic'})); + expect(queryUsedIdentifiers(Type('error')), unorderedEquals({'error'})); + expect(queryUsedIdentifiers(Type('Never')), unorderedEquals({'Never'})); + expect(queryUsedIdentifiers(Type('Null')), unorderedEquals({'Null'})); + expect(queryUsedIdentifiers(Type('void')), unorderedEquals({'void'})); + expect(queryUsedIdentifiers(Type('FutureOr')), + unorderedEquals({'FutureOr', 'int'})); + }); + + test('RecordType', () { + expect(queryUsedIdentifiers(Type('(int, {String s})')), + unorderedEquals({'int', 'String', 's'})); + }); + + test('TypeParameterType', () { + expect(queryUsedIdentifiers(Type('T')), unorderedEquals({'T'})); + expect( + queryUsedIdentifiers(Type('T&int')), unorderedEquals({'T', 'int'})); + }); + + test('UnknownType', () { + expect(queryUsedIdentifiers(Type('_')), isEmpty); + }); + }); + group('substitute:', () { test('FunctionType', () { expect(Type('int Function(int, {int i})').substitute({t: Type('String')}), From c65057eda0b6ac12f8a8c387a7990f44c807b7b2 Mon Sep 17 00:00:00 2001 From: asiva Date: Mon, 18 Nov 2024 18:33:17 +0000 Subject: [PATCH 8/8] [SDK] Remove build rule for dart_precompiled_runtime TEST=ci Change-Id: I2fa2de462a9170941ed9201ba14182d490de65cb Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/395683 Reviewed-by: Alexander Aprelev Commit-Queue: Siva Annamalai --- runtime/bin/BUILD.gn | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/runtime/bin/BUILD.gn b/runtime/bin/BUILD.gn index 22e3c619dec8..135eac8c9a43 100644 --- a/runtime/bin/BUILD.gn +++ b/runtime/bin/BUILD.gn @@ -903,23 +903,6 @@ dart_executable("dart") { } } -# This rule is here to ensure benchmark suites do not break, it can be -# removed once the benchmark suites are updated. -group("dart_precompiled_runtime") { - deps = [ - ":copy_dart_precompiled_runtime", - ":dartaotruntime", - ] -} - -copy("copy_dart_precompiled_runtime") { - visibility = [ ":dart_precompiled_runtime" ] - deps = [ ":dartaotruntime" ] - src_dir = get_label_info(":dartaotruntime", "root_out_dir") - sources = [ "$src_dir/dartaotruntime${executable_suffix}" ] - outputs = [ "$root_out_dir/dart_precompiled_runtime${executable_suffix}" ] -} - dart_executable("dartaotruntime") { extra_configs = [ "..:dart_aotruntime_config",