blob: fc7b84d16f33e328f44b400c28a9d9a7c25ec549 [file] [log] [blame]
// 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
*/