/* * 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); } } }