| // This code was auto-generated, is not intended to be edited, and is subject to |
| // significant change. Please see the README file for more information. |
| |
| library engine.resolver; |
| |
| import 'dart:collection'; |
| import 'dart:uri' show Uri; |
| import 'java_core.dart'; |
| import 'java_engine.dart'; |
| import 'instrumentation.dart'; |
| import 'source.dart'; |
| import 'error.dart'; |
| import 'scanner.dart' as sc; |
| import 'utilities_dart.dart'; |
| import 'ast.dart'; |
| import 'parser.dart' show Parser, ParserErrorCode; |
| import 'sdk.dart' show DartSdk; |
| import 'element.dart' hide HideCombinator, ShowCombinator; |
| import 'html.dart' as ht; |
| import 'engine.dart'; |
| import 'constant.dart'; |
| import 'element.dart' as __imp_combi show HideCombinator, ShowCombinator; |
| |
| /** |
| * Instances of the class {@code CompilationUnitBuilder} build an element model for a single |
| * compilation unit. |
| * @coverage dart.engine.resolver |
| */ |
| class CompilationUnitBuilder { |
| /** |
| * Initialize a newly created compilation unit element builder. |
| * @param analysisContext the analysis context in which the element model will be built |
| */ |
| CompilationUnitBuilder() : super() { |
| } |
| /** |
| * Build the compilation unit element for the given source. |
| * @param source the source describing the compilation unit |
| * @param unit the AST structure representing the compilation unit |
| * @return the compilation unit element that was built |
| * @throws AnalysisException if the analysis could not be performed |
| */ |
| CompilationUnitElementImpl buildCompilationUnit(Source source2, CompilationUnit unit) { |
| if (unit == null) { |
| return null; |
| } |
| ElementHolder holder = new ElementHolder(); |
| ElementBuilder builder = new ElementBuilder(holder); |
| unit.accept(builder); |
| CompilationUnitElementImpl element = new CompilationUnitElementImpl(source2.shortName); |
| element.accessors = holder.accessors; |
| element.functions = holder.functions; |
| element.source = source2; |
| element.typeAliases = holder.typeAliases; |
| element.types = holder.types; |
| element.topLevelVariables = holder.topLevelVariables; |
| unit.element = element; |
| return element; |
| } |
| } |
| /** |
| * Instances of the class {@code ElementBuilder} traverse an AST structure and build the element |
| * model representing the AST structure. |
| * @coverage dart.engine.resolver |
| */ |
| class ElementBuilder extends RecursiveASTVisitor<Object> { |
| /** |
| * The element holder associated with the element that is currently being built. |
| */ |
| ElementHolder _currentHolder; |
| /** |
| * A flag indicating whether a variable declaration is in the context of a field declaration. |
| */ |
| bool _inFieldContext = false; |
| /** |
| * A flag indicating whether a variable declaration is within the body of a method or function. |
| */ |
| bool _inFunction = false; |
| /** |
| * A flag indicating whether the class currently being visited can be used as a mixin. |
| */ |
| bool _isValidMixin = false; |
| /** |
| * Initialize a newly created element builder to build the elements for a compilation unit. |
| * @param initialHolder the element holder associated with the compilation unit being built |
| */ |
| ElementBuilder(ElementHolder initialHolder) { |
| _currentHolder = initialHolder; |
| } |
| Object visitBlock(Block node) { |
| bool wasInField = _inFieldContext; |
| _inFieldContext = false; |
| try { |
| node.visitChildren(this); |
| } finally { |
| _inFieldContext = wasInField; |
| } |
| return null; |
| } |
| Object visitCatchClause(CatchClause node) { |
| SimpleIdentifier exceptionParameter2 = node.exceptionParameter; |
| if (exceptionParameter2 != null) { |
| LocalVariableElementImpl exception = new LocalVariableElementImpl(exceptionParameter2); |
| _currentHolder.addLocalVariable(exception); |
| exceptionParameter2.element = exception; |
| SimpleIdentifier stackTraceParameter2 = node.stackTraceParameter; |
| if (stackTraceParameter2 != null) { |
| LocalVariableElementImpl stackTrace = new LocalVariableElementImpl(stackTraceParameter2); |
| _currentHolder.addLocalVariable(stackTrace); |
| stackTraceParameter2.element = stackTrace; |
| } |
| } |
| return super.visitCatchClause(node); |
| } |
| Object visitClassDeclaration(ClassDeclaration node) { |
| ElementHolder holder = new ElementHolder(); |
| _isValidMixin = true; |
| visitChildren(holder, node); |
| SimpleIdentifier className = node.name; |
| ClassElementImpl element = new ClassElementImpl(className); |
| List<TypeVariableElement> typeVariables2 = holder.typeVariables; |
| InterfaceTypeImpl interfaceType = new InterfaceTypeImpl.con1(element); |
| interfaceType.typeArguments = createTypeVariableTypes(typeVariables2); |
| element.type = interfaceType; |
| List<ConstructorElement> constructors2 = holder.constructors; |
| if (constructors2.length == 0) { |
| ConstructorElementImpl constructor = new ConstructorElementImpl(null); |
| constructor.synthetic = true; |
| FunctionTypeImpl type = new FunctionTypeImpl.con1(constructor); |
| type.returnType = interfaceType; |
| constructor.type = type; |
| constructors2 = <ConstructorElement> [constructor]; |
| } |
| element.abstract = node.abstractKeyword != null; |
| element.accessors = holder.accessors; |
| element.constructors = constructors2; |
| element.fields = holder.fields; |
| element.methods = holder.methods; |
| element.typeVariables = typeVariables2; |
| element.validMixin = _isValidMixin; |
| _currentHolder.addType(element); |
| className.element = element; |
| return null; |
| } |
| Object visitClassTypeAlias(ClassTypeAlias node) { |
| ElementHolder holder = new ElementHolder(); |
| visitChildren(holder, node); |
| SimpleIdentifier className = node.name; |
| ClassElementImpl element = new ClassElementImpl(className); |
| element.abstract = node.abstractKeyword != null; |
| element.typedef = true; |
| List<TypeVariableElement> typeVariables2 = holder.typeVariables; |
| element.typeVariables = typeVariables2; |
| InterfaceTypeImpl interfaceType = new InterfaceTypeImpl.con1(element); |
| interfaceType.typeArguments = createTypeVariableTypes(typeVariables2); |
| element.type = interfaceType; |
| _currentHolder.addType(element); |
| className.element = element; |
| return null; |
| } |
| Object visitConstructorDeclaration(ConstructorDeclaration node) { |
| _isValidMixin = false; |
| ElementHolder holder = new ElementHolder(); |
| bool wasInFunction = _inFunction; |
| _inFunction = true; |
| try { |
| visitChildren(holder, node); |
| } finally { |
| _inFunction = wasInFunction; |
| } |
| SimpleIdentifier constructorName = node.name; |
| ConstructorElementImpl element = new ConstructorElementImpl(constructorName); |
| if (node.factoryKeyword != null) { |
| element.factory = true; |
| } |
| element.functions = holder.functions; |
| element.labels = holder.labels; |
| element.localVariables = holder.localVariables; |
| element.parameters = holder.parameters; |
| element.const2 = node.constKeyword != null; |
| _currentHolder.addConstructor(element); |
| node.element = element; |
| if (constructorName == null) { |
| Identifier returnType2 = node.returnType; |
| if (returnType2 != null) { |
| element.nameOffset = returnType2.offset; |
| } |
| } else { |
| constructorName.element = element; |
| } |
| return null; |
| } |
| Object visitDeclaredIdentifier(DeclaredIdentifier node) { |
| SimpleIdentifier variableName = node.identifier; |
| sc.Token keyword2 = node.keyword; |
| LocalVariableElementImpl element = new LocalVariableElementImpl(variableName); |
| ForEachStatement statement = node.parent as ForEachStatement; |
| int declarationEnd = node.offset + node.length; |
| int statementEnd = statement.offset + statement.length; |
| element.setVisibleRange(declarationEnd, statementEnd - declarationEnd - 1); |
| element.const3 = matches(keyword2, sc.Keyword.CONST); |
| element.final2 = matches(keyword2, sc.Keyword.FINAL); |
| _currentHolder.addLocalVariable(element); |
| variableName.element = element; |
| return super.visitDeclaredIdentifier(node); |
| } |
| Object visitDefaultFormalParameter(DefaultFormalParameter node) { |
| ElementHolder holder = new ElementHolder(); |
| visit(holder, node.defaultValue); |
| FunctionElementImpl initializer = new FunctionElementImpl(); |
| initializer.functions = holder.functions; |
| initializer.labels = holder.labels; |
| initializer.localVariables = holder.localVariables; |
| initializer.parameters = holder.parameters; |
| SimpleIdentifier parameterName = node.parameter.identifier; |
| ParameterElementImpl parameter; |
| if (node.isConst()) { |
| parameter = new ConstParameterElementImpl(parameterName); |
| parameter.const3 = true; |
| } else if (node.parameter is FieldFormalParameter) { |
| parameter = new FieldFormalParameterElementImpl(parameterName); |
| } else { |
| parameter = new ParameterElementImpl(parameterName); |
| } |
| parameter.final2 = node.isFinal(); |
| parameter.initializer = initializer; |
| parameter.parameterKind = node.kind; |
| FunctionBody body = getFunctionBody(node); |
| if (body != null) { |
| parameter.setVisibleRange(body.offset, body.length); |
| } |
| _currentHolder.addParameter(parameter); |
| parameterName.element = parameter; |
| node.parameter.accept(this); |
| return null; |
| } |
| Object visitFieldDeclaration(FieldDeclaration node) { |
| bool wasInField = _inFieldContext; |
| _inFieldContext = true; |
| try { |
| node.visitChildren(this); |
| } finally { |
| _inFieldContext = wasInField; |
| } |
| return null; |
| } |
| Object visitFieldFormalParameter(FieldFormalParameter node) { |
| if (node.parent is! DefaultFormalParameter) { |
| SimpleIdentifier parameterName = node.identifier; |
| FieldFormalParameterElementImpl parameter = new FieldFormalParameterElementImpl(parameterName); |
| parameter.const3 = node.isConst(); |
| parameter.initializingFormal = true; |
| parameter.final2 = node.isFinal(); |
| parameter.parameterKind = node.kind; |
| _currentHolder.addParameter(parameter); |
| parameterName.element = parameter; |
| } |
| return super.visitFieldFormalParameter(node); |
| } |
| Object visitFunctionDeclaration(FunctionDeclaration node) { |
| FunctionExpression expression = node.functionExpression; |
| if (expression != null) { |
| ElementHolder holder = new ElementHolder(); |
| bool wasInFunction = _inFunction; |
| _inFunction = true; |
| try { |
| visitChildren(holder, expression); |
| } finally { |
| _inFunction = wasInFunction; |
| } |
| sc.Token property = node.propertyKeyword; |
| if (property == null) { |
| SimpleIdentifier functionName = node.name; |
| FunctionElementImpl element = new FunctionElementImpl.con1(functionName); |
| element.functions = holder.functions; |
| element.labels = holder.labels; |
| element.localVariables = holder.localVariables; |
| element.parameters = holder.parameters; |
| FunctionTypeImpl type = new FunctionTypeImpl.con1(element); |
| element.type = type; |
| _currentHolder.addFunction(element); |
| expression.element = element; |
| functionName.element = element; |
| } else { |
| SimpleIdentifier propertyNameNode = node.name; |
| if (propertyNameNode == null) { |
| return null; |
| } |
| String propertyName = propertyNameNode.name; |
| FieldElementImpl field = _currentHolder.getField(propertyName) as FieldElementImpl; |
| if (field == null) { |
| field = new FieldElementImpl.con2(node.name.name); |
| field.final2 = true; |
| _currentHolder.addField(field); |
| } |
| if (matches(property, sc.Keyword.GET)) { |
| PropertyAccessorElementImpl getter = new PropertyAccessorElementImpl.con1(propertyNameNode); |
| getter.functions = holder.functions; |
| getter.labels = holder.labels; |
| getter.localVariables = holder.localVariables; |
| getter.variable = field; |
| getter.getter = true; |
| field.getter = getter; |
| _currentHolder.addAccessor(getter); |
| propertyNameNode.element = getter; |
| } else { |
| PropertyAccessorElementImpl setter = new PropertyAccessorElementImpl.con1(propertyNameNode); |
| setter.functions = holder.functions; |
| setter.labels = holder.labels; |
| setter.localVariables = holder.localVariables; |
| setter.parameters = holder.parameters; |
| setter.variable = field; |
| setter.setter = true; |
| field.setter = setter; |
| field.final2 = false; |
| _currentHolder.addAccessor(setter); |
| propertyNameNode.element = setter; |
| } |
| } |
| } |
| return null; |
| } |
| Object visitFunctionExpression(FunctionExpression node) { |
| ElementHolder holder = new ElementHolder(); |
| bool wasInFunction = _inFunction; |
| _inFunction = true; |
| try { |
| visitChildren(holder, node); |
| } finally { |
| _inFunction = wasInFunction; |
| } |
| FunctionElementImpl element = new FunctionElementImpl.con2(node.beginToken.offset); |
| element.functions = holder.functions; |
| element.labels = holder.labels; |
| element.localVariables = holder.localVariables; |
| element.parameters = holder.parameters; |
| if (_inFunction) { |
| Block enclosingBlock = node.getAncestor(Block); |
| if (enclosingBlock != null) { |
| int functionEnd = node.offset + node.length; |
| int blockEnd = enclosingBlock.offset + enclosingBlock.length; |
| element.setVisibleRange(functionEnd, blockEnd - functionEnd - 1); |
| } |
| } |
| FunctionTypeImpl type = new FunctionTypeImpl.con1(element); |
| element.type = type; |
| _currentHolder.addFunction(element); |
| node.element = element; |
| return null; |
| } |
| Object visitFunctionTypeAlias(FunctionTypeAlias node) { |
| ElementHolder holder = new ElementHolder(); |
| visitChildren(holder, node); |
| SimpleIdentifier aliasName = node.name; |
| List<ParameterElement> parameters2 = holder.parameters; |
| List<TypeVariableElement> typeVariables2 = holder.typeVariables; |
| FunctionTypeAliasElementImpl element = new FunctionTypeAliasElementImpl(aliasName); |
| element.parameters = parameters2; |
| element.typeVariables = typeVariables2; |
| FunctionTypeImpl type = new FunctionTypeImpl.con2(element); |
| type.typeArguments = createTypeVariableTypes(typeVariables2); |
| element.type = type; |
| _currentHolder.addTypeAlias(element); |
| aliasName.element = element; |
| return null; |
| } |
| Object visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) { |
| if (node.parent is! DefaultFormalParameter) { |
| SimpleIdentifier parameterName = node.identifier; |
| ParameterElementImpl parameter = new ParameterElementImpl(parameterName); |
| parameter.parameterKind = node.kind; |
| _currentHolder.addParameter(parameter); |
| parameterName.element = parameter; |
| } |
| ElementHolder holder = new ElementHolder(); |
| visitChildren(holder, node); |
| ((node.element as ParameterElementImpl)).parameters = holder.parameters; |
| return null; |
| } |
| Object visitLabeledStatement(LabeledStatement node) { |
| bool onSwitchStatement = node.statement is SwitchStatement; |
| for (Label label in node.labels) { |
| SimpleIdentifier labelName = label.label; |
| LabelElementImpl element = new LabelElementImpl(labelName, onSwitchStatement, false); |
| _currentHolder.addLabel(element); |
| labelName.element = element; |
| } |
| return super.visitLabeledStatement(node); |
| } |
| Object visitMethodDeclaration(MethodDeclaration node) { |
| ElementHolder holder = new ElementHolder(); |
| bool wasInFunction = _inFunction; |
| _inFunction = true; |
| try { |
| visitChildren(holder, node); |
| } finally { |
| _inFunction = wasInFunction; |
| } |
| sc.Token property = node.propertyKeyword; |
| if (property == null) { |
| SimpleIdentifier methodName = node.name; |
| String nameOfMethod = methodName.name; |
| if (nameOfMethod == sc.TokenType.MINUS.lexeme && node.parameters.parameters.length == 0) { |
| nameOfMethod = "unary-"; |
| } |
| MethodElementImpl element = new MethodElementImpl.con2(nameOfMethod, methodName.offset); |
| element.abstract = node.isAbstract(); |
| element.functions = holder.functions; |
| element.labels = holder.labels; |
| element.localVariables = holder.localVariables; |
| element.parameters = holder.parameters; |
| element.static = node.isStatic(); |
| _currentHolder.addMethod(element); |
| methodName.element = element; |
| } else { |
| SimpleIdentifier propertyNameNode = node.name; |
| String propertyName = propertyNameNode.name; |
| FieldElementImpl field = _currentHolder.getField(propertyName) as FieldElementImpl; |
| if (field == null) { |
| field = new FieldElementImpl.con2(node.name.name); |
| field.final2 = true; |
| field.static = matches(node.modifierKeyword, sc.Keyword.STATIC); |
| _currentHolder.addField(field); |
| } |
| if (matches(property, sc.Keyword.GET)) { |
| PropertyAccessorElementImpl getter = new PropertyAccessorElementImpl.con1(propertyNameNode); |
| getter.functions = holder.functions; |
| getter.labels = holder.labels; |
| getter.localVariables = holder.localVariables; |
| getter.variable = field; |
| getter.getter = true; |
| field.getter = getter; |
| _currentHolder.addAccessor(getter); |
| propertyNameNode.element = getter; |
| } else { |
| PropertyAccessorElementImpl setter = new PropertyAccessorElementImpl.con1(propertyNameNode); |
| setter.functions = holder.functions; |
| setter.labels = holder.labels; |
| setter.localVariables = holder.localVariables; |
| setter.parameters = holder.parameters; |
| setter.variable = field; |
| setter.setter = true; |
| field.setter = setter; |
| field.final2 = false; |
| _currentHolder.addAccessor(setter); |
| propertyNameNode.element = setter; |
| } |
| } |
| return null; |
| } |
| Object visitSimpleFormalParameter(SimpleFormalParameter node) { |
| if (node.parent is! DefaultFormalParameter) { |
| SimpleIdentifier parameterName = node.identifier; |
| ParameterElementImpl parameter = new ParameterElementImpl(parameterName); |
| parameter.const3 = node.isConst(); |
| parameter.final2 = node.isFinal(); |
| parameter.parameterKind = node.kind; |
| _currentHolder.addParameter(parameter); |
| parameterName.element = parameter; |
| } |
| return super.visitSimpleFormalParameter(node); |
| } |
| Object visitSuperExpression(SuperExpression node) { |
| _isValidMixin = false; |
| return super.visitSuperExpression(node); |
| } |
| Object visitSwitchCase(SwitchCase node) { |
| for (Label label in node.labels) { |
| SimpleIdentifier labelName = label.label; |
| LabelElementImpl element = new LabelElementImpl(labelName, false, true); |
| _currentHolder.addLabel(element); |
| labelName.element = element; |
| } |
| return super.visitSwitchCase(node); |
| } |
| Object visitSwitchDefault(SwitchDefault node) { |
| for (Label label in node.labels) { |
| SimpleIdentifier labelName = label.label; |
| LabelElementImpl element = new LabelElementImpl(labelName, false, true); |
| _currentHolder.addLabel(element); |
| labelName.element = element; |
| } |
| return super.visitSwitchDefault(node); |
| } |
| Object visitTypeParameter(TypeParameter node) { |
| SimpleIdentifier parameterName = node.name; |
| TypeVariableElementImpl element = new TypeVariableElementImpl(parameterName); |
| TypeVariableTypeImpl type = new TypeVariableTypeImpl(element); |
| element.type = type; |
| _currentHolder.addTypeVariable(element); |
| parameterName.element = element; |
| return super.visitTypeParameter(node); |
| } |
| Object visitVariableDeclaration(VariableDeclaration node) { |
| sc.Token keyword2 = ((node.parent as VariableDeclarationList)).keyword; |
| bool isConst = matches(keyword2, sc.Keyword.CONST); |
| bool isFinal = matches(keyword2, sc.Keyword.FINAL); |
| bool hasInitializer = node.initializer != null; |
| VariableElementImpl element; |
| if (_inFieldContext) { |
| SimpleIdentifier fieldName = node.name; |
| FieldElementImpl field; |
| if (isConst && hasInitializer) { |
| field = new ConstFieldElementImpl(fieldName); |
| } else { |
| field = new FieldElementImpl.con1(fieldName); |
| } |
| element = field; |
| _currentHolder.addField(field); |
| fieldName.element = field; |
| } else if (_inFunction) { |
| SimpleIdentifier variableName = node.name; |
| LocalVariableElementImpl variable; |
| if (isConst && hasInitializer) { |
| variable = new ConstLocalVariableElementImpl(variableName); |
| } else { |
| variable = new LocalVariableElementImpl(variableName); |
| } |
| element = variable; |
| Block enclosingBlock = node.getAncestor(Block); |
| int functionEnd = node.offset + node.length; |
| int blockEnd = enclosingBlock.offset + enclosingBlock.length; |
| variable.setVisibleRange(functionEnd, blockEnd - functionEnd - 1); |
| _currentHolder.addLocalVariable(variable); |
| variableName.element = element; |
| } else { |
| SimpleIdentifier variableName = node.name; |
| TopLevelVariableElementImpl variable; |
| if (isConst && hasInitializer) { |
| variable = new ConstTopLevelVariableElementImpl(variableName); |
| } else { |
| variable = new TopLevelVariableElementImpl.con1(variableName); |
| } |
| element = variable; |
| _currentHolder.addTopLevelVariable(variable); |
| variableName.element = element; |
| } |
| element.const3 = isConst; |
| element.final2 = isFinal; |
| if (hasInitializer) { |
| ElementHolder holder = new ElementHolder(); |
| bool wasInFieldContext = _inFieldContext; |
| _inFieldContext = false; |
| try { |
| visit(holder, node.initializer); |
| } finally { |
| _inFieldContext = wasInFieldContext; |
| } |
| FunctionElementImpl initializer = new FunctionElementImpl(); |
| initializer.functions = holder.functions; |
| initializer.labels = holder.labels; |
| initializer.localVariables = holder.localVariables; |
| initializer.synthetic = true; |
| element.initializer = initializer; |
| } |
| if (element is PropertyInducingElementImpl) { |
| PropertyInducingElementImpl variable = element as PropertyInducingElementImpl; |
| PropertyAccessorElementImpl getter = new PropertyAccessorElementImpl.con2(variable); |
| getter.getter = true; |
| _currentHolder.addAccessor(getter); |
| variable.getter = getter; |
| if (!isFinal) { |
| PropertyAccessorElementImpl setter = new PropertyAccessorElementImpl.con2(variable); |
| setter.setter = true; |
| _currentHolder.addAccessor(setter); |
| variable.setter = setter; |
| } |
| if (_inFieldContext) { |
| ((variable as FieldElementImpl)).static = matches(((node.parent.parent as FieldDeclaration)).keyword, sc.Keyword.STATIC); |
| } |
| } |
| return null; |
| } |
| List<Type2> createTypeVariableTypes(List<TypeVariableElement> typeVariables) { |
| int typeVariableCount = typeVariables.length; |
| List<Type2> typeArguments = new List<Type2>(typeVariableCount); |
| for (int i = 0; i < typeVariableCount; i++) { |
| TypeVariableElementImpl typeVariable = typeVariables[i] as TypeVariableElementImpl; |
| TypeVariableTypeImpl typeArgument = new TypeVariableTypeImpl(typeVariable); |
| typeVariable.type = typeArgument; |
| typeArguments[i] = typeArgument; |
| } |
| return typeArguments; |
| } |
| /** |
| * Return the body of the function that contains the given parameter, or {@code null} if no |
| * function body could be found. |
| * @param node the parameter contained in the function whose body is to be returned |
| * @return the body of the function that contains the given parameter |
| */ |
| FunctionBody getFunctionBody(FormalParameter node) { |
| ASTNode parent2 = node.parent; |
| while (parent2 != null) { |
| if (parent2 is FunctionExpression) { |
| return ((parent2 as FunctionExpression)).body; |
| } else if (parent2 is MethodDeclaration) { |
| return ((parent2 as MethodDeclaration)).body; |
| } |
| parent2 = parent2.parent; |
| } |
| return null; |
| } |
| /** |
| * Return {@code true} if the given token is a token for the given keyword. |
| * @param token the token being tested |
| * @param keyword the keyword being tested for |
| * @return {@code true} if the given token is a token for the given keyword |
| */ |
| bool matches(sc.Token token, sc.Keyword keyword2) => token != null && identical(token.type, sc.TokenType.KEYWORD) && identical(((token as sc.KeywordToken)).keyword, keyword2); |
| /** |
| * Make the given holder be the current holder while visiting the given node. |
| * @param holder the holder that will gather elements that are built while visiting the children |
| * @param node the node to be visited |
| */ |
| void visit(ElementHolder holder, ASTNode node) { |
| if (node != null) { |
| ElementHolder previousHolder = _currentHolder; |
| _currentHolder = holder; |
| try { |
| node.accept(this); |
| } finally { |
| _currentHolder = previousHolder; |
| } |
| } |
| } |
| /** |
| * Make the given holder be the current holder while visiting the children of the given node. |
| * @param holder the holder that will gather elements that are built while visiting the children |
| * @param node the node whose children are to be visited |
| */ |
| void visitChildren(ElementHolder holder, ASTNode node) { |
| if (node != null) { |
| ElementHolder previousHolder = _currentHolder; |
| _currentHolder = holder; |
| try { |
| node.visitChildren(this); |
| } finally { |
| _currentHolder = previousHolder; |
| } |
| } |
| } |
| } |
| /** |
| * Instances of the class {@code ElementHolder} hold on to elements created while traversing an AST |
| * structure so that they can be accessed when creating their enclosing element. |
| * @coverage dart.engine.resolver |
| */ |
| class ElementHolder { |
| List<PropertyAccessorElement> _accessors = new List<PropertyAccessorElement>(); |
| List<ConstructorElement> _constructors = new List<ConstructorElement>(); |
| List<FieldElement> _fields = new List<FieldElement>(); |
| List<FunctionElement> _functions = new List<FunctionElement>(); |
| List<LabelElement> _labels = new List<LabelElement>(); |
| List<VariableElement> _localVariables = new List<VariableElement>(); |
| List<MethodElement> _methods = new List<MethodElement>(); |
| List<FunctionTypeAliasElement> _typeAliases = new List<FunctionTypeAliasElement>(); |
| List<ParameterElement> _parameters = new List<ParameterElement>(); |
| List<VariableElement> _topLevelVariables = new List<VariableElement>(); |
| List<ClassElement> _types = new List<ClassElement>(); |
| List<TypeVariableElement> _typeVariables = new List<TypeVariableElement>(); |
| /** |
| * Initialize a newly created element holder. |
| */ |
| ElementHolder() : super() { |
| } |
| void addAccessor(PropertyAccessorElement element) { |
| _accessors.add(element); |
| } |
| void addConstructor(ConstructorElement element) { |
| _constructors.add(element); |
| } |
| void addField(FieldElement element) { |
| _fields.add(element); |
| } |
| void addFunction(FunctionElement element) { |
| _functions.add(element); |
| } |
| void addLabel(LabelElement element) { |
| _labels.add(element); |
| } |
| void addLocalVariable(LocalVariableElement element) { |
| _localVariables.add(element); |
| } |
| void addMethod(MethodElement element) { |
| _methods.add(element); |
| } |
| void addParameter(ParameterElement element) { |
| _parameters.add(element); |
| } |
| void addTopLevelVariable(TopLevelVariableElement element) { |
| _topLevelVariables.add(element); |
| } |
| void addType(ClassElement element) { |
| _types.add(element); |
| } |
| void addTypeAlias(FunctionTypeAliasElement element) { |
| _typeAliases.add(element); |
| } |
| void addTypeVariable(TypeVariableElement element) { |
| _typeVariables.add(element); |
| } |
| List<PropertyAccessorElement> get accessors { |
| if (_accessors.isEmpty) { |
| return PropertyAccessorElementImpl.EMPTY_ARRAY; |
| } |
| return new List.from(_accessors); |
| } |
| List<ConstructorElement> get constructors { |
| if (_constructors.isEmpty) { |
| return ConstructorElementImpl.EMPTY_ARRAY; |
| } |
| return new List.from(_constructors); |
| } |
| FieldElement getField(String fieldName) { |
| for (FieldElement field in _fields) { |
| if (field.name == fieldName) { |
| return field; |
| } |
| } |
| return null; |
| } |
| List<FieldElement> get fields { |
| if (_fields.isEmpty) { |
| return FieldElementImpl.EMPTY_ARRAY; |
| } |
| return new List.from(_fields); |
| } |
| List<FunctionElement> get functions { |
| if (_functions.isEmpty) { |
| return FunctionElementImpl.EMPTY_ARRAY; |
| } |
| return new List.from(_functions); |
| } |
| List<LabelElement> get labels { |
| if (_labels.isEmpty) { |
| return LabelElementImpl.EMPTY_ARRAY; |
| } |
| return new List.from(_labels); |
| } |
| List<LocalVariableElement> get localVariables { |
| if (_localVariables.isEmpty) { |
| return LocalVariableElementImpl.EMPTY_ARRAY; |
| } |
| return new List.from(_localVariables); |
| } |
| List<MethodElement> get methods { |
| if (_methods.isEmpty) { |
| return MethodElementImpl.EMPTY_ARRAY; |
| } |
| return new List.from(_methods); |
| } |
| List<ParameterElement> get parameters { |
| if (_parameters.isEmpty) { |
| return ParameterElementImpl.EMPTY_ARRAY; |
| } |
| return new List.from(_parameters); |
| } |
| List<TopLevelVariableElement> get topLevelVariables { |
| if (_topLevelVariables.isEmpty) { |
| return TopLevelVariableElementImpl.EMPTY_ARRAY; |
| } |
| return new List.from(_topLevelVariables); |
| } |
| List<FunctionTypeAliasElement> get typeAliases { |
| if (_typeAliases.isEmpty) { |
| return FunctionTypeAliasElementImpl.EMPTY_ARRAY; |
| } |
| return new List.from(_typeAliases); |
| } |
| List<ClassElement> get types { |
| if (_types.isEmpty) { |
| return ClassElementImpl.EMPTY_ARRAY; |
| } |
| return new List.from(_types); |
| } |
| List<TypeVariableElement> get typeVariables { |
| if (_typeVariables.isEmpty) { |
| return TypeVariableElementImpl.EMPTY_ARRAY; |
| } |
| return new List.from(_typeVariables); |
| } |
| } |
| /** |
| * Instances of the class {@code HtmlUnitBuilder} build an element model for a single HTML unit. |
| */ |
| class HtmlUnitBuilder implements ht.XmlVisitor<Object> { |
| static String _APPLICATION_DART_IN_DOUBLE_QUOTES = "\"application/dart\""; |
| static String _APPLICATION_DART_IN_SINGLE_QUOTES = "'application/dart'"; |
| static String _SCRIPT = "script"; |
| static String _SRC = "src"; |
| static String _TYPE = "type"; |
| /** |
| * The analysis context in which the element model will be built. |
| */ |
| InternalAnalysisContext _context; |
| /** |
| * The error listener to which errors will be reported. |
| */ |
| AnalysisErrorListener _errorListener; |
| /** |
| * The line information associated with the source for which an element is being built, or{@code null} if we are not building an element. |
| */ |
| LineInfo _lineInfo; |
| /** |
| * The HTML element being built. |
| */ |
| HtmlElementImpl _htmlElement; |
| /** |
| * The script elements being built. |
| */ |
| List<HtmlScriptElement> _scripts; |
| /** |
| * Initialize a newly created HTML unit builder. |
| * @param context the analysis context in which the element model will be built |
| * @param errorListener the error listener to which errors will be reported |
| */ |
| HtmlUnitBuilder(InternalAnalysisContext context, AnalysisErrorListener errorListener) { |
| this._context = context; |
| this._errorListener = errorListener; |
| } |
| /** |
| * Build the HTML element for the given source. |
| * @param source the source describing the compilation unit |
| * @return the HTML element that was built |
| * @throws AnalysisException if the analysis could not be performed |
| */ |
| HtmlElementImpl buildHtmlElement(Source source) => buildHtmlElement2(source, _context.parseHtmlUnit(source)); |
| /** |
| * Build the HTML element for the given source. |
| * @param source the source describing the compilation unit |
| * @param unit the AST structure representing the HTML |
| * @throws AnalysisException if the analysis could not be performed |
| */ |
| HtmlElementImpl buildHtmlElement2(Source source2, ht.HtmlUnit unit) { |
| _lineInfo = _context.computeLineInfo(source2); |
| HtmlElementImpl result = new HtmlElementImpl(_context, source2.shortName); |
| result.source = source2; |
| _htmlElement = result; |
| unit.accept(this); |
| _htmlElement = null; |
| unit.element = result; |
| return result; |
| } |
| Object visitHtmlUnit(ht.HtmlUnit node) { |
| _scripts = new List<HtmlScriptElement>(); |
| node.visitChildren(this); |
| _htmlElement.scripts = new List.from(_scripts); |
| _scripts = null; |
| return null; |
| } |
| Object visitXmlAttributeNode(ht.XmlAttributeNode node) => null; |
| Object visitXmlTagNode(ht.XmlTagNode node) { |
| if (isScriptNode(node)) { |
| Source htmlSource = _htmlElement.source; |
| ht.XmlAttributeNode scriptAttribute = getScriptSourcePath(node); |
| String scriptSourcePath = scriptAttribute == null ? null : scriptAttribute.text; |
| if (identical(node.attributeEnd.type, ht.TokenType.GT) && scriptSourcePath == null) { |
| EmbeddedHtmlScriptElementImpl script = new EmbeddedHtmlScriptElementImpl(node); |
| String contents = node.content; |
| int attributeEnd2 = node.attributeEnd.end; |
| LineInfo_Location location = _lineInfo.getLocation(attributeEnd2); |
| sc.StringScanner scanner = new sc.StringScanner(htmlSource, contents, _errorListener); |
| scanner.setSourceStart(location.lineNumber, location.columnNumber, attributeEnd2); |
| sc.Token firstToken = scanner.tokenize(); |
| List<int> lineStarts2 = scanner.lineStarts; |
| Parser parser = new Parser(null, _errorListener); |
| CompilationUnit unit = parser.parseCompilationUnit(firstToken); |
| unit.lineInfo = new LineInfo(lineStarts2); |
| try { |
| CompilationUnitBuilder builder = new CompilationUnitBuilder(); |
| CompilationUnitElementImpl elem = builder.buildCompilationUnit(htmlSource, unit); |
| LibraryElementImpl library = new LibraryElementImpl(_context, null); |
| library.definingCompilationUnit = elem; |
| script.scriptLibrary = library; |
| } on AnalysisException catch (exception) { |
| print(exception); |
| } |
| _scripts.add(script); |
| } else { |
| ExternalHtmlScriptElementImpl script = new ExternalHtmlScriptElementImpl(node); |
| if (scriptSourcePath != null) { |
| try { |
| new Uri(scriptSourcePath); |
| Source scriptSource = _context.sourceFactory.resolveUri(htmlSource, scriptSourcePath); |
| script.scriptSource = scriptSource; |
| if (!scriptSource.exists()) { |
| reportError(HtmlWarningCode.URI_DOES_NOT_EXIST, scriptAttribute.offset + 1, scriptSourcePath.length, []); |
| } |
| } on URISyntaxException catch (exception) { |
| reportError(HtmlWarningCode.INVALID_URI, scriptAttribute.offset + 1, scriptSourcePath.length, []); |
| } |
| } |
| _scripts.add(script); |
| } |
| } else { |
| node.visitChildren(this); |
| } |
| return null; |
| } |
| /** |
| * Return the first source attribute for the given tag node, or {@code null} if it does not exist. |
| * @param node the node containing attributes |
| * @return the source attribute contained in the given tag |
| */ |
| ht.XmlAttributeNode getScriptSourcePath(ht.XmlTagNode node) { |
| for (ht.XmlAttributeNode attribute in node.attributes) { |
| if (attribute.name.lexeme == _SRC) { |
| return attribute; |
| } |
| } |
| return null; |
| } |
| /** |
| * Determine if the specified node is a Dart script. |
| * @param node the node to be tested (not {@code null}) |
| * @return {@code true} if the node is a Dart script |
| */ |
| bool isScriptNode(ht.XmlTagNode node) { |
| if (node.tagNodes.length != 0 || node.tag.lexeme != _SCRIPT) { |
| return false; |
| } |
| for (ht.XmlAttributeNode attribute in node.attributes) { |
| if (attribute.name.lexeme == _TYPE) { |
| ht.Token valueToken = attribute.value; |
| if (valueToken != null) { |
| String value = valueToken.lexeme; |
| if (value == _APPLICATION_DART_IN_DOUBLE_QUOTES || value == _APPLICATION_DART_IN_SINGLE_QUOTES) { |
| return true; |
| } |
| } |
| } |
| } |
| return false; |
| } |
| /** |
| * Report an error with the given error code at the given location. Use the given arguments to |
| * compose the error message. |
| * @param errorCode the error code of the error to be reported |
| * @param offset the offset of the first character to be highlighted |
| * @param length the number of characters to be highlighted |
| * @param arguments the arguments used to compose the error message |
| */ |
| void reportError(ErrorCode errorCode, int offset, int length, List<Object> arguments) { |
| _errorListener.onError(new AnalysisError.con2(_htmlElement.source, offset, length, errorCode, arguments)); |
| } |
| } |
| /** |
| * Instances of the class {@code DeclarationResolver} are used to resolve declarations in an AST |
| * structure to already built elements. |
| */ |
| class DeclarationResolver extends RecursiveASTVisitor<Object> { |
| /** |
| * The compilation unit containing the AST nodes being visited. |
| */ |
| CompilationUnitElement _enclosingUnit; |
| /** |
| * The function type alias containing the AST nodes being visited, or {@code null} if we are not |
| * in the scope of a function type alias. |
| */ |
| FunctionTypeAliasElement _enclosingAlias; |
| /** |
| * The class containing the AST nodes being visited, or {@code null} if we are not in the scope of |
| * a class. |
| */ |
| ClassElement _enclosingClass; |
| /** |
| * The method or function containing the AST nodes being visited, or {@code null} if we are not in |
| * the scope of a method or function. |
| */ |
| ExecutableElement _enclosingExecutable; |
| /** |
| * The parameter containing the AST nodes being visited, or {@code null} if we are not in the |
| * scope of a parameter. |
| */ |
| ParameterElement _enclosingParameter; |
| /** |
| * Initialize a newly created resolver. |
| */ |
| DeclarationResolver() : super() { |
| } |
| /** |
| * Resolve the declarations within the given compilation unit to the elements rooted at the given |
| * element. |
| * @param unit the compilation unit to be resolved |
| * @param element the root of the element model used to resolve the AST nodes |
| */ |
| void resolve(CompilationUnit unit, CompilationUnitElement element2) { |
| _enclosingUnit = element2; |
| unit.element = element2; |
| unit.accept(this); |
| } |
| Object visitCatchClause(CatchClause node) { |
| SimpleIdentifier exceptionParameter2 = node.exceptionParameter; |
| if (exceptionParameter2 != null) { |
| List<LocalVariableElement> localVariables2 = _enclosingExecutable.localVariables; |
| find3(localVariables2, exceptionParameter2); |
| SimpleIdentifier stackTraceParameter2 = node.stackTraceParameter; |
| if (stackTraceParameter2 != null) { |
| find3(localVariables2, stackTraceParameter2); |
| } |
| } |
| return super.visitCatchClause(node); |
| } |
| Object visitClassDeclaration(ClassDeclaration node) { |
| ClassElement outerClass = _enclosingClass; |
| try { |
| SimpleIdentifier className = node.name; |
| _enclosingClass = find3(_enclosingUnit.types, className); |
| return super.visitClassDeclaration(node); |
| } finally { |
| _enclosingClass = outerClass; |
| } |
| } |
| Object visitClassTypeAlias(ClassTypeAlias node) { |
| ClassElement outerClass = _enclosingClass; |
| try { |
| SimpleIdentifier className = node.name; |
| _enclosingClass = find3(_enclosingUnit.types, className); |
| return super.visitClassTypeAlias(node); |
| } finally { |
| _enclosingClass = outerClass; |
| } |
| } |
| Object visitConstructorDeclaration(ConstructorDeclaration node) { |
| ExecutableElement outerExecutable = _enclosingExecutable; |
| try { |
| SimpleIdentifier constructorName = node.name; |
| if (constructorName == null) { |
| _enclosingExecutable = _enclosingClass.unnamedConstructor; |
| } else { |
| _enclosingExecutable = _enclosingClass.getNamedConstructor(constructorName.name); |
| constructorName.element = _enclosingExecutable; |
| } |
| node.element = _enclosingExecutable as ConstructorElement; |
| return super.visitConstructorDeclaration(node); |
| } finally { |
| _enclosingExecutable = outerExecutable; |
| } |
| } |
| Object visitDeclaredIdentifier(DeclaredIdentifier node) { |
| SimpleIdentifier variableName = node.identifier; |
| find3(_enclosingExecutable.localVariables, variableName); |
| return super.visitDeclaredIdentifier(node); |
| } |
| Object visitDefaultFormalParameter(DefaultFormalParameter node) { |
| SimpleIdentifier parameterName = node.parameter.identifier; |
| ParameterElement element = null; |
| if (_enclosingExecutable != null) { |
| element = find3(_enclosingExecutable.parameters, parameterName); |
| } else { |
| PrintStringWriter writer = new PrintStringWriter(); |
| writer.println("Invalid state found in the Analysis Engine:"); |
| writer.println("DeclarationResolver.visitDefaultFormalParameter() is visiting a parameter that does not appear to be in a method or function."); |
| writer.println("Ancestors:"); |
| ASTNode parent2 = node.parent; |
| while (parent2 != null) { |
| writer.println(parent2.runtimeType.toString()); |
| writer.println("---------"); |
| parent2 = parent2.parent; |
| } |
| AnalysisEngine.instance.logger.logError2(writer.toString(), new AnalysisException()); |
| } |
| Expression defaultValue2 = node.defaultValue; |
| if (defaultValue2 != null) { |
| ExecutableElement outerExecutable = _enclosingExecutable; |
| try { |
| if (element == null) { |
| } else { |
| _enclosingExecutable = element.initializer; |
| } |
| defaultValue2.accept(this); |
| } finally { |
| _enclosingExecutable = outerExecutable; |
| } |
| } |
| ParameterElement outerParameter = _enclosingParameter; |
| try { |
| _enclosingParameter = element; |
| return super.visitDefaultFormalParameter(node); |
| } finally { |
| _enclosingParameter = outerParameter; |
| } |
| } |
| Object visitExportDirective(ExportDirective node) { |
| String uri2 = getStringValue(node.uri); |
| if (uri2 != null) { |
| LibraryElement library2 = _enclosingUnit.library; |
| ExportElement exportElement = find5(library2.exports, _enclosingUnit.context.sourceFactory.resolveUri(_enclosingUnit.source, uri2)); |
| node.element = exportElement; |
| } |
| return super.visitExportDirective(node); |
| } |
| Object visitFieldFormalParameter(FieldFormalParameter node) { |
| if (node.parent is! DefaultFormalParameter) { |
| SimpleIdentifier parameterName = node.identifier; |
| ParameterElement element = find3(_enclosingExecutable.parameters, parameterName); |
| ParameterElement outerParameter = _enclosingParameter; |
| try { |
| _enclosingParameter = element; |
| return super.visitFieldFormalParameter(node); |
| } finally { |
| _enclosingParameter = outerParameter; |
| } |
| } else { |
| return super.visitFieldFormalParameter(node); |
| } |
| } |
| Object visitFunctionDeclaration(FunctionDeclaration node) { |
| ExecutableElement outerExecutable = _enclosingExecutable; |
| try { |
| SimpleIdentifier functionName = node.name; |
| sc.Token property = node.propertyKeyword; |
| if (property == null) { |
| if (_enclosingExecutable != null) { |
| _enclosingExecutable = find3(_enclosingExecutable.functions, functionName); |
| } else { |
| _enclosingExecutable = find3(_enclosingUnit.functions, functionName); |
| } |
| } else { |
| PropertyAccessorElement accessor = find3(_enclosingUnit.accessors, functionName); |
| if (identical(((property as sc.KeywordToken)).keyword, sc.Keyword.SET)) { |
| accessor = accessor.variable.setter; |
| functionName.element = accessor; |
| } |
| _enclosingExecutable = accessor; |
| } |
| node.functionExpression.element = _enclosingExecutable; |
| return super.visitFunctionDeclaration(node); |
| } finally { |
| _enclosingExecutable = outerExecutable; |
| } |
| } |
| Object visitFunctionExpression(FunctionExpression node) { |
| if (node.parent is! FunctionDeclaration) { |
| FunctionElement element = find2(_enclosingExecutable.functions, node.beginToken.offset); |
| node.element = element; |
| } |
| ExecutableElement outerExecutable = _enclosingExecutable; |
| try { |
| _enclosingExecutable = node.element; |
| return super.visitFunctionExpression(node); |
| } finally { |
| _enclosingExecutable = outerExecutable; |
| } |
| } |
| Object visitFunctionTypeAlias(FunctionTypeAlias node) { |
| FunctionTypeAliasElement outerAlias = _enclosingAlias; |
| try { |
| SimpleIdentifier aliasName = node.name; |
| _enclosingAlias = find3(_enclosingUnit.functionTypeAliases, aliasName); |
| return super.visitFunctionTypeAlias(node); |
| } finally { |
| _enclosingAlias = outerAlias; |
| } |
| } |
| Object visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) { |
| if (node.parent is! DefaultFormalParameter) { |
| SimpleIdentifier parameterName = node.identifier; |
| ParameterElement element = find3(_enclosingExecutable.parameters, parameterName); |
| ParameterElement outerParameter = _enclosingParameter; |
| try { |
| _enclosingParameter = element; |
| return super.visitFunctionTypedFormalParameter(node); |
| } finally { |
| _enclosingParameter = outerParameter; |
| } |
| } else { |
| return super.visitFunctionTypedFormalParameter(node); |
| } |
| } |
| Object visitImportDirective(ImportDirective node) { |
| String uri2 = getStringValue(node.uri); |
| if (uri2 != null) { |
| LibraryElement library2 = _enclosingUnit.library; |
| ImportElement importElement = find6(library2.imports, _enclosingUnit.context.sourceFactory.resolveUri(_enclosingUnit.source, uri2), node.prefix); |
| node.element = importElement; |
| } |
| return super.visitImportDirective(node); |
| } |
| Object visitLabeledStatement(LabeledStatement node) { |
| for (Label label in node.labels) { |
| SimpleIdentifier labelName = label.label; |
| find3(_enclosingExecutable.labels, labelName); |
| } |
| return super.visitLabeledStatement(node); |
| } |
| Object visitLibraryDirective(LibraryDirective node) { |
| node.element = _enclosingUnit.library; |
| return super.visitLibraryDirective(node); |
| } |
| Object visitMethodDeclaration(MethodDeclaration node) { |
| ExecutableElement outerExecutable = _enclosingExecutable; |
| try { |
| sc.Token property = node.propertyKeyword; |
| SimpleIdentifier methodName = node.name; |
| String nameOfMethod = methodName.name; |
| if (nameOfMethod == sc.TokenType.MINUS.lexeme && node.parameters.parameters.length == 0) { |
| nameOfMethod = "unary-"; |
| } |
| if (property == null) { |
| _enclosingExecutable = find4(_enclosingClass.methods, nameOfMethod, methodName.offset); |
| methodName.element = _enclosingExecutable; |
| } else { |
| PropertyAccessorElement accessor = find3(_enclosingClass.accessors, methodName); |
| if (identical(((property as sc.KeywordToken)).keyword, sc.Keyword.SET)) { |
| accessor = accessor.variable.setter; |
| methodName.element = accessor; |
| } |
| _enclosingExecutable = accessor; |
| } |
| return super.visitMethodDeclaration(node); |
| } finally { |
| _enclosingExecutable = outerExecutable; |
| } |
| } |
| Object visitPartDirective(PartDirective node) { |
| String uri2 = getStringValue(node.uri); |
| if (uri2 != null) { |
| Source partSource = _enclosingUnit.context.sourceFactory.resolveUri(_enclosingUnit.source, uri2); |
| node.element = find(_enclosingUnit.library.parts, partSource); |
| } |
| return super.visitPartDirective(node); |
| } |
| Object visitPartOfDirective(PartOfDirective node) { |
| node.element = _enclosingUnit.library; |
| return super.visitPartOfDirective(node); |
| } |
| Object visitSimpleFormalParameter(SimpleFormalParameter node) { |
| if (node.parent is! DefaultFormalParameter) { |
| SimpleIdentifier parameterName = node.identifier; |
| ParameterElement element = null; |
| if (_enclosingParameter != null) { |
| element = find3(_enclosingParameter.parameters, parameterName); |
| } else if (_enclosingExecutable != null) { |
| element = find3(_enclosingExecutable.parameters, parameterName); |
| } else if (_enclosingAlias != null) { |
| element = find3(_enclosingAlias.parameters, parameterName); |
| } else { |
| } |
| ParameterElement outerParameter = _enclosingParameter; |
| try { |
| _enclosingParameter = element; |
| return super.visitSimpleFormalParameter(node); |
| } finally { |
| _enclosingParameter = outerParameter; |
| } |
| } else { |
| } |
| return super.visitSimpleFormalParameter(node); |
| } |
| Object visitSwitchCase(SwitchCase node) { |
| for (Label label in node.labels) { |
| SimpleIdentifier labelName = label.label; |
| find3(_enclosingExecutable.labels, labelName); |
| } |
| return super.visitSwitchCase(node); |
| } |
| Object visitSwitchDefault(SwitchDefault node) { |
| for (Label label in node.labels) { |
| SimpleIdentifier labelName = label.label; |
| find3(_enclosingExecutable.labels, labelName); |
| } |
| return super.visitSwitchDefault(node); |
| } |
| Object visitTypeParameter(TypeParameter node) { |
| SimpleIdentifier parameterName = node.name; |
| if (_enclosingClass != null) { |
| find3(_enclosingClass.typeVariables, parameterName); |
| } else if (_enclosingAlias != null) { |
| find3(_enclosingAlias.typeVariables, parameterName); |
| } |
| return super.visitTypeParameter(node); |
| } |
| Object visitVariableDeclaration(VariableDeclaration node) { |
| VariableElement element = null; |
| SimpleIdentifier variableName = node.name; |
| if (_enclosingExecutable != null) { |
| element = find3(_enclosingExecutable.localVariables, variableName); |
| } |
| if (element == null && _enclosingClass != null) { |
| element = find3(_enclosingClass.fields, variableName); |
| } |
| if (element == null && _enclosingUnit != null) { |
| element = find3(_enclosingUnit.topLevelVariables, variableName); |
| } |
| Expression initializer2 = node.initializer; |
| if (initializer2 != null) { |
| ExecutableElement outerExecutable = _enclosingExecutable; |
| try { |
| if (element == null) { |
| } else { |
| _enclosingExecutable = element.initializer; |
| } |
| return super.visitVariableDeclaration(node); |
| } finally { |
| _enclosingExecutable = outerExecutable; |
| } |
| } |
| return super.visitVariableDeclaration(node); |
| } |
| /** |
| * Append the value of the given string literal to the given string builder. |
| * @param builder the builder to which the string's value is to be appended |
| * @param literal the string literal whose value is to be appended to the builder |
| * @throws IllegalArgumentException if the string is not a constant string without any string |
| * interpolation |
| */ |
| void appendStringValue(JavaStringBuilder builder, StringLiteral literal) { |
| if (literal is SimpleStringLiteral) { |
| builder.append(((literal as SimpleStringLiteral)).value); |
| } else if (literal is AdjacentStrings) { |
| for (StringLiteral stringLiteral in ((literal as AdjacentStrings)).strings) { |
| appendStringValue(builder, stringLiteral); |
| } |
| } else { |
| throw new IllegalArgumentException(); |
| } |
| } |
| /** |
| * Return the element for the part with the given source, or {@code null} if there is no element |
| * for the given source. |
| * @param parts the elements for the parts |
| * @param partSource the source for the part whose element is to be returned |
| * @return the element for the part with the given source |
| */ |
| CompilationUnitElement find(List<CompilationUnitElement> parts, Source partSource) { |
| for (CompilationUnitElement part in parts) { |
| if (part.source == partSource) { |
| return part; |
| } |
| } |
| return null; |
| } |
| /** |
| * Return the element in the given array of elements that was created for the declaration at the |
| * given offset. This method should only be used when there is no name |
| * @param elements the elements of the appropriate kind that exist in the current context |
| * @param offset the offset of the name of the element to be returned |
| * @return the element at the given offset |
| */ |
| Element find2(List<Element> elements, int offset) => find4(elements, "", offset); |
| /** |
| * Return the element in the given array of elements that was created for the declaration with the |
| * given name. |
| * @param elements the elements of the appropriate kind that exist in the current context |
| * @param identifier the name node in the declaration of the element to be returned |
| * @return the element created for the declaration with the given name |
| */ |
| Element find3(List<Element> elements, SimpleIdentifier identifier) { |
| Element element = find4(elements, identifier.name, identifier.offset); |
| identifier.element = element; |
| return element; |
| } |
| /** |
| * Return the element in the given array of elements that was created for the declaration with the |
| * given name at the given offset. |
| * @param elements the elements of the appropriate kind that exist in the current context |
| * @param name the name of the element to be returned |
| * @param offset the offset of the name of the element to be returned |
| * @return the element with the given name and offset |
| */ |
| Element find4(List<Element> elements, String name2, int offset) { |
| for (Element element in elements) { |
| if (element.name == name2 && element.nameOffset == offset) { |
| return element; |
| } |
| } |
| return null; |
| } |
| /** |
| * Return the export element from the given array whose library has the given source, or{@code null} if there is no such export. |
| * @param exports the export elements being searched |
| * @param source the source of the library associated with the export element to being searched |
| * for |
| * @return the export element whose library has the given source |
| */ |
| ExportElement find5(List<ExportElement> exports, Source source2) { |
| for (ExportElement export in exports) { |
| if (export.exportedLibrary.source == source2) { |
| return export; |
| } |
| } |
| return null; |
| } |
| /** |
| * Return the import element from the given array whose library has the given source and that has |
| * the given prefix, or {@code null} if there is no such import. |
| * @param imports the import elements being searched |
| * @param source the source of the library associated with the import element to being searched |
| * for |
| * @param prefix the prefix with which the library was imported |
| * @return the import element whose library has the given source and prefix |
| */ |
| ImportElement find6(List<ImportElement> imports, Source source2, SimpleIdentifier prefix2) { |
| for (ImportElement element in imports) { |
| if (element.importedLibrary.source == source2) { |
| PrefixElement prefixElement = element.prefix; |
| if (prefix2 == null) { |
| if (prefixElement == null) { |
| return element; |
| } |
| } else { |
| if (prefixElement != null && prefix2.name == prefixElement.name) { |
| return element; |
| } |
| } |
| } |
| } |
| return null; |
| } |
| /** |
| * Return the value of the given string literal, or {@code null} if the string is not a constant |
| * string without any string interpolation. |
| * @param literal the string literal whose value is to be returned |
| * @return the value of the given string literal |
| */ |
| String getStringValue(StringLiteral literal) { |
| if (literal is StringInterpolation) { |
| return null; |
| } |
| JavaStringBuilder builder = new JavaStringBuilder(); |
| try { |
| appendStringValue(builder, literal); |
| } on IllegalArgumentException catch (exception) { |
| return null; |
| } |
| return builder.toString().trim(); |
| } |
| } |
| /** |
| * Instances of the class {@code ElementResolver} are used by instances of {@link ResolverVisitor}to resolve references within the AST structure to the elements being referenced. The requirements |
| * for the element resolver are: |
| * <ol> |
| * <li>Every {@link SimpleIdentifier} should be resolved to the element to which it refers. |
| * Specifically: |
| * <ul> |
| * <li>An identifier within the declaration of that name should resolve to the element being |
| * declared.</li> |
| * <li>An identifier denoting a prefix should resolve to the element representing the import that |
| * defines the prefix (an {@link ImportElement}).</li> |
| * <li>An identifier denoting a variable should resolve to the element representing the variable (a{@link VariableElement}).</li> |
| * <li>An identifier denoting a parameter should resolve to the element representing the parameter |
| * (a {@link ParameterElement}).</li> |
| * <li>An identifier denoting a field should resolve to the element representing the getter or |
| * setter being invoked (a {@link PropertyAccessorElement}).</li> |
| * <li>An identifier denoting the name of a method or function being invoked should resolve to the |
| * element representing the method or function (a {@link ExecutableElement}).</li> |
| * <li>An identifier denoting a label should resolve to the element representing the label (a{@link LabelElement}).</li> |
| * </ul> |
| * The identifiers within directives are exceptions to this rule and are covered below.</li> |
| * <li>Every node containing a token representing an operator that can be overridden ({@link BinaryExpression}, {@link PrefixExpression}, {@link PostfixExpression}) should resolve to |
| * the element representing the method invoked by that operator (a {@link MethodElement}).</li> |
| * <li>Every {@link FunctionExpressionInvocation} should resolve to the element representing the |
| * function being invoked (a {@link 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.</li> |
| * <li>Every {@link LibraryDirective} and {@link PartOfDirective} should resolve to the element |
| * representing the library being specified by the directive (a {@link LibraryElement}) unless, in |
| * the case of a part-of directive, the specified library does not exist.</li> |
| * <li>Every {@link ImportDirective} and {@link ExportDirective} should resolve to the element |
| * representing the library being specified by the directive unless the specified library does not |
| * exist (an {@link ImportElement} or {@link ExportElement}).</li> |
| * <li>The identifier representing the prefix in an {@link ImportDirective} should resolve to the |
| * element representing the prefix (a {@link PrefixElement}).</li> |
| * <li>The identifiers in the hide and show combinators in {@link ImportDirective}s and{@link 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).</li> |
| * <li>Every {@link PartDirective} should resolve to the element representing the compilation unit |
| * being specified by the string unless the specified compilation unit does not exist (a{@link CompilationUnitElement}).</li> |
| * </ol> |
| * 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). |
| * @coverage dart.engine.resolver |
| */ |
| class ElementResolver extends SimpleASTVisitor<Object> { |
| /** |
| * The resolver driving this participant. |
| */ |
| ResolverVisitor _resolver; |
| /** |
| * Initialize a newly created visitor to resolve the nodes in a compilation unit. |
| * @param resolver the resolver driving this participant |
| */ |
| ElementResolver(ResolverVisitor resolver) { |
| this._resolver = resolver; |
| } |
| Object visitAssignmentExpression(AssignmentExpression node) { |
| sc.TokenType operator2 = node.operator.type; |
| if (operator2 != sc.TokenType.EQ) { |
| operator2 = operatorFromCompoundAssignment(operator2); |
| Expression leftNode = node.leftHandSide; |
| if (leftNode != null) { |
| Type2 leftType = getType(leftNode); |
| if (leftType != null) { |
| MethodElement method = lookUpMethod(leftType, operator2.lexeme); |
| if (method != null) { |
| node.element = method; |
| } else { |
| } |
| } |
| } |
| } |
| return null; |
| } |
| Object visitBinaryExpression(BinaryExpression node) { |
| sc.Token operator2 = node.operator; |
| if (operator2.isUserDefinableOperator()) { |
| Type2 leftType = getType(node.leftOperand); |
| if (leftType == null || leftType.isDynamic()) { |
| return null; |
| } else if (leftType is FunctionType) { |
| leftType = _resolver.typeProvider.functionType; |
| } |
| String methodName = operator2.lexeme; |
| MethodElement member = lookUpMethod(leftType, methodName); |
| if (member == null) { |
| _resolver.reportError3(StaticWarningCode.UNDEFINED_OPERATOR, operator2, [methodName, leftType.name]); |
| } else { |
| node.element = member; |
| } |
| } |
| return null; |
| } |
| Object visitBreakStatement(BreakStatement node) { |
| SimpleIdentifier labelNode = node.label; |
| LabelElementImpl labelElement = lookupLabel(node, labelNode); |
| if (labelElement != null && labelElement.isOnSwitchMember()) { |
| _resolver.reportError(ResolverErrorCode.BREAK_LABEL_ON_SWITCH_MEMBER, labelNode, []); |
| } |
| return null; |
| } |
| Object visitCommentReference(CommentReference node) { |
| Identifier identifier2 = node.identifier; |
| if (identifier2 is SimpleIdentifier) { |
| SimpleIdentifier simpleIdentifier = identifier2 as SimpleIdentifier; |
| visitSimpleIdentifier(simpleIdentifier); |
| Element element2 = simpleIdentifier.element; |
| if (element2 != null) { |
| if (element2.library != _resolver.definingLibrary) { |
| } |
| if (node.newKeyword != null) { |
| if (element2 is ClassElement) { |
| ConstructorElement constructor = ((element2 as ClassElement)).unnamedConstructor; |
| recordResolution(simpleIdentifier, constructor); |
| } else { |
| } |
| } |
| } |
| } else if (identifier2 is PrefixedIdentifier) { |
| PrefixedIdentifier prefixedIdentifier = identifier2 as PrefixedIdentifier; |
| SimpleIdentifier prefix2 = prefixedIdentifier.prefix; |
| SimpleIdentifier name = prefixedIdentifier.identifier; |
| visitSimpleIdentifier(prefix2); |
| Element element3 = prefix2.element; |
| if (element3 != null) { |
| if (element3 is PrefixElement) { |
| element3 = _resolver.nameScope.lookup(identifier2, _resolver.definingLibrary); |
| recordResolution(name, element3); |
| return null; |
| } |
| if (element3.library != _resolver.definingLibrary) { |
| } |
| if (node.newKeyword == null) { |
| if (element3 is ClassElement) { |
| Element memberElement = lookupGetterOrMethod(((element3 as ClassElement)).type, name.name); |
| if (memberElement == null) { |
| memberElement = ((element3 as ClassElement)).getNamedConstructor(name.name); |
| } |
| if (memberElement == null) { |
| reportGetterOrSetterNotFound(prefixedIdentifier, name, element3.name); |
| } else { |
| recordResolution(name, memberElement); |
| } |
| } else { |
| } |
| } else { |
| if (element3 is ClassElement) { |
| ConstructorElement constructor = ((element3 as ClassElement)).getNamedConstructor(name.name); |
| if (constructor != null) { |
| recordResolution(name, constructor); |
| } |
| } else { |
| } |
| } |
| } |
| } |
| return null; |
| } |
| Object visitConstructorFieldInitializer(ConstructorFieldInitializer node) { |
| FieldElement fieldElement = null; |
| SimpleIdentifier fieldName2 = node.fieldName; |
| ClassElement enclosingClass2 = _resolver.enclosingClass; |
| fieldElement = ((enclosingClass2 as ClassElementImpl)).getField(fieldName2.name); |
| if (fieldElement == null) { |
| _resolver.reportError(CompileTimeErrorCode.INITIALIZER_FOR_NON_EXISTANT_FIELD, node, [fieldName2]); |
| } else if (!fieldElement.isSynthetic()) { |
| recordResolution(fieldName2, fieldElement); |
| if (fieldElement.isStatic()) { |
| _resolver.reportError(CompileTimeErrorCode.INITIALIZER_FOR_STATIC_FIELD, node, [fieldName2]); |
| } |
| } |
| return null; |
| } |
| Object visitConstructorName(ConstructorName node) { |
| Type2 type2 = node.type.type; |
| if (type2 is DynamicTypeImpl) { |
| return null; |
| } else if (type2 is! InterfaceType) { |
| ASTNode parent2 = node.parent; |
| if (parent2 is InstanceCreationExpression) { |
| if (((parent2 as InstanceCreationExpression)).isConst()) { |
| } else { |
| } |
| } else { |
| } |
| return null; |
| } |
| ClassElement classElement = ((type2 as InterfaceType)).element; |
| ConstructorElement constructor; |
| SimpleIdentifier name2 = node.name; |
| if (name2 == null) { |
| constructor = classElement.unnamedConstructor; |
| } else { |
| constructor = classElement.getNamedConstructor(name2.name); |
| name2.element = constructor; |
| } |
| node.element = constructor; |
| return null; |
| } |
| Object visitContinueStatement(ContinueStatement node) { |
| SimpleIdentifier labelNode = node.label; |
| LabelElementImpl labelElement = lookupLabel(node, labelNode); |
| if (labelElement != null && labelElement.isOnSwitchStatement()) { |
| _resolver.reportError(ResolverErrorCode.CONTINUE_LABEL_ON_SWITCH, labelNode, []); |
| } |
| return null; |
| } |
| Object visitExportDirective(ExportDirective node) { |
| Element element2 = node.element; |
| if (element2 is ExportElement) { |
| resolveCombinators(((element2 as ExportElement)).exportedLibrary, node.combinators); |
| } |
| return null; |
| } |
| Object visitFieldFormalParameter(FieldFormalParameter node) { |
| String fieldName = node.identifier.name; |
| ClassElement classElement = _resolver.enclosingClass; |
| if (classElement != null) { |
| FieldElement fieldElement = ((classElement as ClassElementImpl)).getField(fieldName); |
| if (fieldElement != null) { |
| if (!fieldElement.isSynthetic()) { |
| ParameterElement parameterElement = node.element; |
| if (parameterElement is FieldFormalParameterElementImpl) { |
| FieldFormalParameterElementImpl fieldFormal = parameterElement as FieldFormalParameterElementImpl; |
| fieldFormal.field = fieldElement; |
| Type2 declaredType = fieldFormal.type; |
| Type2 fieldType = fieldElement.type; |
| if (node.type == null) { |
| fieldFormal.type = fieldType; |
| } |
| if (fieldElement.isStatic()) { |
| _resolver.reportError(CompileTimeErrorCode.INITIALIZING_FORMAL_FOR_STATIC_FIELD, node, [fieldName]); |
| } else if (declaredType != null && fieldType != null && !declaredType.isAssignableTo(fieldType)) { |
| _resolver.reportError(StaticWarningCode.FIELD_INITIALIZER_WITH_INVALID_TYPE, node, [declaredType.name, fieldType.name]); |
| } |
| } |
| } |
| } else { |
| _resolver.reportError(CompileTimeErrorCode.INITIALIZING_FORMAL_FOR_NON_EXISTANT_FIELD, node, [fieldName]); |
| } |
| } |
| return super.visitFieldFormalParameter(node); |
| } |
| Object visitFunctionExpressionInvocation(FunctionExpressionInvocation node) => null; |
| Object visitImportDirective(ImportDirective node) { |
| SimpleIdentifier prefixNode = node.prefix; |
| if (prefixNode != null) { |
| String prefixName = prefixNode.name; |
| for (PrefixElement prefixElement in _resolver.definingLibrary.prefixes) { |
| if (prefixElement.name == prefixName) { |
| recordResolution(prefixNode, prefixElement); |
| break; |
| } |
| } |
| } |
| Element element2 = node.element; |
| if (element2 is ImportElement) { |
| resolveCombinators(((element2 as ImportElement)).importedLibrary, node.combinators); |
| } |
| return null; |
| } |
| Object visitIndexExpression(IndexExpression node) { |
| Type2 arrayType = getType(node.realTarget); |
| if (arrayType == null || arrayType.isDynamic()) { |
| return null; |
| } |
| String operator; |
| if (node.inSetterContext()) { |
| operator = sc.TokenType.INDEX_EQ.lexeme; |
| } else { |
| operator = sc.TokenType.INDEX.lexeme; |
| } |
| MethodElement member = lookUpMethod(arrayType, operator); |
| if (member == null) { |
| _resolver.reportError(StaticWarningCode.UNDEFINED_OPERATOR, node, [operator, arrayType.name]); |
| } else { |
| node.element = member; |
| } |
| return null; |
| } |
| Object visitInstanceCreationExpression(InstanceCreationExpression node) { |
| ConstructorElement invokedConstructor = node.constructorName.element; |
| node.element = invokedConstructor; |
| resolveNamedArguments(node.argumentList, invokedConstructor); |
| return null; |
| } |
| Object visitMethodInvocation(MethodInvocation node) { |
| SimpleIdentifier methodName2 = node.methodName; |
| Expression target = node.realTarget; |
| Element element; |
| if (target == null) { |
| element = _resolver.nameScope.lookup(methodName2, _resolver.definingLibrary); |
| if (element == null) { |
| ClassElement enclosingClass2 = _resolver.enclosingClass; |
| if (enclosingClass2 != null) { |
| InterfaceType enclosingType = enclosingClass2.type; |
| element = lookUpMethod(enclosingType, methodName2.name); |
| if (element == null) { |
| PropertyAccessorElement getter = lookUpGetter(enclosingType, methodName2.name); |
| if (getter != null) { |
| FunctionType getterType = getter.type; |
| if (getterType != null) { |
| Type2 returnType2 = getterType.returnType; |
| if (!isExecutableType(returnType2)) { |
| _resolver.reportError(StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION, methodName2, [methodName2.name]); |
| } |
| } |
| recordResolution(methodName2, getter); |
| return null; |
| } |
| } |
| } |
| } |
| } else { |
| Type2 targetType = getType(target); |
| if (targetType is InterfaceType) { |
| InterfaceType classType = targetType as InterfaceType; |
| element = lookUpMethod(classType, methodName2.name); |
| if (element == null) { |
| PropertyAccessorElement accessor = classType.getGetter(methodName2.name); |
| if (accessor != null) { |
| Type2 returnType3 = accessor.type.returnType; |
| if (!isExecutableType(returnType3)) { |
| _resolver.reportError(StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION, methodName2, [methodName2.name]); |
| return null; |
| } |
| element = accessor; |
| } |
| } |
| if (element == null && target is SuperExpression) { |
| _resolver.reportError(StaticTypeWarningCode.UNDEFINED_SUPER_METHOD, methodName2, [methodName2.name, targetType.element.name]); |
| return null; |
| } |
| } else if (target is SimpleIdentifier) { |
| Element targetElement = ((target as SimpleIdentifier)).element; |
| if (targetElement is PrefixElement) { |
| String name3 = "${((target as SimpleIdentifier)).name}.${methodName2}"; |
| Identifier functionName = new Identifier_8(name3); |
| element = _resolver.nameScope.lookup(functionName, _resolver.definingLibrary); |
| } else { |
| return null; |
| } |
| } else { |
| return null; |
| } |
| } |
| ExecutableElement invokedMethod = null; |
| if (element is PropertyAccessorElement) { |
| PropertyAccessorElement getter = element as PropertyAccessorElement; |
| FunctionType getterType = getter.type; |
| if (getterType != null) { |
| Type2 returnType4 = getterType.returnType; |
| if (!isExecutableType(returnType4)) { |
| _resolver.reportError(StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION, methodName2, [methodName2.name]); |
| } |
| } |
| recordResolution(methodName2, element); |
| return null; |
| } else if (element is ExecutableElement) { |
| invokedMethod = element as ExecutableElement; |
| } else { |
| if (element is PropertyInducingElement) { |
| PropertyAccessorElement getter2 = ((element as PropertyInducingElement)).getter; |
| FunctionType getterType = getter2.type; |
| if (getterType != null) { |
| Type2 returnType5 = getterType.returnType; |
| if (!isExecutableType(returnType5)) { |
| _resolver.reportError(StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION, methodName2, [methodName2.name]); |
| } |
| } |
| recordResolution(methodName2, element); |
| return null; |
| } else if (element is VariableElement) { |
| Type2 variableType = _resolver.overrideManager.getType(element); |
| if (variableType == null) { |
| variableType = ((element as VariableElement)).type; |
| } |
| if (!isExecutableType(variableType)) { |
| _resolver.reportError(StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION, methodName2, [methodName2.name]); |
| } |
| recordResolution(methodName2, element); |
| return null; |
| } else { |
| if (target == null) { |
| ClassElement enclosingClass3 = _resolver.enclosingClass; |
| if (enclosingClass3 == null) { |
| _resolver.reportError(StaticTypeWarningCode.UNDEFINED_FUNCTION, methodName2, [methodName2.name]); |
| } else if (element == null) { |
| _resolver.reportError(StaticTypeWarningCode.UNDEFINED_METHOD, methodName2, [methodName2.name, enclosingClass3.name]); |
| } else { |
| _resolver.reportError(StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION, methodName2, [methodName2.name]); |
| } |
| } else { |
| Type2 targetType = getType(target); |
| String targetTypeName = targetType == null ? null : targetType.name; |
| if (targetTypeName == null) { |
| _resolver.reportError(StaticTypeWarningCode.UNDEFINED_FUNCTION, methodName2, [methodName2.name]); |
| } else { |
| if (!doesClassDeclareNoSuchMethod(targetType.element)) { |
| _resolver.reportError(StaticTypeWarningCode.UNDEFINED_METHOD, methodName2, [methodName2.name, targetTypeName]); |
| } |
| } |
| } |
| return null; |
| } |
| } |
| recordResolution(methodName2, invokedMethod); |
| resolveNamedArguments(node.argumentList, invokedMethod); |
| return null; |
| } |
| Object visitPostfixExpression(PostfixExpression node) { |
| sc.Token operator2 = node.operator; |
| Type2 operandType = getType(node.operand); |
| if (operandType == null || operandType.isDynamic()) { |
| return null; |
| } |
| String methodName; |
| if (identical(operator2.type, sc.TokenType.PLUS_PLUS)) { |
| methodName = sc.TokenType.PLUS.lexeme; |
| } else { |
| methodName = sc.TokenType.MINUS.lexeme; |
| } |
| MethodElement member = lookUpMethod(operandType, methodName); |
| if (member == null) { |
| _resolver.reportError3(StaticWarningCode.UNDEFINED_OPERATOR, operator2, [methodName, operandType.name]); |
| } else { |
| node.element = member; |
| } |
| return null; |
| } |
| Object visitPrefixedIdentifier(PrefixedIdentifier node) { |
| SimpleIdentifier prefix2 = node.prefix; |
| SimpleIdentifier identifier2 = node.identifier; |
| Element prefixElement = prefix2.element; |
| if (prefixElement is PrefixElement) { |
| Element element = _resolver.nameScope.lookup(node, _resolver.definingLibrary); |
| if (element == null) { |
| return null; |
| } |
| recordResolution(identifier2, element); |
| return null; |
| } |
| if (prefixElement is ClassElement) { |
| Element memberElement; |
| if (node.identifier.inSetterContext()) { |
| memberElement = ((prefixElement as ClassElementImpl)).getSetter(identifier2.name); |
| } else { |
| memberElement = ((prefixElement as ClassElementImpl)).getGetter(identifier2.name); |
| } |
| if (memberElement == null) { |
| MethodElement methodElement = lookUpMethod(((prefixElement as ClassElement)).type, identifier2.name); |
| if (methodElement != null) { |
| recordResolution(identifier2, methodElement); |
| return null; |
| } |
| } |
| if (memberElement == null) { |
| reportGetterOrSetterNotFound(node, identifier2, prefixElement.name); |
| } else { |
| recordResolution(identifier2, memberElement); |
| } |
| return null; |
| } |
| Type2 variableType; |
| if (prefixElement is PropertyAccessorElement) { |
| PropertyAccessorElement accessor = prefixElement as PropertyAccessorElement; |
| FunctionType type2 = accessor.type; |
| if (type2 == null) { |
| return null; |
| } |
| if (accessor.isGetter()) { |
| variableType = type2.returnType; |
| } else { |
| variableType = type2.normalParameterTypes[0]; |
| } |
| if (variableType == null || variableType.isDynamic()) { |
| return null; |
| } |
| } else if (prefixElement is VariableElement) { |
| variableType = _resolver.overrideManager.getType(prefixElement); |
| if (variableType == null) { |
| variableType = ((prefixElement as VariableElement)).type; |
| } |
| if (variableType == null || variableType.isDynamic()) { |
| return null; |
| } |
| } else { |
| return null; |
| } |
| PropertyAccessorElement memberElement = null; |
| if (node.identifier.inSetterContext()) { |
| memberElement = lookUpSetter(variableType, identifier2.name); |
| } |
| if (memberElement == null && node.identifier.inGetterContext()) { |
| memberElement = lookUpGetter(variableType, identifier2.name); |
| } |
| if (memberElement == null) { |
| MethodElement methodElement = lookUpMethod(variableType, identifier2.name); |
| if (methodElement != null) { |
| recordResolution(identifier2, methodElement); |
| return null; |
| } |
| } |
| if (memberElement == null) { |
| reportGetterOrSetterNotFound(node, identifier2, variableType.element.name); |
| } else { |
| recordResolution(identifier2, memberElement); |
| } |
| return null; |
| } |
| Object visitPrefixExpression(PrefixExpression node) { |
| sc.Token operator2 = node.operator; |
| sc.TokenType operatorType = operator2.type; |
| if (operatorType.isUserDefinableOperator() || identical(operatorType, sc.TokenType.PLUS_PLUS) || identical(operatorType, sc.TokenType.MINUS_MINUS)) { |
| Type2 operandType = getType(node.operand); |
| if (operandType == null || operandType.isDynamic()) { |
| return null; |
| } |
| String methodName; |
| if (identical(operatorType, sc.TokenType.PLUS_PLUS)) { |
| methodName = sc.TokenType.PLUS.lexeme; |
| } else if (identical(operatorType, sc.TokenType.MINUS_MINUS)) { |
| methodName = sc.TokenType.MINUS.lexeme; |
| } else if (identical(operatorType, sc.TokenType.MINUS)) { |
| methodName = "unary-"; |
| } else { |
| methodName = operator2.lexeme; |
| } |
| MethodElement member = lookUpMethod(operandType, methodName); |
| if (member == null) { |
| _resolver.reportError3(StaticWarningCode.UNDEFINED_OPERATOR, operator2, [methodName, operandType.name]); |
| } else { |
| node.element = member; |
| } |
| } |
| return null; |
| } |
| Object visitPropertyAccess(PropertyAccess node) { |
| Type2 targetType = getType(node.realTarget); |
| if (targetType is! InterfaceType) { |
| return null; |
| } |
| SimpleIdentifier identifier = node.propertyName; |
| PropertyAccessorElement memberElement = null; |
| if (identifier.inSetterContext()) { |
| memberElement = lookUpSetter(targetType, identifier.name); |
| } |
| if (memberElement == null && identifier.inGetterContext()) { |
| memberElement = lookUpGetter(targetType, identifier.name); |
| } |
| if (memberElement == null) { |
| MethodElement methodElement = lookUpMethod(targetType, identifier.name); |
| if (methodElement != null) { |
| recordResolution(identifier, methodElement); |
| return null; |
| } |
| } |
| if (memberElement == null) { |
| if (!doesClassDeclareNoSuchMethod(targetType.element)) { |
| if (identifier.inSetterContext()) { |
| _resolver.reportError(StaticWarningCode.UNDEFINED_SETTER, identifier, [identifier.name, targetType.name]); |
| } else if (identifier.inGetterContext()) { |
| _resolver.reportError(StaticWarningCode.UNDEFINED_GETTER, identifier, [identifier.name, targetType.name]); |
| } else { |
| System.out.println("two ${identifier.name}"); |
| _resolver.reportError(StaticWarningCode.UNDEFINED_IDENTIFIER, identifier, [identifier.name]); |
| } |
| } |
| } else { |
| recordResolution(identifier, memberElement); |
| } |
| return null; |
| } |
| Object visitRedirectingConstructorInvocation(RedirectingConstructorInvocation node) { |
| ClassElement enclosingClass2 = _resolver.enclosingClass; |
| if (enclosingClass2 == null) { |
| return null; |
| } |
| SimpleIdentifier name = node.constructorName; |
| ConstructorElement element; |
| if (name == null) { |
| element = enclosingClass2.unnamedConstructor; |
| } else { |
| element = enclosingClass2.getNamedConstructor(name.name); |
| } |
| if (element == null) { |
| return null; |
| } |
| if (name != null) { |
| recordResolution(name, element); |
| } |
| node.element = element; |
| resolveNamedArguments(node.argumentList, element); |
| return null; |
| } |
| Object visitSimpleIdentifier(SimpleIdentifier node) { |
| if (node.element != null) { |
| return null; |
| } |
| Element element = _resolver.nameScope.lookup(node, _resolver.definingLibrary); |
| if (element is PropertyAccessorElement && node.inSetterContext()) { |
| PropertyInducingElement variable2 = ((element as PropertyAccessorElement)).variable; |
| if (variable2 != null) { |
| PropertyAccessorElement setter2 = variable2.setter; |
| if (setter2 != null) { |
| element = setter2; |
| } |
| } |
| } |
| ClassElement enclosingClass2 = _resolver.enclosingClass; |
| if (element == null && enclosingClass2 != null) { |
| InterfaceType enclosingType = enclosingClass2.type; |
| if (element == null && node.inSetterContext()) { |
| element = lookUpSetter(enclosingType, node.name); |
| } |
| if (element == null && node.inGetterContext()) { |
| element = lookUpGetter(enclosingType, node.name); |
| } |
| if (element == null) { |
| element = lookUpMethod(enclosingType, node.name); |
| } |
| } |
| if (element == null) { |
| if (!doesClassDeclareNoSuchMethod(enclosingClass2)) { |
| _resolver.reportError(StaticWarningCode.UNDEFINED_IDENTIFIER, node, [node.name]); |
| } |
| } |
| recordResolution(node, element); |
| return null; |
| } |
| Object visitSuperConstructorInvocation(SuperConstructorInvocation node) { |
| ClassElement enclosingClass2 = _resolver.enclosingClass; |
| if (enclosingClass2 == null) { |
| return null; |
| } |
| ClassElement superclass = getSuperclass(enclosingClass2); |
| if (superclass == null) { |
| return null; |
| } |
| SimpleIdentifier name = node.constructorName; |
| ConstructorElement element; |
| if (name == null) { |
| element = superclass.unnamedConstructor; |
| } else { |
| element = superclass.getNamedConstructor(name.name); |
| } |
| if (element == null) { |
| return null; |
| } |
| if (name != null) { |
| recordResolution(name, element); |
| } |
| node.element = element; |
| resolveNamedArguments(node.argumentList, element); |
| return null; |
| } |
| Object visitTypeParameter(TypeParameter node) { |
| TypeName bound2 = node.bound; |
| if (bound2 != null) { |
| TypeVariableElementImpl variable = node.name.element as TypeVariableElementImpl; |
| if (variable != null) { |
| variable.bound = bound2.type; |
| } |
| } |
| return null; |
| } |
| /** |
| * Return {@code true} if the passed {@link Element} is a {@link ClassElement} that declares a |
| * method "noSuchMethod". |
| * @param element the {@link Element} to evaluate |
| * @return {@code true} if the passed {@link Element} is a {@link ClassElement} that declares a |
| * method "noSuchMethod" |
| */ |
| bool doesClassDeclareNoSuchMethod(Element element) { |
| if (element == null) { |
| return false; |
| } |
| if (element is! ClassElementImpl) { |
| return false; |
| } |
| ClassElementImpl classElement = element as ClassElementImpl; |
| MethodElement method = classElement.lookUpMethod("noSuchMethod", _resolver.definingLibrary); |
| if (method == null) { |
| return false; |
| } |
| return true; |
| } |
| /** |
| * Search through the array of parameters for a parameter whose name matches the given name. |
| * Return the parameter with the given name, or {@code null} if there is no such parameter. |
| * @param parameters the parameters being searched |
| * @param name the name being searched for |
| * @return the parameter with the given name |
| */ |
| ParameterElement findNamedParameter(List<ParameterElement> parameters, String name2) { |
| for (ParameterElement parameter in parameters) { |
| if (identical(parameter.parameterKind, ParameterKind.NAMED)) { |
| String parameteName = parameter.name; |
| if (parameteName != null && parameteName == name2) { |
| return parameter; |
| } |
| } |
| } |
| return null; |
| } |
| /** |
| * Return the element representing the superclass of the given class. |
| * @param targetClass the class whose superclass is to be returned |
| * @return the element representing the superclass of the given class |
| */ |
| ClassElement getSuperclass(ClassElement targetClass) { |
| InterfaceType superType = targetClass.supertype; |
| if (superType == null) { |
| return null; |
| } |
| return superType.element; |
| } |
| /** |
| * Return the type of the given expression that is to be used for type analysis. |
| * @param expression the expression whose type is to be returned |
| * @return the type of the given expression |
| */ |
| Type2 getType(Expression expression) { |
| if (expression is NullLiteral) { |
| return _resolver.typeProvider.objectType; |
| } |
| return expression.staticType; |
| } |
| /** |
| * Return {@code true} if the given type represents an object that could be invoked using the call |
| * operator '()'. |
| * @param type the type being tested |
| * @return {@code true} if the given type represents an object that could be invoked |
| */ |
| bool isExecutableType(Type2 type) { |
| if (type.isDynamic() || (type is FunctionType) || type.isDartCoreFunction()) { |
| return true; |
| } else if (type is InterfaceType) { |
| ClassElement classElement = ((type as InterfaceType)).element; |
| MethodElement methodElement = classElement.lookUpMethod("call", _resolver.definingLibrary); |
| return methodElement != null; |
| } |
| return false; |
| } |
| /** |
| * Look up the getter with the given name in the given type. Return the element representing the |
| * getter that was found, or {@code null} if there is no getter with the given name. |
| * @param type the type in which the getter is defined |
| * @param getterName the name of the getter being looked up |
| * @return the element representing the getter that was found |
| */ |
| PropertyAccessorElement lookUpGetter(Type2 type, String getterName) { |
| type = resolveTypeVariable(type); |
| if (type is InterfaceType) { |
| InterfaceType interfaceType = type as InterfaceType; |
| PropertyAccessorElement accessor = interfaceType.lookUpGetter(getterName, _resolver.definingLibrary); |
| if (accessor != null) { |
| return accessor; |
| } |
| return lookUpGetterInInterfaces(interfaceType, getterName, new Set<ClassElement>()); |
| } |
| return null; |
| } |
| /** |
| * Look up the getter with the given name in the interfaces implemented by the given type, either |
| * directly or indirectly. Return the element representing the getter that was found, or{@code null} if there is no getter with the given name. |
| * @param targetType the type in which the getter might be defined |
| * @param getterName the name of the getter being looked up |
| * @param visitedInterfaces a set containing all of the interfaces that have been examined, used |
| * to prevent infinite recursion and to optimize the search |
| * @return the element representing the getter that was found |
| */ |
| PropertyAccessorElement lookUpGetterInInterfaces(InterfaceType targetType, String getterName, Set<ClassElement> visitedInterfaces) { |
| ClassElement targetClass = targetType.element; |
| if (visitedInterfaces.contains(targetClass)) { |
| return null; |
| } |
| javaSetAdd(visitedInterfaces, targetClass); |
| PropertyAccessorElement getter = targetType.getGetter(getterName); |
| if (getter != null) { |
| return getter; |
| } |
| for (InterfaceType interfaceType in targetType.interfaces) { |
| getter = lookUpGetterInInterfaces(interfaceType, getterName, visitedInterfaces); |
| if (getter != null) { |
| return getter; |
| } |
| } |
| InterfaceType superclass2 = targetType.superclass; |
| if (superclass2 == null) { |
| return null; |
| } |
| return lookUpGetterInInterfaces(superclass2, getterName, visitedInterfaces); |
| } |
| /** |
| * Look up the method or getter with the given name in the given type. Return the element |
| * representing the method or getter that was found, or {@code null} if there is no method or |
| * getter with the given name. |
| * @param type the type in which the method or getter is defined |
| * @param memberName the name of the method or getter being looked up |
| * @return the element representing the method or getter that was found |
| */ |
| ExecutableElement lookupGetterOrMethod(Type2 type, String memberName) { |
| type = resolveTypeVariable(type); |
| if (type is InterfaceType) { |
| InterfaceType interfaceType = type as InterfaceType; |
| ExecutableElement member = interfaceType.lookUpMethod(memberName, _resolver.definingLibrary); |
| if (member != null) { |
| return member; |
| } |
| member = interfaceType.lookUpGetter(memberName, _resolver.definingLibrary); |
| if (member != null) { |
| return member; |
| } |
| return lookUpGetterOrMethodInInterfaces(interfaceType, memberName, new Set<ClassElement>()); |
| } |
| return null; |
| } |
| /** |
| * Look up the method or getter with the given name in the interfaces implemented by the given |
| * type, either directly or indirectly. Return the element representing the method or getter that |
| * was found, or {@code null} if there is no method or getter with the given name. |
| * @param targetType the type in which the method or getter might be defined |
| * @param memberName the name of the method or getter being looked up |
| * @param visitedInterfaces a set containing all of the interfaces that have been examined, used |
| * to prevent infinite recursion and to optimize the search |
| * @return the element representing the method or getter that was found |
| */ |
| ExecutableElement lookUpGetterOrMethodInInterfaces(InterfaceType targetType, String memberName, Set<ClassElement> visitedInterfaces) { |
| ClassElement targetClass = targetType.element; |
| if (visitedInterfaces.contains(targetClass)) { |
| return null; |
| } |
| javaSetAdd(visitedInterfaces, targetClass); |
| 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) { |
| member = lookUpGetterOrMethodInInterfaces(interfaceType, memberName, visitedInterfaces); |
| if (member != null) { |
| return member; |
| } |
| } |
| InterfaceType superclass2 = targetType.superclass; |
| if (superclass2 == null) { |
| return null; |
| } |
| return lookUpGetterInInterfaces(superclass2, memberName, visitedInterfaces); |
| } |
| /** |
| * Find the element corresponding to the given label node in the current label scope. |
| * @param parentNode the node containing the given label |
| * @param labelNode the node representing the label being looked up |
| * @return the element corresponding to the given label node in the current scope |
| */ |
| LabelElementImpl lookupLabel(ASTNode parentNode, SimpleIdentifier labelNode) { |
| LabelScope labelScope2 = _resolver.labelScope; |
| LabelElementImpl labelElement = null; |
| if (labelNode == null) { |
| if (labelScope2 == null) { |
| } else { |
| labelElement = labelScope2.lookup2(LabelScope.EMPTY_LABEL) as LabelElementImpl; |
| if (labelElement == null) { |
| } |
| labelElement = null; |
| } |
| } else { |
| if (labelScope2 == null) { |
| _resolver.reportError(CompileTimeErrorCode.LABEL_UNDEFINED, labelNode, [labelNode.name]); |
| } else { |
| labelElement = labelScope2.lookup(labelNode) as LabelElementImpl; |
| if (labelElement == null) { |
| _resolver.reportError(CompileTimeErrorCode.LABEL_UNDEFINED, labelNode, [labelNode.name]); |
| } else { |
| recordResolution(labelNode, labelElement); |
| } |
| } |
| } |
| if (labelElement != null) { |
| ExecutableElement labelContainer = labelElement.getAncestor(ExecutableElement); |
| if (labelContainer != _resolver.enclosingFunction) { |
| _resolver.reportError(CompileTimeErrorCode.LABEL_IN_OUTER_SCOPE, labelNode, [labelNode.name]); |
| labelElement = null; |
| } |
| } |
| return labelElement; |
| } |
| /** |
| * Look up the method with the given name in the given type. Return the element representing the |
| * method that was found, or {@code null} if there is no method with the given name. |
| * @param type the type in which the method is defined |
| * @param methodName the name of the method being looked up |
| * @return the element representing the method that was found |
| */ |
| MethodElement lookUpMethod(Type2 type, String methodName) { |
| type = resolveTypeVariable(type); |
| if (type is InterfaceType) { |
| InterfaceType interfaceType = type as InterfaceType; |
| MethodElement method = interfaceType.lookUpMethod(methodName, _resolver.definingLibrary); |
| if (method != null) { |
| return method; |
| } |
| return lookUpMethodInInterfaces(interfaceType, methodName, new Set<ClassElement>()); |
| } |
| return null; |
| } |
| /** |
| * Look up the method with the given name in the interfaces implemented by the given type, either |
| * directly or indirectly. Return the element representing the method that was found, or{@code null} if there is no method with the given name. |
| * @param targetType the type in which the member might be defined |
| * @param methodName the name of the method being looked up |
| * @param visitedInterfaces a set containing all of the interfaces that have been examined, used |
| * to prevent infinite recursion and to optimize the search |
| * @return the element representing the method that was found |
| */ |
| MethodElement lookUpMethodInInterfaces(InterfaceType targetType, String methodName, Set<ClassElement> visitedInterfaces) { |
| ClassElement targetClass = targetType.element; |
| if (visitedInterfaces.contains(targetClass)) { |
| return null; |
| } |
| javaSetAdd(visitedInterfaces, targetClass); |
| MethodElement method = targetType.getMethod(methodName); |
| if (method != null) { |
| return method; |
| } |
| for (InterfaceType interfaceType in targetType.interfaces) { |
| method = lookUpMethodInInterfaces(interfaceType, methodName, visitedInterfaces); |
| if (method != null) { |
| return method; |
| } |
| } |
| InterfaceType superclass2 = targetType.superclass; |
| if (superclass2 == null) { |
| return null; |
| } |
| return lookUpMethodInInterfaces(superclass2, methodName, visitedInterfaces); |
| } |
| /** |
| * Look up the setter with the given name in the given type. Return the element representing the |
| * setter that was found, or {@code null} if there is no setter with the given name. |
| * @param type the type in which the setter is defined |
| * @param setterName the name of the setter being looked up |
| * @return the element representing the setter that was found |
| */ |
| PropertyAccessorElement lookUpSetter(Type2 type, String setterName) { |
| type = resolveTypeVariable(type); |
| if (type is InterfaceType) { |
| InterfaceType interfaceType = type as InterfaceType; |
| PropertyAccessorElement accessor = interfaceType.lookUpSetter(setterName, _resolver.definingLibrary); |
| if (accessor != null) { |
| return accessor; |
| } |
| return lookUpSetterInInterfaces(interfaceType, setterName, new Set<ClassElement>()); |
| } |
| return null; |
| } |
| /** |
| * Look up the setter with the given name in the interfaces implemented by the given type, either |
| * directly or indirectly. Return the element representing the setter that was found, or{@code null} if there is no setter with the given name. |
| * @param targetType the type in which the setter might be defined |
| * @param setterName the name of the setter being looked up |
| * @param visitedInterfaces a set containing all of the interfaces that have been examined, used |
| * to prevent infinite recursion and to optimize the search |
| * @return the element representing the setter that was found |
| */ |
| PropertyAccessorElement lookUpSetterInInterfaces(InterfaceType targetType, String setterName, Set<ClassElement> visitedInterfaces) { |
| ClassElement targetClass = targetType.element; |
| if (visitedInterfaces.contains(targetClass)) { |
| return null; |
| } |
| javaSetAdd(visitedInterfaces, targetClass); |
| PropertyAccessorElement setter = targetType.getGetter(setterName); |
| if (setter != null) { |
| return setter; |
| } |
| for (InterfaceType interfaceType in targetType.interfaces) { |
| setter = lookUpSetterInInterfaces(interfaceType, setterName, visitedInterfaces); |
| if (setter != null) { |
| return setter; |
| } |
| } |
| InterfaceType superclass2 = targetType.superclass; |
| if (superclass2 == null) { |
| return null; |
| } |
| return lookUpSetterInInterfaces(superclass2, setterName, visitedInterfaces); |
| } |
| /** |
| * Return the binary operator that is invoked by the given compound assignment operator. |
| * @param operator the assignment operator being mapped |
| * @return the binary operator that invoked by the given 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; |
| } |
| break; |
| } |
| AnalysisEngine.instance.logger.logError("Failed to map ${operator.lexeme} to it's corresponding operator"); |
| return operator; |
| } |
| /** |
| * Record the fact that the given AST node was resolved to the given element. |
| * @param node the AST node that was resolved |
| * @param element the element to which the AST node was resolved |
| */ |
| void recordResolution(SimpleIdentifier node, Element element2) { |
| if (element2 != null) { |
| node.element = element2; |
| } |
| } |
| /** |
| * Report the {@link StaticTypeWarningCode}s <code>UNDEFINED_SETTER</code> and <code>UNDEFINED_GETTER</code>. |
| * @param node the prefixed identifier that gives the context to determine if the error on the |
| * undefined identifier is a getter or a setter |
| * @param identifier the identifier in the passed prefix identifier |
| * @param typeName the name of the type of the left hand side of the passed prefixed identifier |
| */ |
| void reportGetterOrSetterNotFound(PrefixedIdentifier node, SimpleIdentifier identifier2, String typeName) { |
| Type2 targetType = getType(node); |
| if (targetType != null && doesClassDeclareNoSuchMethod(targetType.element)) { |
| return; |
| } |
| bool isSetterContext = node.identifier.inSetterContext(); |
| ErrorCode errorCode = isSetterContext ? StaticTypeWarningCode.UNDEFINED_SETTER : StaticTypeWarningCode.UNDEFINED_GETTER; |
| _resolver.reportError(errorCode, identifier2, [identifier2.name, typeName]); |
| } |
| /** |
| * Resolve the names in the given combinators in the scope of the given library. |
| * @param library the library that defines the names |
| * @param combinators the combinators containing the names to be resolved |
| */ |
| void resolveCombinators(LibraryElement library, NodeList<Combinator> combinators) { |
| if (library == null) { |
| return; |
| } |
| Namespace namespace = new NamespaceBuilder().createExportNamespace(library); |
| for (Combinator combinator in combinators) { |
| NodeList<SimpleIdentifier> names; |
| if (combinator is HideCombinator) { |
| names = ((combinator as HideCombinator)).hiddenNames; |
| } else { |
| names = ((combinator as ShowCombinator)).shownNames; |
| } |
| for (SimpleIdentifier name in names) { |
| Element element = namespace.get(name.name); |
| if (element != null) { |
| name.element = element; |
| } |
| } |
| } |
| } |
| /** |
| * Resolve the names associated with any named arguments to the parameter elements named by the |
| * argument. |
| * @param argumentList the arguments to be resolved |
| * @param invokedMethod the method or function defining the parameters to which the named |
| * arguments are to be resolved |
| */ |
| void resolveNamedArguments(ArgumentList argumentList, ExecutableElement invokedMethod) { |
| if (invokedMethod == null) { |
| return; |
| } |
| List<ParameterElement> parameters2 = invokedMethod.parameters; |
| for (Expression argument in argumentList.arguments) { |
| if (argument is NamedExpression) { |
| SimpleIdentifier name2 = ((argument as NamedExpression)).name.label; |
| ParameterElement parameter = findNamedParameter(parameters2, name2.name); |
| if (parameter != null) { |
| recordResolution(name2, parameter); |
| } |
| } |
| } |
| } |
| /** |
| * If the given type is a type variable, resolve it to the type that should be used when looking |
| * up members. Otherwise, return the original type. |
| * @param type the type that is to be resolved if it is a type variable |
| * @return the type that should be used in place of the argument if it is a type variable, or the |
| * original argument if it isn't a type variable |
| */ |
| Type2 resolveTypeVariable(Type2 type) { |
| if (type is TypeVariableType) { |
| Type2 bound2 = ((type as TypeVariableType)).element.bound; |
| if (bound2 == null) { |
| return _resolver.typeProvider.objectType; |
| } |
| return bound2; |
| } |
| return type; |
| } |
| } |
| class Identifier_8 extends Identifier { |
| String name3; |
| Identifier_8(this.name3) : super(); |
| accept(ASTVisitor visitor) => null; |
| sc.Token get beginToken => null; |
| Element get element => null; |
| sc.Token get endToken => null; |
| String get name => name3; |
| void visitChildren(ASTVisitor<Object> visitor) { |
| } |
| } |
| /** |
| * Instances of the class {@code Library} represent the data about a single library during the |
| * resolution of some (possibly different) library. They are not intended to be used except during |
| * the resolution process. |
| * @coverage dart.engine.resolver |
| */ |
| class Library { |
| /** |
| * The analysis context in which this library is being analyzed. |
| */ |
| InternalAnalysisContext _analysisContext; |
| /** |
| * The listener to which analysis errors will be reported. |
| */ |
| AnalysisErrorListener _errorListener; |
| /** |
| * The source specifying the defining compilation unit of this library. |
| */ |
| Source _librarySource; |
| /** |
| * The library element representing this library. |
| */ |
| LibraryElementImpl _libraryElement; |
| /** |
| * A list containing all of the libraries that are imported into this library. |
| */ |
| Map<ImportDirective, Library> _importedLibraries = new Map<ImportDirective, Library>(); |
| /** |
| * A flag indicating whether this library explicitly imports core. |
| */ |
| bool _explicitlyImportsCore = false; |
| /** |
| * A list containing all of the libraries that are exported from this library. |
| */ |
| Map<ExportDirective, Library> _exportedLibraries = new Map<ExportDirective, Library>(); |
| /** |
| * A table mapping the sources for the compilation units in this library to their corresponding |
| * AST structures. |
| */ |
| Map<Source, CompilationUnit> _astMap = new Map<Source, CompilationUnit>(); |
| /** |
| * The library scope used when resolving elements within this library's compilation units. |
| */ |
| LibraryScope _libraryScope; |
| /** |
| * Initialize a newly created data holder that can maintain the data associated with a library. |
| * @param analysisContext the analysis context in which this library is being analyzed |
| * @param errorListener the listener to which analysis errors will be reported |
| * @param librarySource the source specifying the defining compilation unit of this library |
| */ |
| Library(InternalAnalysisContext analysisContext, AnalysisErrorListener errorListener, Source librarySource) { |
| this._analysisContext = analysisContext; |
| this._errorListener = errorListener; |
| this._librarySource = librarySource; |
| this._libraryElement = analysisContext.getLibraryElement(librarySource) as LibraryElementImpl; |
| } |
| /** |
| * Record that the given library is exported from this library. |
| * @param importLibrary the library that is exported from this library |
| */ |
| void addExport(ExportDirective directive, Library exportLibrary) { |
| _exportedLibraries[directive] = exportLibrary; |
| } |
| /** |
| * Record that the given library is imported into this library. |
| * @param importLibrary the library that is imported into this library |
| */ |
| void addImport(ImportDirective directive, Library importLibrary) { |
| _importedLibraries[directive] = importLibrary; |
| } |
| /** |
| * Return the AST structure associated with the given source. |
| * @param source the source representing the compilation unit whose AST is to be returned |
| * @return the AST structure associated with the given source |
| * @throws AnalysisException if an AST structure could not be created for the compilation unit |
| */ |
| CompilationUnit getAST(Source source) { |
| CompilationUnit unit = _astMap[source]; |
| if (unit == null) { |
| unit = _analysisContext.computeResolvableCompilationUnit(source); |
| _astMap[source] = unit; |
| } |
| return unit; |
| } |
| /** |
| * Return a collection containing the sources for the compilation units in this library, including |
| * the defining compilation unit. |
| * @return the sources for the compilation units in this library |
| */ |
| Set<Source> get compilationUnitSources => _astMap.keys.toSet(); |
| /** |
| * Return the AST structure associated with the defining compilation unit for this library. |
| * @return the AST structure associated with the defining compilation unit for this library |
| * @throws AnalysisException if an AST structure could not be created for the defining compilation |
| * unit |
| */ |
| CompilationUnit get definingCompilationUnit => getAST(librarySource); |
| /** |
| * Return {@code true} if this library explicitly imports core. |
| * @return {@code true} if this library explicitly imports core |
| */ |
| bool get explicitlyImportsCore => _explicitlyImportsCore; |
| /** |
| * Return the library exported by the given directive. |
| * @param directive the directive that exports the library to be returned |
| * @return the library exported by the given directive |
| */ |
| Library getExport(ExportDirective directive) => _exportedLibraries[directive]; |
| /** |
| * Return an array containing the libraries that are exported from this library. |
| * @return an array containing the libraries that are exported from this library |
| */ |
| List<Library> get exports { |
| Set<Library> libraries = new Set<Library>(); |
| libraries.addAll(_exportedLibraries.values); |
| return new List.from(libraries); |
| } |
| /** |
| * Return the library imported by the given directive. |
| * @param directive the directive that imports the library to be returned |
| * @return the library imported by the given directive |
| */ |
| Library getImport(ImportDirective directive) => _importedLibraries[directive]; |
| /** |
| * Return an array containing the libraries that are imported into this library. |
| * @return an array containing the libraries that are imported into this library |
| */ |
| List<Library> get imports { |
| Set<Library> libraries = new Set<Library>(); |
| libraries.addAll(_importedLibraries.values); |
| return new List.from(libraries); |
| } |
| /** |
| * Return an array containing the libraries that are either imported or exported from this |
| * library. |
| * @return the libraries that are either imported or exported from this library |
| */ |
| List<Library> get importsAndExports { |
| Set<Library> libraries = new Set<Library>(); |
| libraries.addAll(_importedLibraries.values); |
| libraries.addAll(_exportedLibraries.values); |
| return new List.from(libraries); |
| } |
| /** |
| * Return the library element representing this library, creating it if necessary. |
| * @return the library element representing this library |
| */ |
| LibraryElementImpl get libraryElement { |
| if (_libraryElement == null) { |
| try { |
| _libraryElement = _analysisContext.computeLibraryElement(_librarySource) as LibraryElementImpl; |
| } on AnalysisException catch (exception) { |
| AnalysisEngine.instance.logger.logError2("Could not compute ilbrary element for ${_librarySource.fullName}", exception); |
| } |
| } |
| return _libraryElement; |
| } |
| /** |
| * Return the library scope used when resolving elements within this library's compilation units. |
| * @return the library scope used when resolving elements within this library's compilation units |
| */ |
| LibraryScope get libraryScope { |
| if (_libraryScope == null) { |
| _libraryScope = new LibraryScope(_libraryElement, _errorListener); |
| } |
| return _libraryScope; |
| } |
| /** |
| * Return the source specifying the defining compilation unit of this library. |
| * @return the source specifying the defining compilation unit of this library |
| */ |
| Source get librarySource => _librarySource; |
| /** |
| * Return the result of resolving the given URI against the URI of the library, or {@code null} if |
| * the URI is not valid. If the URI is not valid, report the error. |
| * @param uriLiteral the string literal specifying the URI to be resolved |
| * @return the result of resolving the given URI against the URI of the library |
| */ |
| Source getSource(StringLiteral uriLiteral) { |
| if (uriLiteral is StringInterpolation) { |
| _errorListener.onError(new AnalysisError.con2(_librarySource, uriLiteral.offset, uriLiteral.length, CompileTimeErrorCode.URI_WITH_INTERPOLATION, [])); |
| return null; |
| } |
| Source source = getSource2(getStringValue(uriLiteral)); |
| if (source == null || !source.exists()) { |
| _errorListener.onError(new AnalysisError.con2(_librarySource, uriLiteral.offset, uriLiteral.length, CompileTimeErrorCode.INVALID_URI, [uriLiteral.toSource()])); |
| } |
| return source; |
| } |
| /** |
| * Set whether this library explicitly imports core to match the given value. |
| * @param explicitlyImportsCore {@code true} if this library explicitly imports core |
| */ |
| void set explicitlyImportsCore(bool explicitlyImportsCore2) { |
| this._explicitlyImportsCore = explicitlyImportsCore2; |
| } |
| /** |
| * Set the library element representing this library to the given library element. |
| * @param libraryElement the library element representing this library |
| */ |
| void set libraryElement(LibraryElementImpl libraryElement2) { |
| this._libraryElement = libraryElement2; |
| } |
| String toString() => _librarySource.shortName; |
| /** |
| * Append the value of the given string literal to the given string builder. |
| * @param builder the builder to which the string's value is to be appended |
| * @param literal the string literal whose value is to be appended to the builder |
| * @throws IllegalArgumentException if the string is not a constant string without any string |
| * interpolation |
| */ |
| |