Index: analyzer/lib/src/generated/element_resolver.dart |
diff --git a/analyzer/lib/src/generated/element_resolver.dart b/analyzer/lib/src/generated/element_resolver.dart |
deleted file mode 100644 |
index b93931f940e6ffe92b5622d00da32b6335e92823..0000000000000000000000000000000000000000 |
--- a/analyzer/lib/src/generated/element_resolver.dart |
+++ /dev/null |
@@ -1,2812 +0,0 @@ |
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
-// for details. All rights reserved. Use of this source code is governed by a |
-// BSD-style license that can be found in the LICENSE file. |
- |
-library engine.resolver.element_resolver; |
- |
-import 'dart:collection'; |
- |
-import 'ast.dart'; |
-import 'element.dart'; |
-import 'engine.dart'; |
-import 'error.dart'; |
-import 'resolver.dart'; |
-import 'scanner.dart' as sc; |
-import 'utilities_dart.dart'; |
- |
-/** |
- * An object used by instances of [ResolverVisitor] to resolve references within |
- * the AST structure to the elements being referenced. The requirements for the |
- * element resolver are: |
- * |
- * 1. Every [SimpleIdentifier] should be resolved to the element to which it |
- * refers. Specifically: |
- * * An identifier within the declaration of that name should resolve to the |
- * element being declared. |
- * * An identifier denoting a prefix should resolve to the element |
- * representing the import that defines the prefix (an [ImportElement]). |
- * * An identifier denoting a variable should resolve to the element |
- * representing the variable (a [VariableElement]). |
- * * An identifier denoting a parameter should resolve to the element |
- * representing the parameter (a [ParameterElement]). |
- * * An identifier denoting a field should resolve to the element |
- * representing the getter or setter being invoked (a |
- * [PropertyAccessorElement]). |
- * * An identifier denoting the name of a method or function being invoked |
- * should resolve to the element representing the method or function (an |
- * [ExecutableElement]). |
- * * An identifier denoting a label should resolve to the element |
- * representing the label (a [LabelElement]). |
- * The identifiers within directives are exceptions to this rule and are |
- * covered below. |
- * 2. Every node containing a token representing an operator that can be |
- * overridden ( [BinaryExpression], [PrefixExpression], [PostfixExpression]) |
- * should resolve to the element representing the method invoked by that |
- * operator (a [MethodElement]). |
- * 3. Every [FunctionExpressionInvocation] should resolve to the element |
- * representing the function being invoked (a [FunctionElement]). This will |
- * be the same element as that to which the name is resolved if the function |
- * has a name, but is provided for those cases where an unnamed function is |
- * being invoked. |
- * 4. Every [LibraryDirective] and [PartOfDirective] should resolve to the |
- * element representing the library being specified by the directive (a |
- * [LibraryElement]) unless, in the case of a part-of directive, the |
- * specified library does not exist. |
- * 5. Every [ImportDirective] and [ExportDirective] should resolve to the |
- * element representing the library being specified by the directive unless |
- * the specified library does not exist (an [ImportElement] or |
- * [ExportElement]). |
- * 6. The identifier representing the prefix in an [ImportDirective] should |
- * resolve to the element representing the prefix (a [PrefixElement]). |
- * 7. The identifiers in the hide and show combinators in [ImportDirective]s |
- * and [ExportDirective]s should resolve to the elements that are being |
- * hidden or shown, respectively, unless those names are not defined in the |
- * specified library (or the specified library does not exist). |
- * 8. Every [PartDirective] should resolve to the element representing the |
- * compilation unit being specified by the string unless the specified |
- * compilation unit does not exist (a [CompilationUnitElement]). |
- * |
- * Note that AST nodes that would represent elements that are not defined are |
- * not resolved to anything. This includes such things as references to |
- * undeclared variables (which is an error) and names in hide and show |
- * combinators that are not defined in the imported library (which is not an |
- * error). |
- */ |
-class ElementResolver extends SimpleAstVisitor<Object> { |
- /** |
- * The resolver driving this participant. |
- */ |
- final ResolverVisitor _resolver; |
- |
- /** |
- * The element for the library containing the compilation unit being visited. |
- */ |
- LibraryElement _definingLibrary; |
- |
- /** |
- * A flag indicating whether we should generate hints. |
- */ |
- bool _enableHints = false; |
- |
- /** |
- * A flag indicating whether we should strictly follow the specification when |
- * generating warnings on "call" methods (fixes dartbug.com/21938). |
- */ |
- bool _enableStrictCallChecks = false; |
- |
- /** |
- * The type representing the type 'dynamic'. |
- */ |
- DartType _dynamicType; |
- |
- /** |
- * The type representing the type 'type'. |
- */ |
- DartType _typeType; |
- |
- /** |
- * A utility class for the resolver to answer the question of "what are my |
- * subtypes?". |
- */ |
- SubtypeManager _subtypeManager; |
- |
- /** |
- * The object keeping track of which elements have had their types promoted. |
- */ |
- TypePromotionManager _promoteManager; |
- |
- /** |
- * Initialize a newly created visitor to work for the given [_resolver] to |
- * resolve the nodes in a compilation unit. |
- */ |
- ElementResolver(this._resolver) { |
- this._definingLibrary = _resolver.definingLibrary; |
- AnalysisOptions options = _definingLibrary.context.analysisOptions; |
- _enableHints = options.hint; |
- _enableStrictCallChecks = options.enableStrictCallChecks; |
- _dynamicType = _resolver.typeProvider.dynamicType; |
- _typeType = _resolver.typeProvider.typeType; |
- _subtypeManager = new SubtypeManager(); |
- _promoteManager = _resolver.promoteManager; |
- } |
- |
- /** |
- * Return `true` iff the current enclosing function is a constant constructor |
- * declaration. |
- */ |
- bool get isInConstConstructor { |
- ExecutableElement function = _resolver.enclosingFunction; |
- if (function is ConstructorElement) { |
- return function.isConst; |
- } |
- return false; |
- } |
- |
- @override |
- Object visitAssignmentExpression(AssignmentExpression node) { |
- sc.Token operator = node.operator; |
- sc.TokenType operatorType = operator.type; |
- if (operatorType != sc.TokenType.EQ && |
- operatorType != sc.TokenType.QUESTION_QUESTION_EQ) { |
- operatorType = _operatorFromCompoundAssignment(operatorType); |
- Expression leftHandSide = node.leftHandSide; |
- if (leftHandSide != null) { |
- String methodName = operatorType.lexeme; |
- DartType staticType = _getStaticType(leftHandSide); |
- MethodElement staticMethod = |
- _lookUpMethod(leftHandSide, staticType, methodName); |
- node.staticElement = staticMethod; |
- DartType propagatedType = _getPropagatedType(leftHandSide); |
- MethodElement propagatedMethod = |
- _lookUpMethod(leftHandSide, propagatedType, methodName); |
- node.propagatedElement = propagatedMethod; |
- if (_shouldReportMissingMember(staticType, staticMethod)) { |
- _recordUndefinedToken(staticType.element, |
- StaticTypeWarningCode.UNDEFINED_METHOD, operator, [ |
- methodName, |
- staticType.displayName |
- ]); |
- } else if (_enableHints && |
- _shouldReportMissingMember(propagatedType, propagatedMethod) && |
- !_memberFoundInSubclass( |
- propagatedType.element, methodName, true, false)) { |
- _recordUndefinedToken(propagatedType.element, |
- HintCode.UNDEFINED_METHOD, operator, [ |
- methodName, |
- propagatedType.displayName |
- ]); |
- } |
- } |
- } |
- return null; |
- } |
- |
- @override |
- Object visitBinaryExpression(BinaryExpression node) { |
- sc.Token operator = node.operator; |
- if (operator.isUserDefinableOperator) { |
- _resolveBinaryExpression(node, operator.lexeme); |
- } else if (operator.type == sc.TokenType.BANG_EQ) { |
- _resolveBinaryExpression(node, sc.TokenType.EQ_EQ.lexeme); |
- } |
- return null; |
- } |
- |
- @override |
- Object visitBreakStatement(BreakStatement node) { |
- node.target = _lookupBreakOrContinueTarget(node, node.label, false); |
- return null; |
- } |
- |
- @override |
- Object visitClassDeclaration(ClassDeclaration node) { |
- setMetadata(node.element, node); |
- return null; |
- } |
- @override |
- Object visitClassTypeAlias(ClassTypeAlias node) { |
- setMetadata(node.element, node); |
- return null; |
- } |
- |
- @override |
- Object visitCommentReference(CommentReference node) { |
- Identifier identifier = node.identifier; |
- if (identifier is SimpleIdentifier) { |
- SimpleIdentifier simpleIdentifier = identifier; |
- Element element = _resolveSimpleIdentifier(simpleIdentifier); |
- if (element == null) { |
- // |
- // This might be a reference to an imported name that is missing the |
- // prefix. |
- // |
- element = _findImportWithoutPrefix(simpleIdentifier); |
- if (element is MultiplyDefinedElement) { |
- // TODO(brianwilkerson) Report this error? |
- element = null; |
- } |
- } |
- if (element == null) { |
- // TODO(brianwilkerson) Report this error? |
- // resolver.reportError( |
- // StaticWarningCode.UNDEFINED_IDENTIFIER, |
- // simpleIdentifier, |
- // simpleIdentifier.getName()); |
- } else { |
- if (element.library == null || element.library != _definingLibrary) { |
- // TODO(brianwilkerson) Report this error? |
- } |
- simpleIdentifier.staticElement = element; |
- if (node.newKeyword != null) { |
- if (element is ClassElement) { |
- ConstructorElement constructor = element.unnamedConstructor; |
- if (constructor == null) { |
- // TODO(brianwilkerson) Report this error. |
- } else { |
- simpleIdentifier.staticElement = constructor; |
- } |
- } else { |
- // TODO(brianwilkerson) Report this error. |
- } |
- } |
- } |
- } else if (identifier is PrefixedIdentifier) { |
- PrefixedIdentifier prefixedIdentifier = identifier; |
- SimpleIdentifier prefix = prefixedIdentifier.prefix; |
- SimpleIdentifier name = prefixedIdentifier.identifier; |
- Element element = _resolveSimpleIdentifier(prefix); |
- if (element == null) { |
-// resolver.reportError(StaticWarningCode.UNDEFINED_IDENTIFIER, prefix, prefix.getName()); |
- } else { |
- if (element is PrefixElement) { |
- prefix.staticElement = element; |
- // TODO(brianwilkerson) Report this error? |
- element = _resolver.nameScope.lookup(identifier, _definingLibrary); |
- name.staticElement = element; |
- return null; |
- } |
- LibraryElement library = element.library; |
- if (library == null) { |
- // TODO(brianwilkerson) We need to understand how the library could |
- // ever be null. |
- AnalysisEngine.instance.logger |
- .logError("Found element with null library: ${element.name}"); |
- } else if (library != _definingLibrary) { |
- // TODO(brianwilkerson) Report this error. |
- } |
- name.staticElement = element; |
- if (node.newKeyword == null) { |
- if (element is ClassElement) { |
- Element memberElement = |
- _lookupGetterOrMethod(element.type, name.name); |
- if (memberElement == null) { |
- memberElement = element.getNamedConstructor(name.name); |
- if (memberElement == null) { |
- memberElement = _lookUpSetter(prefix, element.type, name.name); |
- } |
- } |
- if (memberElement == null) { |
-// reportGetterOrSetterNotFound(prefixedIdentifier, name, element.getDisplayName()); |
- } else { |
- name.staticElement = memberElement; |
- } |
- } else { |
- // TODO(brianwilkerson) Report this error. |
- } |
- } else { |
- if (element is ClassElement) { |
- ConstructorElement constructor = |
- element.getNamedConstructor(name.name); |
- if (constructor == null) { |
- // TODO(brianwilkerson) Report this error. |
- } else { |
- name.staticElement = constructor; |
- } |
- } else { |
- // TODO(brianwilkerson) Report this error. |
- } |
- } |
- } |
- } |
- return null; |
- } |
- |
- @override |
- Object visitConstructorDeclaration(ConstructorDeclaration node) { |
- super.visitConstructorDeclaration(node); |
- ConstructorElement element = node.element; |
- if (element is ConstructorElementImpl) { |
- ConstructorElementImpl constructorElement = element; |
- ConstructorName redirectedNode = node.redirectedConstructor; |
- if (redirectedNode != null) { |
- // set redirected factory constructor |
- ConstructorElement redirectedElement = redirectedNode.staticElement; |
- constructorElement.redirectedConstructor = redirectedElement; |
- } else { |
- // set redirected generative constructor |
- for (ConstructorInitializer initializer in node.initializers) { |
- if (initializer is RedirectingConstructorInvocation) { |
- ConstructorElement redirectedElement = initializer.staticElement; |
- constructorElement.redirectedConstructor = redirectedElement; |
- } |
- } |
- } |
- setMetadata(constructorElement, node); |
- } |
- return null; |
- } |
- |
- @override |
- Object visitConstructorFieldInitializer(ConstructorFieldInitializer node) { |
- SimpleIdentifier fieldName = node.fieldName; |
- ClassElement enclosingClass = _resolver.enclosingClass; |
- FieldElement fieldElement = enclosingClass.getField(fieldName.name); |
- fieldName.staticElement = fieldElement; |
- return null; |
- } |
- |
- @override |
- Object visitConstructorName(ConstructorName node) { |
- DartType type = node.type.type; |
- if (type != null && type.isDynamic) { |
- return null; |
- } else if (type is! InterfaceType) { |
-// TODO(brianwilkerson) Report these errors. |
-// ASTNode parent = node.getParent(); |
-// if (parent instanceof InstanceCreationExpression) { |
-// if (((InstanceCreationExpression) parent).isConst()) { |
-// // CompileTimeErrorCode.CONST_WITH_NON_TYPE |
-// } else { |
-// // StaticWarningCode.NEW_WITH_NON_TYPE |
-// } |
-// } else { |
-// // This is part of a redirecting factory constructor; not sure which error code to use |
-// } |
- return null; |
- } |
- // look up ConstructorElement |
- ConstructorElement constructor; |
- SimpleIdentifier name = node.name; |
- InterfaceType interfaceType = type as InterfaceType; |
- if (name == null) { |
- constructor = interfaceType.lookUpConstructor(null, _definingLibrary); |
- } else { |
- constructor = |
- interfaceType.lookUpConstructor(name.name, _definingLibrary); |
- name.staticElement = constructor; |
- } |
- node.staticElement = constructor; |
- return null; |
- } |
- |
- @override |
- Object visitContinueStatement(ContinueStatement node) { |
- node.target = _lookupBreakOrContinueTarget(node, node.label, true); |
- return null; |
- } |
- |
- @override |
- Object visitDeclaredIdentifier(DeclaredIdentifier node) { |
- setMetadata(node.element, node); |
- return null; |
- } |
- |
- @override |
- Object visitEnumDeclaration(EnumDeclaration node) { |
- setMetadata(node.element, node); |
- return null; |
- } |
- |
- @override |
- Object visitExportDirective(ExportDirective node) { |
- ExportElement exportElement = node.element; |
- if (exportElement != null) { |
- // The element is null when the URI is invalid |
- // TODO(brianwilkerson) Figure out whether the element can ever be |
- // something other than an ExportElement |
- _resolveCombinators(exportElement.exportedLibrary, node.combinators); |
- setMetadata(exportElement, node); |
- } |
- return null; |
- } |
- |
- @override |
- Object visitFieldFormalParameter(FieldFormalParameter node) { |
- _setMetadataForParameter(node.element, node); |
- return super.visitFieldFormalParameter(node); |
- } |
- |
- @override |
- Object visitFunctionDeclaration(FunctionDeclaration node) { |
- setMetadata(node.element, node); |
- return null; |
- } |
- |
- @override |
- Object visitFunctionExpressionInvocation(FunctionExpressionInvocation node) { |
- // TODO(brianwilkerson) Can we ever resolve the function being invoked? |
- Expression expression = node.function; |
- if (expression is FunctionExpression) { |
- FunctionExpression functionExpression = expression; |
- ExecutableElement functionElement = functionExpression.element; |
- ArgumentList argumentList = node.argumentList; |
- List<ParameterElement> parameters = |
- _resolveArgumentsToFunction(false, argumentList, functionElement); |
- if (parameters != null) { |
- argumentList.correspondingStaticParameters = parameters; |
- } |
- } |
- return null; |
- } |
- |
- @override |
- Object visitFunctionTypeAlias(FunctionTypeAlias node) { |
- setMetadata(node.element, node); |
- return null; |
- } |
- |
- @override |
- Object visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) { |
- _setMetadataForParameter(node.element, node); |
- return null; |
- } |
- |
- @override |
- Object visitImportDirective(ImportDirective node) { |
- SimpleIdentifier prefixNode = node.prefix; |
- if (prefixNode != null) { |
- String prefixName = prefixNode.name; |
- for (PrefixElement prefixElement in _definingLibrary.prefixes) { |
- if (prefixElement.displayName == prefixName) { |
- prefixNode.staticElement = prefixElement; |
- break; |
- } |
- } |
- } |
- ImportElement importElement = node.element; |
- if (importElement != null) { |
- // The element is null when the URI is invalid |
- LibraryElement library = importElement.importedLibrary; |
- if (library != null) { |
- _resolveCombinators(library, node.combinators); |
- } |
- setMetadata(importElement, node); |
- } |
- return null; |
- } |
- |
- @override |
- Object visitIndexExpression(IndexExpression node) { |
- Expression target = node.realTarget; |
- DartType staticType = _getStaticType(target); |
- DartType propagatedType = _getPropagatedType(target); |
- String getterMethodName = sc.TokenType.INDEX.lexeme; |
- String setterMethodName = sc.TokenType.INDEX_EQ.lexeme; |
- bool isInGetterContext = node.inGetterContext(); |
- bool isInSetterContext = node.inSetterContext(); |
- if (isInGetterContext && isInSetterContext) { |
- // lookup setter |
- MethodElement setterStaticMethod = |
- _lookUpMethod(target, staticType, setterMethodName); |
- MethodElement setterPropagatedMethod = |
- _lookUpMethod(target, propagatedType, setterMethodName); |
- // set setter element |
- node.staticElement = setterStaticMethod; |
- node.propagatedElement = setterPropagatedMethod; |
- // generate undefined method warning |
- _checkForUndefinedIndexOperator(node, target, getterMethodName, |
- setterStaticMethod, setterPropagatedMethod, staticType, |
- propagatedType); |
- // lookup getter method |
- MethodElement getterStaticMethod = |
- _lookUpMethod(target, staticType, getterMethodName); |
- MethodElement getterPropagatedMethod = |
- _lookUpMethod(target, propagatedType, getterMethodName); |
- // set getter element |
- AuxiliaryElements auxiliaryElements = |
- new AuxiliaryElements(getterStaticMethod, getterPropagatedMethod); |
- node.auxiliaryElements = auxiliaryElements; |
- // generate undefined method warning |
- _checkForUndefinedIndexOperator(node, target, getterMethodName, |
- getterStaticMethod, getterPropagatedMethod, staticType, |
- propagatedType); |
- } else if (isInGetterContext) { |
- // lookup getter method |
- MethodElement staticMethod = |
- _lookUpMethod(target, staticType, getterMethodName); |
- MethodElement propagatedMethod = |
- _lookUpMethod(target, propagatedType, getterMethodName); |
- // set getter element |
- node.staticElement = staticMethod; |
- node.propagatedElement = propagatedMethod; |
- // generate undefined method warning |
- _checkForUndefinedIndexOperator(node, target, getterMethodName, |
- staticMethod, propagatedMethod, staticType, propagatedType); |
- } else if (isInSetterContext) { |
- // lookup setter method |
- MethodElement staticMethod = |
- _lookUpMethod(target, staticType, setterMethodName); |
- MethodElement propagatedMethod = |
- _lookUpMethod(target, propagatedType, setterMethodName); |
- // set setter element |
- node.staticElement = staticMethod; |
- node.propagatedElement = propagatedMethod; |
- // generate undefined method warning |
- _checkForUndefinedIndexOperator(node, target, setterMethodName, |
- staticMethod, propagatedMethod, staticType, propagatedType); |
- } |
- return null; |
- } |
- |
- @override |
- Object visitInstanceCreationExpression(InstanceCreationExpression node) { |
- ConstructorElement invokedConstructor = node.constructorName.staticElement; |
- node.staticElement = invokedConstructor; |
- ArgumentList argumentList = node.argumentList; |
- List<ParameterElement> parameters = _resolveArgumentsToFunction( |
- node.isConst, argumentList, invokedConstructor); |
- if (parameters != null) { |
- argumentList.correspondingStaticParameters = parameters; |
- } |
- return null; |
- } |
- |
- @override |
- Object visitLibraryDirective(LibraryDirective node) { |
- setMetadata(node.element, node); |
- return null; |
- } |
- |
- @override |
- Object visitMethodDeclaration(MethodDeclaration node) { |
- setMetadata(node.element, node); |
- return null; |
- } |
- |
- @override |
- Object visitMethodInvocation(MethodInvocation node) { |
- SimpleIdentifier methodName = node.methodName; |
- // |
- // Synthetic identifiers have been already reported during parsing. |
- // |
- if (methodName.isSynthetic) { |
- return null; |
- } |
- // |
- // We have a method invocation of one of two forms: 'e.m(a1, ..., an)' or |
- // 'm(a1, ..., an)'. The first step is to figure out which executable is |
- // being invoked, using both the static and the propagated type information. |
- // |
- Expression target = node.realTarget; |
- if (target is SuperExpression && !_isSuperInValidContext(target)) { |
- return null; |
- } |
- Element staticElement; |
- Element propagatedElement; |
- DartType staticType = null; |
- DartType propagatedType = null; |
- if (target == null) { |
- staticElement = _resolveInvokedElement(methodName); |
- propagatedElement = null; |
- } else if (methodName.name == FunctionElement.LOAD_LIBRARY_NAME && |
- _isDeferredPrefix(target)) { |
- if (node.operator.type == sc.TokenType.QUESTION_PERIOD) { |
- _resolver.reportErrorForNode( |
- CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT, target, |
- [(target as SimpleIdentifier).name]); |
- } |
- LibraryElement importedLibrary = _getImportedLibrary(target); |
- methodName.staticElement = importedLibrary.loadLibraryFunction; |
- return null; |
- } else { |
- staticType = _getStaticType(target); |
- propagatedType = _getPropagatedType(target); |
- // |
- // If this method invocation is of the form 'C.m' where 'C' is a class, |
- // then we don't call resolveInvokedElement(...) which walks up the class |
- // hierarchy, instead we just look for the member in the type only. This |
- // does not apply to conditional method invocation (i.e. 'C?.m(...)'). |
- // |
- bool isConditional = node.operator.type == sc.TokenType.QUESTION_PERIOD; |
- ClassElementImpl typeReference = getTypeReference(target, isConditional); |
- if (typeReference != null) { |
- staticElement = |
- propagatedElement = _resolveElement(typeReference, methodName); |
- } else { |
- staticElement = _resolveInvokedElementWithTarget( |
- target, staticType, methodName, isConditional); |
- propagatedElement = _resolveInvokedElementWithTarget( |
- target, propagatedType, methodName, isConditional); |
- } |
- } |
- staticElement = _convertSetterToGetter(staticElement); |
- propagatedElement = _convertSetterToGetter(propagatedElement); |
- // |
- // Record the results. |
- // |
- methodName.staticElement = staticElement; |
- methodName.propagatedElement = propagatedElement; |
- ArgumentList argumentList = node.argumentList; |
- if (staticElement != null) { |
- List<ParameterElement> parameters = |
- _computeCorrespondingParameters(argumentList, staticElement); |
- if (parameters != null) { |
- argumentList.correspondingStaticParameters = parameters; |
- } |
- } |
- if (propagatedElement != null) { |
- List<ParameterElement> parameters = |
- _computeCorrespondingParameters(argumentList, propagatedElement); |
- if (parameters != null) { |
- argumentList.correspondingPropagatedParameters = parameters; |
- } |
- } |
- // |
- // Then check for error conditions. |
- // |
- ErrorCode errorCode = _checkForInvocationError(target, true, staticElement); |
- bool generatedWithTypePropagation = false; |
- if (_enableHints && errorCode == null && staticElement == null) { |
- // The method lookup may have failed because there were multiple |
- // incompatible choices. In this case we don't want to generate a hint. |
- errorCode = _checkForInvocationError(target, false, propagatedElement); |
- if (identical(errorCode, StaticTypeWarningCode.UNDEFINED_METHOD)) { |
- ClassElement classElementContext = null; |
- if (target == null) { |
- classElementContext = _resolver.enclosingClass; |
- } else { |
- DartType type = _getBestType(target); |
- if (type != null) { |
- if (type.element is ClassElement) { |
- classElementContext = type.element as ClassElement; |
- } |
- } |
- } |
- if (classElementContext != null) { |
- _subtypeManager.ensureLibraryVisited(_definingLibrary); |
- HashSet<ClassElement> subtypeElements = |
- _subtypeManager.computeAllSubtypes(classElementContext); |
- for (ClassElement subtypeElement in subtypeElements) { |
- if (subtypeElement.getMethod(methodName.name) != null) { |
- errorCode = null; |
- } |
- } |
- } |
- } |
- generatedWithTypePropagation = true; |
- } |
- if (errorCode == null) { |
- return null; |
- } |
- if (identical( |
- errorCode, StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION) || |
- identical(errorCode, |
- CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT) || |
- identical(errorCode, StaticTypeWarningCode.UNDEFINED_FUNCTION)) { |
- _resolver.reportErrorForNode(errorCode, methodName, [methodName.name]); |
- } else if (identical(errorCode, StaticTypeWarningCode.UNDEFINED_METHOD)) { |
- String targetTypeName; |
- if (target == null) { |
- ClassElement enclosingClass = _resolver.enclosingClass; |
- targetTypeName = enclosingClass.displayName; |
- ErrorCode proxyErrorCode = (generatedWithTypePropagation |
- ? HintCode.UNDEFINED_METHOD |
- : StaticTypeWarningCode.UNDEFINED_METHOD); |
- _recordUndefinedNode(_resolver.enclosingClass, proxyErrorCode, |
- methodName, [methodName.name, targetTypeName]); |
- } else { |
- // ignore Function "call" |
- // (if we are about to create a hint using type propagation, |
- // then we can use type propagation here as well) |
- DartType targetType = null; |
- if (!generatedWithTypePropagation) { |
- targetType = _getStaticType(target); |
- } else { |
- // choose the best type |
- targetType = _getPropagatedType(target); |
- if (targetType == null) { |
- targetType = _getStaticType(target); |
- } |
- } |
- if (!_enableStrictCallChecks && |
- targetType != null && |
- targetType.isDartCoreFunction && |
- methodName.name == FunctionElement.CALL_METHOD_NAME) { |
- // TODO(brianwilkerson) Can we ever resolve the function being |
- // invoked? |
-// resolveArgumentsToParameters(node.getArgumentList(), invokedFunction); |
- return null; |
- } |
- targetTypeName = targetType == null ? null : targetType.displayName; |
- ErrorCode proxyErrorCode = (generatedWithTypePropagation |
- ? HintCode.UNDEFINED_METHOD |
- : StaticTypeWarningCode.UNDEFINED_METHOD); |
- _recordUndefinedNode(targetType.element, proxyErrorCode, methodName, [ |
- methodName.name, |
- targetTypeName |
- ]); |
- } |
- } else if (identical( |
- errorCode, StaticTypeWarningCode.UNDEFINED_SUPER_METHOD)) { |
- // Generate the type name. |
- // The error code will never be generated via type propagation |
- DartType targetType = _getStaticType(target); |
- if (targetType is InterfaceType && !targetType.isObject) { |
- targetType = (targetType as InterfaceType).superclass; |
- } |
- String targetTypeName = targetType == null ? null : targetType.name; |
- _resolver.reportErrorForNode(StaticTypeWarningCode.UNDEFINED_SUPER_METHOD, |
- methodName, [methodName.name, targetTypeName]); |
- } |
- return null; |
- } |
- |
- @override |
- Object visitPartDirective(PartDirective node) { |
- setMetadata(node.element, node); |
- return null; |
- } |
- |
- @override |
- Object visitPartOfDirective(PartOfDirective node) { |
- setMetadata(node.element, node); |
- return null; |
- } |
- |
- @override |
- Object visitPostfixExpression(PostfixExpression node) { |
- Expression operand = node.operand; |
- String methodName = _getPostfixOperator(node); |
- DartType staticType = _getStaticType(operand); |
- MethodElement staticMethod = _lookUpMethod(operand, staticType, methodName); |
- node.staticElement = staticMethod; |
- DartType propagatedType = _getPropagatedType(operand); |
- MethodElement propagatedMethod = |
- _lookUpMethod(operand, propagatedType, methodName); |
- node.propagatedElement = propagatedMethod; |
- if (_shouldReportMissingMember(staticType, staticMethod)) { |
- if (operand is SuperExpression) { |
- _recordUndefinedToken(staticType.element, |
- StaticTypeWarningCode.UNDEFINED_SUPER_OPERATOR, node.operator, [ |
- methodName, |
- staticType.displayName |
- ]); |
- } else { |
- _recordUndefinedToken(staticType.element, |
- StaticTypeWarningCode.UNDEFINED_OPERATOR, node.operator, [ |
- methodName, |
- staticType.displayName |
- ]); |
- } |
- } else if (_enableHints && |
- _shouldReportMissingMember(propagatedType, propagatedMethod) && |
- !_memberFoundInSubclass( |
- propagatedType.element, methodName, true, false)) { |
- _recordUndefinedToken(propagatedType.element, HintCode.UNDEFINED_OPERATOR, |
- node.operator, [methodName, propagatedType.displayName]); |
- } |
- return null; |
- } |
- |
- @override |
- Object visitPrefixedIdentifier(PrefixedIdentifier node) { |
- SimpleIdentifier prefix = node.prefix; |
- SimpleIdentifier identifier = node.identifier; |
- // |
- // First, check the "lib.loadLibrary" case |
- // |
- if (identifier.name == FunctionElement.LOAD_LIBRARY_NAME && |
- _isDeferredPrefix(prefix)) { |
- LibraryElement importedLibrary = _getImportedLibrary(prefix); |
- identifier.staticElement = importedLibrary.loadLibraryFunction; |
- return null; |
- } |
- // |
- // Check to see whether the prefix is really a prefix. |
- // |
- Element prefixElement = prefix.staticElement; |
- if (prefixElement is PrefixElement) { |
- Element element = _resolver.nameScope.lookup(node, _definingLibrary); |
- if (element == null && identifier.inSetterContext()) { |
- element = _resolver.nameScope.lookup( |
- new SyntheticIdentifier("${node.name}=", node), _definingLibrary); |
- } |
- if (element == null) { |
- if (identifier.inSetterContext()) { |
- _resolver.reportErrorForNode(StaticWarningCode.UNDEFINED_SETTER, |
- identifier, [identifier.name, prefixElement.name]); |
- } else if (node.parent is Annotation) { |
- Annotation annotation = node.parent as Annotation; |
- _resolver.reportErrorForNode( |
- CompileTimeErrorCode.INVALID_ANNOTATION, annotation); |
- return null; |
- } else { |
- _resolver.reportErrorForNode(StaticWarningCode.UNDEFINED_GETTER, |
- identifier, [identifier.name, prefixElement.name]); |
- } |
- return null; |
- } |
- if (element is PropertyAccessorElement && identifier.inSetterContext()) { |
- PropertyInducingElement variable = |
- (element as PropertyAccessorElement).variable; |
- if (variable != null) { |
- PropertyAccessorElement setter = variable.setter; |
- if (setter != null) { |
- element = setter; |
- } |
- } |
- } |
- // TODO(brianwilkerson) The prefix needs to be resolved to the element for |
- // the import that defines the prefix, not the prefix's element. |
- identifier.staticElement = element; |
- // Validate annotation element. |
- if (node.parent is Annotation) { |
- Annotation annotation = node.parent as Annotation; |
- _resolveAnnotationElement(annotation); |
- return null; |
- } |
- return null; |
- } |
- // May be annotation, resolve invocation of "const" constructor. |
- if (node.parent is Annotation) { |
- Annotation annotation = node.parent as Annotation; |
- _resolveAnnotationElement(annotation); |
- } |
- // |
- // Otherwise, the prefix is really an expression that happens to be a simple |
- // identifier and this is really equivalent to a property access node. |
- // |
- _resolvePropertyAccess(prefix, identifier, false); |
- return null; |
- } |
- |
- @override |
- Object visitPrefixExpression(PrefixExpression node) { |
- sc.Token operator = node.operator; |
- sc.TokenType operatorType = operator.type; |
- if (operatorType.isUserDefinableOperator || |
- operatorType == sc.TokenType.PLUS_PLUS || |
- operatorType == sc.TokenType.MINUS_MINUS) { |
- Expression operand = node.operand; |
- String methodName = _getPrefixOperator(node); |
- DartType staticType = _getStaticType(operand); |
- MethodElement staticMethod = |
- _lookUpMethod(operand, staticType, methodName); |
- node.staticElement = staticMethod; |
- DartType propagatedType = _getPropagatedType(operand); |
- MethodElement propagatedMethod = |
- _lookUpMethod(operand, propagatedType, methodName); |
- node.propagatedElement = propagatedMethod; |
- if (_shouldReportMissingMember(staticType, staticMethod)) { |
- if (operand is SuperExpression) { |
- _recordUndefinedToken(staticType.element, |
- StaticTypeWarningCode.UNDEFINED_SUPER_OPERATOR, operator, [ |
- methodName, |
- staticType.displayName |
- ]); |
- } else { |
- _recordUndefinedToken(staticType.element, |
- StaticTypeWarningCode.UNDEFINED_OPERATOR, operator, [ |
- methodName, |
- staticType.displayName |
- ]); |
- } |
- } else if (_enableHints && |
- _shouldReportMissingMember(propagatedType, propagatedMethod) && |
- !_memberFoundInSubclass( |
- propagatedType.element, methodName, true, false)) { |
- _recordUndefinedToken(propagatedType.element, |
- HintCode.UNDEFINED_OPERATOR, operator, [ |
- methodName, |
- propagatedType.displayName |
- ]); |
- } |
- } |
- return null; |
- } |
- |
- @override |
- Object visitPropertyAccess(PropertyAccess node) { |
- Expression target = node.realTarget; |
- if (target is SuperExpression && !_isSuperInValidContext(target)) { |
- return null; |
- } |
- SimpleIdentifier propertyName = node.propertyName; |
- _resolvePropertyAccess(target, propertyName, |
- node.operator.type == sc.TokenType.QUESTION_PERIOD); |
- return null; |
- } |
- |
- @override |
- Object visitRedirectingConstructorInvocation( |
- RedirectingConstructorInvocation node) { |
- ClassElement enclosingClass = _resolver.enclosingClass; |
- if (enclosingClass == null) { |
- // TODO(brianwilkerson) Report this error. |
- return null; |
- } |
- SimpleIdentifier name = node.constructorName; |
- ConstructorElement element; |
- if (name == null) { |
- element = enclosingClass.unnamedConstructor; |
- } else { |
- element = enclosingClass.getNamedConstructor(name.name); |
- } |
- if (element == null) { |
- // TODO(brianwilkerson) Report this error and decide what element to |
- // associate with the node. |
- return null; |
- } |
- if (name != null) { |
- name.staticElement = element; |
- } |
- node.staticElement = element; |
- ArgumentList argumentList = node.argumentList; |
- List<ParameterElement> parameters = |
- _resolveArgumentsToFunction(false, argumentList, element); |
- if (parameters != null) { |
- argumentList.correspondingStaticParameters = parameters; |
- } |
- return null; |
- } |
- |
- @override |
- Object visitSimpleFormalParameter(SimpleFormalParameter node) { |
- _setMetadataForParameter(node.element, node); |
- return null; |
- } |
- |
- @override |
- Object visitSimpleIdentifier(SimpleIdentifier node) { |
- // |
- // Synthetic identifiers have been already reported during parsing. |
- // |
- if (node.isSynthetic) { |
- return null; |
- } |
- // |
- // We ignore identifiers that have already been resolved, such as |
- // identifiers representing the name in a declaration. |
- // |
- if (node.staticElement != null) { |
- return null; |
- } |
- // |
- // The name dynamic denotes a Type object even though dynamic is not a |
- // class. |
- // |
- if (node.name == _dynamicType.name) { |
- node.staticElement = _dynamicType.element; |
- node.staticType = _typeType; |
- return null; |
- } |
- // |
- // Otherwise, the node should be resolved. |
- // |
- Element element = _resolveSimpleIdentifier(node); |
- ClassElement enclosingClass = _resolver.enclosingClass; |
- if (_isFactoryConstructorReturnType(node) && |
- !identical(element, enclosingClass)) { |
- _resolver.reportErrorForNode( |
- CompileTimeErrorCode.INVALID_FACTORY_NAME_NOT_A_CLASS, node); |
- } else if (_isConstructorReturnType(node) && |
- !identical(element, enclosingClass)) { |
- _resolver.reportErrorForNode( |
- CompileTimeErrorCode.INVALID_CONSTRUCTOR_NAME, node); |
- element = null; |
- } else if (element == null || |
- (element is PrefixElement && !_isValidAsPrefix(node))) { |
- // TODO(brianwilkerson) Recover from this error. |
- if (_isConstructorReturnType(node)) { |
- _resolver.reportErrorForNode( |
- CompileTimeErrorCode.INVALID_CONSTRUCTOR_NAME, node); |
- } else if (node.parent is Annotation) { |
- Annotation annotation = node.parent as Annotation; |
- _resolver.reportErrorForNode( |
- CompileTimeErrorCode.INVALID_ANNOTATION, annotation); |
- } else if (element is PrefixElement) { |
- _resolver.reportErrorForNode( |
- CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT, node, |
- [element.name]); |
- } else { |
- _recordUndefinedNode(_resolver.enclosingClass, |
- StaticWarningCode.UNDEFINED_IDENTIFIER, node, [node.name]); |
- } |
- } |
- node.staticElement = element; |
- if (node.inSetterContext() && |
- node.inGetterContext() && |
- enclosingClass != null) { |
- InterfaceType enclosingType = enclosingClass.type; |
- AuxiliaryElements auxiliaryElements = new AuxiliaryElements( |
- _lookUpGetter(null, enclosingType, node.name), null); |
- node.auxiliaryElements = auxiliaryElements; |
- } |
- // |
- // Validate annotation element. |
- // |
- if (node.parent is Annotation) { |
- Annotation annotation = node.parent as Annotation; |
- _resolveAnnotationElement(annotation); |
- } |
- return null; |
- } |
- |
- @override |
- Object visitSuperConstructorInvocation(SuperConstructorInvocation node) { |
- ClassElementImpl enclosingClass = _resolver.enclosingClass; |
- if (enclosingClass == null) { |
- // TODO(brianwilkerson) Report this error. |
- return null; |
- } |
- InterfaceType superType = enclosingClass.supertype; |
- if (superType == null) { |
- // TODO(brianwilkerson) Report this error. |
- return null; |
- } |
- SimpleIdentifier name = node.constructorName; |
- String superName = name != null ? name.name : null; |
- ConstructorElement element = |
- superType.lookUpConstructor(superName, _definingLibrary); |
- if (element == null || |
- (!enclosingClass.doesMixinLackConstructors && |
- !enclosingClass.isSuperConstructorAccessible(element))) { |
- if (name != null) { |
- _resolver.reportErrorForNode( |
- CompileTimeErrorCode.UNDEFINED_CONSTRUCTOR_IN_INITIALIZER, node, [ |
- superType.displayName, |
- name |
- ]); |
- } else { |
- _resolver.reportErrorForNode( |
- CompileTimeErrorCode.UNDEFINED_CONSTRUCTOR_IN_INITIALIZER_DEFAULT, |
- node, [superType.displayName]); |
- } |
- return null; |
- } else { |
- if (element.isFactory) { |
- _resolver.reportErrorForNode( |
- CompileTimeErrorCode.NON_GENERATIVE_CONSTRUCTOR, node, [element]); |
- } |
- } |
- if (name != null) { |
- name.staticElement = element; |
- } |
- node.staticElement = element; |
- ArgumentList argumentList = node.argumentList; |
- List<ParameterElement> parameters = _resolveArgumentsToFunction( |
- isInConstConstructor, argumentList, element); |
- if (parameters != null) { |
- argumentList.correspondingStaticParameters = parameters; |
- } |
- return null; |
- } |
- |
- @override |
- Object visitSuperExpression(SuperExpression node) { |
- if (!_isSuperInValidContext(node)) { |
- _resolver.reportErrorForNode( |
- CompileTimeErrorCode.SUPER_IN_INVALID_CONTEXT, node); |
- } |
- return super.visitSuperExpression(node); |
- } |
- |
- @override |
- Object visitTypeParameter(TypeParameter node) { |
- setMetadata(node.element, node); |
- return null; |
- } |
- |
- @override |
- Object visitVariableDeclaration(VariableDeclaration node) { |
- setMetadata(node.element, node); |
- return null; |
- } |
- |
- /** |
- * Given that we have found code to invoke the given [element], return the |
- * error code that should be reported, or `null` if no error should be |
- * reported. The [target] is the target of the invocation, or `null` if there |
- * was no target. The flag [useStaticContext] should be `true` if the |
- * invocation is in a static constant (does not have access to instance state. |
- */ |
- ErrorCode _checkForInvocationError( |
- Expression target, bool useStaticContext, Element element) { |
- // Prefix is not declared, instead "prefix.id" are declared. |
- if (element is PrefixElement) { |
- return CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT; |
- } |
- if (element is PropertyAccessorElement) { |
- // |
- // This is really a function expression invocation. |
- // |
- // TODO(brianwilkerson) Consider the possibility of re-writing the AST. |
- FunctionType getterType = element.type; |
- if (getterType != null) { |
- DartType returnType = getterType.returnType; |
- if (!_isExecutableType(returnType)) { |
- return StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION; |
- } |
- } |
- } else if (element is ExecutableElement) { |
- return null; |
- } else if (element is MultiplyDefinedElement) { |
- // The error has already been reported |
- return null; |
- } else if (element == null && target is SuperExpression) { |
- // TODO(jwren) We should split the UNDEFINED_METHOD into two error codes, |
- // this one, and a code that describes the situation where the method was |
- // found, but it was not accessible from the current library. |
- return StaticTypeWarningCode.UNDEFINED_SUPER_METHOD; |
- } else { |
- // |
- // This is really a function expression invocation. |
- // |
- // TODO(brianwilkerson) Consider the possibility of re-writing the AST. |
- if (element is PropertyInducingElement) { |
- PropertyAccessorElement getter = element.getter; |
- FunctionType getterType = getter.type; |
- if (getterType != null) { |
- DartType returnType = getterType.returnType; |
- if (!_isExecutableType(returnType)) { |
- return StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION; |
- } |
- } |
- } else if (element is VariableElement) { |
- DartType variableType = element.type; |
- if (!_isExecutableType(variableType)) { |
- return StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION; |
- } |
- } else { |
- if (target == null) { |
- ClassElement enclosingClass = _resolver.enclosingClass; |
- if (enclosingClass == null) { |
- return StaticTypeWarningCode.UNDEFINED_FUNCTION; |
- } else if (element == null) { |
- // Proxy-conditional warning, based on state of |
- // resolver.getEnclosingClass() |
- return StaticTypeWarningCode.UNDEFINED_METHOD; |
- } else { |
- return StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION; |
- } |
- } else { |
- DartType targetType; |
- if (useStaticContext) { |
- targetType = _getStaticType(target); |
- } else { |
- // Compute and use the propagated type, if it is null, then it may |
- // be the case that static type is some type, in which the static |
- // type should be used. |
- targetType = _getBestType(target); |
- } |
- if (targetType == null) { |
- return StaticTypeWarningCode.UNDEFINED_FUNCTION; |
- } else if (!targetType.isDynamic && !targetType.isBottom) { |
- // Proxy-conditional warning, based on state of |
- // targetType.getElement() |
- return StaticTypeWarningCode.UNDEFINED_METHOD; |
- } |
- } |
- } |
- } |
- return null; |
- } |
- |
- /** |
- * Check that the given index [expression] was resolved, otherwise a |
- * [StaticTypeWarningCode.UNDEFINED_OPERATOR] is generated. The [target] is |
- * the target of the expression. The [methodName] is the name of the operator |
- * associated with the context of using of the given index expression. |
- */ |
- bool _checkForUndefinedIndexOperator(IndexExpression expression, |
- Expression target, String methodName, MethodElement staticMethod, |
- MethodElement propagatedMethod, DartType staticType, |
- DartType propagatedType) { |
- bool shouldReportMissingMember_static = |
- _shouldReportMissingMember(staticType, staticMethod); |
- bool shouldReportMissingMember_propagated = |
- !shouldReportMissingMember_static && |
- _enableHints && |
- _shouldReportMissingMember(propagatedType, propagatedMethod) && |
- !_memberFoundInSubclass( |
- propagatedType.element, methodName, true, false); |
- if (shouldReportMissingMember_static || |
- shouldReportMissingMember_propagated) { |
- sc.Token leftBracket = expression.leftBracket; |
- sc.Token rightBracket = expression.rightBracket; |
- ErrorCode errorCode; |
- if (shouldReportMissingMember_static) { |
- if (target is SuperExpression) { |
- errorCode = StaticTypeWarningCode.UNDEFINED_SUPER_OPERATOR; |
- } else { |
- errorCode = StaticTypeWarningCode.UNDEFINED_OPERATOR; |
- } |
- } else { |
- errorCode = HintCode.UNDEFINED_OPERATOR; |
- } |
- DartType type = |
- shouldReportMissingMember_static ? staticType : propagatedType; |
- if (leftBracket == null || rightBracket == null) { |
- _recordUndefinedNode(type.element, errorCode, expression, [ |
- methodName, |
- type.displayName |
- ]); |
- } else { |
- int offset = leftBracket.offset; |
- int length = rightBracket.offset - offset + 1; |
- _recordUndefinedOffset(type.element, errorCode, offset, length, [ |
- methodName, |
- type.displayName |
- ]); |
- } |
- return true; |
- } |
- return false; |
- } |
- |
- /** |
- * Given an [argumentList] and the executable [element] that will be invoked |
- * using those arguments, compute the list of parameters that correspond to |
- * the list of arguments. Return the parameters that correspond to the |
- * arguments, or `null` if no correspondence could be computed. |
- */ |
- List<ParameterElement> _computeCorrespondingParameters( |
- ArgumentList argumentList, Element element) { |
- if (element is PropertyAccessorElement) { |
- // |
- // This is an invocation of the call method defined on the value returned |
- // by the getter. |
- // |
- FunctionType getterType = element.type; |
- if (getterType != null) { |
- DartType getterReturnType = getterType.returnType; |
- if (getterReturnType is InterfaceType) { |
- MethodElement callMethod = getterReturnType.lookUpMethod( |
- FunctionElement.CALL_METHOD_NAME, _definingLibrary); |
- if (callMethod != null) { |
- return _resolveArgumentsToFunction(false, argumentList, callMethod); |
- } |
- } else if (getterReturnType is FunctionType) { |
- List<ParameterElement> parameters = getterReturnType.parameters; |
- return _resolveArgumentsToParameters(false, argumentList, parameters); |
- } |
- } |
- } else if (element is ExecutableElement) { |
- return _resolveArgumentsToFunction(false, argumentList, element); |
- } else if (element is VariableElement) { |
- VariableElement variable = element; |
- DartType type = _promoteManager.getStaticType(variable); |
- if (type is FunctionType) { |
- FunctionType functionType = type; |
- List<ParameterElement> parameters = functionType.parameters; |
- return _resolveArgumentsToParameters(false, argumentList, parameters); |
- } else if (type is InterfaceType) { |
- // "call" invocation |
- MethodElement callMethod = type.lookUpMethod( |
- FunctionElement.CALL_METHOD_NAME, _definingLibrary); |
- if (callMethod != null) { |
- List<ParameterElement> parameters = callMethod.parameters; |
- return _resolveArgumentsToParameters(false, argumentList, parameters); |
- } |
- } |
- } |
- return null; |
- } |
- |
- /** |
- * If the given [element] is a setter, return the getter associated with it. |
- * Otherwise, return the element unchanged. |
- */ |
- Element _convertSetterToGetter(Element element) { |
- // TODO(brianwilkerson) Determine whether and why the element could ever be |
- // a setter. |
- if (element is PropertyAccessorElement) { |
- return element.variable.getter; |
- } |
- return element; |
- } |
- |
- /** |
- * Return `true` if the given [element] is not a proxy. See |
- * [ClassElement.isOrInheritsProxy]. |
- */ |
- bool _doesntHaveProxy(Element element) => |
- !(element is ClassElement && element.isOrInheritsProxy); |
- |
- /** |
- * Look for any declarations of the given [identifier] that are imported using |
- * a prefix. Return the element that was found, or `null` if the name is not |
- * imported using a prefix. |
- */ |
- Element _findImportWithoutPrefix(SimpleIdentifier identifier) { |
- Element element = null; |
- Scope nameScope = _resolver.nameScope; |
- for (ImportElement importElement in _definingLibrary.imports) { |
- PrefixElement prefixElement = importElement.prefix; |
- if (prefixElement != null) { |
- Identifier prefixedIdentifier = new SyntheticIdentifier( |
- "${prefixElement.name}.${identifier.name}", identifier); |
- Element importedElement = |
- nameScope.lookup(prefixedIdentifier, _definingLibrary); |
- if (importedElement != null) { |
- if (element == null) { |
- element = importedElement; |
- } else { |
- element = MultiplyDefinedElementImpl.fromElements( |
- _definingLibrary.context, element, importedElement); |
- } |
- } |
- } |
- } |
- return element; |
- } |
- |
- /** |
- * Return the best type of the given [expression] that is to be used for |
- * type analysis. |
- */ |
- DartType _getBestType(Expression expression) { |
- DartType bestType = _resolveTypeParameter(expression.bestType); |
- if (bestType is FunctionType) { |
- // |
- // All function types are subtypes of 'Function', which is itself a |
- // subclass of 'Object'. |
- // |
- bestType = _resolver.typeProvider.functionType; |
- } |
- return bestType; |
- } |
- |
- /** |
- * Assuming that the given [expression] is a prefix for a deferred import, |
- * return the library that is being imported. |
- */ |
- LibraryElement _getImportedLibrary(Expression expression) { |
- PrefixElement prefixElement = |
- (expression as SimpleIdentifier).staticElement as PrefixElement; |
- List<ImportElement> imports = |
- prefixElement.enclosingElement.getImportsWithPrefix(prefixElement); |
- return imports[0].importedLibrary; |
- } |
- |
- /** |
- * Return the name of the method invoked by the given postfix [expression]. |
- */ |
- String _getPostfixOperator(PostfixExpression expression) => |
- (expression.operator.type == sc.TokenType.PLUS_PLUS) |
- ? sc.TokenType.PLUS.lexeme |
- : sc.TokenType.MINUS.lexeme; |
- |
- /** |
- * Return the name of the method invoked by the given postfix [expression]. |
- */ |
- String _getPrefixOperator(PrefixExpression expression) { |
- sc.Token operator = expression.operator; |
- sc.TokenType operatorType = operator.type; |
- if (operatorType == sc.TokenType.PLUS_PLUS) { |
- return sc.TokenType.PLUS.lexeme; |
- } else if (operatorType == sc.TokenType.MINUS_MINUS) { |
- return sc.TokenType.MINUS.lexeme; |
- } else if (operatorType == sc.TokenType.MINUS) { |
- return "unary-"; |
- } else { |
- return operator.lexeme; |
- } |
- } |
- |
- /** |
- * Return the propagated type of the given [expression] that is to be used for |
- * type analysis. |
- */ |
- DartType _getPropagatedType(Expression expression) { |
- DartType propagatedType = _resolveTypeParameter(expression.propagatedType); |
- if (propagatedType is FunctionType) { |
- // |
- // All function types are subtypes of 'Function', which is itself a |
- // subclass of 'Object'. |
- // |
- propagatedType = _resolver.typeProvider.functionType; |
- } |
- return propagatedType; |
- } |
- |
- /** |
- * Return the static type of the given [expression] that is to be used for |
- * type analysis. |
- */ |
- DartType _getStaticType(Expression expression) { |
- if (expression is NullLiteral) { |
- return _resolver.typeProvider.bottomType; |
- } |
- DartType staticType = _resolveTypeParameter(expression.staticType); |
- if (staticType is FunctionType) { |
- // |
- // All function types are subtypes of 'Function', which is itself a |
- // subclass of 'Object'. |
- // |
- staticType = _resolver.typeProvider.functionType; |
- } |
- return staticType; |
- } |
- |
- /** |
- * Return `true` if the given [expression] is a prefix for a deferred import. |
- */ |
- bool _isDeferredPrefix(Expression expression) { |
- if (expression is! SimpleIdentifier) { |
- return false; |
- } |
- Element element = (expression as SimpleIdentifier).staticElement; |
- if (element is! PrefixElement) { |
- return false; |
- } |
- PrefixElement prefixElement = element as PrefixElement; |
- List<ImportElement> imports = |
- prefixElement.enclosingElement.getImportsWithPrefix(prefixElement); |
- if (imports.length != 1) { |
- return false; |
- } |
- return imports[0].isDeferred; |
- } |
- |
- /** |
- * Return `true` if the given [type] represents an object that could be |
- * invoked using the call operator '()'. |
- */ |
- bool _isExecutableType(DartType type) { |
- if (type.isDynamic || type is FunctionType) { |
- return true; |
- } else if (!_enableStrictCallChecks && |
- (type.isDartCoreFunction || type.isObject)) { |
- return true; |
- } else if (type is InterfaceType) { |
- ClassElement classElement = type.element; |
- // 16078 from Gilad: If the type is a Functor with the @proxy annotation, |
- // treat it as an executable type. |
- // example code: NonErrorResolverTest. |
- // test_invocationOfNonFunction_proxyOnFunctionClass() |
- if (classElement.isProxy && |
- type.isSubtypeOf(_resolver.typeProvider.functionType)) { |
- return true; |
- } |
- MethodElement methodElement = classElement.lookUpMethod( |
- FunctionElement.CALL_METHOD_NAME, _definingLibrary); |
- return methodElement != null; |
- } |
- return false; |
- } |
- |
- /** |
- * Return `true` if the given [element] is a static element. |
- */ |
- bool _isStatic(Element element) { |
- if (element is ExecutableElement) { |
- return element.isStatic; |
- } else if (element is PropertyInducingElement) { |
- return element.isStatic; |
- } |
- return false; |
- } |
- |
- /** |
- * Return `true` if the given [node] can validly be resolved to a prefix: |
- * * it is the prefix in an import directive, or |
- * * it is the prefix in a prefixed identifier. |
- */ |
- bool _isValidAsPrefix(SimpleIdentifier node) { |
- AstNode parent = node.parent; |
- if (parent is ImportDirective) { |
- return identical(parent.prefix, node); |
- } else if (parent is PrefixedIdentifier) { |
- return true; |
- } else if (parent is MethodInvocation) { |
- return identical(parent.target, node); |
- } |
- return false; |
- } |
- |
- /** |
- * Return the target of a break or continue statement, and update the static |
- * element of its label (if any). The [parentNode] is the AST node of the |
- * break or continue statement. The [labelNode] is the label contained in that |
- * statement (if any). The flag [isContinue] is `true` if the node being |
- * visited is a continue statement. |
- */ |
- AstNode _lookupBreakOrContinueTarget( |
- AstNode parentNode, SimpleIdentifier labelNode, bool isContinue) { |
- if (labelNode == null) { |
- return _resolver.implicitLabelScope.getTarget(isContinue); |
- } else { |
- LabelScope labelScope = _resolver.labelScope; |
- if (labelScope == null) { |
- // There are no labels in scope, so by definition the label is |
- // undefined. |
- _resolver.reportErrorForNode( |
- CompileTimeErrorCode.LABEL_UNDEFINED, labelNode, [labelNode.name]); |
- return null; |
- } |
- LabelScope definingScope = labelScope.lookup(labelNode.name); |
- if (definingScope == null) { |
- // No definition of the given label name could be found in any |
- // enclosing scope. |
- _resolver.reportErrorForNode( |
- CompileTimeErrorCode.LABEL_UNDEFINED, labelNode, [labelNode.name]); |
- return null; |
- } |
- // The target has been found. |
- labelNode.staticElement = definingScope.element; |
- ExecutableElement labelContainer = definingScope.element |
- .getAncestor((element) => element is ExecutableElement); |
- if (!identical(labelContainer, _resolver.enclosingFunction)) { |
- _resolver.reportErrorForNode(CompileTimeErrorCode.LABEL_IN_OUTER_SCOPE, |
- labelNode, [labelNode.name]); |
- } |
- return definingScope.node; |
- } |
- } |
- |
- /** |
- * Look up the getter with the given [getterName] in the given [type]. Return |
- * the element representing the getter that was found, or `null` if there is |
- * no getter with the given name. The [target] is the target of the |
- * invocation, or `null` if there is no target. |
- */ |
- PropertyAccessorElement _lookUpGetter( |
- Expression target, DartType type, String getterName) { |
- type = _resolveTypeParameter(type); |
- if (type is InterfaceType) { |
- InterfaceType interfaceType = type; |
- PropertyAccessorElement accessor; |
- if (target is SuperExpression) { |
- accessor = interfaceType.lookUpGetterInSuperclass( |
- getterName, _definingLibrary); |
- } else { |
- accessor = interfaceType.lookUpGetter(getterName, _definingLibrary); |
- } |
- if (accessor != null) { |
- return accessor; |
- } |
- return _lookUpGetterInInterfaces( |
- interfaceType, false, getterName, new HashSet<ClassElement>()); |
- } |
- return null; |
- } |
- |
- /** |
- * Look up the getter with the given [getterName] in the interfaces |
- * implemented by the given [targetType], either directly or indirectly. |
- * Return the element representing the getter that was found, or `null` if |
- * there is no getter with the given name. The flag [includeTargetType] should |
- * be `true` if the search should include the target type. The |
- * [visitedInterfaces] is a set containing all of the interfaces that have |
- * been examined, used to prevent infinite recursion and to optimize the |
- * search. |
- */ |
- PropertyAccessorElement _lookUpGetterInInterfaces(InterfaceType targetType, |
- bool includeTargetType, String getterName, |
- HashSet<ClassElement> visitedInterfaces) { |
- // TODO(brianwilkerson) This isn't correct. Section 8.1.1 of the |
- // specification (titled "Inheritance and Overriding" under "Interfaces") |
- // describes a much more complex scheme for finding the inherited member. |
- // We need to follow that scheme. The code below should cover the 80% case. |
- ClassElement targetClass = targetType.element; |
- if (visitedInterfaces.contains(targetClass)) { |
- return null; |
- } |
- visitedInterfaces.add(targetClass); |
- if (includeTargetType) { |
- PropertyAccessorElement getter = targetType.getGetter(getterName); |
- if (getter != null && getter.isAccessibleIn(_definingLibrary)) { |
- return getter; |
- } |
- } |
- for (InterfaceType interfaceType in targetType.interfaces) { |
- PropertyAccessorElement getter = _lookUpGetterInInterfaces( |
- interfaceType, true, getterName, visitedInterfaces); |
- if (getter != null) { |
- return getter; |
- } |
- } |
- for (InterfaceType mixinType in targetType.mixins.reversed) { |
- PropertyAccessorElement getter = _lookUpGetterInInterfaces( |
- mixinType, true, getterName, visitedInterfaces); |
- if (getter != null) { |
- return getter; |
- } |
- } |
- InterfaceType superclass = targetType.superclass; |
- if (superclass == null) { |
- return null; |
- } |
- return _lookUpGetterInInterfaces( |
- superclass, true, getterName, visitedInterfaces); |
- } |
- |
- /** |
- * Look up the method or getter with the given [memberName] in the given |
- * [type]. Return the element representing the method or getter that was |
- * found, or `null` if there is no method or getter with the given name. |
- */ |
- ExecutableElement _lookupGetterOrMethod(DartType type, String memberName) { |
- type = _resolveTypeParameter(type); |
- if (type is InterfaceType) { |
- InterfaceType interfaceType = type; |
- ExecutableElement member = |
- interfaceType.lookUpMethod(memberName, _definingLibrary); |
- if (member != null) { |
- return member; |
- } |
- member = interfaceType.lookUpGetter(memberName, _definingLibrary); |
- if (member != null) { |
- return member; |
- } |
- return _lookUpGetterOrMethodInInterfaces( |
- interfaceType, false, memberName, new HashSet<ClassElement>()); |
- } |
- return null; |
- } |
- |
- /** |
- * Look up the method or getter with the given [memberName] in the interfaces |
- * implemented by the given [targetType], either directly or indirectly. |
- * Return the element representing the method or getter that was found, or |
- * `null` if there is no method or getter with the given name. The flag |
- * [includeTargetType] should be `true` if the search should include the |
- * target type. The [visitedInterfaces] is a set containing all of the |
- * interfaces that have been examined, used to prevent infinite recursion and |
- * to optimize the search. |
- */ |
- ExecutableElement _lookUpGetterOrMethodInInterfaces(InterfaceType targetType, |
- bool includeTargetType, String memberName, |
- HashSet<ClassElement> visitedInterfaces) { |
- // TODO(brianwilkerson) This isn't correct. Section 8.1.1 of the |
- // specification (titled "Inheritance and Overriding" under "Interfaces") |
- // describes a much more complex scheme for finding the inherited member. |
- // We need to follow that scheme. The code below should cover the 80% case. |
- ClassElement targetClass = targetType.element; |
- if (visitedInterfaces.contains(targetClass)) { |
- return null; |
- } |
- visitedInterfaces.add(targetClass); |
- if (includeTargetType) { |
- ExecutableElement member = targetType.getMethod(memberName); |
- if (member != null) { |
- return member; |
- } |
- member = targetType.getGetter(memberName); |
- if (member != null) { |
- return member; |
- } |
- } |
- for (InterfaceType interfaceType in targetType.interfaces) { |
- ExecutableElement member = _lookUpGetterOrMethodInInterfaces( |
- interfaceType, true, memberName, visitedInterfaces); |
- if (member != null) { |
- return member; |
- } |
- } |
- for (InterfaceType mixinType in targetType.mixins.reversed) { |
- ExecutableElement member = _lookUpGetterOrMethodInInterfaces( |
- mixinType, true, memberName, visitedInterfaces); |
- if (member != null) { |
- return member; |
- } |
- } |
- InterfaceType superclass = targetType.superclass; |
- if (superclass == null) { |
- return null; |
- } |
- return _lookUpGetterOrMethodInInterfaces( |
- superclass, true, memberName, visitedInterfaces); |
- } |
- |
- /** |
- * Look up the method with the given [methodName] in the given [type]. Return |
- * the element representing the method that was found, or `null` if there is |
- * no method with the given name. The [target] is the target of the |
- * invocation, or `null` if there is no target. |
- */ |
- MethodElement _lookUpMethod( |
- Expression target, DartType type, String methodName) { |
- type = _resolveTypeParameter(type); |
- if (type is InterfaceType) { |
- InterfaceType interfaceType = type; |
- MethodElement method; |
- if (target is SuperExpression) { |
- method = interfaceType.lookUpMethodInSuperclass( |
- methodName, _definingLibrary); |
- } else { |
- method = interfaceType.lookUpMethod(methodName, _definingLibrary); |
- } |
- if (method != null) { |
- return method; |
- } |
- return _lookUpMethodInInterfaces( |
- interfaceType, false, methodName, new HashSet<ClassElement>()); |
- } |
- return null; |
- } |
- |
- /** |
- * Look up the method with the given [methodName] in the interfaces |
- * implemented by the given [targetType], either directly or indirectly. |
- * Return the element representing the method that was found, or `null` if |
- * there is no method with the given name. The flag [includeTargetType] should |
- * be `true` if the search should include the target type. The |
- * [visitedInterfaces] is a set containing all of the interfaces that have |
- * been examined, used to prevent infinite recursion and to optimize the |
- * search. |
- */ |
- MethodElement _lookUpMethodInInterfaces(InterfaceType targetType, |
- bool includeTargetType, String methodName, |
- HashSet<ClassElement> visitedInterfaces) { |
- // TODO(brianwilkerson) This isn't correct. Section 8.1.1 of the |
- // specification (titled "Inheritance and Overriding" under "Interfaces") |
- // describes a much more complex scheme for finding the inherited member. |
- // We need to follow that scheme. The code below should cover the 80% case. |
- ClassElement targetClass = targetType.element; |
- if (visitedInterfaces.contains(targetClass)) { |
- return null; |
- } |
- visitedInterfaces.add(targetClass); |
- if (includeTargetType) { |
- MethodElement method = targetType.getMethod(methodName); |
- if (method != null && method.isAccessibleIn(_definingLibrary)) { |
- return method; |
- } |
- } |
- for (InterfaceType interfaceType in targetType.interfaces) { |
- MethodElement method = _lookUpMethodInInterfaces( |
- interfaceType, true, methodName, visitedInterfaces); |
- if (method != null) { |
- return method; |
- } |
- } |
- for (InterfaceType mixinType in targetType.mixins.reversed) { |
- MethodElement method = _lookUpMethodInInterfaces( |
- mixinType, true, methodName, visitedInterfaces); |
- if (method != null) { |
- return method; |
- } |
- } |
- InterfaceType superclass = targetType.superclass; |
- if (superclass == null) { |
- return null; |
- } |
- return _lookUpMethodInInterfaces( |
- superclass, true, methodName, visitedInterfaces); |
- } |
- |
- /** |
- * Look up the setter with the given [setterName] in the given [type]. Return |
- * the element representing the setter that was found, or `null` if there is |
- * no setter with the given name. The [target] is the target of the |
- * invocation, or `null` if there is no target. |
- */ |
- PropertyAccessorElement _lookUpSetter( |
- Expression target, DartType type, String setterName) { |
- type = _resolveTypeParameter(type); |
- if (type is InterfaceType) { |
- InterfaceType interfaceType = type; |
- PropertyAccessorElement accessor; |
- if (target is SuperExpression) { |
- accessor = interfaceType.lookUpSetterInSuperclass( |
- setterName, _definingLibrary); |
- } else { |
- accessor = interfaceType.lookUpSetter(setterName, _definingLibrary); |
- } |
- if (accessor != null) { |
- return accessor; |
- } |
- return _lookUpSetterInInterfaces( |
- interfaceType, false, setterName, new HashSet<ClassElement>()); |
- } |
- return null; |
- } |
- |
- /** |
- * Look up the setter with the given [setterName] in the interfaces |
- * implemented by the given [targetType], either directly or indirectly. |
- * Return the element representing the setter that was found, or `null` if |
- * there is no setter with the given name. The [targetType] is the type in |
- * which the setter might be defined. The flag [includeTargetType] should be |
- * `true` if the search should include the target type. The |
- * [visitedInterfaces] is a set containing all of the interfaces that have |
- * been examined, used to prevent infinite recursion and to optimize the |
- * search. |
- */ |
- PropertyAccessorElement _lookUpSetterInInterfaces(InterfaceType targetType, |
- bool includeTargetType, String setterName, |
- HashSet<ClassElement> visitedInterfaces) { |
- // TODO(brianwilkerson) This isn't correct. Section 8.1.1 of the |
- // specification (titled "Inheritance and Overriding" under "Interfaces") |
- // describes a much more complex scheme for finding the inherited member. |
- // We need to follow that scheme. The code below should cover the 80% case. |
- ClassElement targetClass = targetType.element; |
- if (visitedInterfaces.contains(targetClass)) { |
- return null; |
- } |
- visitedInterfaces.add(targetClass); |
- if (includeTargetType) { |
- PropertyAccessorElement setter = targetType.getSetter(setterName); |
- if (setter != null && setter.isAccessibleIn(_definingLibrary)) { |
- return setter; |
- } |
- } |
- for (InterfaceType interfaceType in targetType.interfaces) { |
- PropertyAccessorElement setter = _lookUpSetterInInterfaces( |
- interfaceType, true, setterName, visitedInterfaces); |
- if (setter != null) { |
- return setter; |
- } |
- } |
- for (InterfaceType mixinType in targetType.mixins.reversed) { |
- PropertyAccessorElement setter = _lookUpSetterInInterfaces( |
- mixinType, true, setterName, visitedInterfaces); |
- if (setter != null) { |
- return setter; |
- } |
- } |
- InterfaceType superclass = targetType.superclass; |
- if (superclass == null) { |
- return null; |
- } |
- return _lookUpSetterInInterfaces( |
- superclass, true, setterName, visitedInterfaces); |
- } |
- |
- /** |
- * Given some class [element], this method uses [_subtypeManager] to find the |
- * set of all subtypes; the subtypes are then searched for a member (method, |
- * getter, or setter), that has the given [memberName]. The flag [asMethod] |
- * should be `true` if the methods should be searched for in the subtypes. The |
- * flag [asAccessor] should be `true` if the accessors (getters and setters) |
- * should be searched for in the subtypes. |
- */ |
- bool _memberFoundInSubclass( |
- Element element, String memberName, bool asMethod, bool asAccessor) { |
- if (element is ClassElement) { |
- _subtypeManager.ensureLibraryVisited(_definingLibrary); |
- HashSet<ClassElement> subtypeElements = |
- _subtypeManager.computeAllSubtypes(element); |
- for (ClassElement subtypeElement in subtypeElements) { |
- if (asMethod && subtypeElement.getMethod(memberName) != null) { |
- return true; |
- } else if (asAccessor && |
- (subtypeElement.getGetter(memberName) != null || |
- subtypeElement.getSetter(memberName) != null)) { |
- return true; |
- } |
- } |
- } |
- return false; |
- } |
- |
- /** |
- * Return the binary operator that is invoked by the given compound assignment |
- * [operator]. |
- */ |
- sc.TokenType _operatorFromCompoundAssignment(sc.TokenType operator) { |
- while (true) { |
- if (operator == sc.TokenType.AMPERSAND_EQ) { |
- return sc.TokenType.AMPERSAND; |
- } else if (operator == sc.TokenType.BAR_EQ) { |
- return sc.TokenType.BAR; |
- } else if (operator == sc.TokenType.CARET_EQ) { |
- return sc.TokenType.CARET; |
- } else if (operator == sc.TokenType.GT_GT_EQ) { |
- return sc.TokenType.GT_GT; |
- } else if (operator == sc.TokenType.LT_LT_EQ) { |
- return sc.TokenType.LT_LT; |
- } else if (operator == sc.TokenType.MINUS_EQ) { |
- return sc.TokenType.MINUS; |
- } else if (operator == sc.TokenType.PERCENT_EQ) { |
- return sc.TokenType.PERCENT; |
- } else if (operator == sc.TokenType.PLUS_EQ) { |
- return sc.TokenType.PLUS; |
- } else if (operator == sc.TokenType.SLASH_EQ) { |
- return sc.TokenType.SLASH; |
- } else if (operator == sc.TokenType.STAR_EQ) { |
- return sc.TokenType.STAR; |
- } else if (operator == sc.TokenType.TILDE_SLASH_EQ) { |
- return sc.TokenType.TILDE_SLASH; |
- } else { |
- // Internal error: Unmapped assignment operator. |
- AnalysisEngine.instance.logger.logError( |
- "Failed to map ${operator.lexeme} to it's corresponding operator"); |
- return operator; |
- } |
- break; |
- } |
- } |
- |
- /** |
- * Record that the given [node] is undefined, causing an error to be reported |
- * if appropriate. The [declaringElement] is the element inside which no |
- * declaration was found. If this element is a proxy, no error will be |
- * reported. If null, then an error will always be reported. The [errorCode] |
- * is the error code to report. The [arguments] are the arguments to the error |
- * message. |
- */ |
- void _recordUndefinedNode(Element declaringElement, ErrorCode errorCode, |
- AstNode node, List<Object> arguments) { |
- if (_doesntHaveProxy(declaringElement)) { |
- _resolver.reportErrorForNode(errorCode, node, arguments); |
- } |
- } |
- |
- /** |
- * Record that the given [offset]/[length] is undefined, causing an error to |
- * be reported if appropriate. The [declaringElement] is the element inside |
- * which no declaration was found. If this element is a proxy, no error will |
- * be reported. If null, then an error will always be reported. The |
- * [errorCode] is the error code to report. The [arguments] are arguments to |
- * the error message. |
- */ |
- void _recordUndefinedOffset(Element declaringElement, ErrorCode errorCode, |
- int offset, int length, List<Object> arguments) { |
- if (_doesntHaveProxy(declaringElement)) { |
- _resolver.reportErrorForOffset(errorCode, offset, length, arguments); |
- } |
- } |
- |
- /** |
- * Record that the given [token] is undefined, causing an error to be reported |
- * if appropriate. The [declaringElement] is the element inside which no |
- * declaration was found. If this element is a proxy, no error will be |
- * reported. If null, then an error will always be reported. The [errorCode] |
- * is the error code to report. The [arguments] are arguments to the error |
- * message. |
- */ |
- void _recordUndefinedToken(Element declaringElement, ErrorCode errorCode, |
- sc.Token token, List<Object> arguments) { |
- if (_doesntHaveProxy(declaringElement)) { |
- _resolver.reportErrorForToken(errorCode, token, arguments); |
- } |
- } |
- |
- void _resolveAnnotationConstructorInvocationArguments( |
- Annotation annotation, ConstructorElement constructor) { |
- ArgumentList argumentList = annotation.arguments; |
- // error will be reported in ConstantVerifier |
- if (argumentList == null) { |
- return; |
- } |
- // resolve arguments to parameters |
- List<ParameterElement> parameters = |
- _resolveArgumentsToFunction(true, argumentList, constructor); |
- if (parameters != null) { |
- argumentList.correspondingStaticParameters = parameters; |
- } |
- } |
- |
- /** |
- * Continues resolution of the given [annotation]. |
- */ |
- void _resolveAnnotationElement(Annotation annotation) { |
- SimpleIdentifier nameNode1; |
- SimpleIdentifier nameNode2; |
- { |
- Identifier annName = annotation.name; |
- if (annName is PrefixedIdentifier) { |
- PrefixedIdentifier prefixed = annName; |
- nameNode1 = prefixed.prefix; |
- nameNode2 = prefixed.identifier; |
- } else { |
- nameNode1 = annName as SimpleIdentifier; |
- nameNode2 = null; |
- } |
- } |
- SimpleIdentifier nameNode3 = annotation.constructorName; |
- ConstructorElement constructor = null; |
- // |
- // CONST or Class(args) |
- // |
- if (nameNode1 != null && nameNode2 == null && nameNode3 == null) { |
- Element element1 = nameNode1.staticElement; |
- // CONST |
- if (element1 is PropertyAccessorElement) { |
- _resolveAnnotationElementGetter(annotation, element1); |
- return; |
- } |
- // Class(args) |
- if (element1 is ClassElement) { |
- ClassElement classElement = element1; |
- constructor = new InterfaceTypeImpl(classElement).lookUpConstructor( |
- null, _definingLibrary); |
- } |
- } |
- // |
- // prefix.CONST or prefix.Class() or Class.CONST or Class.constructor(args) |
- // |
- if (nameNode1 != null && nameNode2 != null && nameNode3 == null) { |
- Element element1 = nameNode1.staticElement; |
- Element element2 = nameNode2.staticElement; |
- // Class.CONST - not resolved yet |
- if (element1 is ClassElement) { |
- ClassElement classElement = element1; |
- element2 = classElement.lookUpGetter(nameNode2.name, _definingLibrary); |
- } |
- // prefix.CONST or Class.CONST |
- if (element2 is PropertyAccessorElement) { |
- nameNode2.staticElement = element2; |
- annotation.element = element2; |
- _resolveAnnotationElementGetter(annotation, element2); |
- return; |
- } |
- // prefix.Class() |
- if (element2 is ClassElement) { |
- constructor = element2.unnamedConstructor; |
- } |
- // Class.constructor(args) |
- if (element1 is ClassElement) { |
- ClassElement classElement = element1; |
- constructor = new InterfaceTypeImpl(classElement).lookUpConstructor( |
- nameNode2.name, _definingLibrary); |
- nameNode2.staticElement = constructor; |
- } |
- } |
- // |
- // prefix.Class.CONST or prefix.Class.constructor(args) |
- // |
- if (nameNode1 != null && nameNode2 != null && nameNode3 != null) { |
- Element element2 = nameNode2.staticElement; |
- // element2 should be ClassElement |
- if (element2 is ClassElement) { |
- ClassElement classElement = element2; |
- String name3 = nameNode3.name; |
- // prefix.Class.CONST |
- PropertyAccessorElement getter = |
- classElement.lookUpGetter(name3, _definingLibrary); |
- if (getter != null) { |
- nameNode3.staticElement = getter; |
- annotation.element = element2; |
- _resolveAnnotationElementGetter(annotation, getter); |
- return; |
- } |
- // prefix.Class.constructor(args) |
- constructor = new InterfaceTypeImpl(classElement).lookUpConstructor( |
- name3, _definingLibrary); |
- nameNode3.staticElement = constructor; |
- } |
- } |
- // we need constructor |
- if (constructor == null) { |
- _resolver.reportErrorForNode( |
- CompileTimeErrorCode.INVALID_ANNOTATION, annotation); |
- return; |
- } |
- // record element |
- annotation.element = constructor; |
- // resolve arguments |
- _resolveAnnotationConstructorInvocationArguments(annotation, constructor); |
- } |
- |
- void _resolveAnnotationElementGetter( |
- Annotation annotation, PropertyAccessorElement accessorElement) { |
- // accessor should be synthetic |
- if (!accessorElement.isSynthetic) { |
- _resolver.reportErrorForNode( |
- CompileTimeErrorCode.INVALID_ANNOTATION, annotation); |
- return; |
- } |
- // variable should be constant |
- VariableElement variableElement = accessorElement.variable; |
- if (!variableElement.isConst) { |
- _resolver.reportErrorForNode( |
- CompileTimeErrorCode.INVALID_ANNOTATION, annotation); |
- } |
- // OK |
- return; |
- } |
- |
- /** |
- * Given an [argumentList] and the [executableElement] that will be invoked |
- * using those argument, compute the list of parameters that correspond to the |
- * list of arguments. An error will be reported if any of the arguments cannot |
- * be matched to a parameter. The flag [reportError] should be `true` if a |
- * compile-time error should be reported; or `false` if a compile-time warning |
- * should be reported. Return the parameters that correspond to the arguments, |
- * or `null` if no correspondence could be computed. |
- */ |
- List<ParameterElement> _resolveArgumentsToFunction(bool reportError, |
- ArgumentList argumentList, ExecutableElement executableElement) { |
- if (executableElement == null) { |
- return null; |
- } |
- List<ParameterElement> parameters = executableElement.parameters; |
- return _resolveArgumentsToParameters(reportError, argumentList, parameters); |
- } |
- |
- /** |
- * Given an [argumentList] and the [parameters] related to the element that |
- * will be invoked using those arguments, compute the list of parameters that |
- * correspond to the list of arguments. An error will be reported if any of |
- * the arguments cannot be matched to a parameter. The flag [reportError] |
- * should be `true` if a compile-time error should be reported; or `false` if |
- * a compile-time warning should be reported. Return the parameters that |
- * correspond to the arguments. |
- */ |
- List<ParameterElement> _resolveArgumentsToParameters(bool reportError, |
- ArgumentList argumentList, List<ParameterElement> parameters) { |
- List<ParameterElement> requiredParameters = new List<ParameterElement>(); |
- List<ParameterElement> positionalParameters = new List<ParameterElement>(); |
- HashMap<String, ParameterElement> namedParameters = |
- new HashMap<String, ParameterElement>(); |
- for (ParameterElement parameter in parameters) { |
- ParameterKind kind = parameter.parameterKind; |
- if (kind == ParameterKind.REQUIRED) { |
- requiredParameters.add(parameter); |
- } else if (kind == ParameterKind.POSITIONAL) { |
- positionalParameters.add(parameter); |
- } else { |
- namedParameters[parameter.name] = parameter; |
- } |
- } |
- List<ParameterElement> unnamedParameters = |
- new List<ParameterElement>.from(requiredParameters); |
- unnamedParameters.addAll(positionalParameters); |
- int unnamedParameterCount = unnamedParameters.length; |
- int unnamedIndex = 0; |
- NodeList<Expression> arguments = argumentList.arguments; |
- int argumentCount = arguments.length; |
- List<ParameterElement> resolvedParameters = |
- new List<ParameterElement>(argumentCount); |
- int positionalArgumentCount = 0; |
- HashSet<String> usedNames = new HashSet<String>(); |
- bool noBlankArguments = true; |
- for (int i = 0; i < argumentCount; i++) { |
- Expression argument = arguments[i]; |
- if (argument is NamedExpression) { |
- SimpleIdentifier nameNode = argument.name.label; |
- String name = nameNode.name; |
- ParameterElement element = namedParameters[name]; |
- if (element == null) { |
- ErrorCode errorCode = (reportError |
- ? CompileTimeErrorCode.UNDEFINED_NAMED_PARAMETER |
- : StaticWarningCode.UNDEFINED_NAMED_PARAMETER); |
- _resolver.reportErrorForNode(errorCode, nameNode, [name]); |
- } else { |
- resolvedParameters[i] = element; |
- nameNode.staticElement = element; |
- } |
- if (!usedNames.add(name)) { |
- _resolver.reportErrorForNode( |
- CompileTimeErrorCode.DUPLICATE_NAMED_ARGUMENT, nameNode, [name]); |
- } |
- } else { |
- if (argument is SimpleIdentifier && argument.name.isEmpty) { |
- noBlankArguments = false; |
- } |
- positionalArgumentCount++; |
- if (unnamedIndex < unnamedParameterCount) { |
- resolvedParameters[i] = unnamedParameters[unnamedIndex++]; |
- } |
- } |
- } |
- if (positionalArgumentCount < requiredParameters.length && |
- noBlankArguments) { |
- ErrorCode errorCode = (reportError |
- ? CompileTimeErrorCode.NOT_ENOUGH_REQUIRED_ARGUMENTS |
- : StaticWarningCode.NOT_ENOUGH_REQUIRED_ARGUMENTS); |
- _resolver.reportErrorForNode(errorCode, argumentList, [ |
- requiredParameters.length, |
- positionalArgumentCount |
- ]); |
- } else if (positionalArgumentCount > unnamedParameterCount && |
- noBlankArguments) { |
- ErrorCode errorCode = (reportError |
- ? CompileTimeErrorCode.EXTRA_POSITIONAL_ARGUMENTS |
- : StaticWarningCode.EXTRA_POSITIONAL_ARGUMENTS); |
- _resolver.reportErrorForNode(errorCode, argumentList, [ |
- unnamedParameterCount, |
- positionalArgumentCount |
- ]); |
- } |
- return resolvedParameters; |
- } |
- |
- void _resolveBinaryExpression(BinaryExpression node, String methodName) { |
- Expression leftOperand = node.leftOperand; |
- if (leftOperand != null) { |
- DartType staticType = _getStaticType(leftOperand); |
- MethodElement staticMethod = |
- _lookUpMethod(leftOperand, staticType, methodName); |
- node.staticElement = staticMethod; |
- DartType propagatedType = _getPropagatedType(leftOperand); |
- MethodElement propagatedMethod = |
- _lookUpMethod(leftOperand, propagatedType, methodName); |
- node.propagatedElement = propagatedMethod; |
- if (_shouldReportMissingMember(staticType, staticMethod)) { |
- if (leftOperand is SuperExpression) { |
- _recordUndefinedToken(staticType.element, |
- StaticTypeWarningCode.UNDEFINED_SUPER_OPERATOR, node.operator, [ |
- methodName, |
- staticType.displayName |
- ]); |
- } else { |
- _recordUndefinedToken(staticType.element, |
- StaticTypeWarningCode.UNDEFINED_OPERATOR, node.operator, [ |
- methodName, |
- staticType.displayName |
- ]); |
- } |
- } else if (_enableHints && |
- _shouldReportMissingMember(propagatedType, propagatedMethod) && |
- !_memberFoundInSubclass( |
- propagatedType.element, methodName, true, false)) { |
- _recordUndefinedToken(propagatedType.element, |
- HintCode.UNDEFINED_OPERATOR, node.operator, [ |
- methodName, |
- propagatedType.displayName |
- ]); |
- } |
- } |
- } |
- |
- /** |
- * Resolve the names in the given [combinators] in the scope of the given |
- * [library]. |
- */ |
- void _resolveCombinators( |
- LibraryElement library, NodeList<Combinator> combinators) { |
- if (library == null) { |
- // |
- // The library will be null if the directive containing the combinators |
- // has a URI that is not valid. |
- // |
- return; |
- } |
- Namespace namespace = |
- new NamespaceBuilder().createExportNamespaceForLibrary(library); |
- for (Combinator combinator in combinators) { |
- NodeList<SimpleIdentifier> names; |
- if (combinator is HideCombinator) { |
- names = combinator.hiddenNames; |
- } else { |
- names = (combinator as ShowCombinator).shownNames; |
- } |
- for (SimpleIdentifier name in names) { |
- String nameStr = name.name; |
- Element element = namespace.get(nameStr); |
- if (element == null) { |
- element = namespace.get("$nameStr="); |
- } |
- if (element != null) { |
- // Ensure that the name always resolves to a top-level variable |
- // rather than a getter or setter |
- if (element is PropertyAccessorElement) { |
- element = (element as PropertyAccessorElement).variable; |
- } |
- name.staticElement = element; |
- } |
- } |
- } |
- } |
- |
- /** |
- * Given that we are accessing a property of the given [classElement] with the |
- * given [propertyName], return the element that represents the property. |
- */ |
- Element _resolveElement( |
- ClassElementImpl classElement, SimpleIdentifier propertyName) { |
- String name = propertyName.name; |
- Element element = null; |
- if (propertyName.inSetterContext()) { |
- element = classElement.getSetter(name); |
- } |
- if (element == null) { |
- element = classElement.getGetter(name); |
- } |
- if (element == null) { |
- element = classElement.getMethod(name); |
- } |
- if (element != null && element.isAccessibleIn(_definingLibrary)) { |
- return element; |
- } |
- return null; |
- } |
- |
- /** |
- * Given an invocation of the form 'm(a1, ..., an)', resolve 'm' to the |
- * element being invoked. If the returned element is a method, then the method |
- * will be invoked. If the returned element is a getter, the getter will be |
- * invoked without arguments and the result of that invocation will then be |
- * invoked with the arguments. The [methodName] is the name of the method |
- * being invoked ('m'). |
- */ |
- Element _resolveInvokedElement(SimpleIdentifier methodName) { |
- // |
- // Look first in the lexical scope. |
- // |
- Element element = _resolver.nameScope.lookup(methodName, _definingLibrary); |
- if (element == null) { |
- // |
- // If it isn't defined in the lexical scope, and the invocation is within |
- // a class, then look in the inheritance scope. |
- // |
- ClassElement enclosingClass = _resolver.enclosingClass; |
- if (enclosingClass != null) { |
- InterfaceType enclosingType = enclosingClass.type; |
- element = _lookUpMethod(null, enclosingType, methodName.name); |
- if (element == null) { |
- // |
- // If there's no method, then it's possible that 'm' is a getter that |
- // returns a function. |
- // |
- element = _lookUpGetter(null, enclosingType, methodName.name); |
- } |
- } |
- } |
- // TODO(brianwilkerson) Report this error. |
- return element; |
- } |
- |
- /** |
- * Given an invocation of the form 'e.m(a1, ..., an)', resolve 'e.m' to the |
- * element being invoked. If the returned element is a method, then the method |
- * will be invoked. If the returned element is a getter, the getter will be |
- * invoked without arguments and the result of that invocation will then be |
- * invoked with the arguments. The [target] is the target of the invocation |
- * ('e'). The [targetType] is the type of the target. The [methodName] is th |
- * name of the method being invoked ('m'). [isConditional] indicates |
- * whether the invocatoin uses a '?.' operator. |
- */ |
- Element _resolveInvokedElementWithTarget(Expression target, |
- DartType targetType, SimpleIdentifier methodName, bool isConditional) { |
- if (targetType is InterfaceType) { |
- Element element = _lookUpMethod(target, targetType, methodName.name); |
- if (element == null) { |
- // |
- // If there's no method, then it's possible that 'm' is a getter that |
- // returns a function. |
- // |
- // TODO (collinsn): need to add union type support here too, in the |
- // style of [lookUpMethod]. |
- element = _lookUpGetter(target, targetType, methodName.name); |
- } |
- return element; |
- } else if (target is SimpleIdentifier) { |
- Element targetElement = target.staticElement; |
- if (targetElement is PrefixElement) { |
- if (isConditional) { |
- _resolver.reportErrorForNode( |
- CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT, |
- target, [target.name]); |
- } |
- // |
- // Look to see whether the name of the method is really part of a |
- // prefixed identifier for an imported top-level function or top-level |
- // getter that returns a function. |
- // |
- String name = "${target.name}.$methodName"; |
- Identifier functionName = new SyntheticIdentifier(name, methodName); |
- Element element = |
- _resolver.nameScope.lookup(functionName, _definingLibrary); |
- if (element != null) { |
- // TODO(brianwilkerson) This isn't a method invocation, it's a |
- // function invocation where the function name is a prefixed |
- // identifier. Consider re-writing the AST. |
- return element; |
- } |
- } |
- } |
- // TODO(brianwilkerson) Report this error. |
- return null; |
- } |
- |
- /** |
- * Given that we are accessing a property of the given [targetType] with the |
- * given [propertyName], return the element that represents the property. The |
- * [target] is the target of the invocation ('e'). |
- */ |
- ExecutableElement _resolveProperty( |
- Expression target, DartType targetType, SimpleIdentifier propertyName) { |
- ExecutableElement memberElement = null; |
- if (propertyName.inSetterContext()) { |
- memberElement = _lookUpSetter(target, targetType, propertyName.name); |
- } |
- if (memberElement == null) { |
- memberElement = _lookUpGetter(target, targetType, propertyName.name); |
- } |
- if (memberElement == null) { |
- memberElement = _lookUpMethod(target, targetType, propertyName.name); |
- } |
- return memberElement; |
- } |
- |
- void _resolvePropertyAccess( |
- Expression target, SimpleIdentifier propertyName, bool isConditional) { |
- DartType staticType = _getStaticType(target); |
- DartType propagatedType = _getPropagatedType(target); |
- Element staticElement = null; |
- Element propagatedElement = null; |
- // |
- // If this property access is of the form 'C.m' where 'C' is a class, |
- // then we don't call resolveProperty(...) which walks up the class |
- // hierarchy, instead we just look for the member in the type only. This |
- // does not apply to conditional property accesses (i.e. 'C?.m'). |
- // |
- ClassElementImpl typeReference = getTypeReference(target, isConditional); |
- if (typeReference != null) { |
- // TODO(brianwilkerson) Why are we setting the propagated element here? |
- // It looks wrong. |
- staticElement = |
- propagatedElement = _resolveElement(typeReference, propertyName); |
- } else { |
- staticElement = _resolveProperty(target, staticType, propertyName); |
- propagatedElement = |
- _resolveProperty(target, propagatedType, propertyName); |
- } |
- // May be part of annotation, record property element only if exists. |
- // Error was already reported in validateAnnotationElement(). |
- if (target.parent.parent is Annotation) { |
- if (staticElement != null) { |
- propertyName.staticElement = staticElement; |
- } |
- return; |
- } |
- propertyName.staticElement = staticElement; |
- propertyName.propagatedElement = propagatedElement; |
- bool shouldReportMissingMember_static = |
- _shouldReportMissingMember(staticType, staticElement); |
- bool shouldReportMissingMember_propagated = |
- !shouldReportMissingMember_static && |
- _enableHints && |
- _shouldReportMissingMember(propagatedType, propagatedElement) && |
- !_memberFoundInSubclass( |
- propagatedType.element, propertyName.name, false, true); |
- if (shouldReportMissingMember_static || |
- shouldReportMissingMember_propagated) { |
- DartType staticOrPropagatedType = |
- shouldReportMissingMember_static ? staticType : propagatedType; |
- Element staticOrPropagatedEnclosingElt = staticOrPropagatedType.element; |
- bool isStaticProperty = _isStatic(staticOrPropagatedEnclosingElt); |
- DartType displayType = staticOrPropagatedType != null |
- ? staticOrPropagatedType |
- : propagatedType != null ? propagatedType : staticType; |
- // Special getter cases. |
- if (propertyName.inGetterContext()) { |
- if (!isStaticProperty && |
- staticOrPropagatedEnclosingElt is ClassElement) { |
- ClassElement classElement = staticOrPropagatedEnclosingElt; |
- InterfaceType targetType = classElement.type; |
- if (!_enableStrictCallChecks && |
- targetType != null && |
- targetType.isDartCoreFunction && |
- propertyName.name == FunctionElement.CALL_METHOD_NAME) { |
- // TODO(brianwilkerson) Can we ever resolve the function being |
- // invoked? |
-// resolveArgumentsToParameters(node.getArgumentList(), invokedFunction); |
- return; |
- } else if (classElement.isEnum && propertyName.name == "_name") { |
- _resolver.reportErrorForNode( |
- CompileTimeErrorCode.ACCESS_PRIVATE_ENUM_FIELD, propertyName, |
- [propertyName.name]); |
- return; |
- } |
- } |
- } |
- Element declaringElement = |
- staticType.isVoid ? null : staticOrPropagatedEnclosingElt; |
- if (propertyName.inSetterContext()) { |
- ErrorCode errorCode; |
- if (shouldReportMissingMember_static) { |
- if (target is SuperExpression) { |
- if (isStaticProperty && !staticType.isVoid) { |
- errorCode = StaticWarningCode.UNDEFINED_SUPER_SETTER; |
- } else { |
- errorCode = StaticTypeWarningCode.UNDEFINED_SUPER_SETTER; |
- } |
- } else { |
- if (isStaticProperty && !staticType.isVoid) { |
- errorCode = StaticWarningCode.UNDEFINED_SETTER; |
- } else { |
- errorCode = StaticTypeWarningCode.UNDEFINED_SETTER; |
- } |
- } |
- } else { |
- errorCode = HintCode.UNDEFINED_SETTER; |
- } |
- _recordUndefinedNode(declaringElement, errorCode, propertyName, [ |
- propertyName.name, |
- displayType.displayName |
- ]); |
- } else if (propertyName.inGetterContext()) { |
- ErrorCode errorCode; |
- if (shouldReportMissingMember_static) { |
- if (target is SuperExpression) { |
- if (isStaticProperty && !staticType.isVoid) { |
- errorCode = StaticWarningCode.UNDEFINED_SUPER_GETTER; |
- } else { |
- errorCode = StaticTypeWarningCode.UNDEFINED_SUPER_GETTER; |
- } |
- } else { |
- if (isStaticProperty && !staticType.isVoid) { |
- errorCode = StaticWarningCode.UNDEFINED_GETTER; |
- } else { |
- errorCode = StaticTypeWarningCode.UNDEFINED_GETTER; |
- } |
- } |
- } else { |
- errorCode = HintCode.UNDEFINED_GETTER; |
- } |
- _recordUndefinedNode(declaringElement, errorCode, propertyName, [ |
- propertyName.name, |
- displayType.displayName |
- ]); |
- } else { |
- _recordUndefinedNode(declaringElement, |
- StaticWarningCode.UNDEFINED_IDENTIFIER, propertyName, |
- [propertyName.name]); |
- } |
- } |
- } |
- |
- /** |
- * Resolve the given simple [identifier] if possible. Return the element to |
- * which it could be resolved, or `null` if it could not be resolved. This |
- * does not record the results of the resolution. |
- */ |
- Element _resolveSimpleIdentifier(SimpleIdentifier identifier) { |
- Element element = _resolver.nameScope.lookup(identifier, _definingLibrary); |
- if (element is PropertyAccessorElement && identifier.inSetterContext()) { |
- PropertyInducingElement variable = |
- (element as PropertyAccessorElement).variable; |
- if (variable != null) { |
- PropertyAccessorElement setter = variable.setter; |
- if (setter == null) { |
- // |
- // Check to see whether there might be a locally defined getter and |
- // an inherited setter. |
- // |
- ClassElement enclosingClass = _resolver.enclosingClass; |
- if (enclosingClass != null) { |
- setter = _lookUpSetter(null, enclosingClass.type, identifier.name); |
- } |
- } |
- if (setter != null) { |
- element = setter; |
- } |
- } |
- } else if (element == null && |
- (identifier.inSetterContext() || |
- identifier.parent is CommentReference)) { |
- element = _resolver.nameScope.lookup( |
- new SyntheticIdentifier("${identifier.name}=", identifier), |
- _definingLibrary); |
- } |
- ClassElement enclosingClass = _resolver.enclosingClass; |
- if (element == null && enclosingClass != null) { |
- InterfaceType enclosingType = enclosingClass.type; |
- if (element == null && |
- (identifier.inSetterContext() || |
- identifier.parent is CommentReference)) { |
- element = _lookUpSetter(null, enclosingType, identifier.name); |
- } |
- if (element == null && identifier.inGetterContext()) { |
- element = _lookUpGetter(null, enclosingType, identifier.name); |
- } |
- if (element == null) { |
- element = _lookUpMethod(null, enclosingType, identifier.name); |
- } |
- } |
- return element; |
- } |
- |
- /** |
- * If the given [type] is a type parameter, resolve it to the type that should |
- * be used when looking up members. Otherwise, return the original type. |
- */ |
- DartType _resolveTypeParameter(DartType type) { |
- if (type is TypeParameterType) { |
- DartType bound = type.element.bound; |
- if (bound == null) { |
- return _resolver.typeProvider.objectType; |
- } |
- return bound; |
- } |
- return type; |
- } |
- |
- /** |
- * Given a [node] that can have annotations associated with it and the |
- * [element] to which that node has been resolved, create the annotations in |
- * the element model representing the annotations on the node. |
- */ |
- void _setMetadataForParameter(Element element, NormalFormalParameter node) { |
- if (element is! ElementImpl) { |
- return; |
- } |
- List<ElementAnnotationImpl> annotationList = |
- new List<ElementAnnotationImpl>(); |
- _addAnnotations(annotationList, node.metadata); |
- if (!annotationList.isEmpty) { |
- (element as ElementImpl).metadata = annotationList; |
- } |
- } |
- |
- /** |
- * Return `true` if we should report an error as a result of looking up a |
- * [member] in the given [type] and not finding any member. |
- */ |
- bool _shouldReportMissingMember(DartType type, Element member) { |
- if (member != null || type == null || type.isDynamic || type.isBottom) { |
- return false; |
- } |
- return true; |
- } |
- |
- /** |
- * Checks whether the given [expression] is a reference to a class. If it is |
- * then the element representing the class is returned, otherwise `null` is |
- * returned. [isConditional] indicates whether [expression] is to the left |
- * of a '?.' opertator. |
- */ |
- static ClassElementImpl getTypeReference( |
- Expression expression, bool isConditional) { |
- if (!isConditional && expression is Identifier) { |
- Element staticElement = expression.staticElement; |
- if (staticElement is ClassElementImpl) { |
- return staticElement; |
- } |
- } |
- return null; |
- } |
- |
- /** |
- * Given a [node] that can have annotations associated with it and the |
- * [element] to which that node has been resolved, create the annotations in |
- * the element model representing the annotations on the node. |
- */ |
- static void setMetadata(Element element, AnnotatedNode node) { |
- if (element is! ElementImpl) { |
- return; |
- } |
- List<ElementAnnotationImpl> annotationList = <ElementAnnotationImpl>[]; |
- _addAnnotations(annotationList, node.metadata); |
- if (node is VariableDeclaration && node.parent is VariableDeclarationList) { |
- VariableDeclarationList list = node.parent as VariableDeclarationList; |
- _addAnnotations(annotationList, list.metadata); |
- if (list.parent is FieldDeclaration) { |
- FieldDeclaration fieldDeclaration = list.parent as FieldDeclaration; |
- _addAnnotations(annotationList, fieldDeclaration.metadata); |
- } else if (list.parent is TopLevelVariableDeclaration) { |
- TopLevelVariableDeclaration variableDeclaration = |
- list.parent as TopLevelVariableDeclaration; |
- _addAnnotations(annotationList, variableDeclaration.metadata); |
- } |
- } |
- if (!annotationList.isEmpty) { |
- (element as ElementImpl).metadata = annotationList; |
- } |
- } |
- |
- /** |
- * Generate annotation elements for each of the annotations in the |
- * [annotationList] and add them to the given list of [annotations]. |
- */ |
- static void _addAnnotations(List<ElementAnnotationImpl> annotationList, |
- NodeList<Annotation> annotations) { |
- int annotationCount = annotations.length; |
- for (int i = 0; i < annotationCount; i++) { |
- Annotation annotation = annotations[i]; |
- Element resolvedElement = annotation.element; |
- if (resolvedElement != null) { |
- ElementAnnotationImpl elementAnnotation = |
- new ElementAnnotationImpl(resolvedElement); |
- annotation.elementAnnotation = elementAnnotation; |
- annotationList.add(elementAnnotation); |
- } |
- } |
- } |
- |
- /** |
- * Return `true` if the given [identifier] is the return type of a constructor |
- * declaration. |
- */ |
- static bool _isConstructorReturnType(SimpleIdentifier identifier) { |
- AstNode parent = identifier.parent; |
- if (parent is ConstructorDeclaration) { |
- return identical(parent.returnType, identifier); |
- } |
- return false; |
- } |
- |
- /** |
- * Return `true` if the given [identifier] is the return type of a factory |
- * constructor. |
- */ |
- static bool _isFactoryConstructorReturnType(SimpleIdentifier identifier) { |
- AstNode parent = identifier.parent; |
- if (parent is ConstructorDeclaration) { |
- ConstructorDeclaration constructor = parent; |
- return identical(constructor.returnType, identifier) && |
- constructor.factoryKeyword != null; |
- } |
- return false; |
- } |
- |
- /** |
- * Return `true` if the given 'super' [expression] is used in a valid context. |
- */ |
- static bool _isSuperInValidContext(SuperExpression expression) { |
- for (AstNode node = expression; node != null; node = node.parent) { |
- if (node is CompilationUnit) { |
- return false; |
- } |
- if (node is ConstructorDeclaration) { |
- return node.factoryKeyword == null; |
- } |
- if (node is ConstructorFieldInitializer) { |
- return false; |
- } |
- if (node is MethodDeclaration) { |
- return !node.isStatic; |
- } |
- } |
- return false; |
- } |
-} |
- |
-/** |
- * An identifier that can be used to look up names in the lexical scope when |
- * there is no identifier in the AST structure. There is no identifier in the |
- * AST when the parser could not distinguish between a method invocation and an |
- * invocation of a top-level function imported with a prefix. |
- */ |
-class SyntheticIdentifier extends Identifier { |
- /** |
- * The name of the synthetic identifier. |
- */ |
- final String name; |
- |
- /** |
- * The identifier to be highlighted in case of an error |
- */ |
- final Identifier targetIdentifier; |
- |
- /** |
- * Initialize a newly created synthetic identifier to have the given [name] |
- * and [targetIdentifier]. |
- */ |
- SyntheticIdentifier(this.name, this.targetIdentifier); |
- |
- @override |
- sc.Token get beginToken => null; |
- |
- @override |
- Element get bestElement => null; |
- |
- @override |
- Iterable get childEntities { |
- // Should never be called, since a SyntheticIdentifier never appears in the |
- // AST--it is just used for lookup. |
- assert(false); |
- return new ChildEntities(); |
- } |
- |
- @override |
- sc.Token get endToken => null; |
- |
- @override |
- int get length => targetIdentifier.length; |
- |
- @override |
- int get offset => targetIdentifier.offset; |
- |
- @override |
- int get precedence => 16; |
- |
- @override |
- Element get propagatedElement => null; |
- |
- @override |
- Element get staticElement => null; |
- |
- @override |
- accept(AstVisitor visitor) => null; |
- |
- @override |
- void visitChildren(AstVisitor visitor) {} |
-} |