| Index: editor/tools/plugins/com.google.dart.engine_test/src/com/google/dart/engine/internal/index/IndexContributorTest.java
|
| diff --git a/editor/tools/plugins/com.google.dart.engine_test/src/com/google/dart/engine/internal/index/IndexContributorTest.java b/editor/tools/plugins/com.google.dart.engine_test/src/com/google/dart/engine/internal/index/IndexContributorTest.java
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..d02c021ea0ac20fcac1972d2b9e4863ac7842a15
|
| --- /dev/null
|
| +++ b/editor/tools/plugins/com.google.dart.engine_test/src/com/google/dart/engine/internal/index/IndexContributorTest.java
|
| @@ -0,0 +1,415 @@
|
| +/*
|
| + * Copyright (c) 2012, 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.index;
|
| +
|
| +import com.google.common.base.Objects;
|
| +import com.google.common.collect.Lists;
|
| +import com.google.dart.engine.EngineTestCase;
|
| +import com.google.dart.engine.ast.ASTFactory;
|
| +import com.google.dart.engine.ast.ASTNode;
|
| +import com.google.dart.engine.ast.ClassDeclaration;
|
| +import com.google.dart.engine.ast.CompilationUnit;
|
| +import com.google.dart.engine.ast.ExtendsClause;
|
| +import com.google.dart.engine.ast.FunctionDeclaration;
|
| +import com.google.dart.engine.ast.FunctionTypeAlias;
|
| +import com.google.dart.engine.ast.ImplementsClause;
|
| +import com.google.dart.engine.ast.NodeList;
|
| +import com.google.dart.engine.ast.PrefixedIdentifier;
|
| +import com.google.dart.engine.ast.SimpleIdentifier;
|
| +import com.google.dart.engine.ast.TopLevelVariableDeclaration;
|
| +import com.google.dart.engine.ast.TypeName;
|
| +import com.google.dart.engine.ast.VariableDeclaration;
|
| +import com.google.dart.engine.ast.VariableDeclarationList;
|
| +import com.google.dart.engine.element.ClassElement;
|
| +import com.google.dart.engine.element.CompilationUnitElement;
|
| +import com.google.dart.engine.element.Element;
|
| +import com.google.dart.engine.element.ElementLocation;
|
| +import com.google.dart.engine.element.ElementProxy;
|
| +import com.google.dart.engine.element.FieldElement;
|
| +import com.google.dart.engine.element.FunctionElement;
|
| +import com.google.dart.engine.element.LibraryElement;
|
| +import com.google.dart.engine.element.TypeAliasElement;
|
| +import com.google.dart.engine.element.VariableElement;
|
| +import com.google.dart.engine.index.IndexStore;
|
| +import com.google.dart.engine.index.Location;
|
| +import com.google.dart.engine.index.Relationship;
|
| +import com.google.dart.engine.source.Source;
|
| +import com.google.dart.engine.type.Type;
|
| +
|
| +import org.mockito.ArgumentCaptor;
|
| +
|
| +import static org.fest.assertions.Assertions.assertThat;
|
| +import static org.mockito.Mockito.atLeast;
|
| +import static org.mockito.Mockito.mock;
|
| +import static org.mockito.Mockito.reset;
|
| +import static org.mockito.Mockito.verify;
|
| +import static org.mockito.Mockito.verifyNoMoreInteractions;
|
| +import static org.mockito.Mockito.when;
|
| +
|
| +import java.util.List;
|
| +
|
| +public class IndexContributorTest extends EngineTestCase {
|
| + private static class ExpectedLocation {
|
| + Element element;
|
| + int offset;
|
| + String name;
|
| +
|
| + ExpectedLocation(Element element, int offset, String name) {
|
| + this.element = element;
|
| + this.offset = offset;
|
| + this.name = name;
|
| + }
|
| + }
|
| +
|
| + /**
|
| + * Information about single relation recorded into {@link IndexStore}.
|
| + */
|
| + private static class RecordedRelation {
|
| + final ElementProxy element;
|
| + final Relationship relation;
|
| + final Location location;
|
| +
|
| + public RecordedRelation(ElementProxy element, Relationship relation, Location location) {
|
| + this.element = element;
|
| + this.relation = relation;
|
| + this.location = location;
|
| + }
|
| +
|
| + @Override
|
| + public String toString() {
|
| + return Objects.toStringHelper(this).add("relation", relation).toString();
|
| + }
|
| + }
|
| +
|
| + /**
|
| + * Asserts that given {@link ElementProxy} represents given {@link Element}.
|
| + */
|
| + private static void assertElementProxy(Element expected, ElementProxy actual) {
|
| + assertEquals(new ElementProxy(expected), actual);
|
| + }
|
| +
|
| + /**
|
| + * Asserts that actual {@link Location} has given properties.
|
| + */
|
| + private static void assertLocation(Location actual, Element expectedElement, int expectedOffset,
|
| + String expectedNameForLength) {
|
| + assertElementProxy(expectedElement, actual.getElement());
|
| + assertEquals(expectedOffset, actual.getOffset());
|
| + assertEquals(expectedNameForLength.length(), actual.getLength());
|
| + assertSame(null, actual.getImportPrefix());
|
| + }
|
| +
|
| + /**
|
| + * Asserts that actual {@link Location} has given properties.
|
| + */
|
| + private static void assertLocation(Location actual, ExpectedLocation expected) {
|
| + assertLocation(actual, expected.element, expected.offset, expected.name);
|
| + }
|
| +
|
| + private static void assertRecordedRelation(RecordedRelation recordedRelation,
|
| + Element expectedElement, Relationship expectedRelationship, ExpectedLocation expectedLocation) {
|
| + assertElementProxy(expectedElement, recordedRelation.element);
|
| + assertSame(expectedRelationship, recordedRelation.relation);
|
| + assertLocation(recordedRelation.location, expectedLocation);
|
| + }
|
| +
|
| + private static <T extends ASTNode> NodeList<T> createNodeList(ASTNode owner, T... nodes) {
|
| + NodeList<T> nodeList = new NodeList<T>(owner);
|
| + for (int i = 0; i < nodes.length; i++) {
|
| + nodeList.add(nodes[i]);
|
| + }
|
| + return nodeList;
|
| + }
|
| +
|
| + private static <T extends Element> T mockElement(Class<T> clazz, Element enclosingElement,
|
| + ElementLocation location, int offset, String name) {
|
| + T element = mockElement(clazz, location, offset, name);
|
| + when(element.getEnclosingElement()).thenReturn(enclosingElement);
|
| + return element;
|
| + }
|
| +
|
| + private static <T extends Element> T mockElement(Class<T> clazz, ElementLocation location,
|
| + int offset, String name) {
|
| + T element = mock(clazz);
|
| + when(element.getLocation()).thenReturn(location);
|
| + when(element.getNameOffset()).thenReturn(offset);
|
| + when(element.getName()).thenReturn(name);
|
| + return element;
|
| + }
|
| +
|
| + private static SimpleIdentifier mockSimpleIdentifier(Element element, int offset, String name) {
|
| + SimpleIdentifier identifier = mock(SimpleIdentifier.class);
|
| + when(identifier.getElement()).thenReturn(element);
|
| + when(identifier.getOffset()).thenReturn(offset);
|
| + when(identifier.getLength()).thenReturn(name.length());
|
| + return identifier;
|
| + }
|
| +
|
| + private static TypeName mockTypeName(Type type, int offset, String name) {
|
| + TypeName typeName = mock(TypeName.class);
|
| + when(typeName.getType()).thenReturn(type);
|
| + when(typeName.getOffset()).thenReturn(offset);
|
| + when(typeName.getLength()).thenReturn(name.length());
|
| + return typeName;
|
| + }
|
| +
|
| + private static VariableDeclarationList mockVariableDeclaration(VariableDeclaration var) {
|
| + VariableDeclarationList variableList = mock(VariableDeclarationList.class);
|
| + NodeList<VariableDeclaration> variableNodeList = createNodeList(variableList, var);
|
| + when(variableList.getVariables()).thenReturn(variableNodeList);
|
| + return variableList;
|
| + }
|
| +
|
| + private IndexStore store = mock(IndexStore.class);
|
| + private IndexContributor index = new IndexContributor(store);
|
| + private Source unitSource = mock(Source.class);
|
| + private CompilationUnit unitNode = mock(CompilationUnit.class);
|
| + private LibraryElement libraryElement = mock(LibraryElement.class);
|
| + private ElementLocation libraryLocation = mock(ElementLocation.class);
|
| +
|
| + private CompilationUnitElement unitElement = mock(CompilationUnitElement.class);
|
| +
|
| + public void test_accessByQualified_field() throws Exception {
|
| + FunctionElement enclosingFunction = mock(FunctionElement.class);
|
| + FieldElement fieldElement = mockElement(FieldElement.class, null, 10, "myField");
|
| + SimpleIdentifier field = mockSimpleIdentifier(fieldElement, 50, "myField");
|
| + // wrap into PrefixedIdentifier
|
| + PrefixedIdentifier prefixedIdentifier = mock(PrefixedIdentifier.class);
|
| + when(field.inGetterContext()).thenReturn(true);
|
| + when(prefixedIdentifier.getIdentifier()).thenReturn(field);
|
| + when(field.getParent()).thenReturn(prefixedIdentifier);
|
| + // index
|
| + index.enterScope(enclosingFunction);
|
| + index.visitSimpleIdentifier(field);
|
| + // verify
|
| + List<RecordedRelation> relations = captureRecordedRelations();
|
| + assertThat(relations).hasSize(1);
|
| + assertRecordedRelation(
|
| + relations.get(0),
|
| + fieldElement,
|
| + IndexConstants.IS_ACCESSED_BY_QUALIFIED,
|
| + new ExpectedLocation(enclosingFunction, 50, "myField"));
|
| + }
|
| +
|
| + public void test_accessByUnqualified_field() throws Exception {
|
| + FunctionElement enclosingFunction = mock(FunctionElement.class);
|
| + FieldElement fieldElement = mockElement(FieldElement.class, null, 10, "myField");
|
| + SimpleIdentifier field = mockSimpleIdentifier(fieldElement, 50, "myField");
|
| + when(field.inGetterContext()).thenReturn(true);
|
| + // index
|
| + index.enterScope(enclosingFunction);
|
| + index.visitSimpleIdentifier(field);
|
| + // verify
|
| + List<RecordedRelation> relations = captureRecordedRelations();
|
| + assertThat(relations).hasSize(1);
|
| + assertRecordedRelation(
|
| + relations.get(0),
|
| + fieldElement,
|
| + IndexConstants.IS_ACCESSED_BY_UNQUALIFIED,
|
| + new ExpectedLocation(enclosingFunction, 50, "myField"));
|
| + }
|
| +
|
| + public void test_createElementLocation() throws Exception {
|
| + ElementLocation elementLocation = mock(ElementLocation.class);
|
| + Element element = mockElement(Element.class, elementLocation, 42, "myName");
|
| + Location location = IndexContributor.createElementLocation(element);
|
| + assertLocation(location, element, 42, "myName");
|
| + }
|
| +
|
| + public void test_createElementLocation_null() throws Exception {
|
| + assertSame(null, IndexContributor.createElementLocation(null));
|
| + }
|
| +
|
| + public void test_definesClass() throws Exception {
|
| + ClassDeclaration classNodeA = mock(ClassDeclaration.class);
|
| + ElementLocation classLocationA = mock(ElementLocation.class);
|
| + ClassElement classElementA = mockElement(ClassElement.class, classLocationA, 42, "ABCDE");
|
| + when(classNodeA.getElement()).thenReturn(classElementA);
|
| + when(classElementA.getEnclosingElement()).thenReturn(unitElement);
|
| + // index
|
| + index.visitClassDeclaration(classNodeA);
|
| + // verify
|
| + List<RecordedRelation> relations = captureRecordedRelations();
|
| + assertThat(relations).hasSize(1);
|
| + assertRecordedRelation(
|
| + relations.get(0),
|
| + libraryElement,
|
| + IndexConstants.DEFINES_CLASS,
|
| + new ExpectedLocation(classElementA, 42, "ABCDE"));
|
| + }
|
| +
|
| + public void test_definesFunction() throws Exception {
|
| + FunctionElement functionElement = mockElement(FunctionElement.class, null, 42, "myFunction");
|
| + FunctionDeclaration function = mock(FunctionDeclaration.class);
|
| + when(function.getElement()).thenReturn(functionElement);
|
| + // index
|
| + index.visitFunctionDeclaration(function);
|
| + // verify
|
| + List<RecordedRelation> relations = captureRecordedRelations();
|
| + assertThat(relations).hasSize(1);
|
| + assertRecordedRelation(
|
| + relations.get(0),
|
| + libraryElement,
|
| + IndexConstants.DEFINES_FUNCTION,
|
| + new ExpectedLocation(functionElement, 42, "myFunction"));
|
| + }
|
| +
|
| + public void test_definesFunctionType() throws Exception {
|
| + TypeAliasElement functionElement = mockElement(TypeAliasElement.class, null, 42, "MyFunction");
|
| + FunctionTypeAlias function = mock(FunctionTypeAlias.class);
|
| + when(function.getElement()).thenReturn(functionElement);
|
| + // index
|
| + index.visitFunctionTypeAlias(function);
|
| + // verify
|
| + List<RecordedRelation> relations = captureRecordedRelations();
|
| + assertThat(relations).hasSize(1);
|
| + assertRecordedRelation(
|
| + relations.get(0),
|
| + libraryElement,
|
| + IndexConstants.DEFINES_FUNCTION_TYPE,
|
| + new ExpectedLocation(functionElement, 42, "MyFunction"));
|
| + }
|
| +
|
| + public void test_definesVariable() throws Exception {
|
| + // VariableDeclaration
|
| + ElementLocation varLocation = mock(ElementLocation.class);
|
| + VariableElement varElement = mockElement(VariableElement.class, varLocation, 42, "myVar");
|
| + VariableDeclaration var = mock(VariableDeclaration.class);
|
| + when(var.getElement()).thenReturn(varElement);
|
| + // TopLevelVariableDeclaration
|
| + TopLevelVariableDeclaration topDeclaration = mock(TopLevelVariableDeclaration.class);
|
| + VariableDeclarationList variableList = mockVariableDeclaration(var);
|
| + when(topDeclaration.getVariables()).thenReturn(variableList);
|
| + index.visitTopLevelVariableDeclaration(topDeclaration);
|
| + // verify
|
| + List<RecordedRelation> relations = captureRecordedRelations();
|
| + assertThat(relations).hasSize(1);
|
| + assertRecordedRelation(
|
| + relations.get(0),
|
| + libraryElement,
|
| + IndexConstants.DEFINES_VARIABLE,
|
| + new ExpectedLocation(varElement, 42, "myVar"));
|
| + }
|
| +
|
| + public void test_isExtendedBy() throws Exception {
|
| + // class B {}
|
| + ElementLocation classLocationB = mock(ElementLocation.class);
|
| + ClassElement classElementB = mockElement(
|
| + ClassElement.class,
|
| + libraryElement,
|
| + classLocationB,
|
| + 1042,
|
| + "B");
|
| + Type typeB = mock(Type.class);
|
| + when(typeB.getElement()).thenReturn(classElementB);
|
| + // class A extends B {}
|
| + ClassDeclaration classNodeA = mock(ClassDeclaration.class);
|
| + ElementLocation classLocationA = mock(ElementLocation.class);
|
| + ClassElement classElementA = mockElement(ClassElement.class, classLocationA, 42, "ABCDE");
|
| + when(classNodeA.getElement()).thenReturn(classElementA);
|
| + when(classElementA.getEnclosingElement()).thenReturn(unitElement);
|
| + {
|
| + TypeName extendsTypeNameA = mockTypeName(typeB, 142, "B");
|
| + ExtendsClause extendsClauseA = ASTFactory.extendsClause(extendsTypeNameA);
|
| + when(classNodeA.getExtendsClause()).thenReturn(extendsClauseA);
|
| + }
|
| + // index
|
| + reset(store);
|
| + index.visitClassDeclaration(classNodeA);
|
| + // verify
|
| + List<RecordedRelation> relations = captureRecordedRelations();
|
| + assertThat(relations).hasSize(2);
|
| + assertRecordedRelation(
|
| + relations.get(1),
|
| + classElementB,
|
| + IndexConstants.IS_EXTENDED_BY,
|
| + new ExpectedLocation(classElementA, 142, "B"));
|
| + }
|
| +
|
| + public void test_isImplementedBy() throws Exception {
|
| + // class B {}
|
| + ElementLocation classLocationB = mock(ElementLocation.class);
|
| + ClassElement classElementB = mockElement(
|
| + ClassElement.class,
|
| + libraryElement,
|
| + classLocationB,
|
| + 2042,
|
| + "B");
|
| + Type typeB = mock(Type.class);
|
| + when(typeB.getElement()).thenReturn(classElementB);
|
| + ClassDeclaration classNodeA = mock(ClassDeclaration.class);
|
| + // class A implements MyInterface {}
|
| + ElementLocation classLocationA = mock(ElementLocation.class);
|
| + ClassElement classElementA = mockElement(ClassElement.class, classLocationA, 42, "ABCDE");
|
| + when(classNodeA.getElement()).thenReturn(classElementA);
|
| + when(classElementA.getEnclosingElement()).thenReturn(unitElement);
|
| + {
|
| + TypeName implementsTypeNameA = mockTypeName(typeB, 242, "B");
|
| + ImplementsClause implementsClauseA = ASTFactory.implementsClause(implementsTypeNameA);
|
| + when(classNodeA.getImplementsClause()).thenReturn(implementsClauseA);
|
| + }
|
| + // index
|
| + reset(store);
|
| + index.visitClassDeclaration(classNodeA);
|
| + // verify
|
| + List<RecordedRelation> relations = captureRecordedRelations();
|
| + assertThat(relations).hasSize(2);
|
| + assertRecordedRelation(
|
| + relations.get(1),
|
| + classElementB,
|
| + IndexConstants.IS_IMPLEMENTED_BY,
|
| + new ExpectedLocation(classElementA, 242, "B"));
|
| + }
|
| +
|
| + public void test_unresolvedUnit() throws Exception {
|
| + index = new IndexContributor(store);
|
| + // no CompilationUnitElement, but no NPE
|
| + unitNode = mock(CompilationUnit.class);
|
| + index.visitCompilationUnit(unitNode);
|
| + verify(unitNode).getElement();
|
| + verifyNoMoreInteractions(unitNode);
|
| + // no enclosing element
|
| + assertSame(null, index.peekElement());
|
| + }
|
| +
|
| + @Override
|
| + protected void setUp() throws Exception {
|
| + super.setUp();
|
| + when(libraryElement.getLocation()).thenReturn(libraryLocation);
|
| + when(libraryElement.getDefiningCompilationUnit()).thenReturn(unitElement);
|
| + when(unitNode.getElement()).thenReturn(unitElement);
|
| + when(unitElement.getSource()).thenReturn(unitSource);
|
| + when(unitElement.getEnclosingElement()).thenReturn(libraryElement);
|
| + index.visitCompilationUnit(unitNode);
|
| + }
|
| +
|
| + private List<RecordedRelation> captureRecordedRelations() {
|
| + ArgumentCaptor<ElementProxy> argElement = ArgumentCaptor.forClass(ElementProxy.class);
|
| + ArgumentCaptor<Relationship> argRel = ArgumentCaptor.forClass(Relationship.class);
|
| + ArgumentCaptor<Location> argLocation = ArgumentCaptor.forClass(Location.class);
|
| + verify(store, atLeast(0)).recordRelationship(
|
| + argElement.capture(),
|
| + argRel.capture(),
|
| + argLocation.capture());
|
| + List<RecordedRelation> relations = Lists.newArrayList();
|
| + int count = argElement.getAllValues().size();
|
| + for (int i = 0; i < count; i++) {
|
| + relations.add(new RecordedRelation(
|
| + argElement.getAllValues().get(i),
|
| + argRel.getAllValues().get(i),
|
| + argLocation.getAllValues().get(i)));
|
| + }
|
| + return relations;
|
| + }
|
| +}
|
|
|