1 12 13 package org.eclipse.jdt.internal.junit.launcher; 14 15 import java.util.Collection ; 16 import java.util.HashSet ; 17 import java.util.Iterator ; 18 import java.util.Set ; 19 20 import org.eclipse.core.runtime.CoreException; 21 import org.eclipse.core.runtime.IProgressMonitor; 22 import org.eclipse.core.runtime.NullProgressMonitor; 23 import org.eclipse.core.runtime.SubProgressMonitor; 24 25 import org.eclipse.jdt.core.Flags; 26 import org.eclipse.jdt.core.IJavaElement; 27 import org.eclipse.jdt.core.IMember; 28 import org.eclipse.jdt.core.IMethod; 29 import org.eclipse.jdt.core.IRegion; 30 import org.eclipse.jdt.core.IType; 31 import org.eclipse.jdt.core.ITypeHierarchy; 32 import org.eclipse.jdt.core.JavaCore; 33 import org.eclipse.jdt.core.JavaModelException; 34 import org.eclipse.jdt.core.dom.AST; 35 import org.eclipse.jdt.core.dom.ASTNode; 36 import org.eclipse.jdt.core.dom.ASTParser; 37 import org.eclipse.jdt.core.dom.CompilationUnit; 38 import org.eclipse.jdt.core.dom.IAnnotationBinding; 39 import org.eclipse.jdt.core.dom.IBinding; 40 import org.eclipse.jdt.core.dom.IMethodBinding; 41 import org.eclipse.jdt.core.dom.ITypeBinding; 42 import org.eclipse.jdt.core.dom.Modifier; 43 import org.eclipse.jdt.core.dom.TypeDeclaration; 44 import org.eclipse.jdt.core.search.IJavaSearchConstants; 45 import org.eclipse.jdt.core.search.IJavaSearchScope; 46 import org.eclipse.jdt.core.search.SearchEngine; 47 import org.eclipse.jdt.core.search.SearchMatch; 48 import org.eclipse.jdt.core.search.SearchParticipant; 49 import org.eclipse.jdt.core.search.SearchPattern; 50 import org.eclipse.jdt.core.search.SearchRequestor; 51 52 import org.eclipse.jdt.internal.corext.SourceRange; 53 54 import org.eclipse.jdt.internal.junit.ui.JUnitMessages; 55 import org.eclipse.jdt.internal.junit.ui.JUnitPlugin; 56 import org.eclipse.jdt.internal.junit.util.TestSearchEngine; 57 58 59 public class JUnit4TestFinder implements ITestFinder { 60 61 private static class Annotation { 62 63 private static final Annotation RUN_WITH= new Annotation("org.junit.runner.RunWith"); private static final Annotation TEST= new Annotation("org.junit.Test"); 66 private final String fName; 67 68 private Annotation(String name) { 69 fName= name; 70 } 71 72 public String getName() { 73 return fName; 74 } 75 76 private boolean annotates(IAnnotationBinding[] annotations) throws JavaModelException { 77 for (int i= 0; i < annotations.length; i++) { 78 ITypeBinding annotationType= annotations[i].getAnnotationType(); 79 if (annotationType != null && (annotationType.getQualifiedName().equals(fName))) { 80 return true; 81 } 82 } 83 return false; 84 } 85 86 public boolean annotatesTypeOrSuperTypes(ITypeBinding type) throws JavaModelException { 87 while (type != null) { 88 if (annotates(type.getAnnotations())) { 89 return true; 90 } 91 type= type.getSuperclass(); 92 } 93 return false; 94 } 95 96 public boolean annotatesAtLeastOneMethod(ITypeBinding type) throws JavaModelException { 97 while (type != null) { 98 IMethodBinding[] declaredMethods= type.getDeclaredMethods(); 99 for (int i= 0; i < declaredMethods.length; i++) { 100 IMethodBinding curr= declaredMethods[i]; 101 if (annotates(curr.getAnnotations())) { 102 return true; 103 } 104 } 105 type= type.getSuperclass(); 106 } 107 return false; 108 } 109 } 110 111 public void findTestsInContainer(IJavaElement element, Set result, IProgressMonitor pm) throws CoreException { 112 if (element == null || result == null) { 113 throw new IllegalArgumentException (); 114 } 115 116 if (element instanceof IType) { 117 if (internalIsTest((IType) element, pm)) { 118 result.add(element); 119 return; 120 } 121 } 122 123 if (pm == null) 124 pm= new NullProgressMonitor(); 125 126 try { 127 pm.beginTask(JUnitMessages.JUnit4TestFinder_searching_description, 4); 128 129 IRegion region= TestSearchEngine.getRegion(element); 130 ITypeHierarchy hierarchy= JavaCore.newTypeHierarchy(region, null, new SubProgressMonitor(pm, 1)); 131 IType[] allClasses= hierarchy.getAllClasses(); 132 133 HashSet candidates= new HashSet (allClasses.length); 135 SearchRequestor requestor= new AnnotationSearchRequestor(hierarchy, candidates); 136 137 IJavaSearchScope scope= SearchEngine.createJavaSearchScope(allClasses, IJavaSearchScope.SOURCES); 138 int matchRule= SearchPattern.R_EXACT_MATCH | SearchPattern.R_CASE_SENSITIVE; 139 SearchPattern runWithPattern= SearchPattern.createPattern(Annotation.RUN_WITH.getName(), IJavaSearchConstants.ANNOTATION_TYPE, IJavaSearchConstants.REFERENCES, matchRule); 140 SearchPattern testPattern= SearchPattern.createPattern(Annotation.TEST.getName(), IJavaSearchConstants.ANNOTATION_TYPE, IJavaSearchConstants.REFERENCES, matchRule); 141 142 147 SearchParticipant[] searchParticipants= new SearchParticipant[] { SearchEngine.getDefaultSearchParticipant() }; 148 new SearchEngine().search(runWithPattern, searchParticipants, scope, requestor, new SubProgressMonitor(pm, 1)); 149 new SearchEngine().search(testPattern, searchParticipants, scope, requestor, new SubProgressMonitor(pm, 1)); 150 151 for (Iterator iterator= candidates.iterator(); iterator.hasNext();) { 153 IType curr= (IType) iterator.next(); 154 if (TestSearchEngine.isAccessibleClass(curr) && !Flags.isAbstract(curr.getFlags()) && region.contains(curr)) { 155 result.add(curr); 156 } 157 } 158 159 IType testInterface= element.getJavaProject().findType(JUnitPlugin.TEST_INTERFACE_NAME); 161 if (testInterface != null) { 162 TestSearchEngine.findTestImplementorClasses(hierarchy, testInterface, region, result); 163 } 164 165 TestSearchEngine.findSuiteMethods(element, result, new SubProgressMonitor(pm, 1)); 167 } finally { 168 pm.done(); 169 } 170 } 171 172 private static class AnnotationSearchRequestor extends SearchRequestor { 173 174 private final Collection fResult; 175 private final ITypeHierarchy fHierarchy; 176 177 public AnnotationSearchRequestor(ITypeHierarchy hierarchy, Collection result) { 178 fHierarchy= hierarchy; 179 fResult= result; 180 } 181 182 public void acceptSearchMatch(SearchMatch match) throws CoreException { 183 if (match.getAccuracy() == SearchMatch.A_ACCURATE && !match.isInsideDocComment()) { 184 Object element= match.getElement(); 185 if (element instanceof IType || element instanceof IMethod) { 186 IMember member= (IMember) element; 187 if (member.getNameRange().getOffset() > match.getOffset()) { 188 IType type= member.getElementType() == IJavaElement.TYPE ? (IType) member : member.getDeclaringType(); 189 addTypeAndSubtypes(type); 190 } 191 } 192 } 193 } 194 195 private void addTypeAndSubtypes(IType type) { 196 if (fResult.add(type)) { 197 IType[] subclasses= fHierarchy.getSubclasses(type); 198 for (int i= 0; i < subclasses.length; i++) { 199 addTypeAndSubtypes(subclasses[i]); 200 } 201 } 202 } 203 } 204 205 public boolean isTest(IType type) throws JavaModelException { 206 return internalIsTest(type, null); 207 } 208 209 private boolean internalIsTest(IType type, IProgressMonitor monitor) throws JavaModelException { 210 if (TestSearchEngine.isAccessibleClass(type)) { 211 if (TestSearchEngine.hasSuiteMethod(type)) { return true; 213 } 214 ASTParser parser= ASTParser.newParser(AST.JLS3); 215 222 223 if (type.getCompilationUnit() != null) { 224 parser.setSource(type.getCompilationUnit()); 225 } else if (! SourceRange.isAvailable(type.getSourceRange())) { parser.setProject(type.getJavaProject()); 227 IBinding[] bindings= parser.createBindings(new IJavaElement[] { type }, monitor); 228 if (bindings.length == 1 && bindings[0] instanceof ITypeBinding) { 229 ITypeBinding binding= (ITypeBinding) bindings[0]; 230 return isTest(binding); 231 } 232 return false; 233 } else { 234 parser.setSource(type.getClassFile()); 235 } 236 parser.setFocalPosition(0); 237 parser.setResolveBindings(true); 238 CompilationUnit root= (CompilationUnit) parser.createAST(monitor); 239 ASTNode node= root.findDeclaringNode(type.getKey()); 240 if (node instanceof TypeDeclaration) { 241 ITypeBinding binding= ((TypeDeclaration) node).resolveBinding(); 242 if (binding != null) { 243 return isTest(binding); 244 } 245 } 246 } 247 return false; 248 249 } 250 251 252 private boolean isTest(ITypeBinding binding) throws JavaModelException { 253 if (Modifier.isAbstract(binding.getModifiers())) 254 return false; 255 256 if (Annotation.RUN_WITH.annotatesTypeOrSuperTypes(binding) || Annotation.TEST.annotatesAtLeastOneMethod(binding)) { 257 return true; 258 } 259 return TestSearchEngine.isTestImplementor(binding); 260 } 261 } 262 | Popular Tags |