blob: 1abdc296210ad1f7b0063824086f964a51e6bcf5 [file] [log] [blame]
/*
* Copyright (c) 2013, the Dart project authors.
*
* Licensed under the Eclipse Public License v1.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.eclipse.org/legal/epl-v10.html
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.dart.engine.internal.resolver;
import com.google.dart.engine.EngineTestCase;
import com.google.dart.engine.ast.AssignmentExpression;
import com.google.dart.engine.ast.AstNode;
import com.google.dart.engine.ast.BinaryExpression;
import com.google.dart.engine.ast.BreakStatement;
import com.google.dart.engine.ast.ConstructorName;
import com.google.dart.engine.ast.ContinueStatement;
import com.google.dart.engine.ast.ExportDirective;
import com.google.dart.engine.ast.FieldFormalParameter;
import com.google.dart.engine.ast.Identifier;
import com.google.dart.engine.ast.ImportDirective;
import com.google.dart.engine.ast.IndexExpression;
import com.google.dart.engine.ast.InstanceCreationExpression;
import com.google.dart.engine.ast.MethodInvocation;
import com.google.dart.engine.ast.NamedExpression;
import com.google.dart.engine.ast.PostfixExpression;
import com.google.dart.engine.ast.PrefixExpression;
import com.google.dart.engine.ast.PrefixedIdentifier;
import com.google.dart.engine.ast.PropertyAccess;
import com.google.dart.engine.ast.ShowCombinator;
import com.google.dart.engine.ast.SimpleIdentifier;
import com.google.dart.engine.ast.Statement;
import com.google.dart.engine.ast.SuperConstructorInvocation;
import com.google.dart.engine.ast.SuperExpression;
import com.google.dart.engine.ast.ThisExpression;
import com.google.dart.engine.element.ClassElement;
import com.google.dart.engine.element.ConstructorElement;
import com.google.dart.engine.element.Element;
import com.google.dart.engine.element.FieldElement;
import com.google.dart.engine.element.ImportElement;
import com.google.dart.engine.element.MethodElement;
import com.google.dart.engine.element.ParameterElement;
import com.google.dart.engine.element.PropertyAccessorElement;
import com.google.dart.engine.element.TopLevelVariableElement;
import com.google.dart.engine.error.GatheringErrorListener;
import com.google.dart.engine.internal.context.AnalysisContextImpl;
import com.google.dart.engine.internal.element.ClassElementImpl;
import com.google.dart.engine.internal.element.CompilationUnitElementImpl;
import com.google.dart.engine.internal.element.ConstructorElementImpl;
import com.google.dart.engine.internal.element.FieldElementImpl;
import com.google.dart.engine.internal.element.FieldFormalParameterElementImpl;
import com.google.dart.engine.internal.element.LabelElementImpl;
import com.google.dart.engine.internal.element.LibraryElementImpl;
import com.google.dart.engine.internal.element.MethodElementImpl;
import com.google.dart.engine.internal.element.TopLevelVariableElementImpl;
import com.google.dart.engine.internal.element.VariableElementImpl;
import com.google.dart.engine.internal.scope.ClassScope;
import com.google.dart.engine.internal.scope.EnclosedScope;
import com.google.dart.engine.internal.scope.LabelScope;
import com.google.dart.engine.internal.scope.Scope;
import com.google.dart.engine.internal.scope.TypeParameterScope;
import com.google.dart.engine.scanner.Keyword;
import com.google.dart.engine.scanner.TokenType;
import com.google.dart.engine.sdk.DirectoryBasedDartSdk;
import com.google.dart.engine.source.DartUriResolver;
import com.google.dart.engine.source.FileBasedSource;
import com.google.dart.engine.source.SourceFactory;
import com.google.dart.engine.type.InterfaceType;
import com.google.dart.engine.type.Type;
import com.google.dart.engine.utilities.io.FileUtilities2;
import static com.google.dart.engine.ast.AstFactory.assignmentExpression;
import static com.google.dart.engine.ast.AstFactory.binaryExpression;
import static com.google.dart.engine.ast.AstFactory.breakStatement;
import static com.google.dart.engine.ast.AstFactory.constructorName;
import static com.google.dart.engine.ast.AstFactory.continueStatement;
import static com.google.dart.engine.ast.AstFactory.exportDirective;
import static com.google.dart.engine.ast.AstFactory.expressionFunctionBody;
import static com.google.dart.engine.ast.AstFactory.fieldFormalParameter;
import static com.google.dart.engine.ast.AstFactory.formalParameterList;
import static com.google.dart.engine.ast.AstFactory.hideCombinator;
import static com.google.dart.engine.ast.AstFactory.identifier;
import static com.google.dart.engine.ast.AstFactory.importDirective;
import static com.google.dart.engine.ast.AstFactory.indexExpression;
import static com.google.dart.engine.ast.AstFactory.instanceCreationExpression;
import static com.google.dart.engine.ast.AstFactory.integer;
import static com.google.dart.engine.ast.AstFactory.methodDeclaration;
import static com.google.dart.engine.ast.AstFactory.methodInvocation;
import static com.google.dart.engine.ast.AstFactory.namedExpression;
import static com.google.dart.engine.ast.AstFactory.nullLiteral;
import static com.google.dart.engine.ast.AstFactory.postfixExpression;
import static com.google.dart.engine.ast.AstFactory.prefixExpression;
import static com.google.dart.engine.ast.AstFactory.propertyAccess;
import static com.google.dart.engine.ast.AstFactory.showCombinator;
import static com.google.dart.engine.ast.AstFactory.superConstructorInvocation;
import static com.google.dart.engine.ast.AstFactory.superExpression;
import static com.google.dart.engine.ast.AstFactory.thisExpression;
import static com.google.dart.engine.ast.AstFactory.typeName;
import static com.google.dart.engine.element.ElementFactory.classElement;
import static com.google.dart.engine.element.ElementFactory.constructorElement;
import static com.google.dart.engine.element.ElementFactory.exportFor;
import static com.google.dart.engine.element.ElementFactory.fieldElement;
import static com.google.dart.engine.element.ElementFactory.fieldFormalParameter;
import static com.google.dart.engine.element.ElementFactory.getterElement;
import static com.google.dart.engine.element.ElementFactory.importFor;
import static com.google.dart.engine.element.ElementFactory.library;
import static com.google.dart.engine.element.ElementFactory.localVariableElement;
import static com.google.dart.engine.element.ElementFactory.methodElement;
import static com.google.dart.engine.element.ElementFactory.namedParameter;
import static com.google.dart.engine.element.ElementFactory.prefix;
import static com.google.dart.engine.element.ElementFactory.setterElement;
import static com.google.dart.engine.element.ElementFactory.topLevelVariableElement;
import java.lang.reflect.Field;
public class ElementResolverTest extends EngineTestCase {
/**
* The error listener to which errors will be reported.
*/
private GatheringErrorListener listener;
/**
* The type provider used to access the types.
*/
private TestTypeProvider typeProvider;
/**
* The library containing the code being resolved.
*/
private LibraryElementImpl definingLibrary;
/**
* The resolver visitor that maintains the state for the resolver.
*/
private ResolverVisitor visitor;
/**
* The resolver being used to resolve the test cases.
*/
private ElementResolver resolver;
public void fail_visitExportDirective_combinators() {
fail("Not yet tested");
// Need to set up the exported library so that the identifier can be resolved
ExportDirective directive = exportDirective(null, hideCombinator("A"));
resolveNode(directive);
listener.assertNoErrors();
}
public void fail_visitFunctionExpressionInvocation() {
fail("Not yet tested");
listener.assertNoErrors();
}
public void fail_visitImportDirective_combinators_noPrefix() {
fail("Not yet tested");
// Need to set up the imported library so that the identifier can be resolved
ImportDirective directive = importDirective(null, null, showCombinator("A"));
resolveNode(directive);
listener.assertNoErrors();
}
public void fail_visitImportDirective_combinators_prefix() {
fail("Not yet tested");
// Need to set up the imported library so that the identifiers can be resolved
String prefixName = "p";
definingLibrary.setImports(new ImportElement[] {importFor(null, prefix(prefixName))});
ImportDirective directive = importDirective(
null,
prefixName,
showCombinator("A"),
hideCombinator("B"));
resolveNode(directive);
listener.assertNoErrors();
}
public void fail_visitRedirectingConstructorInvocation() throws Exception {
fail("Not yet tested");
listener.assertNoErrors();
}
@Override
public void setUp() {
listener = new GatheringErrorListener();
typeProvider = new TestTypeProvider();
resolver = createResolver();
}
public void test_lookUpMethodInInterfaces() throws Exception {
InterfaceType intType = typeProvider.getIntType();
//
// abstract class A { int operator[](int index); }
//
ClassElementImpl classA = classElement("A");
MethodElement operator = methodElement("[]", intType, intType);
classA.setMethods(new MethodElement[] {operator});
//
// class B implements A {}
//
ClassElementImpl classB = classElement("B");
classB.setInterfaces(new InterfaceType[] {classA.getType()});
//
// class C extends Object with B {}
//
ClassElementImpl classC = classElement("C");
classC.setMixins(new InterfaceType[] {classB.getType()});
//
// class D extends C {}
//
ClassElementImpl classD = classElement("D", classC.getType());
//
// D a;
// a[i];
//
SimpleIdentifier array = identifier("a");
array.setStaticType(classD.getType());
IndexExpression expression = indexExpression(array, identifier("i"));
assertSame(operator, resolveIndexExpression(expression));
listener.assertNoErrors();
}
public void test_visitAssignmentExpression_compound() throws Exception {
InterfaceType intType = typeProvider.getIntType();
SimpleIdentifier leftHandSide = identifier("a");
leftHandSide.setStaticType(intType);
AssignmentExpression assignment = assignmentExpression(
leftHandSide,
TokenType.PLUS_EQ,
integer(1L));
resolveNode(assignment);
assertSame(getMethod(typeProvider.getNumType(), "+"), assignment.getStaticElement());
listener.assertNoErrors();
}
public void test_visitAssignmentExpression_simple() throws Exception {
AssignmentExpression expression = assignmentExpression(
identifier("x"),
TokenType.EQ,
integer(0));
resolveNode(expression);
assertNull(expression.getStaticElement());
listener.assertNoErrors();
}
public void test_visitBinaryExpression() throws Exception { // _found and _notFound?
// num i;
// var j;
// i + j
InterfaceType numType = typeProvider.getNumType();
SimpleIdentifier left = identifier("i");
left.setStaticType(numType);
BinaryExpression expression = binaryExpression(left, TokenType.PLUS, identifier("j"));
resolveNode(expression);
assertEquals(getMethod(numType, "+"), expression.getStaticElement());
assertNull(expression.getPropagatedElement());
listener.assertNoErrors();
}
public void test_visitBinaryExpression_propagatedElement() throws Exception {
// var i = 1;
// var j;
// i + j
InterfaceType numType = typeProvider.getNumType();
SimpleIdentifier left = identifier("i");
left.setPropagatedType(numType);
BinaryExpression expression = binaryExpression(left, TokenType.PLUS, identifier("j"));
resolveNode(expression);
assertNull(expression.getStaticElement());
assertEquals(getMethod(numType, "+"), expression.getPropagatedElement());
listener.assertNoErrors();
}
public void test_visitBreakStatement_withLabel() throws Exception {
String label = "loop";
LabelElementImpl labelElement = new LabelElementImpl(identifier(label), false, false);
BreakStatement statement = breakStatement(label);
assertSame(labelElement, resolveBreak(statement, labelElement));
listener.assertNoErrors();
}
public void test_visitBreakStatement_withoutLabel() throws Exception {
BreakStatement statement = breakStatement();
resolveStatement(statement, null);
listener.assertNoErrors();
}
public void test_visitConstructorName_named() {
ClassElementImpl classA = classElement("A");
String constructorName = "a";
ConstructorElement constructor = constructorElement(classA, constructorName);
classA.setConstructors(new ConstructorElement[] {constructor});
ConstructorName name = constructorName(typeName(classA), constructorName);
resolveNode(name);
assertSame(constructor, name.getStaticElement());
listener.assertNoErrors();
}
public void test_visitConstructorName_unnamed() {
ClassElementImpl classA = classElement("A");
String constructorName = null;
ConstructorElement constructor = constructorElement(classA, constructorName);
classA.setConstructors(new ConstructorElement[] {constructor});
ConstructorName name = constructorName(typeName(classA), constructorName);
resolveNode(name);
assertSame(constructor, name.getStaticElement());
listener.assertNoErrors();
}
public void test_visitContinueStatement_withLabel() throws Exception {
String label = "loop";
LabelElementImpl labelElement = new LabelElementImpl(identifier(label), false, false);
ContinueStatement statement = continueStatement(label);
assertSame(labelElement, resolveContinue(statement, labelElement));
listener.assertNoErrors();
}
public void test_visitContinueStatement_withoutLabel() throws Exception {
ContinueStatement statement = continueStatement();
resolveStatement(statement, null);
listener.assertNoErrors();
}
public void test_visitExportDirective_noCombinators() {
ExportDirective directive = exportDirective(null);
directive.setElement(exportFor(library(definingLibrary.getContext(), "lib")));
resolveNode(directive);
listener.assertNoErrors();
}
public void test_visitFieldFormalParameter() throws Exception {
String fieldName = "f";
InterfaceType intType = typeProvider.getIntType();
FieldElementImpl fieldElement = fieldElement(fieldName, false, false, false, intType);
ClassElementImpl classA = classElement("A");
classA.setFields(new FieldElement[] {fieldElement});
FieldFormalParameter parameter = fieldFormalParameter(fieldName);
FieldFormalParameterElementImpl parameterElement = fieldFormalParameter(parameter.getIdentifier());
parameterElement.setField(fieldElement);
parameterElement.setType(intType);
parameter.getIdentifier().setStaticElement(parameterElement);
resolveInClass(parameter, classA);
assertSame(intType, parameter.getElement().getType());
}
public void test_visitImportDirective_noCombinators_noPrefix() {
ImportDirective directive = importDirective(null, null);
directive.setElement(importFor(library(definingLibrary.getContext(), "lib"), null));
resolveNode(directive);
listener.assertNoErrors();
}
public void test_visitImportDirective_noCombinators_prefix() {
String prefixName = "p";
ImportElement importElement = importFor(
library(definingLibrary.getContext(), "lib"),
prefix(prefixName));
definingLibrary.setImports(new ImportElement[] {importElement});
ImportDirective directive = importDirective(null, prefixName);
directive.setElement(importElement);
resolveNode(directive);
listener.assertNoErrors();
}
public void test_visitImportDirective_withCombinators() {
ShowCombinator combinator = showCombinator("A", "B", "C");
ImportDirective directive = importDirective(null, null, combinator);
LibraryElementImpl library = library(definingLibrary.getContext(), "lib");
TopLevelVariableElementImpl varA = topLevelVariableElement("A");
TopLevelVariableElementImpl varB = topLevelVariableElement("B");
TopLevelVariableElementImpl varC = topLevelVariableElement("C");
CompilationUnitElementImpl unit = (CompilationUnitElementImpl) library.getDefiningCompilationUnit();
unit.setAccessors(new PropertyAccessorElement[] {
varA.getGetter(), varA.getSetter(), varB.getGetter(), varC.getSetter()});
unit.setTopLevelVariables(new TopLevelVariableElement[] {varA, varB, varC});
directive.setElement(importFor(library, null));
resolveNode(directive);
assertSame(varA, combinator.getShownNames().get(0).getStaticElement());
assertSame(varB, combinator.getShownNames().get(1).getStaticElement());
assertSame(varC, combinator.getShownNames().get(2).getStaticElement());
listener.assertNoErrors();
}
public void test_visitIndexExpression_get() throws Exception {
ClassElementImpl classA = classElement("A");
InterfaceType intType = typeProvider.getIntType();
MethodElement getter = methodElement("[]", intType, intType);
classA.setMethods(new MethodElement[] {getter});
SimpleIdentifier array = identifier("a");
array.setStaticType(classA.getType());
IndexExpression expression = indexExpression(array, identifier("i"));
assertSame(getter, resolveIndexExpression(expression));
listener.assertNoErrors();
}
public void test_visitIndexExpression_set() throws Exception {
ClassElementImpl classA = classElement("A");
InterfaceType intType = typeProvider.getIntType();
MethodElement setter = methodElement("[]=", intType, intType);
classA.setMethods(new MethodElement[] {setter});
SimpleIdentifier array = identifier("a");
array.setStaticType(classA.getType());
IndexExpression expression = indexExpression(array, identifier("i"));
assignmentExpression(expression, TokenType.EQ, integer(0L));
assertSame(setter, resolveIndexExpression(expression));
listener.assertNoErrors();
}
public void test_visitInstanceCreationExpression_named() {
ClassElementImpl classA = classElement("A");
String constructorName = "a";
ConstructorElement constructor = constructorElement(classA, constructorName);
classA.setConstructors(new ConstructorElement[] {constructor});
ConstructorName name = constructorName(typeName(classA), constructorName);
name.setStaticElement(constructor);
InstanceCreationExpression creation = instanceCreationExpression(Keyword.NEW, name);
resolveNode(creation);
assertSame(constructor, creation.getStaticElement());
listener.assertNoErrors();
}
public void test_visitInstanceCreationExpression_unnamed() {
ClassElementImpl classA = classElement("A");
String constructorName = null;
ConstructorElement constructor = constructorElement(classA, constructorName);
classA.setConstructors(new ConstructorElement[] {constructor});
ConstructorName name = constructorName(typeName(classA), constructorName);
name.setStaticElement(constructor);
InstanceCreationExpression creation = instanceCreationExpression(Keyword.NEW, name);
resolveNode(creation);
assertSame(constructor, creation.getStaticElement());
listener.assertNoErrors();
}
public void test_visitInstanceCreationExpression_unnamed_namedParameter() {
ClassElementImpl classA = classElement("A");
String constructorName = null;
ConstructorElementImpl constructor = constructorElement(classA, constructorName);
String parameterName = "a";
ParameterElement parameter = namedParameter(parameterName);
constructor.setParameters(new ParameterElement[] {parameter});
classA.setConstructors(new ConstructorElement[] {constructor});
ConstructorName name = constructorName(typeName(classA), constructorName);
name.setStaticElement(constructor);
InstanceCreationExpression creation = instanceCreationExpression(
Keyword.NEW,
name,
namedExpression(parameterName, integer(0)));
resolveNode(creation);
assertSame(constructor, creation.getStaticElement());
assertSame(
parameter,
((NamedExpression) creation.getArgumentList().getArguments().get(0)).getName().getLabel().getStaticElement());
listener.assertNoErrors();
}
public void test_visitMethodInvocation() throws Exception {
InterfaceType numType = typeProvider.getNumType();
SimpleIdentifier left = identifier("i");
left.setStaticType(numType);
String methodName = "abs";
MethodInvocation invocation = methodInvocation(left, methodName);
resolveNode(invocation);
assertSame(getMethod(numType, methodName), invocation.getMethodName().getStaticElement());
listener.assertNoErrors();
}
public void test_visitMethodInvocation_namedParameter() throws Exception {
ClassElementImpl classA = classElement("A");
String methodName = "m";
String parameterName = "p";
MethodElementImpl method = methodElement(methodName, null);
ParameterElement parameter = namedParameter(parameterName);
method.setParameters(new ParameterElement[] {parameter});
classA.setMethods(new MethodElement[] {method});
SimpleIdentifier left = identifier("i");
left.setStaticType(classA.getType());
MethodInvocation invocation = methodInvocation(
left,
methodName,
namedExpression(parameterName, integer(0)));
resolveNode(invocation);
assertSame(method, invocation.getMethodName().getStaticElement());
assertSame(
parameter,
((NamedExpression) invocation.getArgumentList().getArguments().get(0)).getName().getLabel().getStaticElement());
listener.assertNoErrors();
}
public void test_visitPostfixExpression() throws Exception {
InterfaceType numType = typeProvider.getNumType();
SimpleIdentifier operand = identifier("i");
operand.setStaticType(numType);
PostfixExpression expression = postfixExpression(operand, TokenType.PLUS_PLUS);
resolveNode(expression);
assertEquals(getMethod(numType, "+"), expression.getStaticElement());
listener.assertNoErrors();
}
public void test_visitPrefixedIdentifier_dynamic() throws Exception {
Type dynamicType = typeProvider.getDynamicType();
SimpleIdentifier target = identifier("a");
VariableElementImpl variable = localVariableElement(target);
variable.setType(dynamicType);
target.setStaticElement(variable);
target.setStaticType(dynamicType);
PrefixedIdentifier identifier = identifier(target, identifier("b"));
resolveNode(identifier);
assertNull(identifier.getStaticElement());
assertNull(identifier.getIdentifier().getStaticElement());
listener.assertNoErrors();
}
public void test_visitPrefixedIdentifier_nonDynamic() throws Exception {
ClassElementImpl classA = classElement("A");
String getterName = "b";
PropertyAccessorElement getter = getterElement(getterName, false, typeProvider.getIntType());
classA.setAccessors(new PropertyAccessorElement[] {getter});
SimpleIdentifier target = identifier("a");
VariableElementImpl variable = localVariableElement(target);
variable.setType(classA.getType());
target.setStaticElement(variable);
target.setStaticType(classA.getType());
PrefixedIdentifier identifier = identifier(target, identifier(getterName));
resolveNode(identifier);
assertSame(getter, identifier.getStaticElement());
assertSame(getter, identifier.getIdentifier().getStaticElement());
listener.assertNoErrors();
}
public void test_visitPrefixedIdentifier_staticClassMember_getter() throws Exception {
ClassElementImpl classA = classElement("A");
// set accessors
String propName = "b";
PropertyAccessorElement getter = getterElement(propName, false, typeProvider.getIntType());
PropertyAccessorElement setter = setterElement(propName, false, typeProvider.getIntType());
classA.setAccessors(new PropertyAccessorElement[] {getter, setter});
// prepare "A.m"
SimpleIdentifier target = identifier("A");
target.setStaticElement(classA);
target.setStaticType(classA.getType());
PrefixedIdentifier identifier = identifier(target, identifier(propName));
// resolve
resolveNode(identifier);
assertSame(getter, identifier.getStaticElement());
assertSame(getter, identifier.getIdentifier().getStaticElement());
listener.assertNoErrors();
}
public void test_visitPrefixedIdentifier_staticClassMember_method() throws Exception {
ClassElementImpl classA = classElement("A");
// set accessors
String propName = "m";
PropertyAccessorElement setter = setterElement(propName, false, typeProvider.getIntType());
classA.setAccessors(new PropertyAccessorElement[] {setter});
// set methods
MethodElement method = methodElement("m", typeProvider.getIntType());
classA.setMethods(new MethodElement[] {method});
// prepare "A.m"
SimpleIdentifier target = identifier("A");
target.setStaticElement(classA);
target.setStaticType(classA.getType());
PrefixedIdentifier identifier = identifier(target, identifier(propName));
assignmentExpression(identifier, TokenType.EQ, nullLiteral());
// resolve
resolveNode(identifier);
assertSame(method, identifier.getStaticElement());
assertSame(method, identifier.getIdentifier().getStaticElement());
listener.assertNoErrors();
}
public void test_visitPrefixedIdentifier_staticClassMember_setter() throws Exception {
ClassElementImpl classA = classElement("A");
// set accessors
String propName = "b";
PropertyAccessorElement getter = getterElement(propName, false, typeProvider.getIntType());
PropertyAccessorElement setter = setterElement(propName, false, typeProvider.getIntType());
classA.setAccessors(new PropertyAccessorElement[] {getter, setter});
// prepare "A.b = null"
SimpleIdentifier target = identifier("A");
target.setStaticElement(classA);
target.setStaticType(classA.getType());
PrefixedIdentifier identifier = identifier(target, identifier(propName));
assignmentExpression(identifier, TokenType.EQ, nullLiteral());
// resolve
resolveNode(identifier);
assertSame(setter, identifier.getStaticElement());
assertSame(setter, identifier.getIdentifier().getStaticElement());
listener.assertNoErrors();
}
public void test_visitPrefixExpression() throws Exception {
InterfaceType numType = typeProvider.getNumType();
SimpleIdentifier operand = identifier("i");
operand.setStaticType(numType);
PrefixExpression expression = prefixExpression(TokenType.PLUS_PLUS, operand);
resolveNode(expression);
assertEquals(getMethod(numType, "+"), expression.getStaticElement());
listener.assertNoErrors();
}
public void test_visitPropertyAccess_getter_identifier() throws Exception {
ClassElementImpl classA = classElement("A");
String getterName = "b";
PropertyAccessorElement getter = getterElement(getterName, false, typeProvider.getIntType());
classA.setAccessors(new PropertyAccessorElement[] {getter});
SimpleIdentifier target = identifier("a");
target.setStaticType(classA.getType());
PropertyAccess access = propertyAccess(target, getterName);
resolveNode(access);
assertSame(getter, access.getPropertyName().getStaticElement());
listener.assertNoErrors();
}
public void test_visitPropertyAccess_getter_super() throws Exception {
//
// class A {
// int get b;
// }
// class B {
// ... super.m ...
// }
//
ClassElementImpl classA = classElement("A");
String getterName = "b";
PropertyAccessorElement getter = getterElement(getterName, false, typeProvider.getIntType());
classA.setAccessors(new PropertyAccessorElement[] {getter});
SuperExpression target = superExpression();
target.setStaticType(classElement("B", classA.getType()).getType());
PropertyAccess access = propertyAccess(target, getterName);
methodDeclaration(
null,
null,
null,
null,
identifier("m"),
formalParameterList(),
expressionFunctionBody(access));
resolveNode(access);
assertSame(getter, access.getPropertyName().getStaticElement());
listener.assertNoErrors();
}
public void test_visitPropertyAccess_setter_this() throws Exception {
ClassElementImpl classA = classElement("A");
String setterName = "b";
PropertyAccessorElement setter = setterElement(setterName, false, typeProvider.getIntType());
classA.setAccessors(new PropertyAccessorElement[] {setter});
ThisExpression target = thisExpression();
target.setStaticType(classA.getType());
PropertyAccess access = propertyAccess(target, setterName);
assignmentExpression(access, TokenType.EQ, integer(0));
resolveNode(access);
assertSame(setter, access.getPropertyName().getStaticElement());
listener.assertNoErrors();
}
public void test_visitSimpleIdentifier_classScope() throws Exception {
InterfaceType doubleType = typeProvider.getDoubleType();
String fieldName = "NAN";
SimpleIdentifier node = identifier(fieldName);
resolveInClass(node, doubleType.getElement());
assertEquals(getGetter(doubleType, fieldName), node.getStaticElement());
listener.assertNoErrors();
}
public void test_visitSimpleIdentifier_dynamic() throws Exception {
SimpleIdentifier node = identifier("dynamic");
resolveIdentifier(node);
assertSame(typeProvider.getDynamicType().getElement(), node.getStaticElement());
assertSame(typeProvider.getTypeType(), node.getStaticType());
listener.assertNoErrors();
}
public void test_visitSimpleIdentifier_lexicalScope() throws Exception {
SimpleIdentifier node = identifier("i");
VariableElementImpl element = localVariableElement(node);
assertSame(element, resolveIdentifier(node, element));
listener.assertNoErrors();
}
public void test_visitSimpleIdentifier_lexicalScope_field_setter() throws Exception {
InterfaceType intType = typeProvider.getIntType();
ClassElementImpl classA = classElement("A");
String fieldName = "a";
FieldElement field = fieldElement(fieldName, false, false, false, intType);
classA.setFields(new FieldElement[] {field});
classA.setAccessors(new PropertyAccessorElement[] {field.getGetter(), field.getSetter()});
SimpleIdentifier node = identifier(fieldName);
assignmentExpression(node, TokenType.EQ, integer(0L));
resolveInClass(node, classA);
Element element = node.getStaticElement();
assertInstanceOf(PropertyAccessorElement.class, element);
assertTrue(((PropertyAccessorElement) element).isSetter());
listener.assertNoErrors();
}
public void test_visitSuperConstructorInvocation() throws Exception {
ClassElementImpl superclass = classElement("A");
ConstructorElementImpl superConstructor = constructorElement(superclass, null);
superclass.setConstructors(new ConstructorElement[] {superConstructor});
ClassElementImpl subclass = classElement("B", superclass.getType());
ConstructorElementImpl subConstructor = constructorElement(subclass, null);
subclass.setConstructors(new ConstructorElement[] {subConstructor});
SuperConstructorInvocation invocation = superConstructorInvocation();
resolveInClass(invocation, subclass);
assertEquals(superConstructor, invocation.getStaticElement());
listener.assertNoErrors();
}
public void test_visitSuperConstructorInvocation_namedParameter() throws Exception {
ClassElementImpl superclass = classElement("A");
ConstructorElementImpl superConstructor = constructorElement(superclass, null);
String parameterName = "p";
ParameterElement parameter = namedParameter(parameterName);
superConstructor.setParameters(new ParameterElement[] {parameter});
superclass.setConstructors(new ConstructorElement[] {superConstructor});
ClassElementImpl subclass = classElement("B", superclass.getType());
ConstructorElementImpl subConstructor = constructorElement(subclass, null);
subclass.setConstructors(new ConstructorElement[] {subConstructor});
SuperConstructorInvocation invocation = superConstructorInvocation(namedExpression(
parameterName,
integer(0)));
resolveInClass(invocation, subclass);
assertEquals(superConstructor, invocation.getStaticElement());
assertSame(
parameter,
((NamedExpression) invocation.getArgumentList().getArguments().get(0)).getName().getLabel().getStaticElement());
listener.assertNoErrors();
}
/**
* Create the resolver used by the tests.
*
* @return the resolver that was created
*/
private ElementResolver createResolver() {
AnalysisContextImpl context = new AnalysisContextImpl();
SourceFactory sourceFactory = new SourceFactory(new DartUriResolver(
DirectoryBasedDartSdk.getDefaultSdk()));
context.setSourceFactory(sourceFactory);
FileBasedSource source = new FileBasedSource(FileUtilities2.createFile("/test.dart"));
CompilationUnitElementImpl definingCompilationUnit = new CompilationUnitElementImpl("test.dart");
definingCompilationUnit.setSource(source);
definingLibrary = library(context, "test");
definingLibrary.setDefiningCompilationUnit(definingCompilationUnit);
Library library = new Library(context, listener, source);
library.setLibraryElement(definingLibrary);
visitor = new ResolverVisitor(library, source, typeProvider);
try {
Field resolverField = visitor.getClass().getDeclaredField("elementResolver");
resolverField.setAccessible(true);
return (ElementResolver) resolverField.get(visitor);
} catch (Exception exception) {
throw new IllegalArgumentException("Could not create resolver", exception);
}
}
/**
* Return the element associated with the label of the given statement after the resolver has
* resolved the statement.
*
* @param statement the statement to be resolved
* @param labelElement the label element to be defined in the statement's label scope
* @return the element to which the statement's label was resolved
*/
private Element resolveBreak(BreakStatement statement, LabelElementImpl labelElement) {
resolveStatement(statement, labelElement);
return statement.getLabel().getStaticElement();
}
/**
* Return the element associated with the label of the given statement after the resolver has
* resolved the statement.
*
* @param statement the statement to be resolved
* @param labelElement the label element to be defined in the statement's label scope
* @return the element to which the statement's label was resolved
*/
private Element resolveContinue(ContinueStatement statement, LabelElementImpl labelElement) {
resolveStatement(statement, labelElement);
return statement.getLabel().getStaticElement();
}
/**
* Return the element associated with the given identifier after the resolver has resolved the
* identifier.
*
* @param node the expression to be resolved
* @param definedElements the elements that are to be defined in the scope in which the element is
* being resolved
* @return the element to which the expression was resolved
*/
private Element resolveIdentifier(Identifier node, Element... definedElements) {
resolveNode(node, definedElements);
return node.getStaticElement();
}
/**
* Return the element associated with the given identifier after the resolver has resolved the
* identifier.
*
* @param node the expression to be resolved
* @param enclosingClass the element representing the class enclosing the identifier
* @return the element to which the expression was resolved
*/
private void resolveInClass(AstNode node, ClassElement enclosingClass) {
try {
Field enclosingClassField = visitor.getClass().getDeclaredField("enclosingClass");
enclosingClassField.setAccessible(true);
Field scopeField = visitor.getClass().getSuperclass().getDeclaredField("nameScope");
scopeField.setAccessible(true);
Scope outerScope = (Scope) scopeField.get(visitor);
try {
enclosingClassField.set(visitor, enclosingClass);
EnclosedScope innerScope = new ClassScope(
new TypeParameterScope(outerScope, enclosingClass),
enclosingClass);
scopeField.set(visitor, innerScope);
node.accept(resolver);
} finally {
enclosingClassField.set(visitor, null);
scopeField.set(visitor, outerScope);
}
} catch (Exception exception) {
throw new IllegalArgumentException("Could not resolve node", exception);
}
}
/**
* Return the element associated with the given expression after the resolver has resolved the
* expression.
*
* @param node the expression to be resolved
* @param definedElements the elements that are to be defined in the scope in which the element is
* being resolved
* @return the element to which the expression was resolved
*/
private Element resolveIndexExpression(IndexExpression node, Element... definedElements) {
resolveNode(node, definedElements);
return node.getStaticElement();
}
/**
* Return the element associated with the given identifier after the resolver has resolved the
* identifier.
*
* @param node the expression to be resolved
* @param definedElements the elements that are to be defined in the scope in which the element is
* being resolved
* @return the element to which the expression was resolved
*/
private void resolveNode(AstNode node, Element... definedElements) {
try {
Field scopeField = visitor.getClass().getSuperclass().getDeclaredField("nameScope");
scopeField.setAccessible(true);
Scope outerScope = (Scope) scopeField.get(visitor);
try {
EnclosedScope innerScope = new EnclosedScope(outerScope);
for (Element element : definedElements) {
innerScope.define(element);
}
scopeField.set(visitor, innerScope);
node.accept(resolver);
} finally {
scopeField.set(visitor, outerScope);
}
} catch (Exception exception) {
throw new IllegalArgumentException("Could not resolve node", exception);
}
}
/**
* Return the element associated with the label of the given statement after the resolver has
* resolved the statement.
*
* @param statement the statement to be resolved
* @param labelElement the label element to be defined in the statement's label scope
* @return the element to which the statement's label was resolved
*/
private void resolveStatement(Statement statement, LabelElementImpl labelElement) {
try {
Field scopeField = visitor.getClass().getSuperclass().getDeclaredField("labelScope");
scopeField.setAccessible(true);
LabelScope outerScope = (LabelScope) scopeField.get(visitor);
try {
LabelScope innerScope;
if (labelElement == null) {
innerScope = new LabelScope(outerScope, false, false);
} else {
innerScope = new LabelScope(outerScope, labelElement.getName(), labelElement);
}
scopeField.set(visitor, innerScope);
statement.accept(resolver);
} finally {
scopeField.set(visitor, outerScope);
}
} catch (Exception exception) {
throw new IllegalArgumentException("Could not resolve node", exception);
}
}
}