blob: b0819469fe35d775f7d1bc799a411c89d5bbb590 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* David Saff (saff@mit.edu) - initial API and implementation
* (bug 102632: [JUnit] Support for JUnit 4.)
*******************************************************************************/
package org.eclipse.jdt.internal.junit.launcher;
import java.util.Set;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jdt.core.Flags;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IMember;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.ISourceRange;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.ToolFactory;
import org.eclipse.jdt.core.compiler.IScanner;
import org.eclipse.jdt.core.compiler.ITerminalSymbols;
import org.eclipse.jdt.core.compiler.InvalidInputException;
import org.eclipse.jdt.internal.junit.util.TestSearchEngine;
public class JUnit4TestFinder implements ITestFinder {
private JUnit3TestFinder fJUnit3TestFinder= new JUnit3TestFinder();
private static class Annotation {
private static final JUnit4TestFinder.Annotation RUN_WITH= new JUnit4TestFinder.Annotation(new String[] { "RunWith", "org.junit.runner.RunWith" }); //$NON-NLS-1$ //$NON-NLS-2$
private static final JUnit4TestFinder.Annotation TEST= new JUnit4TestFinder.Annotation(new String[] { "Test", "org.junit.Test" }); //$NON-NLS-1$ //$NON-NLS-2$
private final String[] names;
private Annotation(String[] names) {
this.names= names;
}
public boolean foundIn(String source) {
IScanner scanner= ToolFactory.createScanner(false, true, false, false);
scanner.setSource(source.toCharArray());
try {
int tok;
do {
tok= scanner.getNextToken();
if (tok == ITerminalSymbols.TokenNameAT) {
String annotationName= ""; //$NON-NLS-1$
tok= scanner.getNextToken();
while (tok == ITerminalSymbols.TokenNameIdentifier || tok == ITerminalSymbols.TokenNameDOT) {
annotationName+= String.valueOf(scanner.getCurrentTokenSource());
tok= scanner.getNextToken();
}
for (int i= 0; i < names.length; i++) {
String annotation= names[i];
if (annotationName.equals(annotation))
return true;
}
}
} while (tok != ITerminalSymbols.TokenNameEOF);
} catch (InvalidInputException e) {
return false;
}
return false;
}
boolean annotates(IMember member) throws JavaModelException {
ISourceRange sourceRange= member.getSourceRange();
ISourceRange nameRange= member.getNameRange();
int charsToSearch= nameRange.getOffset() - sourceRange.getOffset();
String source= member.getSource().substring(0, charsToSearch);
return foundIn(source);
}
boolean annotatesAtLeastOneMethod(IType type) throws JavaModelException {
IMethod[] methods= type.getMethods();
for (int i= 0; i < methods.length; i++) {
if (annotates(methods[i]))
return true;
}
return false;
}
}
public void findTestsInContainer(Object[] elements, Set result, IProgressMonitor pm) {
try {
for (int i= 0; i < elements.length; i++) {
Object container= TestSearchEngine.computeScope(elements[i]);
if (container instanceof IJavaProject) {
IJavaProject project= (IJavaProject) container;
findTestsInProject(project, result);
} else if (container instanceof IPackageFragmentRoot) {
IPackageFragmentRoot root= (IPackageFragmentRoot) container;
findTestsInPackageFragmentRoot(root, result);
} else if (container instanceof IPackageFragment) {
IPackageFragment fragment= (IPackageFragment) container;
findTestsInPackageFragment(fragment, result);
} else if (container instanceof ICompilationUnit) {
ICompilationUnit cu= (ICompilationUnit) container;
findTestsInCompilationUnit(cu, result);
} else if (container instanceof IType) {
IType type= (IType) container;
findTestsInType(type, result);
}
}
} catch (JavaModelException e) {
// do nothing
}
}
private void findTestsInProject(IJavaProject project, Set result) throws JavaModelException {
IPackageFragmentRoot[] roots= project.getPackageFragmentRoots();
for (int i= 0; i < roots.length; i++) {
IPackageFragmentRoot root= roots[i];
findTestsInPackageFragmentRoot(root, result);
}
}
private void findTestsInPackageFragmentRoot(IPackageFragmentRoot root, Set result) throws JavaModelException {
IJavaElement[] children= root.getChildren();
for (int j= 0; j < children.length; j++) {
IPackageFragment fragment= (IPackageFragment) children[j];
findTestsInPackageFragment(fragment, result);
}
}
private void findTestsInPackageFragment(IPackageFragment fragment, Set result) throws JavaModelException {
ICompilationUnit[] compilationUnits= fragment.getCompilationUnits();
for (int k= 0; k < compilationUnits.length; k++) {
ICompilationUnit unit= compilationUnits[k];
findTestsInCompilationUnit(unit, result);
}
}
private void findTestsInCompilationUnit(ICompilationUnit unit, Set result) throws JavaModelException {
IType[] types= unit.getAllTypes();
for (int l= 0; l < types.length; l++) {
IType type= types[l];
findTestsInType(type, result);
}
}
private void findTestsInType(IType type, Set result) throws JavaModelException {
if (isTest(type))
result.add(type);
}
public boolean isTest(IType type) throws JavaModelException {
if (!Flags.isAbstract(type.getFlags())) {
if (Annotation.RUN_WITH.annotates(type) || Annotation.TEST.annotatesAtLeastOneMethod(type))
return true;
return fJUnit3TestFinder.isTest(type);
}
return false;
}
}