/* * 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.services.util; import com.google.dart.engine.element.ClassElement; import com.google.dart.engine.element.ClassMemberElement; import com.google.dart.engine.element.CompilationUnitElement; 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.MethodElement; import com.google.dart.engine.services.internal.correction.CorrectionUtils; import com.google.dart.engine.services.internal.refactoring.RefactoringImplTest; import static org.fest.assertions.Assertions.assertThat; import java.util.Iterator; import java.util.List; import java.util.Set; public class HierarchyUtilsTest extends RefactoringImplTest { private static void removeObjectMembers(List<Element> members) { for (Iterator<Element> iter = members.iterator(); iter.hasNext();) { Element element = iter.next(); if (element.getEnclosingElement() instanceof ClassElement) { ClassElement clazz = (ClassElement) element.getEnclosingElement(); if (clazz.getSupertype() == null) { iter.remove(); } } } } public void test_getDirectMembers() throws Exception { indexTestUnit( "// filler filler filler filler filler filler filler filler filler filler", "class A {", " A() {}", " var ma1;", " ma2() {}", "}", "class B extends A {", " B() {}", " B.named() {}", " var mb1;", " mb2() {}", "}", ""); ClassElement classA = getClassElement("A"); ClassElement classB = getClassElement("B"); // A { List<Element> members = HierarchyUtils.getDirectMembers(classA, false); assertThat(members).hasSize(2); assertThat(members.get(0)).isInstanceOf(FieldElement.class); assertEquals("ma1", members.get(0).getDisplayName()); assertThat(members.get(1)).isInstanceOf(MethodElement.class); assertEquals("ma2", members.get(1).getDisplayName()); } // B { List<Element> members = HierarchyUtils.getDirectMembers(classB, false); assertThat(members).hasSize(2); assertThat(members.get(0)).isInstanceOf(FieldElement.class); assertEquals("mb1", members.get(0).getDisplayName()); assertThat(members.get(1)).isInstanceOf(MethodElement.class); assertEquals("mb2", members.get(1).getDisplayName()); } } public void test_getHierarchyMembers_constructors() throws Exception { indexTestUnit( "// filler filler filler filler filler filler filler filler filler filler", "class A { A() {} }", "class B extends A { B() {} }", ""); ConstructorElement methodA = getConstructorElement("A", null); ConstructorElement methodB = getConstructorElement("B", null); // A { Set<ClassMemberElement> members = HierarchyUtils.getHierarchyMembers(searchEngine, methodA); assertThat(members).containsOnly(methodA); } // B { Set<ClassMemberElement> members = HierarchyUtils.getHierarchyMembers(searchEngine, methodB); assertThat(members).containsOnly(methodB); } } public void test_getHierarchyMembers_fields() throws Exception { indexTestUnit( "// filler filler filler filler filler filler filler filler filler filler", "class A { int foo; }", "class B extends A { get foo => null; }", "class C extends B { set foo(x) {} }", "class D { int foo; }", ""); FieldElement fieldA = getFieldElement("A", "foo"); FieldElement fieldB = getFieldElement("B", "foo"); FieldElement fieldC = getFieldElement("C", "foo"); // A { Set<ClassMemberElement> members = HierarchyUtils.getHierarchyMembers(searchEngine, fieldA); assertThat(members).containsOnly(fieldA, fieldB, fieldC); } // B { Set<ClassMemberElement> members = HierarchyUtils.getHierarchyMembers(searchEngine, fieldB); assertThat(members).containsOnly(fieldA, fieldB, fieldC); } // C { Set<ClassMemberElement> members = HierarchyUtils.getHierarchyMembers(searchEngine, fieldC); assertThat(members).containsOnly(fieldA, fieldB, fieldC); } } public void test_getHierarchyMembers_methods() throws Exception { indexTestUnit( "// filler filler filler filler filler filler filler filler filler filler", "class A { foo() {} }", "class B extends A { foo() {} }", "class C extends B { foo() {} }", "class D { foo() {} }", "class E extends D { foo() {} }", ""); MethodElement methodA = getMethodElement("A", "foo"); MethodElement methodB = getMethodElement("B", "foo"); MethodElement methodC = getMethodElement("C", "foo"); MethodElement methodD = getMethodElement("D", "foo"); MethodElement methodE = getMethodElement("E", "foo"); // A { Set<ClassMemberElement> members = HierarchyUtils.getHierarchyMembers(searchEngine, methodA); assertThat(members).containsOnly(methodA, methodB, methodC); } // B { Set<ClassMemberElement> members = HierarchyUtils.getHierarchyMembers(searchEngine, methodB); assertThat(members).containsOnly(methodA, methodB, methodC); } // C { Set<ClassMemberElement> members = HierarchyUtils.getHierarchyMembers(searchEngine, methodC); assertThat(members).containsOnly(methodA, methodB, methodC); } // D { Set<ClassMemberElement> members = HierarchyUtils.getHierarchyMembers(searchEngine, methodD); assertThat(members).containsOnly(methodD, methodE); } // E { Set<ClassMemberElement> members = HierarchyUtils.getHierarchyMembers(searchEngine, methodE); assertThat(members).containsOnly(methodD, methodE); } } public void test_getHierarchyMembers_withInterfaces() throws Exception { indexTestUnit( "// filler filler filler filler filler filler filler filler filler filler", "class A { foo() {} }", "class B implements A { foo() {} }", "abstract class C implements A { }", "class D extends C { foo() {} }", "class E { foo() {} }", ""); MethodElement methodA = getMethodElement("A", "foo"); MethodElement methodB = getMethodElement("B", "foo"); MethodElement methodD = getMethodElement("D", "foo"); // A { Set<ClassMemberElement> members = HierarchyUtils.getHierarchyMembers(searchEngine, methodA); assertThat(members).containsOnly(methodA, methodB, methodD); } // B { Set<ClassMemberElement> members = HierarchyUtils.getHierarchyMembers(searchEngine, methodB); assertThat(members).containsOnly(methodA, methodB, methodD); } // C { Set<ClassMemberElement> members = HierarchyUtils.getHierarchyMembers(searchEngine, methodD); assertThat(members).containsOnly(methodA, methodB, methodD); } } public void test_getMembers() throws Exception { indexTestUnit( "// filler filler filler filler filler filler filler filler filler filler", "class A {", " A() {}", " var ma1;", " ma2() {}", "}", "class B extends A {", " B() {}", " B.named() {}", " var mb1;", " mb2() {}", "}", ""); ClassElement classA = getClassElement("A"); ClassElement classB = getClassElement("B"); // A { List<Element> members = HierarchyUtils.getMembers(classA, false); removeObjectMembers(members); assertThat(members).hasSize(2); assertThat(members.get(0)).isInstanceOf(FieldElement.class); assertEquals("ma1", members.get(0).getDisplayName()); assertThat(members.get(1)).isInstanceOf(MethodElement.class); assertEquals("ma2", members.get(1).getDisplayName()); } // B { List<Element> members = HierarchyUtils.getMembers(classB, false); removeObjectMembers(members); assertThat(members).hasSize(4); // mb1 assertThat(members.get(0)).isInstanceOf(FieldElement.class); assertEquals("mb1", members.get(0).getDisplayName()); // mb2 assertThat(members.get(1)).isInstanceOf(MethodElement.class); assertEquals("mb2", members.get(1).getDisplayName()); // ma1 assertThat(members.get(2)).isInstanceOf(FieldElement.class); assertEquals("ma1", members.get(2).getDisplayName()); // ma2 assertThat(members.get(3)).isInstanceOf(MethodElement.class); assertEquals("ma2", members.get(3).getDisplayName()); } } public void test_getSubClasses() throws Exception { indexTestUnit( "// filler filler filler filler filler filler filler filler filler filler", "class A {}", "class B extends A {}", "class C extends B {}", "class D extends B implements A {}", "class M {}", "class E extends A with M {}", ""); ClassElement classA = getClassElement("A"); ClassElement classB = getClassElement("B"); ClassElement classC = getClassElement("C"); ClassElement classD = getClassElement("D"); ClassElement classE = getClassElement("E"); ClassElement classM = getClassElement("M"); // A { Set<ClassElement> subs = HierarchyUtils.getSubClasses(searchEngine, classA); assertThat(subs).containsOnly(classB, classC, classD, classE); } // B { Set<ClassElement> subs = HierarchyUtils.getSubClasses(searchEngine, classB); assertThat(subs).containsOnly(classC, classD); } // C { Set<ClassElement> subs = HierarchyUtils.getSubClasses(searchEngine, classC); assertThat(subs).containsOnly(); } // M { Set<ClassElement> subs = HierarchyUtils.getSubClasses(searchEngine, classM); assertThat(subs).containsOnly(classE); } } public void test_getSuperClasses() throws Exception { parseTestUnit( "// filler filler filler filler filler filler filler filler filler filler", "class A {}", "class B extends A {}", "class C extends B {}", "class D extends B implements A {}", "class M {}", "class E extends A with M {}", "class F implements A {}", ""); ClassElement classA = getClassElement("A"); ClassElement classB = getClassElement("B"); ClassElement classC = getClassElement("C"); ClassElement classD = getClassElement("D"); ClassElement classE = getClassElement("E"); ClassElement classF = getClassElement("F"); ClassElement objectElement = classA.getSupertype().getElement(); // Object { Set<ClassElement> supers = HierarchyUtils.getSuperClasses(objectElement); assertThat(supers).containsOnly(); } // A { Set<ClassElement> supers = HierarchyUtils.getSuperClasses(classA); assertThat(supers).containsOnly(objectElement); } // B { Set<ClassElement> supers = HierarchyUtils.getSuperClasses(classB); assertThat(supers).containsOnly(objectElement, classA); } // C { Set<ClassElement> supers = HierarchyUtils.getSuperClasses(classC); assertThat(supers).containsOnly(objectElement, classA, classB); } // D { Set<ClassElement> supers = HierarchyUtils.getSuperClasses(classD); assertThat(supers).containsOnly(objectElement, classA, classB); } // E { Set<ClassElement> supers = HierarchyUtils.getSuperClasses(classE); assertThat(supers).containsOnly(objectElement, classA); } // F { Set<ClassElement> supers = HierarchyUtils.getSuperClasses(classF); assertThat(supers).containsOnly(objectElement, classA); } } /** * @return the existing {@link ClassElement} form "testUnit". */ private ClassElement getClassElement(String name) { CompilationUnitElement unitElement = testUnit.getElement(); return (ClassElement) CorrectionUtils.getChildren(unitElement, name).get(0); } /** * @return the existing {@link ConstructorElement}. */ private ConstructorElement getConstructorElement(String className, String name) { ClassElement classElement = getClassElement(className); if (name != null) { return classElement.getNamedConstructor(name); } return classElement.getUnnamedConstructor(); } /** * @return the existing {@link FieldElement}. */ private FieldElement getFieldElement(String className, String fieldName) { ClassElement classElement = getClassElement(className); FieldElement fieldElement = classElement.getField(fieldName); if (fieldElement == null) { fail("Not found: " + fieldName); } return fieldElement; } /** * @return the existing {@link MethodElement}. */ private MethodElement getMethodElement(String className, String methodName) { ClassElement classElement = getClassElement(className); return classElement.getMethod(methodName); } }