
org.checkerframework.common.util.count.JavaCodeStatistics Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of checker Show documentation
Show all versions of checker Show documentation
The Checker Framework enhances Java's type system to
make it more powerful and useful. This lets software developers
detect and prevent errors in their Java programs.
The Checker Framework includes compiler plug-ins ("checkers")
that find bugs or verify their absence. It also permits you to
write your own compiler plug-ins.
package org.checkerframework.common.util.count;
import com.sun.source.tree.AnnotationTree;
import com.sun.source.tree.ArrayAccessTree;
import com.sun.source.tree.AssertTree;
import com.sun.source.tree.ClassTree;
import com.sun.source.tree.ExpressionTree;
import com.sun.source.tree.MethodInvocationTree;
import com.sun.source.tree.MethodTree;
import com.sun.source.tree.NewArrayTree;
import com.sun.source.tree.NewClassTree;
import com.sun.source.tree.ParameterizedTypeTree;
import com.sun.source.tree.TypeCastTree;
import com.sun.tools.javac.util.Log;
import org.checkerframework.framework.source.SourceChecker;
import org.checkerframework.framework.source.SourceVisitor;
import org.checkerframework.javacutil.AnnotationProvider;
import org.checkerframework.javacutil.AnnotationUtils;
import org.checkerframework.javacutil.TreeUtils;
import java.util.List;
import javax.annotation.processing.SupportedSourceVersion;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.ExecutableElement;
/**
* An annotation processor for counting a few specific aspects about the size of Java code:
*
*
* - The number of type parameter declarations and uses.
*
- The number of array accesses and dimensions in array creations.
*
- The number of type casts.
*
*
* To invoke it, use
*
*
* javac -proc:only -processor org.checkerframework.common.util.count.JavaCodeStatistics MyFile.java ...
*
*
* @see AnnotationStatistics
* @see org.checkerframework.common.util.report.ReportChecker
*/
@SupportedSourceVersion(SourceVersion.RELEASE_8)
public class JavaCodeStatistics extends SourceChecker {
/** The number of type parameter declarations and uses. */
int generics = 0;
/** The number of array accesses and dimensions in array creations. */
int arrayAccesses = 0;
/** The number of type casts. */
int typecasts = 0;
String[] warningKeys = {
"index", "lowerbound", "samelen", "searchindex", "substringindex", "upperbound"
};
/**
* The number of warning suppressions with at least one key that matches one of the Index
* Checker subcheckers.
*/
int numberOfIndexWarningSuppressions = 0;
/** The SuppressWarnings.value field/element. */
final ExecutableElement suppressWarningsValueElement =
TreeUtils.getMethod(SuppressWarnings.class, "value", 0, processingEnv);
/** Creates a JavaCodeStatistics. */
public JavaCodeStatistics() {
// This checker never issues any warnings, so don't warn about
// @SuppressWarnings("allcheckers:...").
this.useAllcheckersPrefix = false;
}
@Override
public void typeProcessingOver() {
Log log = getCompilerLog();
if (log.nerrors != 0) {
System.out.printf("Not outputting statistics, because compilation issued an error.%n");
} else {
System.out.printf("Found %d generic type uses.%n", generics);
System.out.printf("Found %d array accesses and creations.%n", arrayAccesses);
System.out.printf("Found %d typecasts.%n", typecasts);
System.out.printf(
"Found %d warning suppression annotations for the Index Checker.%n",
numberOfIndexWarningSuppressions);
}
super.typeProcessingOver();
}
@Override
protected SourceVisitor, ?> createSourceVisitor() {
return new Visitor(this);
}
class Visitor extends SourceVisitor {
public Visitor(JavaCodeStatistics l) {
super(l);
}
@Override
public Void visitAnnotation(AnnotationTree tree, Void aVoid) {
AnnotationMirror annotationMirror = TreeUtils.annotationFromAnnotationTree(tree);
if (AnnotationUtils.annotationName(annotationMirror)
.equals(SuppressWarnings.class.getCanonicalName())) {
List keys =
AnnotationUtils.getElementValueArray(
annotationMirror, suppressWarningsValueElement, String.class);
for (String foundKey : keys) {
for (String indexKey : warningKeys) {
if (foundKey.startsWith(indexKey)) {
numberOfIndexWarningSuppressions++;
return super.visitAnnotation(tree, aVoid);
}
}
}
}
return super.visitAnnotation(tree, aVoid);
}
@Override
public Void visitAssert(AssertTree tree, Void aVoid) {
ExpressionTree detail = tree.getDetail();
if (detail != null) {
String msg = detail.toString();
for (String indexKey : warningKeys) {
String key = "@AssumeAssertion(" + indexKey;
if (msg.contains(key)) {
numberOfIndexWarningSuppressions++;
return super.visitAssert(tree, aVoid);
}
}
}
return super.visitAssert(tree, aVoid);
}
@Override
public Void visitClass(ClassTree tree, Void p) {
if (shouldSkipDefs(tree)) {
// Not "return super.visitClass(classTree, p);" because that would recursively call
// visitors on subtrees; we want to skip the class entirely.
return null;
}
generics += tree.getTypeParameters().size();
return super.visitClass(tree, p);
}
@Override
public Void visitNewArray(NewArrayTree tree, Void aVoid) {
arrayAccesses += tree.getDimensions().size();
return super.visitNewArray(tree, aVoid);
}
@Override
public Void visitNewClass(NewClassTree tree, Void aVoid) {
if (TreeUtils.isDiamondTree(tree)) {
generics++;
}
generics += tree.getTypeArguments().size();
return super.visitNewClass(tree, aVoid);
}
@Override
public Void visitMethodInvocation(MethodInvocationTree tree, Void aVoid) {
generics += tree.getTypeArguments().size();
return super.visitMethodInvocation(tree, aVoid);
}
@Override
public Void visitMethod(MethodTree tree, Void aVoid) {
generics += tree.getTypeParameters().size();
return super.visitMethod(tree, aVoid);
}
@Override
public Void visitParameterizedType(ParameterizedTypeTree tree, Void p) {
generics += tree.getTypeArguments().size();
return super.visitParameterizedType(tree, p);
}
@Override
public Void visitArrayAccess(ArrayAccessTree tree, Void aVoid) {
arrayAccesses++;
return super.visitArrayAccess(tree, aVoid);
}
@Override
public Void visitTypeCast(TypeCastTree tree, Void aVoid) {
typecasts++;
return super.visitTypeCast(tree, aVoid);
}
}
@Override
public AnnotationProvider getAnnotationProvider() {
throw new UnsupportedOperationException(
"getAnnotationProvider is not implemented for this class.");
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy