diff --git a/pkg/analysis_server/analyzer_use_new_elements.txt b/pkg/analysis_server/analyzer_use_new_elements.txt index 5d8eef369999..e9b92bc190dd 100644 --- a/pkg/analysis_server/analyzer_use_new_elements.txt +++ b/pkg/analysis_server/analyzer_use_new_elements.txt @@ -30,7 +30,6 @@ lib/src/search/type_hierarchy.dart lib/src/services/completion/dart/completion_manager.dart lib/src/services/completion/dart/declaration_helper.dart lib/src/services/completion/dart/identifier_helper.dart -lib/src/services/completion/dart/in_scope_completion_pass.dart lib/src/services/completion/dart/visibility_tracker.dart lib/src/services/correction/dart/import_library.dart lib/src/services/correction/dart/use_different_division_operator.dart diff --git a/pkg/analysis_server/lib/src/services/completion/dart/declaration_helper.dart b/pkg/analysis_server/lib/src/services/completion/dart/declaration_helper.dart index d3a22781c31b..1349f92cf94a 100644 --- a/pkg/analysis_server/lib/src/services/completion/dart/declaration_helper.dart +++ b/pkg/analysis_server/lib/src/services/completion/dart/declaration_helper.dart @@ -173,6 +173,11 @@ class DeclarationHelper { } } + /// Add suggestions for all constructors of [element]. + void addConstructorNamesForElement2({required InterfaceElement2 element}) { + addConstructorNamesForElement(element: element.asElement); + } + /// Add suggestions for all of the named constructors in the [type]. If /// [exclude] is not `null` it is the name of a constructor that should be /// omitted from the list, typically because suggesting it would result in an @@ -229,6 +234,11 @@ class DeclarationHelper { } } + /// Add suggestions for declarations through [prefixElement]. + void addDeclarationsThroughImportPrefix2(PrefixElement2 prefixElement) { + addDeclarationsThroughImportPrefix(prefixElement.asElement); + } + /// Add any fields that can be initialized in the initializer list of the /// given [constructor]. If a [fieldToInclude] is provided, then it should not /// be skipped because the cursor is inside that field's name. @@ -277,6 +287,19 @@ class DeclarationHelper { } } + /// Add any fields that can be initialized in the initializer list of the + /// given [constructor]. If a [fieldToInclude] is provided, then it should not + /// be skipped because the cursor is inside that field's name. + void addFieldsForInitializers2( + ConstructorDeclaration constructor, + FieldElement2? fieldToInclude, + ) { + addFieldsForInitializers( + constructor, + fieldToInclude == null ? null : fieldToInclude.asElement as FieldElement, + ); + } + /// Add suggestions for all of the top-level declarations that are exported /// from the [library] except for those whose name is in the set of /// [excludedNames]. @@ -288,6 +311,17 @@ class DeclarationHelper { } } + /// Add suggestions for all of the top-level declarations that are exported + /// from the [library] except for those whose name is in the set of + /// [excludedNames]. + void addFromLibrary2(LibraryElement2 library, Set excludedNames) { + for (var entry in library.exportNamespace.definedNames.entries) { + if (!excludedNames.contains(entry.key)) { + _addImportedElement(entry.value); + } + } + } + /// Adds suggestions for the getters defined by the [type], except for those /// whose names are in the set of [excludedGetters]. void addGetters({ @@ -457,6 +491,17 @@ class DeclarationHelper { } } + /// Add members from the given [ExtensionElement2]. + void addMembersFromExtensionElement2( + ExtensionElement2 extension, { + ImportData? importData, + }) { + addMembersFromExtensionElement( + extension.asElement as ExtensionElement, + importData: importData, + ); + } + /// Adds suggestions for any constructors that are visible within the not yet /// imported [library]. void addNotImportedConstructors(LibraryElement2 library) { @@ -599,6 +644,18 @@ class DeclarationHelper { } } + /// Add suggestions for all of the constructor in the [library] that could be + /// a redirection target for the [redirectingConstructor]. + void addPossibleRedirectionsInLibrary2( + ConstructorElement2 redirectingConstructor, + LibraryElement2 library, + ) { + addPossibleRedirectionsInLibrary( + redirectingConstructor.asElement, + library.asElement, + ); + } + /// Add any static members defined by the given [element]. void addStaticMembersOfElement(Element element) { if (element is TypeAliasElement) { @@ -638,6 +695,11 @@ class DeclarationHelper { } } + /// Add any static members defined by the given [element]. + void addStaticMembersOfElement2(Element2 element) { + addStaticMembersOfElement(element.asElement!); + } + /// Adds suggestions for any constructors that are declared within the /// [library]. void _addConstructors(LibraryElement library, ImportData importData) { diff --git a/pkg/analysis_server/lib/src/services/completion/dart/in_scope_completion_pass.dart b/pkg/analysis_server/lib/src/services/completion/dart/in_scope_completion_pass.dart index 3074717c86c5..283e10eda052 100644 --- a/pkg/analysis_server/lib/src/services/completion/dart/in_scope_completion_pass.dart +++ b/pkg/analysis_server/lib/src/services/completion/dart/in_scope_completion_pass.dart @@ -22,7 +22,6 @@ import 'package:analyzer/dart/ast/ast.dart'; 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/type.dart'; import 'package:analyzer/source/source_range.dart'; @@ -30,7 +29,6 @@ import 'package:analyzer/src/dart/ast/ast.dart'; import 'package:analyzer/src/dart/ast/extensions.dart'; import 'package:analyzer/src/dart/ast/token.dart'; import 'package:analyzer/src/utilities/extensions/ast.dart'; -import 'package:analyzer/src/utilities/extensions/element.dart'; import 'package:analyzer/src/utilities/extensions/flutter.dart'; /// A completion pass that will create candidate suggestions based on the @@ -309,11 +307,11 @@ class InScopeCompletionPass extends SimpleAstVisitor { var parameters = node.invokedFormalParameters; if (parameters != null) { var positionalParameterCount = 0; - var availableNamedParameters = []; + var availableNamedParameters = []; for (int i = 0; i < parameters.length; i++) { var parameter = parameters[i]; if (parameter.isNamed) { - if (!usedNames.contains(parameter.name)) { + if (!usedNames.contains(parameter.name3)) { availableNamedParameters.add(parameter); } } else { @@ -377,10 +375,10 @@ class InScopeCompletionPass extends SimpleAstVisitor { for (var parameter in availableNamedParameters) { var matcherScore = state.matcher.score(parameter.displayName); if (matcherScore != -1) { - var isWidget = isFlutterWidgetParameter(parameter.asElement2); + var isWidget = isFlutterWidgetParameter(parameter); collector.addSuggestion( NamedArgumentSuggestion( - parameter: parameter.asElement2, + parameter: parameter, appendColon: true, appendComma: appendComma, replacementLength: replacementLength, @@ -738,14 +736,14 @@ class InScopeCompletionPass extends SimpleAstVisitor { _forConstructorInitializer(node, null); } } else if (type == TokenType.EQ) { - var constructorElement = node.declaredElement; + var constructorElement = node.declaredFragment?.element; if (constructorElement == null) { return; } - var libraryElement = state.libraryElement.asElement; + var libraryElement = state.libraryElement; declarationHelper( mustBeConstant: constructorElement.isConst, - ).addPossibleRedirectionsInLibrary(constructorElement, libraryElement); + ).addPossibleRedirectionsInLibrary2(constructorElement, libraryElement); } } @@ -785,14 +783,14 @@ class InScopeCompletionPass extends SimpleAstVisitor { @override void visitConstructorName(ConstructorName node) { if (node.parent is ConstructorReference) { - var element = node.type.element; - if (element is InterfaceElement) { + var element = node.type.element2; + if (element is InterfaceElement2) { declarationHelper( preferNonInvocation: true, - ).addConstructorNamesForElement(element: element); + ).addConstructorNamesForElement2(element: element); declarationHelper( preferNonInvocation: true, - ).addStaticMembersOfElement(element); + ).addStaticMembersOfElement2(element); } } else { var type = node.type.type; @@ -846,10 +844,10 @@ class InScopeCompletionPass extends SimpleAstVisitor { return; } - var enumElement = enumDeclaration.declaredElement!; + var enumElement = enumDeclaration.declaredFragment!.element; declarationHelper( suggestUnnamedAsNew: true, - ).addConstructorNamesForElement(element: enumElement); + ).addConstructorNamesForElement2(element: enumElement); } @override @@ -1275,12 +1273,12 @@ class InScopeCompletionPass extends SimpleAstVisitor { constructor = constructor.parent; } if (constructor is ConstructorDeclaration) { - var declaredElement = node.declaredElement; - FieldElement? field; - if (declaredElement is FieldFormalParameterElement) { - field = declaredElement.field; + var declaredElement = node.declaredFragment?.element; + FieldElement2? field; + if (declaredElement is FieldFormalParameterElement2) { + field = declaredElement.field2; } - declarationHelper().addFieldsForInitializers(constructor, field); + declarationHelper().addFieldsForInitializers2(constructor, field); } } @@ -1664,29 +1662,29 @@ class InScopeCompletionPass extends SimpleAstVisitor { void visitImportPrefixReference(ImportPrefixReference node) { var parent = node.parent; if (parent is NamedType && offset <= parent.name2.offset) { - var element = node.element; + var element = node.element2; DartType type; collector.completionLocation = 'PropertyAccess_propertyName'; - if (element is FunctionTypedElement) { - if (element is PropertyAccessorElement && element.isGetter) { + if (element is FunctionTypedElement2) { + if (element is GetterElement) { type = element.type.returnType; } else { type = element.type; } - } else if (element is PrefixElement) { + } else if (element is PrefixElement2) { var isInstanceCreation = node.parent?.parent?.parent is InstanceCreationExpression; declarationHelper( excludeTypeNames: isInstanceCreation, mustBeType: !isInstanceCreation, mustBeNonVoid: isInstanceCreation, - ).addDeclarationsThroughImportPrefix(element); + ).addDeclarationsThroughImportPrefix2(element); return; - } else if (element is VariableElement) { + } else if (element is VariableElement2) { type = element.type; } else { - if (element is InterfaceElement || element is ExtensionElement) { - declarationHelper().addStaticMembersOfElement(element!); + if (element is InterfaceElement2 || element is ExtensionElement2) { + declarationHelper().addStaticMembersOfElement2(element!); } return; } @@ -1931,12 +1929,12 @@ class InScopeCompletionPass extends SimpleAstVisitor { if ((type == null || type is InvalidType || type.isDartCoreType) && target is Identifier && (!node.isCascaded || offset == operator.offset + 1)) { - var element = target.staticElement; - if (element is InterfaceElement || element is ExtensionTypeElement) { - declarationHelper().addStaticMembersOfElement(element!); + var element = target.element; + if (element is InterfaceElement2 || element is ExtensionTypeElement2) { + declarationHelper().addStaticMembersOfElement2(element!); } - if (element is PrefixElement) { - declarationHelper().addDeclarationsThroughImportPrefix(element); + if (element is PrefixElement2) { + declarationHelper().addDeclarationsThroughImportPrefix2(element); } } } @@ -2015,15 +2013,14 @@ class InScopeCompletionPass extends SimpleAstVisitor { for (int i = 0; i < parameters.length; i++) { var parameter = parameters[i]; if (parameter.isNamed) { - if (!usedNames.contains(parameter.name)) { + if (!usedNames.contains(parameter.name3)) { var matcherScore = state.matcher.score(parameter.displayName); if (matcherScore != -1) { - var isWidget = isFlutterWidgetParameter( - parameter.asElement2, - ); + var isWidget = isFlutterWidgetParameter(parameter); collector.addSuggestion( NamedArgumentSuggestion( - parameter: parameter.asElement2, + parameter: + parameter, matcherScore: matcherScore, appendColon: appendColon, appendComma: false, @@ -2052,7 +2049,7 @@ class InScopeCompletionPass extends SimpleAstVisitor { collector.completionLocation = 'ArgumentList_method_named'; } _forExpression(node, mustBeNonVoid: inArgumentList); - var parameterType = node.staticParameterElement?.type; + var parameterType = node.element2?.type; if (parameterType is FunctionType) { var includeTrailingComma = !node.isFollowedByComma; _addClosureSuggestion(parameterType, includeTrailingComma); @@ -2063,14 +2060,14 @@ class InScopeCompletionPass extends SimpleAstVisitor { @override void visitNamedType(NamedType node) { var importPrefix = node.importPrefix; - var prefixElement = importPrefix?.element; + var prefixElement = importPrefix?.element2; // `prefix.x^ print(0);` is recovered as `prefix.x print; (0);`. - if (prefixElement is PrefixElement) { + if (prefixElement is PrefixElement2) { if (node.parent case VariableDeclarationList variableList) { if (variableList.parent case VariableDeclarationStatement statement) { if (statement.semicolon.isSynthetic) { - declarationHelper().addDeclarationsThroughImportPrefix( + declarationHelper().addDeclarationsThroughImportPrefix2( prefixElement, ); return; @@ -2258,14 +2255,14 @@ class InScopeCompletionPass extends SimpleAstVisitor { if (element is PrefixElement2) { declarationHelper( mustBeAssignable: mustBeAssignable, - ).addDeclarationsThroughImportPrefix(element.asElement); + ).addDeclarationsThroughImportPrefix2(element); } else { declarationHelper( mustBeAssignable: mustBeAssignable, preferNonInvocation: element is InterfaceElement2 && - state.request.shouldSuggestTearOff(element), - ).addStaticMembersOfElement(element.asElement!); + state.request.shouldSuggestTearOff2(element), + ).addStaticMembersOfElement2(element); } } } @@ -2308,16 +2305,16 @@ class InScopeCompletionPass extends SimpleAstVisitor { if ((type == null || type is InvalidType || type.isDartCoreType) && target is Identifier && (!node.isCascaded || offset == operator.offset + 1)) { - var element = target.staticElement; - if (element is InterfaceElement || element is ExtensionTypeElement) { - declarationHelper().addStaticMembersOfElement(element!); + var element = target.element; + if (element is InterfaceElement2 || element is ExtensionTypeElement2) { + declarationHelper().addStaticMembersOfElement2(element!); } - if (element is PrefixElement) { - declarationHelper().addDeclarationsThroughImportPrefix(element); + if (element is PrefixElement2) { + declarationHelper().addDeclarationsThroughImportPrefix2(element); } } if (type == null && target is ExtensionOverride) { - declarationHelper().addMembersFromExtensionElement(target.element); + declarationHelper().addMembersFromExtensionElement2(target.element2); } } } @@ -2555,12 +2552,12 @@ class InScopeCompletionPass extends SimpleAstVisitor { collector.completionLocation = 'FormalParameterList_parameter'; if (type is NamedType) { if (type.importPrefix case var importPrefix?) { - var prefixElement = importPrefix.element; - if (prefixElement is PrefixElement) { + var prefixElement = importPrefix.element2; + if (prefixElement is PrefixElement2) { if (type.name2.coversOffset(offset)) { declarationHelper( mustBeType: true, - ).addDeclarationsThroughImportPrefix(prefixElement); + ).addDeclarationsThroughImportPrefix2(prefixElement); } } } @@ -2637,8 +2634,8 @@ class InScopeCompletionPass extends SimpleAstVisitor { offset <= node.argumentList.offset) { var container = constructor.parent; var superType = switch (container) { - ClassDeclaration() => container.declaredElement?.supertype, - EnumDeclaration() => container.declaredElement?.supertype, + ClassDeclaration() => container.declaredFragment?.supertype, + EnumDeclaration() => container.declaredFragment?.supertype, _ => null, }; if (superType != null) { @@ -3070,8 +3067,8 @@ class InScopeCompletionPass extends SimpleAstVisitor { } _suggestOverridesFor( element: switch (container) { - ClassDeclaration() => container.declaredElement, - MixinDeclaration() => container.declaredElement, + ClassDeclaration() => container.declaredFragment?.element, + MixinDeclaration() => container.declaredFragment?.element, _ => null, }, ); @@ -3090,7 +3087,7 @@ class InScopeCompletionPass extends SimpleAstVisitor { if (equals != null && offset >= equals.end) { collector.completionLocation = 'VariableDeclaration_initializer'; _forExpression(node, mustBeNonVoid: true); - var variableType = node.declaredElement?.type; + var variableType = node.declaredFragment?.element.type; if (variableType is FunctionType) { _addClosureSuggestion(variableType, false); } @@ -3279,7 +3276,7 @@ class InScopeCompletionPass extends SimpleAstVisitor { void _forClassMember(ClassDeclaration node) { keywordHelper.addClassMemberKeywords(); declarationHelper(mustBeType: true).addLexicalDeclarations(node); - _suggestOverridesFor(element: node.declaredElement); + _suggestOverridesFor(element: node.declaredFragment?.element); } /// Adds the suggestions that are appropriate when the selection is at the @@ -3314,7 +3311,7 @@ class InScopeCompletionPass extends SimpleAstVisitor { if (directive is! NamespaceDirective) { return; } - var library = directive.referencedLibrary?.asElement; + var library = directive.referencedLibrary; if (library == null) { return; } @@ -3330,7 +3327,7 @@ class InScopeCompletionPass extends SimpleAstVisitor { .toSet(); declarationHelper( preferNonInvocation: true, - ).addFromLibrary(library, excludedNames); + ).addFromLibrary2(library, excludedNames); } /// Adds the suggestions that are appropriate when the selection is at the @@ -3385,13 +3382,13 @@ class InScopeCompletionPass extends SimpleAstVisitor { ConstructorDeclaration constructor, ConstructorFieldInitializer? initializer, ) { - var element = initializer?.fieldName.staticElement; - FieldElement? field; - if (element is FieldElement) { + var element = initializer?.fieldName.element; + FieldElement2? field; + if (element is FieldElement2) { field = element; } keywordHelper.addConstructorInitializerKeywords(constructor, initializer); - declarationHelper().addFieldsForInitializers(constructor, field); + declarationHelper().addFieldsForInitializers2(constructor, field); } /// Adds the suggestions that are appropriate when the selection is at the @@ -3538,7 +3535,7 @@ class InScopeCompletionPass extends SimpleAstVisitor { void _forMixinMember(MixinDeclaration node) { keywordHelper.addMixinMemberKeywords(); declarationHelper(mustBeType: true).addLexicalDeclarations(node); - _suggestOverridesFor(element: node.declaredElement); + _suggestOverridesFor(element: node.declaredFragment?.element); } /// Adds the suggestions that are appropriate when the selection is in the @@ -3665,9 +3662,10 @@ class InScopeCompletionPass extends SimpleAstVisitor { ) { var container = constructor.parent; var thisType = switch (container) { - ClassDeclaration() => container.declaredElement?.thisType, - EnumDeclaration() => container.declaredElement?.thisType, - ExtensionTypeDeclaration() => container.declaredElement?.thisType, + ClassDeclaration() => container.declaredFragment?.element.thisType, + EnumDeclaration() => container.declaredFragment?.element.thisType, + ExtensionTypeDeclaration() => + container.declaredFragment?.element.thisType, _ => null, }; if (thisType != null) { @@ -3706,8 +3704,8 @@ class InScopeCompletionPass extends SimpleAstVisitor { if (node is NamedType) { if (node.importPrefix case var importPrefix?) { - var prefixElement = importPrefix.element; - if (prefixElement is PrefixElement) { + var prefixElement = importPrefix.element2; + if (prefixElement is PrefixElement2) { declarationHelper( mustBeExtensible: mustBeExtensible, mustBeImplementable: mustBeImplementable, @@ -3715,7 +3713,7 @@ class InScopeCompletionPass extends SimpleAstVisitor { mustBeNonVoid: mustBeNonVoid, excludedNodes: excludedNodes, excludeTypeNames: excludeTypeNames, - ).addDeclarationsThroughImportPrefix(prefixElement); + ).addDeclarationsThroughImportPrefix2(prefixElement); } return; } @@ -3890,7 +3888,7 @@ class InScopeCompletionPass extends SimpleAstVisitor { /// If the budget has been exceeded, then the results are marked as incomplete /// and no suggestions are added. void _suggestOverridesFor({ - required InterfaceElement? element, + required InterfaceElement2? element, bool skipAt = false, }) { if (state.budget.isEmpty) { @@ -3900,7 +3898,7 @@ class InScopeCompletionPass extends SimpleAstVisitor { } if (suggestOverrides && element != null) { overrideHelper.computeOverridesFor( - interfaceElement: element.asElement2, + interfaceElement: element, replacementRange: SourceRange(offset, 0), skipAt: skipAt, ); @@ -3981,8 +3979,8 @@ class InScopeCompletionPass extends SimpleAstVisitor { void _tryOverrideAnnotation(Token identifier, Declaration node) { var lexeme = identifier.lexeme; if (lexeme.isNotEmpty && 'override'.startsWith(lexeme)) { - var declaredElement = node.declaredElement; - if (declaredElement is InterfaceElement) { + var declaredElement = node.declaredFragment?.element; + if (declaredElement is InterfaceElement2) { _suggestOverridesFor(element: declaredElement, skipAt: true); } } @@ -4178,37 +4176,37 @@ extension on ClassMember { extension on ArgumentList { /// The element being invoked by the expression containing this argument list, /// or `null` if the element is not known. - Element? get invokedElement { + Element2? get invokedElement { switch (parent) { case Annotation invocation: - return invocation.element; + return invocation.element2; case EnumConstantArguments invocation: var grandParent = invocation.parent; if (grandParent is EnumConstantDeclaration) { - return grandParent.constructorElement; + return grandParent.constructorElement2; } case FunctionExpressionInvocation invocation: - var element = invocation.staticElement; + var element = invocation.element; if (element == null) { var function = invocation.function.unParenthesized; if (function is SimpleIdentifier) { - return function.staticElement; + return function.element; } } return element; case InstanceCreationExpression invocation: - return invocation.constructorName.staticElement; + return invocation.constructorName.element; case MethodInvocation invocation: - return invocation.methodName.staticElement; + return invocation.methodName.element; case SuperConstructorInvocation invocation: - return invocation.staticElement; + return invocation.element; case RedirectingConstructorInvocation invocation: - return invocation.staticElement; + return invocation.element; } return null; } - List? get invokedFormalParameters { + List? get invokedFormalParameters { var result = invokedElement?.getParameters(); if (result != null) { return result; @@ -4218,7 +4216,7 @@ extension on ArgumentList { case FunctionExpressionInvocation invocation: var functionType = invocation.function.staticType; if (functionType is FunctionType) { - return functionType.parameters; + return functionType.formalParameters; } } @@ -4300,7 +4298,7 @@ extension on CompilationUnit { } } -extension on Element? { +extension on Element2? { /// Returns the parameters associated with this element, or `null` if this /// element doesn't have any parameters associated with it. /// @@ -4308,16 +4306,16 @@ extension on Element? { /// the method / function's parameters. If this element is a variable and the /// variable's type is a function type, then return the parameters from the /// function type. - List? getParameters() { + List? getParameters() { var self = this; - if (self is PropertyAccessorElement && self.isGetter) { - return self.returnType.ifTypeOrNull()?.parameters; - } else if (self is ExecutableElement) { - return self.parameters; - } else if (self is VariableElement) { + if (self is GetterElement) { + return self.returnType.ifTypeOrNull()?.formalParameters; + } else if (self is ExecutableElement2) { + return self.formalParameters; + } else if (self is VariableElement2) { var type = self.type; if (type is FunctionType) { - return type.parameters; + return type.formalParameters; } } return null; diff --git a/pkg/analysis_server/lib/src/utilities/extensions/ast.dart b/pkg/analysis_server/lib/src/utilities/extensions/ast.dart index 0be97a95e404..d23f8e5c0044 100644 --- a/pkg/analysis_server/lib/src/utilities/extensions/ast.dart +++ b/pkg/analysis_server/lib/src/utilities/extensions/ast.dart @@ -280,6 +280,7 @@ extension DirectiveExtension on Directive { } } + /// If [referencedUri] is a [DirectiveUriWithSource], returns the [Source] /// from it. Source? get referencedSource { diff --git a/pkg/analysis_server/lib/src/utilities/extensions/completion_request.dart b/pkg/analysis_server/lib/src/utilities/extensions/completion_request.dart index bdec5776ce5d..452becac8541 100644 --- a/pkg/analysis_server/lib/src/utilities/extensions/completion_request.dart +++ b/pkg/analysis_server/lib/src/utilities/extensions/completion_request.dart @@ -38,4 +38,13 @@ extension DartCompletionRequestExtensions on DartCompletionRequest { contextType.returnType, ); } + + /// Return `true` if the constructor tear-offs feature is enabled, and the + /// context type is a function type that matches an instantiation of the + /// [element]. + /// + // TODO(scheglov): Validate that suggesting a tear-off instead of invocation + // is statistically a good choice. + bool shouldSuggestTearOff2(InterfaceElement2 element) => + shouldSuggestTearOff(element); } diff --git a/pkg/analyzer/lib/src/utilities/extensions/element.dart b/pkg/analyzer/lib/src/utilities/extensions/element.dart index 8c8c85c71ac1..bbdeae09bd75 100644 --- a/pkg/analyzer/lib/src/utilities/extensions/element.dart +++ b/pkg/analyzer/lib/src/utilities/extensions/element.dart @@ -81,6 +81,8 @@ extension Element2OrNullExtension on Element2? { return self; case ExecutableMember(): return self.declaration as Element; + case ExtensionElementImpl2(): + return self.firstFragment as Element; case FieldElementImpl2(): return self.firstFragment as Element; case FieldMember():