/* * 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.constant; import com.google.dart.engine.EngineTestCase; import com.google.dart.engine.ast.AstNode; import com.google.dart.engine.ast.ConstructorDeclaration; import com.google.dart.engine.ast.ConstructorInitializer; import com.google.dart.engine.ast.InstanceCreationExpression; import com.google.dart.engine.ast.SimpleIdentifier; import com.google.dart.engine.ast.SuperConstructorInvocation; import com.google.dart.engine.ast.TypeName; import com.google.dart.engine.ast.VariableDeclaration; import com.google.dart.engine.element.ConstructorElement; import com.google.dart.engine.element.VariableElement; import com.google.dart.engine.internal.element.ClassElementImpl; import com.google.dart.engine.internal.element.ConstructorElementImpl; import com.google.dart.engine.internal.element.VariableElementImpl; import com.google.dart.engine.scanner.Keyword; import com.google.dart.engine.scanner.KeywordToken; import com.google.dart.engine.utilities.collection.DirectedGraph; import static com.google.dart.engine.ast.AstFactory.constructorDeclaration; import static com.google.dart.engine.ast.AstFactory.formalParameterList; import static com.google.dart.engine.ast.AstFactory.identifier; import static com.google.dart.engine.ast.AstFactory.instanceCreationExpression; import static com.google.dart.engine.ast.AstFactory.superConstructorInvocation; import static com.google.dart.engine.ast.AstFactory.typeName; import static com.google.dart.engine.ast.AstFactory.variableDeclaration; import static com.google.dart.engine.ast.AstFactory.variableDeclarationList; 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.localVariableElement; import java.util.ArrayList; import java.util.HashMap; import java.util.Set; public class ReferenceFinderTest extends EngineTestCase { private DirectedGraph<AstNode> referenceGraph; private HashMap<VariableElement, VariableDeclaration> variableDeclarationMap; private HashMap<ConstructorElement, ConstructorDeclaration> constructorDeclarationMap; private VariableDeclaration head; private AstNode tail; public void test_visitInstanceCreationExpression_const() { visitNode(makeTailConstructor("A", true, true, true)); assertOneArc(tail); } public void test_visitInstanceCreationExpression_nonConstDeclaration() { // In the source: // const x = const A(); // x depends on "const A()" even if the A constructor isn't declared as const. visitNode(makeTailConstructor("A", false, true, true)); assertOneArc(tail); } public void test_visitInstanceCreationExpression_nonConstUsage() { visitNode(makeTailConstructor("A", true, false, true)); assertNoArcs(); } public void test_visitInstanceCreationExpression_notInMap() { // In the source: // const x = const A(); // x depends on "const A()" even if the AST for the A constructor isn't available. visitNode(makeTailConstructor("A", true, true, false)); assertOneArc(tail); } public void test_visitSimpleIdentifier_const() { visitNode(makeTailVariable("v2", true, true)); assertOneArc(tail); } public void test_visitSimpleIdentifier_nonConst() { visitNode(makeTailVariable("v2", false, true)); assertNoArcs(); } public void test_visitSimpleIdentifier_notInMap() { visitNode(makeTailVariable("v2", true, false)); assertNoArcs(); } public void test_visitSuperConstructorInvocation_const() { visitNode(makeTailSuperConstructorInvocation("A", true, true)); assertOneArc(tail); } public void test_visitSuperConstructorInvocation_nonConst() { visitNode(makeTailSuperConstructorInvocation("A", false, true)); assertNoArcs(); } public void test_visitSuperConstructorInvocation_notInMap() { visitNode(makeTailSuperConstructorInvocation("A", true, false)); assertNoArcs(); } public void test_visitSuperConstructorInvocation_unresolved() { SuperConstructorInvocation superConstructorInvocation = superConstructorInvocation(); tail = superConstructorInvocation; visitNode(superConstructorInvocation); assertNoArcs(); } @Override protected void setUp() { referenceGraph = new DirectedGraph<AstNode>(); variableDeclarationMap = new HashMap<VariableElement, VariableDeclaration>(); constructorDeclarationMap = new HashMap<ConstructorElement, ConstructorDeclaration>(); head = variableDeclaration("v1"); } private void assertNoArcs() { Set<AstNode> tails = referenceGraph.getTails(head); assertSizeOfSet(0, tails); } private void assertOneArc(AstNode tail) { Set<AstNode> tails = referenceGraph.getTails(head); assertSizeOfSet(1, tails); assertSame(tail, tails.iterator().next()); } private ReferenceFinder createReferenceFinder(AstNode source) { return new ReferenceFinder( source, referenceGraph, variableDeclarationMap, constructorDeclarationMap); } private InstanceCreationExpression makeTailConstructor(String name, boolean isConstDeclaration, boolean isConstUsage, boolean inMap) { ArrayList<ConstructorInitializer> initializers = new ArrayList<ConstructorInitializer>(); ConstructorDeclaration constructorDeclaration = constructorDeclaration( identifier(name), null, formalParameterList(), initializers); if (isConstDeclaration) { constructorDeclaration.setConstKeyword(new KeywordToken(Keyword.CONST, 0)); } ClassElementImpl classElement = classElement(name); SimpleIdentifier identifier = identifier(name); TypeName type = typeName(identifier); InstanceCreationExpression instanceCreationExpression = instanceCreationExpression(isConstUsage ? Keyword.CONST : Keyword.NEW, type); tail = instanceCreationExpression; ConstructorElementImpl constructorElement = constructorElement( classElement, name, isConstDeclaration); if (inMap) { constructorDeclarationMap.put(constructorElement, constructorDeclaration); } instanceCreationExpression.setStaticElement(constructorElement); return instanceCreationExpression; } private SuperConstructorInvocation makeTailSuperConstructorInvocation(String name, boolean isConst, boolean inMap) { ArrayList<ConstructorInitializer> initializers = new ArrayList<ConstructorInitializer>(); ConstructorDeclaration constructorDeclaration = constructorDeclaration( identifier(name), null, formalParameterList(), initializers); tail = constructorDeclaration; if (isConst) { constructorDeclaration.setConstKeyword(new KeywordToken(Keyword.CONST, 0)); } ClassElementImpl classElement = classElement(name); SuperConstructorInvocation superConstructorInvocation = superConstructorInvocation(); ConstructorElementImpl constructorElement = constructorElement(classElement, name, isConst); if (inMap) { constructorDeclarationMap.put(constructorElement, constructorDeclaration); } superConstructorInvocation.setStaticElement(constructorElement); return superConstructorInvocation; } private SimpleIdentifier makeTailVariable(String name, boolean isConst, boolean inMap) { VariableDeclaration variableDeclaration = variableDeclaration(name); tail = variableDeclaration; VariableElementImpl variableElement = localVariableElement(name); variableElement.setConst(isConst); variableDeclarationList(isConst ? Keyword.CONST : Keyword.VAR, variableDeclaration); if (inMap) { variableDeclarationMap.put(variableElement, variableDeclaration); } SimpleIdentifier identifier = identifier(name); identifier.setStaticElement(variableElement); return identifier; } private void visitNode(AstNode node) { node.accept(createReferenceFinder(head)); } }