org.netbeans.modules.testng.TopClassFinder Maven / Gradle / Ivy
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
*
* 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 org.netbeans.modules.testng;
import com.sun.source.tree.ClassTree;
import com.sun.source.tree.CompilationUnitTree;
import com.sun.source.tree.Tree;
import com.sun.source.util.TreePath;
import com.sun.source.util.Trees;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.TypeElement;
import org.netbeans.api.java.classpath.ClassPath;
import org.netbeans.api.java.source.CancellableTask;
import org.netbeans.api.java.source.ClasspathInfo.PathKind;
import org.netbeans.api.java.source.CompilationController;
import org.netbeans.api.java.source.CompilationInfo;
import org.netbeans.api.java.source.ElementHandle;
import org.netbeans.api.java.source.JavaSource;
import org.netbeans.api.java.source.JavaSource.Phase;
import org.netbeans.api.java.source.TreeUtilities;
import org.netbeans.modules.testng.TestabilityResult.SkippedClass;
import org.openide.filesystems.FileObject;
/**
* Finds all non-annotation top-level classes in a compilation unit.
*
* @author Marian Petras
*/
final class TopClassFinder {
interface Filter {
boolean passes(TypeElement topClass,
CompilationInfo compInfo);
}
static class BasicTestabilityFilter implements Filter {
public boolean passes(TypeElement topClass,
CompilationInfo compInfo) {
ElementKind elemKind = topClass.getKind();
return (elemKind != ElementKind.ANNOTATION_TYPE)
&& (elemKind.isClass()|| elemKind.isInterface());
}
}
static final class MainClassOnly extends BasicTestabilityFilter {
@Override
public boolean passes(TypeElement topClass,
CompilationInfo compInfo) {
if (!super.passes(topClass, compInfo)) {
return false;
}
FileObject javaFileObj = compInfo.getFileObject();
ClassPath sourceCP = compInfo.getClasspathInfo().getClassPath(PathKind.SOURCE);
String qualifiedClassName = topClass.getQualifiedName().toString();
return qualifiedClassName.equals(sourceCP.getResourceName(javaFileObj, '.', false));
}
}
static final class ExtendedTestabilityFilter implements Filter {
private final TestabilityJudge testabilityJudge;
private final Collection nonTestable;
private final long skipTestabilityResultMask;
ExtendedTestabilityFilter(TestabilityJudge testabilityJudge,
Collection nonTestable,
long skipTestabilityResultMask) {
this.testabilityJudge = testabilityJudge;
this.nonTestable = nonTestable;
this.skipTestabilityResultMask = skipTestabilityResultMask;
}
public boolean passes(TypeElement topClass,
CompilationInfo compInfo) {
TestabilityResult testabilityStatus
= testabilityJudge.isClassTestable(compInfo,
topClass, skipTestabilityResultMask);
if (testabilityStatus.isTestable()) {
return true;
} else {
nonTestable.add(
new SkippedClass(topClass.getQualifiedName().toString(),
testabilityStatus));
return false;
}
}
}
private TopClassFinder() { }
/**
*/
private static class TopClassFinderTask
implements CancellableTask {
private final Filter filter;
private List> topClassElems;
private volatile boolean cancelled;
private TopClassFinderTask() {
this(new BasicTestabilityFilter());
}
private TopClassFinderTask(Filter filter) {
this.filter = filter;
}
public void run(CompilationController controller) throws IOException {
controller.toPhase(Phase.ELEMENTS_RESOLVED);
if (cancelled) {
return;
}
if (topClassElems == null) {
topClassElems = new ArrayList>(10);
}
topClassElems.addAll(findTopClassElemHandles(
controller,
controller.getCompilationUnit(),
filter));
}
public void cancel() {
cancelled = true;
}
}
/**
*/
static List> findTopClasses(
JavaSource javaSource)
throws IOException {
TopClassFinderTask analyzer = new TopClassFinderTask();
javaSource.runUserActionTask(analyzer, true);
return analyzer.topClassElems;
}
/**
* Finds main top classes, i.e. those whose name matches with the name
* of the file they reside in.
*/
static List> findMainTopClasses(
JavaSource javaSource)
throws IOException {
TopClassFinderTask analyzer = new TopClassFinderTask(new MainClassOnly());
javaSource.runUserActionTask(analyzer, true);
return analyzer.topClassElems;
}
/**
* Finds testable top-level classes, interfaces and enums in a given
* Java source.
*
* @param javaSource source in which testable classes should be found
* @param judge {@code TestCreator} that will select testable
* top-level classes
* (see {@link TestCreator#isClassTestable})
* @param nonTestable container where names of found non-testable classes
* should be stored
* @return handles to testable top-level classes, interfaces and enums
* @exception java.lang.IllegalArgumentException
* if any of the parameters is {@code null}
*/
static List> findTestableTopClasses(
JavaSource javaSource,
TestabilityJudge testabilityJudge,
Collection nonTestable,
long skipTestabilityResultMask)
throws IOException {
TopClassFinderTask analyzer = new TopClassFinderTask(new ExtendedTestabilityFilter(testabilityJudge, nonTestable, skipTestabilityResultMask));
javaSource.runUserActionTask(analyzer, true);
return analyzer.topClassElems;
}
/**
*
* @return list of top classes, or an empty list of none were found
*/
static List findTopClasses(
CompilationUnitTree compilationUnit,
TreeUtilities treeUtils) {
List extends Tree> typeDecls = compilationUnit.getTypeDecls();
if ((typeDecls == null) || typeDecls.isEmpty()) {
return Collections.emptyList();
}
List result = new ArrayList(typeDecls.size());
for (Tree typeDecl : typeDecls) {
if (TreeUtilities.CLASS_TREE_KINDS.contains(typeDecl.getKind())) {
ClassTree clsTree = (ClassTree) typeDecl;
if (isTestable(clsTree, treeUtils)) {
result.add(clsTree);
}
}
}
return result;
}
/**
*
* @return list of {@code Element}s representing top classes,
* or an empty list of none were found
*/
private static List findTopClassElems(
CompilationInfo compInfo,
CompilationUnitTree compilationUnit,
Filter filter) {
List extends Tree> typeDecls = compilationUnit.getTypeDecls();
if ((typeDecls == null) || typeDecls.isEmpty()) {
return Collections.emptyList();
}
List result = new ArrayList(typeDecls.size());
Trees trees = compInfo.getTrees();
for (Tree typeDecl : typeDecls) {
if (TreeUtilities.CLASS_TREE_KINDS.contains(typeDecl.getKind())) {
Element element = trees.getElement(
new TreePath(new TreePath(compilationUnit), typeDecl));
TypeElement typeElement = (TypeElement) element;
if (filter.passes(typeElement, compInfo)) {
result.add(typeElement);
}
}
}
return result;
}
/**
*
* @return list of handles to {@code Element}s representing top classes,
* or an empty list of none were found
*/
private static List> findTopClassElemHandles(
CompilationInfo compInfo,
CompilationUnitTree compilationUnit,
Filter filter) {
return getElemHandles(
findTopClassElems(compInfo, compilationUnit, filter));
}
private static List> getElemHandles(List elements) {
if (elements == null) {
return null;
}
if (elements.isEmpty()) {
return Collections.>emptyList();
}
List> handles = new ArrayList>(elements.size());
for (T element : elements) {
handles.add(ElementHandle.create(element));
}
return handles;
}
private static boolean isTestable(ClassTree typeDecl,
TreeUtilities treeUtils) {
return !treeUtils.isAnnotation(typeDecl);
}
static boolean isTestable(TypeElement typeDeclElement) {
ElementKind elemKind = typeDeclElement.getKind();
return (elemKind != ElementKind.ANNOTATION_TYPE)
&& (elemKind.isClass()|| elemKind.isInterface());
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy