aboutsummaryrefslogtreecommitdiffhomepage
path: root/third_party/checker_framework_javacutil
diff options
context:
space:
mode:
authorGravatar Liam Miller-Cushon <cushon@google.com>2017-10-15 23:31:56 -0700
committerGravatar Damien Martin-Guillerez <dmarting@google.com>2017-10-16 14:16:39 +0200
commit6bf3f268f4a01963a2ee13f60178664bb056a802 (patch)
tree32a870dc293e07af88f52b241c75d9cbd462f63f /third_party/checker_framework_javacutil
parent80a34dc97799961201e6dce20fd58dd08022c032 (diff)
Update checker framework dataflow and javacutils to 2.1.14
Change-Id: I62ad827fc4bbd54d022097003af63e351e44b98c
Diffstat (limited to 'third_party/checker_framework_javacutil')
-rw-r--r--third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/AbstractTypeProcessor.java184
-rw-r--r--third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/AnnotationProvider.java34
-rw-r--r--third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/AnnotationUtils.java501
-rw-r--r--third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/BasicAnnotationProvider.java14
-rw-r--r--third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/BasicTypeProcessor.java28
-rw-r--r--third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/CollectionUtils.java26
-rw-r--r--third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/ElementUtils.java314
-rw-r--r--third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/ErrorHandler.java7
-rw-r--r--third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/ErrorReporter.java33
-rw-r--r--third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/InternalUtils.java291
-rw-r--r--third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/Pair.java11
-rw-r--r--third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/Resolver.java350
-rw-r--r--third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/TreeUtils.java628
-rw-r--r--third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/TypeAnnotationUtils.java543
-rw-r--r--third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/TypesUtils.java296
-rw-r--r--third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/dist/ManualTaglet.java37
-rw-r--r--third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/trees/DetachedVarSymbol.java21
-rw-r--r--third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/trees/TreeBuilder.java686
-rw-r--r--third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/trees/TreeParser.java61
19 files changed, 2239 insertions, 1826 deletions
diff --git a/third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/AbstractTypeProcessor.java b/third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/AbstractTypeProcessor.java
index 04389039e8..114ce6d0b6 100644
--- a/third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/AbstractTypeProcessor.java
+++ b/third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/AbstractTypeProcessor.java
@@ -1,136 +1,117 @@
package org.checkerframework.javacutil;
-import java.util.HashSet;
-import java.util.Set;
-
-import javax.annotation.processing.*;
-import javax.lang.model.element.Name;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.util.ElementFilter;
-
-import com.sun.tools.javac.main.JavaCompiler;
-import com.sun.tools.javac.comp.CompileStates.CompileState;
-import com.sun.tools.javac.processing.JavacProcessingEnvironment;
-import com.sun.tools.javac.util.Context;
-import com.sun.tools.javac.util.Log;
-
import com.sun.source.tree.ClassTree;
import com.sun.source.util.JavacTask;
import com.sun.source.util.TaskEvent;
import com.sun.source.util.TaskListener;
import com.sun.source.util.TreePath;
import com.sun.source.util.Trees;
+import com.sun.tools.javac.comp.CompileStates.CompileState;
+import com.sun.tools.javac.main.JavaCompiler;
+import com.sun.tools.javac.processing.JavacProcessingEnvironment;
+import com.sun.tools.javac.util.Context;
+import com.sun.tools.javac.util.Log;
+import java.util.HashSet;
+import java.util.Set;
+import javax.annotation.processing.AbstractProcessor;
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.annotation.processing.Processor;
+import javax.annotation.processing.RoundEnvironment;
+import javax.lang.model.element.Name;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.util.ElementFilter;
/**
- * This class is an abstract annotation processor designed to be a
- * convenient superclass for concrete "type processors", processors that
- * require the type information in the processed source.
+ * This class is an abstract annotation processor designed to be a convenient superclass for
+ * concrete "type processors", processors that require the type information in the processed source.
*
- * <p>Type processing occurs in one round after the tool (e.g. Java compiler)
- * analyzes the source (all sources taken as input to the tool and sources
- * generated by other annotation processors).
+ * <p>Type processing occurs in one round after the tool (e.g. Java compiler) analyzes the source
+ * (all sources taken as input to the tool and sources generated by other annotation processors).
*
- * <p>The tool infrastructure will interact with classes extending this abstract
- * class as follows.
+ * <p>The tool infrastructure will interact with classes extending this abstract class as follows.
*
- * <p>
- * 1-3 are Identical to the {@link Processor} life cycle.
- * 4-5 are unique to {@code AbstractTypeProcessor} subclasses.
+ * <p>1-3 are identical to the {@link Processor} life cycle. 4-5 are unique to {@code
+ * AbstractTypeProcessor} subclasses.
*
* <ol>
- *
- * <li>If an existing {@code Processor} object is not being used, to
- * create an instance of a processor the tool calls the no-arg
- * constructor of the processor class.
- *
- * <li>Next, the tool calls the {@link #init init} method with
- * an appropriate {@code ProcessingEnvironment}.
- *
- * <li>Afterwards, the tool calls {@link #getSupportedAnnotationTypes
- * getSupportedAnnotationTypes}, {@link #getSupportedOptions
- * getSupportedOptions}, and {@link #getSupportedSourceVersion
- * getSupportedSourceVersion}. These methods are only called once per
- * run, not on each round.
- *
- *
- * <li>For each class containing a supported annotation, the tool calls
- * {@link #typeProcess(TypeElement, TreePath) typeProcess} method on the
- * {@code Processor}. The class is guaranteed to be type-checked Java code
- * and all the tree type and symbol information is resolved.
- *
- * <li>Finally, the tools calls the
- * {@link #typeProcessingOver() typeProcessingOver} method
- * on the {@code Processor}.
- *
+ * <li>If an existing {@code Processor} object is not being used, to create an instance of a
+ * processor the tool calls the no-arg constructor of the processor class.
+ * <li>Next, the tool calls the {@link #init init} method with an appropriate {@code
+ * ProcessingEnvironment}.
+ * <li>Afterwards, the tool calls {@link #getSupportedAnnotationTypes
+ * getSupportedAnnotationTypes}, {@link #getSupportedOptions getSupportedOptions}, and {@link
+ * #getSupportedSourceVersion getSupportedSourceVersion}. These methods are only called once
+ * per run, not on each round.
+ * <li>For each class containing a supported annotation, the tool calls {@link
+ * #typeProcess(TypeElement, TreePath) typeProcess} method on the {@code Processor}. The class
+ * is guaranteed to be type-checked Java code and all the tree type and symbol information is
+ * resolved.
+ * <li>Finally, the tools calls the {@link #typeProcessingOver() typeProcessingOver} method on the
+ * {@code Processor}.
* </ol>
*
- * <p>The tool is permitted to ask type processors to process a class once
- * it is analyzed before the rest of classes are analyzed. The tool is also
- * permitted to stop type processing immediately if any errors are raised,
- * without invoking {@code typeProcessingOver}
+ * <p>The tool is permitted to ask type processors to process a class once it is analyzed before the
+ * rest of classes are analyzed. The tool is also permitted to stop type processing immediately if
+ * any errors are raised, without invoking {@code typeProcessingOver}
*
- * <p>A subclass may override any of the methods in this class, as long as the
- * general {@link javax.annotation.processing.Processor Processor}
- * contract is obeyed, with one notable exception.
- * {@link #process(Set, RoundEnvironment)} may not be overridden, as it
- * is called during the declaration annotation phase before classes are analyzed.
+ * <p>A subclass may override any of the methods in this class, as long as the general {@link
+ * javax.annotation.processing.Processor Processor} contract is obeyed, with one notable exception.
+ * {@link #process(Set, RoundEnvironment)} may not be overridden, as it is called during the
+ * declaration annotation phase before classes are analyzed.
*
* @author Mahmood Ali
* @author Werner Dietl
*/
public abstract class AbstractTypeProcessor extends AbstractProcessor {
/**
- * The set of fully-qualified element names that should be type-checked.
- * We store the names of the elements, in order to prevent
- * possible confusion between different Element instantiations.
+ * The set of fully-qualified element names that should be type-checked. We store the names of
+ * the elements, in order to prevent possible confusion between different Element
+ * instantiations.
*/
private final Set<Name> elements = new HashSet<Name>();
/**
- * Method {@link #typeProcessingStart()} must be invoked exactly once,
- * before any invocation of {@link #typeProcess(TypeElement, TreePath)}.
+ * Method {@link #typeProcessingStart()} must be invoked exactly once, before any invocation of
+ * {@link #typeProcess(TypeElement, TreePath)}.
*/
private boolean hasInvokedTypeProcessingStart = false;
/**
- * Method {@link #typeProcessingOver()} must be invoked exactly once,
- * after the last invocation of {@link #typeProcess(TypeElement, TreePath)}.
+ * Method {@link #typeProcessingOver()} must be invoked exactly once, after the last invocation
+ * of {@link #typeProcess(TypeElement, TreePath)}.
*/
private static boolean hasInvokedTypeProcessingOver = false;
- /**
- * The TaskListener registered for completion of attribution.
- */
+ /** The TaskListener registered for completion of attribution. */
private final AttributionTaskListener listener = new AttributionTaskListener();
- /**
- * Constructor for subclasses to call.
- */
- protected AbstractTypeProcessor() { }
+ /** Constructor for subclasses to call. */
+ protected AbstractTypeProcessor() {}
/**
* {@inheritDoc}
*
- * Register a TaskListener that will get called after FLOW.
+ * <p>Register a TaskListener that will get called after FLOW.
*/
@Override
- public void init(ProcessingEnvironment env) {
+ public synchronized void init(ProcessingEnvironment env) {
super.init(env);
JavacTask.instance(env).addTaskListener(listener);
Context ctx = ((JavacProcessingEnvironment) processingEnv).getContext();
JavaCompiler compiler = JavaCompiler.instance(ctx);
- compiler.shouldStopPolicyIfNoError = CompileState.max(compiler.shouldStopPolicyIfNoError,
- CompileState.FLOW);
+ compiler.shouldStopPolicyIfNoError =
+ CompileState.max(compiler.shouldStopPolicyIfNoError, CompileState.FLOW);
+ compiler.shouldStopPolicyIfError =
+ CompileState.max(compiler.shouldStopPolicyIfError, CompileState.FLOW);
}
/**
- * The use of this method is obsolete in type processors. The method is
- * called during declaration annotation processing phase only.
- * It registers the names of elements to process.
+ * The use of this method is obsolete in type processors. The method is called during
+ * declaration annotation processing phase only. It registers the names of elements to process.
*/
@Override
- public final boolean process(Set<? extends TypeElement> annotations,
- RoundEnvironment roundEnv) {
+ public final boolean process(
+ Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
for (TypeElement elem : ElementFilter.typesIn(roundEnv.getRootElements())) {
elements.add(elem.getQualifiedName());
}
@@ -145,39 +126,35 @@ public abstract class AbstractTypeProcessor extends AbstractProcessor {
public void typeProcessingStart() {}
/**
- * Processes a fully analyzed class that contains a supported annotation
- * (look {@link #getSupportedAnnotationTypes()}).
+ * Processes a fully-analyzed class that contains a supported annotation (see {@link
+ * #getSupportedAnnotationTypes()}).
*
* <p>The passed class is always valid type-checked Java code.
*
- * @param element element of the analyzed class
- * @param tree the tree path to the element, with the leaf being a
- * {@link ClassTree}
+ * @param element element of the analyzed class
+ * @param tree the tree path to the element, with the leaf being a {@link ClassTree}
*/
public abstract void typeProcess(TypeElement element, TreePath tree);
/**
- * A method to be called once all the classes are processed and no error
- * is reported.
+ * A method to be called once all the classes are processed and no error is reported.
*
- * <p>Subclasses may override this method to do any aggregate analysis
- * (e.g. generate report, persistence) or resource deallocation.
+ * <p>Subclasses may override this method to do any aggregate analysis (e.g. generate report,
+ * persistence) or resource deallocation.
*
- * <p>If an error (a Java error or a processor error) is reported, this
- * method is not guaranteed to be invoked.
+ * <p>If an error (a Java error or a processor error) is reported, this method is not guaranteed
+ * to be invoked.
*/
- public void typeProcessingOver() { }
+ public void typeProcessingOver() {}
- /**
- * A task listener that invokes the processor whenever a class is fully
- * analyzed.
- */
+ /** A task listener that invokes the processor whenever a class is fully analyzed. */
private final class AttributionTaskListener implements TaskListener {
@Override
public void finished(TaskEvent e) {
- if (e.getKind() != TaskEvent.Kind.ANALYZE)
+ if (e.getKind() != TaskEvent.Kind.ANALYZE) {
return;
+ }
if (!hasInvokedTypeProcessingStart) {
typeProcessingStart();
@@ -191,13 +168,16 @@ public abstract class AbstractTypeProcessor extends AbstractProcessor {
hasInvokedTypeProcessingOver = true;
}
- if (e.getTypeElement() == null)
+ if (e.getTypeElement() == null) {
throw new AssertionError("event task without a type element");
- if (e.getCompilationUnit() == null)
+ }
+ if (e.getCompilationUnit() == null) {
throw new AssertionError("event task without compilation unit");
+ }
- if (!elements.remove(e.getTypeElement().getQualifiedName()))
+ if (!elements.remove(e.getTypeElement().getQualifiedName())) {
return;
+ }
TypeElement elem = e.getTypeElement();
TreePath p = Trees.instance(processingEnv).getPath(elem);
@@ -211,6 +191,6 @@ public abstract class AbstractTypeProcessor extends AbstractProcessor {
}
@Override
- public void started(TaskEvent e) { }
+ public void started(TaskEvent e) {}
}
}
diff --git a/third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/AnnotationProvider.java b/third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/AnnotationProvider.java
index 8ed857a9b2..1245960edd 100644
--- a/third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/AnnotationProvider.java
+++ b/third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/AnnotationProvider.java
@@ -1,38 +1,28 @@
package org.checkerframework.javacutil;
+import com.sun.source.tree.Tree;
import java.lang.annotation.Annotation;
-
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.Element;
-import com.sun.source.tree.Tree;
-
-/**
- * An implementation of AnnotationProvider returns annotations on
- * Java AST elements.
- */
+/** An implementation of AnnotationProvider returns annotations on Java AST elements. */
public interface AnnotationProvider {
/**
- * Returns the actual annotation mirror used to annotate this type,
- * whose name equals the passed annotationName if one exists, null otherwise.
+ * Returns the actual annotation mirror used to annotate this type, whose name equals the passed
+ * annotationName if one exists, null otherwise.
*
* @param anno annotation class
* @return the annotation mirror for anno
*/
- public AnnotationMirror getDeclAnnotation(Element elt,
- Class<? extends Annotation> anno);
-
+ public AnnotationMirror getDeclAnnotation(Element elt, Class<? extends Annotation> anno);
+
/**
- * Return the annotation on <code>tree</code> that has the class
- * <code>target</code>. If no annotation for the given target class exists,
- * the result is <code>null</code>
- *
- * @param tree
- * The tree of which the annotation is returned
- * @param target
- * The class of the annotation
+ * Return the annotation on {@code tree} that has the class {@code target}. If no annotation for
+ * the given target class exists, the result is {@code null}
+ *
+ * @param tree the tree of which the annotation is returned
+ * @param target the class of the annotation
*/
- public AnnotationMirror getAnnotationMirror(Tree tree,
- Class<? extends Annotation> target);
+ public AnnotationMirror getAnnotationMirror(Tree tree, Class<? extends Annotation> target);
}
diff --git a/third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/AnnotationUtils.java b/third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/AnnotationUtils.java
index 54eb54d2fb..c80f57cc5d 100644
--- a/third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/AnnotationUtils.java
+++ b/third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/AnnotationUtils.java
@@ -7,7 +7,12 @@ import org.checkerframework.checker.nullness.qual.*;
import org.checkerframework.checker.interning.qual.*;
*/
-
+import com.sun.source.tree.AnnotationTree;
+import com.sun.source.tree.MethodTree;
+import com.sun.source.tree.ModifiersTree;
+import com.sun.tools.javac.code.Symbol.VarSymbol;
+import com.sun.tools.javac.code.Type;
+import com.sun.tools.javac.model.JavacElements;
import java.lang.annotation.Annotation;
import java.lang.annotation.Inherited;
import java.util.ArrayList;
@@ -21,7 +26,6 @@ import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
-
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.AnnotationValue;
import javax.lang.model.element.ElementKind;
@@ -33,23 +37,19 @@ import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.ElementFilter;
import javax.lang.model.util.Elements;
-import com.sun.tools.javac.code.Symbol.VarSymbol;
-import com.sun.tools.javac.code.Type;
-import com.sun.tools.javac.model.JavacElements;
-/**
- * A utility class for working with annotations.
- */
+/** A utility class for working with annotations. */
public class AnnotationUtils {
// Class cannot be instantiated.
- private AnnotationUtils() { throw new AssertionError("Class AnnotationUtils cannot be instantiated."); }
+ private AnnotationUtils() {
+ throw new AssertionError("Class AnnotationUtils cannot be instantiated.");
+ }
// TODO: hack to clear out static state.
- // {@link org.checkerframework.qualframework.util.QualifierContext} should
- // handle instantiation of utility classes.
public static void clear() {
annotationsFromNames.clear();
annotationMirrorNames.clear();
+ annotationMirrorSimpleNames.clear();
annotationClassNames.clear();
}
@@ -58,68 +58,85 @@ public class AnnotationUtils {
// **********************************************************************
/** Caching for annotation creation. */
- private static final Map<CharSequence, AnnotationMirror> annotationsFromNames
- = new HashMap<CharSequence, AnnotationMirror>();
+ private static final Map<CharSequence, AnnotationMirror> annotationsFromNames =
+ Collections.synchronizedMap(new HashMap<CharSequence, AnnotationMirror>());
+
+ private static final int ANNOTATION_CACHE_SIZE = 500;
/**
- * Cache names of AnnotationMirrors for faster access. Values in
- * the map are interned Strings, so they can be compared with ==.
+ * Cache names of AnnotationMirrors for faster access. Values in the map are interned Strings,
+ * so they can be compared with ==.
*/
- private static final Map<AnnotationMirror, /*@Interned*/ String> annotationMirrorNames
- = new HashMap<AnnotationMirror, /*@Interned*/ String>();
+ private static final Map<AnnotationMirror, /*@Interned*/ String> annotationMirrorNames =
+ Collections.synchronizedMap(
+ CollectionUtils.<AnnotationMirror, /*@Interned*/ String>createLRUCache(
+ ANNOTATION_CACHE_SIZE));
/**
- * Cache names of classes representing AnnotationMirrors for
- * faster access. Values in the map are interned Strings, so they
- * can be compared with ==.
+ * Cache simple names of AnnotationMirrors for faster access. Values in the map are interned
+ * Strings, so they can be compared with ==.
*/
- private static final Map<Class<? extends Annotation>, /*@Interned*/ String> annotationClassNames
- = new HashMap<Class<? extends Annotation>, /*@Interned*/ String>();
+ private static final Map<AnnotationMirror, /*@Interned*/ String> annotationMirrorSimpleNames =
+ Collections.synchronizedMap(
+ CollectionUtils.<AnnotationMirror, /*@Interned*/ String>createLRUCache(
+ ANNOTATION_CACHE_SIZE));
/**
- * Creates an {@link AnnotationMirror} given by a particular
- * fully-qualified name. getElementValues on the result returns an
- * empty map.
+ * Cache names of classes representing AnnotationMirrors for faster access. Values in the map
+ * are interned Strings, so they can be compared with ==.
+ */
+ private static final Map<Class<? extends Annotation>, /*@Interned*/ String>
+ annotationClassNames =
+ Collections.synchronizedMap(
+ new HashMap<Class<? extends Annotation>, /*@Interned*/ String>());
+
+ /**
+ * Creates an {@link AnnotationMirror} given by a particular fully-qualified name.
+ * getElementValues on the result returns an empty map.
*
* @param elements the element utilities to use
* @param name the name of the annotation to create
* @return an {@link AnnotationMirror} of type {@code} name
*/
public static AnnotationMirror fromName(Elements elements, CharSequence name) {
- if (annotationsFromNames.containsKey(name))
- return annotationsFromNames.get(name);
+ AnnotationMirror res = annotationsFromNames.get(name);
+ if (res != null) {
+ return res;
+ }
final DeclaredType annoType = typeFromName(elements, name);
- if (annoType == null)
+ if (annoType == null) {
return null;
+ }
if (annoType.asElement().getKind() != ElementKind.ANNOTATION_TYPE) {
ErrorReporter.errorAbort(annoType + " is not an annotation");
return null; // dead code
}
- AnnotationMirror result = new AnnotationMirror() {
- String toString = "@" + annoType;
-
- @Override
- public DeclaredType getAnnotationType() {
- return annoType;
- }
- @Override
- public Map<? extends ExecutableElement, ? extends AnnotationValue>
- getElementValues() {
- return Collections.emptyMap();
- }
- /*@SideEffectFree*/
- @Override
- public String toString() {
- return toString;
- }
- };
+ AnnotationMirror result =
+ new AnnotationMirror() {
+ String toString = "@" + annoType;
+
+ @Override
+ public DeclaredType getAnnotationType() {
+ return annoType;
+ }
+
+ @Override
+ public Map<? extends ExecutableElement, ? extends AnnotationValue>
+ getElementValues() {
+ return Collections.emptyMap();
+ }
+ /*@SideEffectFree*/
+ @Override
+ public String toString() {
+ return toString;
+ }
+ };
annotationsFromNames.put(name, result);
return result;
}
/**
- * Creates an {@link AnnotationMirror} given by a particular annotation
- * class.
+ * Creates an {@link AnnotationMirror} given by a particular annotation class.
*
* @param elements the element utilities to use
* @param clazz the annotation class
@@ -130,8 +147,8 @@ public class AnnotationUtils {
}
/**
- * A utility method that converts a {@link CharSequence} (usually a {@link
- * String}) into a {@link TypeMirror} named thereby.
+ * A utility method that converts a {@link CharSequence} (usually a {@link String}) into a
+ * {@link TypeMirror} named thereby.
*
* @param elements the element utilities to use
* @param name the name of a type
@@ -139,26 +156,25 @@ public class AnnotationUtils {
*/
private static DeclaredType typeFromName(Elements elements, CharSequence name) {
/*@Nullable*/ TypeElement typeElt = elements.getTypeElement(name);
- if (typeElt == null)
+ if (typeElt == null) {
return null;
+ }
return (DeclaredType) typeElt.asType();
}
-
// **********************************************************************
// Helper methods to handle annotations. mainly workaround
// AnnotationMirror.equals undesired property
// (I think the undesired property is that it's reference equality.)
// **********************************************************************
- /**
- * @return the fully-qualified name of an annotation as a Name
- */
+ /** @return the fully-qualified name of an annotation as a String */
public static final /*@Interned*/ String annotationName(AnnotationMirror annotation) {
- if (annotationMirrorNames.containsKey(annotation))
- return annotationMirrorNames.get(annotation);
-
+ String res = annotationMirrorNames.get(annotation);
+ if (res != null) {
+ return res;
+ }
final DeclaredType annoType = annotation.getAnnotationType();
final TypeElement elm = (TypeElement) annoType.asElement();
/*@Interned*/ String name = elm.getQualifiedName().toString().intern();
@@ -166,25 +182,40 @@ public class AnnotationUtils {
return name;
}
+ /** @return the simple name of an annotation as a String */
+ public static String annotationSimpleName(AnnotationMirror annotation) {
+ String res = annotationMirrorSimpleNames.get(annotation);
+ if (res != null) {
+ return res;
+ }
+ final DeclaredType annoType = annotation.getAnnotationType();
+ final TypeElement elm = (TypeElement) annoType.asElement();
+ /*@Interned*/ String name = elm.getSimpleName().toString().intern();
+ annotationMirrorSimpleNames.put(annotation, name);
+ return name;
+ }
+
/**
* Checks if both annotations are the same.
*
- * Returns true iff both annotations are of the same type and have the
- * same annotation values. This behavior differs from
- * {@code AnnotationMirror.equals(Object)}. The equals method returns
- * true iff both annotations are the same and annotate the same annotation
- * target (e.g. field, variable, etc).
+ * <p>Returns true iff both annotations are of the same type and have the same annotation
+ * values. This behavior differs from {@code AnnotationMirror.equals(Object)}. The equals method
+ * returns true iff both annotations are the same and annotate the same annotation target (e.g.
+ * field, variable, etc).
*
* @return true iff a1 and a2 are the same annotation
*/
- public static boolean areSame(/*@Nullable*/ AnnotationMirror a1, /*@Nullable*/ AnnotationMirror a2) {
+ public static boolean areSame(
+ /*@Nullable*/ AnnotationMirror a1, /*@Nullable*/ AnnotationMirror a2) {
if (a1 != null && a2 != null) {
if (annotationName(a1) != annotationName(a2)) {
return false;
}
- Map<? extends ExecutableElement, ? extends AnnotationValue> elval1 = getElementValuesWithDefaults(a1);
- Map<? extends ExecutableElement, ? extends AnnotationValue> elval2 = getElementValuesWithDefaults(a2);
+ Map<? extends ExecutableElement, ? extends AnnotationValue> elval1 =
+ getElementValuesWithDefaults(a1);
+ Map<? extends ExecutableElement, ? extends AnnotationValue> elval2 =
+ getElementValuesWithDefaults(a2);
return elval1.toString().equals(elval2.toString());
}
@@ -198,30 +229,22 @@ public class AnnotationUtils {
* @return true iff a1 and a2 have the same annotation type
*/
public static boolean areSameIgnoringValues(AnnotationMirror a1, AnnotationMirror a2) {
- if (a1 != null && a2 != null)
+ if (a1 != null && a2 != null) {
return annotationName(a1) == annotationName(a2);
+ }
return a1 == a2;
}
- /**
- * Checks that the annotation {@code am} has the name {@code aname}. Values
- * are ignored.
- */
+ /** Checks that the annotation {@code am} has the name {@code aname}. Values are ignored. */
public static boolean areSameByName(AnnotationMirror am, /*@Interned*/ String aname) {
// Both strings are interned.
return annotationName(am) == aname;
}
- /**
- * Checks that the annotation {@code am} has the name of {@code anno}.
- * Values are ignored.
- */
- public static boolean areSameByClass(AnnotationMirror am,
- Class<? extends Annotation> anno) {
- /*@Interned*/ String canonicalName;
- if (annotationClassNames.containsKey(anno)) {
- canonicalName = annotationClassNames.get(anno).intern();
- } else {
+ /** Checks that the annotation {@code am} has the name of {@code anno}. Values are ignored. */
+ public static boolean areSameByClass(AnnotationMirror am, Class<? extends Annotation> anno) {
+ /*@Interned*/ String canonicalName = annotationClassNames.get(anno);
+ if (canonicalName == null) {
canonicalName = anno.getCanonicalName().intern();
annotationClassNames.put(anno, canonicalName);
}
@@ -233,11 +256,14 @@ public class AnnotationUtils {
*
* @return true iff c1 and c2 contain the same annotations
*/
- public static boolean areSame(Collection<? extends AnnotationMirror> c1, Collection<? extends AnnotationMirror> c2) {
- if (c1.size() != c2.size())
+ public static boolean areSame(
+ Collection<? extends AnnotationMirror> c1, Collection<? extends AnnotationMirror> c2) {
+ if (c1.size() != c2.size()) {
return false;
- if (c1.size() == 1)
+ }
+ if (c1.size() == 1) {
return areSame(c1.iterator().next(), c2.iterator().next());
+ }
Set<AnnotationMirror> s1 = createAnnotationSet();
Set<AnnotationMirror> s2 = createAnnotationSet();
@@ -251,78 +277,122 @@ public class AnnotationUtils {
while (iter1.hasNext()) {
AnnotationMirror anno1 = iter1.next();
AnnotationMirror anno2 = iter2.next();
- if (!areSame(anno1, anno2))
+ if (!areSame(anno1, anno2)) {
return false;
+ }
}
return true;
}
/**
- * Checks that the collection contains the annotation.
- * Using Collection.contains does not always work, because it
- * does not use areSame for comparison.
+ * Checks that the collection contains the annotation. Using Collection.contains does not always
+ * work, because it does not use areSame for comparison.
*
- * @return true iff c contains anno, according to areSame.
+ * @return true iff c contains anno, according to areSame
*/
- public static boolean containsSame(Collection<? extends AnnotationMirror> c, AnnotationMirror anno) {
- for(AnnotationMirror an : c) {
- if(AnnotationUtils.areSame(an, anno)) {
- return true;
- }
- }
- return false;
+ public static boolean containsSame(
+ Collection<? extends AnnotationMirror> c, AnnotationMirror anno) {
+ return getSame(c, anno) != null;
}
/**
- * Checks that the collection contains the annotation.
- * Using Collection.contains does not always work, because it
- * does not use areSame for comparison.
+ * Returns the AnnotationMirror in {@code c} that is the same annotation as {@code anno}.
*
- * @return true iff c contains anno, according to areSameByClass.
+ * @return AnnotationMirror with the same class as {@code anno} iff c contains anno, according
+ * to areSame; otherwise, {@code null}
*/
- public static boolean containsSameByClass(Collection<? extends AnnotationMirror> c, Class<? extends Annotation> anno) {
- for(AnnotationMirror an : c) {
- if(AnnotationUtils.areSameByClass(an, anno)) {
- return true;
+ public static AnnotationMirror getSame(
+ Collection<? extends AnnotationMirror> c, AnnotationMirror anno) {
+ for (AnnotationMirror an : c) {
+ if (AnnotationUtils.areSame(an, anno)) {
+ return an;
}
}
- return false;
+ return null;
}
/**
- * Checks that the collection contains the annotation ignoring values.
- * Using Collection.contains does not always work, because it
- * does not use areSameIgnoringValues for comparison.
+ * Checks that the collection contains the annotation. Using Collection.contains does not always
+ * work, because it does not use areSame for comparison.
*
- * @return true iff c contains anno, according to areSameIgnoringValues.
+ * @return true iff c contains anno, according to areSameByClass
*/
- public static boolean containsSameIgnoringValues(Collection<? extends AnnotationMirror> c, AnnotationMirror anno) {
- for(AnnotationMirror an : c) {
- if(AnnotationUtils.areSameIgnoringValues(an, anno)) {
- return true;
+ public static boolean containsSameByClass(
+ Collection<? extends AnnotationMirror> c, Class<? extends Annotation> anno) {
+ return getAnnotationByClass(c, anno) != null;
+ }
+
+ /**
+ * Returns the AnnotationMirror in {@code c} that has the same class as {@code anno}.
+ *
+ * @return AnnotationMirror with the same class as {@code anno} iff c contains anno, according
+ * to areSameByClass; otherwise, {@code null}
+ */
+ public static AnnotationMirror getAnnotationByClass(
+ Collection<? extends AnnotationMirror> c, Class<? extends Annotation> anno) {
+ for (AnnotationMirror an : c) {
+ if (AnnotationUtils.areSameByClass(an, anno)) {
+ return an;
}
}
- return false;
+ return null;
}
- private static final Comparator<AnnotationMirror> ANNOTATION_ORDERING
- = new Comparator<AnnotationMirror>() {
- @Override
- public int compare(AnnotationMirror a1, AnnotationMirror a2) {
- String n1 = a1.toString();
- String n2 = a2.toString();
+ /**
+ * Checks that the collection contains the annotation ignoring values. Using Collection.contains
+ * does not always work, because it does not use areSameIgnoringValues for comparison.
+ *
+ * @return true iff c contains anno, according to areSameIgnoringValues
+ */
+ public static boolean containsSameIgnoringValues(
+ Collection<? extends AnnotationMirror> c, AnnotationMirror anno) {
+ return getSameIgnoringValues(c, anno) != null;
+ }
- return n1.compareTo(n2);
+ /**
+ * Returns the AnnotationMirror in {@code c} that is the same annotation as {@code anno}
+ * ignoring values.
+ *
+ * @return AnnotationMirror with the same class as {@code anno} iff c contains anno, according
+ * to areSameIgnoringValues; otherwise, {@code null}
+ */
+ public static AnnotationMirror getSameIgnoringValues(
+ Collection<? extends AnnotationMirror> c, AnnotationMirror anno) {
+ for (AnnotationMirror an : c) {
+ if (AnnotationUtils.areSameIgnoringValues(an, anno)) {
+ return an;
+ }
}
- };
+ return null;
+ }
+
+ private static final Comparator<AnnotationMirror> ANNOTATION_ORDERING =
+ new Comparator<AnnotationMirror>() {
+ @Override
+ public int compare(AnnotationMirror a1, AnnotationMirror a2) {
+ // AnnotationMirror.toString() prints the elements of an annotation in the
+ // order in which they were written. So, use areSame to check for equality.
+ if (AnnotationUtils.areSame(a1, a2)) {
+ return 0;
+ }
+
+ String n1 = a1.toString();
+ String n2 = a2.toString();
+
+ // Because the AnnotationMirror.toString prints the annotation as it appears
+ // in source code, the order in which annotations of the same class are
+ // sorted may be confusing. For example, it might order
+ // @IntRange(from=1, to=MAX) before @IntRange(to=MAX,from=0).
+ return n1.compareTo(n2);
+ }
+ };
/**
- * provide ordering for {@link AnnotationMirror} based on their fully
- * qualified name. The ordering ignores annotation values when ordering.
+ * provide ordering for {@link AnnotationMirror} based on their fully qualified name. The
+ * ordering ignores annotation values when ordering.
*
- * The ordering is meant to be used as {@link TreeSet} or {@link TreeMap}
- * ordering. A {@link Set} should not contain two annotations that only
- * differ in values.
+ * <p>The ordering is meant to be used as {@link TreeSet} or {@link TreeMap} ordering. A {@link
+ * Set} should not contain two annotations that only differ in values.
*/
public static Comparator<AnnotationMirror> annotationOrdering() {
return ANNOTATION_ORDERING;
@@ -331,8 +401,8 @@ public class AnnotationUtils {
/**
* Create a map suitable for storing {@link AnnotationMirror} as keys.
*
- * It can store one instance of {@link AnnotationMirror} of a given
- * declared type, regardless of the annotation element values.
+ * <p>It can store one instance of {@link AnnotationMirror} of a given declared type, regardless
+ * of the annotation element values.
*
* @param <V> the value of the map
* @return a new map with {@link AnnotationMirror} as key
@@ -344,8 +414,8 @@ public class AnnotationUtils {
/**
* Constructs a {@link Set} suitable for storing {@link AnnotationMirror}s.
*
- * It stores at most once instance of {@link AnnotationMirror} of a given
- * type, regardless of the annotation element values.
+ * <p>It stores at most once instance of {@link AnnotationMirror} of a given type, regardless of
+ * the annotation element values.
*
* @return a new set to store {@link AnnotationMirror} as element
*/
@@ -358,62 +428,75 @@ public class AnnotationUtils {
return anno.getAnnotationType().asElement().getAnnotation(Inherited.class) != null;
}
-
// **********************************************************************
// Extractors for annotation values
// **********************************************************************
/**
- * Returns the values of an annotation's attributes, including defaults.
- * The method with the same name in JavacElements cannot be used directly,
- * because it includes a cast to Attribute.Compound, which doesn't hold
- * for annotations generated by the Checker Framework.
+ * Returns the values of an annotation's attributes, including defaults. The method with the
+ * same name in JavacElements cannot be used directly, because it includes a cast to
+ * Attribute.Compound, which doesn't hold for annotations generated by the Checker Framework.
*
* @see AnnotationMirror#getElementValues()
* @see JavacElements#getElementValuesWithDefaults(AnnotationMirror)
- *
- * @param ad annotation to examine
+ * @param ad annotation to examine
* @return the values of the annotation's elements, including defaults
*/
public static Map<? extends ExecutableElement, ? extends AnnotationValue>
- getElementValuesWithDefaults(AnnotationMirror ad) {
- Map<ExecutableElement, AnnotationValue> valMap
- = new HashMap<ExecutableElement, AnnotationValue>();
+ getElementValuesWithDefaults(AnnotationMirror ad) {
+ Map<ExecutableElement, AnnotationValue> valMap =
+ new HashMap<ExecutableElement, AnnotationValue>();
if (ad.getElementValues() != null) {
valMap.putAll(ad.getElementValues());
}
for (ExecutableElement meth :
- ElementFilter.methodsIn(ad.getAnnotationType().asElement().getEnclosedElements())) {
+ ElementFilter.methodsIn(ad.getAnnotationType().asElement().getEnclosedElements())) {
AnnotationValue defaultValue = meth.getDefaultValue();
- if (defaultValue != null && !valMap.containsKey(meth))
+ if (defaultValue != null && !valMap.containsKey(meth)) {
valMap.put(meth, defaultValue);
+ }
}
return valMap;
}
/**
- * Get the attribute with the name {@code name} of the annotation
- * {@code anno}. The result is expected to have type {@code expectedType}.
+ * Verify whether the attribute with the name {@code name} exists in the annotation {@code
+ * anno}.
*
- * <p>
- * <em>Note 1</em>: The method does not work well for attributes of an array
- * type (as it would return a list of {@link AnnotationValue}s). Use
- * {@code getElementValueArray} instead.
+ * @param anno the annotation to examine
+ * @param name the name of the attribute
+ * @return whether the attribute exists in anno
+ */
+ public static <T> boolean hasElementValue(AnnotationMirror anno, CharSequence name) {
+ Map<? extends ExecutableElement, ? extends AnnotationValue> valmap =
+ anno.getElementValues();
+ for (ExecutableElement elem : valmap.keySet()) {
+ if (elem.getSimpleName().contentEquals(name)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Get the attribute with the name {@code name} of the annotation {@code anno}. The result is
+ * expected to have type {@code expectedType}.
*
- * <p>
- * <em>Note 2</em>: The method does not work for attributes of an enum type,
- * as the AnnotationValue is a VarSymbol and would be cast to the enum type,
- * which doesn't work. Use {@code getElementValueEnum} instead.
+ * <p><em>Note 1</em>: The method does not work well for attributes of an array type (as it
+ * would return a list of {@link AnnotationValue}s). Use {@code getElementValueArray} instead.
*
+ * <p><em>Note 2</em>: The method does not work for attributes of an enum type, as the
+ * AnnotationValue is a VarSymbol and would be cast to the enum type, which doesn't work. Use
+ * {@code getElementValueEnum} instead.
*
* @param anno the annotation to disassemble
* @param name the name of the attribute to access
* @param expectedType the expected type used to cast the return type
- * @param useDefaults whether to apply default values to the attribute.
+ * @param useDefaults whether to apply default values to the attribute
* @return the value of the attribute with the given name
*/
- public static <T> T getElementValue(AnnotationMirror anno, CharSequence name,
- Class<T> expectedType, boolean useDefaults) {
+ public static <T> T getElementValue(
+ AnnotationMirror anno, CharSequence name, Class<T> expectedType, boolean useDefaults) {
Map<? extends ExecutableElement, ? extends AnnotationValue> valmap;
if (useDefaults) {
valmap = getElementValuesWithDefaults(anno);
@@ -430,34 +513,31 @@ public class AnnotationUtils {
return null; // dead code
}
- /**
- * Version that is suitable for Enum elements.
- */
+ /** Version that is suitable for Enum elements. */
public static <T extends Enum<T>> T getElementValueEnum(
- AnnotationMirror anno, CharSequence name, Class<T> t,
- boolean useDefaults) {
+ AnnotationMirror anno, CharSequence name, Class<T> t, boolean useDefaults) {
VarSymbol vs = getElementValue(anno, name, VarSymbol.class, useDefaults);
T value = Enum.valueOf(t, vs.getSimpleName().toString());
return value;
}
/**
- * Get the attribute with the name {@code name} of the annotation
- * {@code anno}, where the attribute has an array type. One element of the
- * result is expected to have type {@code expectedType}.
+ * Get the attribute with the name {@code name} of the annotation {@code anno}, where the
+ * attribute has an array type. One element of the result is expected to have type {@code
+ * expectedType}.
*
- * Parameter useDefaults is used to determine whether default values
- * should be used for annotation values. Finding defaults requires
- * more computation, so should be false when no defaulting is needed.
+ * <p>Parameter useDefaults is used to determine whether default values should be used for
+ * annotation values. Finding defaults requires more computation, so should be false when no
+ * defaulting is needed.
*
* @param anno the annotation to disassemble
* @param name the name of the attribute to access
* @param expectedType the expected type used to cast the return type
- * @param useDefaults whether to apply default values to the attribute.
+ * @param useDefaults whether to apply default values to the attribute
* @return the value of the attribute with the given name
*/
- public static <T> List<T> getElementValueArray(AnnotationMirror anno,
- CharSequence name, Class<T> expectedType, boolean useDefaults) {
+ public static <T> List<T> getElementValueArray(
+ AnnotationMirror anno, CharSequence name, Class<T> expectedType, boolean useDefaults) {
@SuppressWarnings("unchecked")
List<AnnotationValue> la = getElementValue(anno, name, List.class, useDefaults);
List<T> result = new ArrayList<T>(la.size());
@@ -468,14 +548,13 @@ public class AnnotationUtils {
}
/**
- * Get the attribute with the name {@code name} of the annotation
- * {@code anno}, or the default value if no attribute is present explicitly,
- * where the attribute has an array type and the elements are {@code Enum}s.
- * One element of the result is expected to have type {@code expectedType}.
+ * Get the attribute with the name {@code name} of the annotation {@code anno}, or the default
+ * value if no attribute is present explicitly, where the attribute has an array type and the
+ * elements are {@code Enum}s. One element of the result is expected to have type {@code
+ * expectedType}.
*/
public static <T extends Enum<T>> List<T> getElementValueEnumArray(
- AnnotationMirror anno, CharSequence name, Class<T> t,
- boolean useDefaults) {
+ AnnotationMirror anno, CharSequence name, Class<T> t, boolean useDefaults) {
@SuppressWarnings("unchecked")
List<AnnotationValue> la = getElementValue(anno, name, List.class, useDefaults);
List<T> result = new ArrayList<T>(la.size());
@@ -487,42 +566,58 @@ public class AnnotationUtils {
}
/**
- * Get the Name of the class that is referenced by attribute 'name'.
- * This is a convenience method for the most common use-case.
- * Like getElementValue(anno, name, ClassType.class).getQualifiedName(), but
- * this method ensures consistent use of the qualified name.
+ * Get the Name of the class that is referenced by attribute {@code name}.
+ *
+ * <p>This is a convenience method for the most common use-case. Like getElementValue(anno,
+ * name, ClassType.class).getQualifiedName(), but this method ensures consistent use of the
+ * qualified name.
*/
- public static Name getElementValueClassName(AnnotationMirror anno, CharSequence name,
- boolean useDefaults) {
+ public static Name getElementValueClassName(
+ AnnotationMirror anno, CharSequence name, boolean useDefaults) {
Type.ClassType ct = getElementValue(anno, name, Type.ClassType.class, useDefaults);
// TODO: Is it a problem that this returns the type parameters too? Should I cut them off?
return ct.asElement().getQualifiedName();
}
+ /** Get the list of Names of the classes that are referenced by attribute {@code name}. */
+ public static List<Name> getElementValueClassNames(
+ AnnotationMirror anno, CharSequence name, boolean useDefaults) {
+ List<Type.ClassType> la =
+ getElementValueArray(anno, name, Type.ClassType.class, useDefaults);
+ List<Name> names = new ArrayList<>();
+ for (Type.ClassType classType : la) {
+ names.add(classType.asElement().getQualifiedName());
+ }
+ return names;
+ }
+
/**
- * Get the Class that is referenced by attribute 'name'.
- * This method uses Class.forName to load the class. It returns
- * null if the class wasn't found.
+ * Get the Class that is referenced by attribute {@code name}. This method uses Class.forName to
+ * load the class. It returns null if the class wasn't found.
*/
- public static Class<?> getElementValueClass(AnnotationMirror anno, CharSequence name,
- boolean useDefaults) {
+ public static Class<?> getElementValueClass(
+ AnnotationMirror anno, CharSequence name, boolean useDefaults) {
Name cn = getElementValueClassName(anno, name, useDefaults);
try {
- Class<?> cls = Class.forName(cn.toString());
+ ClassLoader classLoader = InternalUtils.getClassLoaderForClass(AnnotationUtils.class);
+ Class<?> cls = Class.forName(cn.toString(), true, classLoader);
return cls;
} catch (ClassNotFoundException e) {
- ErrorReporter.errorAbort("Could not load class '" + cn + "' for field '" + name +
- "' in annotation " + anno, e);
+ String msg =
+ String.format(
+ "Could not load class '%s' for field '%s' in annotation %s",
+ cn, name, anno);
+ ErrorReporter.errorAbort(msg, e);
return null; // dead code
}
}
/**
- * See checkers.types.QualifierHierarchy#updateMappingToMutableSet(QualifierHierarchy, Map, Object, AnnotationMirror)
- * (Not linked because it is in an independent project.
+ * See checkers.types.QualifierHierarchy#updateMappingToMutableSet(QualifierHierarchy, Map,
+ * Object, AnnotationMirror) (Not linked because it is in an independent project.
*/
- public static <T> void updateMappingToImmutableSet(Map<T, Set<AnnotationMirror>> map,
- T key, Set<AnnotationMirror> newQual) {
+ public static <T> void updateMappingToImmutableSet(
+ Map<T, Set<AnnotationMirror>> map, T key, Set<AnnotationMirror> newQual) {
Set<AnnotationMirror> result = AnnotationUtils.createAnnotationSet();
// TODO: if T is also an AnnotationMirror, should we use areSame?
@@ -534,4 +629,22 @@ public class AnnotationUtils {
}
map.put(key, Collections.unmodifiableSet(result));
}
+
+ /**
+ * Returns the annotations explicitly written on a constructor result. Callers should check that
+ * {@code constructorDeclaration} is in fact a declaration of a constructor.
+ *
+ * @param constructorDeclaration declaration tree of constructor
+ * @return set of annotations explicit on the resulting type of the constructor
+ */
+ public static Set<AnnotationMirror> getExplicitAnnotationsOnConstructorResult(
+ MethodTree constructorDeclaration) {
+ Set<AnnotationMirror> annotationSet = AnnotationUtils.createAnnotationSet();
+ ModifiersTree modifiersTree = constructorDeclaration.getModifiers();
+ if (modifiersTree != null) {
+ List<? extends AnnotationTree> annotationTrees = modifiersTree.getAnnotations();
+ annotationSet.addAll(InternalUtils.annotationsFromTypeAnnotationTrees(annotationTrees));
+ }
+ return annotationSet;
+ }
}
diff --git a/third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/BasicAnnotationProvider.java b/third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/BasicAnnotationProvider.java
index b885b5cbea..6cf40e79cf 100644
--- a/third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/BasicAnnotationProvider.java
+++ b/third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/BasicAnnotationProvider.java
@@ -1,21 +1,16 @@
package org.checkerframework.javacutil;
+import com.sun.source.tree.Tree;
import java.lang.annotation.Annotation;
-
import java.util.List;
-
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.Element;
-import com.sun.source.tree.Tree;
-
public class BasicAnnotationProvider implements AnnotationProvider {
@Override
- public AnnotationMirror getDeclAnnotation(Element elt,
- Class<? extends Annotation> anno) {
- List<? extends AnnotationMirror> annotationMirrors = elt
- .getAnnotationMirrors();
+ public AnnotationMirror getDeclAnnotation(Element elt, Class<? extends Annotation> anno) {
+ List<? extends AnnotationMirror> annotationMirrors = elt.getAnnotationMirrors();
// Then look at the real annotations.
for (AnnotationMirror am : annotationMirrors) {
@@ -28,8 +23,7 @@ public class BasicAnnotationProvider implements AnnotationProvider {
}
@Override
- public AnnotationMirror getAnnotationMirror(Tree tree,
- Class<? extends Annotation> target) {
+ public AnnotationMirror getAnnotationMirror(Tree tree, Class<? extends Annotation> target) {
return null;
}
}
diff --git a/third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/BasicTypeProcessor.java b/third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/BasicTypeProcessor.java
index c83a00021c..6b68fa4dc2 100644
--- a/third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/BasicTypeProcessor.java
+++ b/third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/BasicTypeProcessor.java
@@ -1,28 +1,22 @@
package org.checkerframework.javacutil;
-import javax.lang.model.element.TypeElement;
-
import com.sun.source.tree.CompilationUnitTree;
-
import com.sun.source.util.TreePath;
import com.sun.source.util.TreePathScanner;
+import javax.lang.model.element.TypeElement;
/**
- * Process the types in an AST in a trivial manner, with hooks for derived classes
- * to actually do something.
+ * Process the types in an AST in a trivial manner, with hooks for derived classes to actually do
+ * something.
*/
public abstract class BasicTypeProcessor extends AbstractTypeProcessor {
/** The source tree that's being scanned. */
protected CompilationUnitTree currentRoot;
- /**
- * Create a TreePathScanner at the given root.
- */
+ /** Create a TreePathScanner at the given root. */
protected abstract TreePathScanner<?, ?> createTreePathScanner(CompilationUnitTree root);
- /**
- * Visit the tree path for the type element.
- */
+ /** Visit the tree path for the type element. */
@Override
public void typeProcess(TypeElement e, TreePath p) {
currentRoot = p.getCompilationUnit();
@@ -32,12 +26,12 @@ public abstract class BasicTypeProcessor extends AbstractTypeProcessor {
scanner = createTreePathScanner(currentRoot);
scanner.scan(p, null);
} catch (Throwable t) {
- System.err.println("BasicTypeProcessor.typeProcess: unexpected Throwable (" +
- t.getClass().getSimpleName() + ") when processing "
- + currentRoot.getSourceFile().getName() +
- (t.getMessage()!=null ? "; message: " + t.getMessage() : ""));
+ System.err.println(
+ "BasicTypeProcessor.typeProcess: unexpected Throwable ("
+ + t.getClass().getSimpleName()
+ + ") when processing "
+ + currentRoot.getSourceFile().getName()
+ + (t.getMessage() != null ? "; message: " + t.getMessage() : ""));
}
}
-
}
-
diff --git a/third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/CollectionUtils.java b/third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/CollectionUtils.java
new file mode 100644
index 0000000000..a6a58250fc
--- /dev/null
+++ b/third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/CollectionUtils.java
@@ -0,0 +1,26 @@
+package org.checkerframework.javacutil;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/** Utility methods related to Java Collections */
+public class CollectionUtils {
+
+ /**
+ * A Utility method for creating LRU cache
+ *
+ * @param size size of the cache
+ * @return a new cache with the provided size
+ */
+ public static <K, V> Map<K, V> createLRUCache(final int size) {
+ return new LinkedHashMap<K, V>() {
+
+ private static final long serialVersionUID = 5261489276168775084L;
+
+ @Override
+ protected boolean removeEldestEntry(Map.Entry<K, V> entry) {
+ return size() > size;
+ }
+ };
+ }
+}
diff --git a/third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/ElementUtils.java b/third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/ElementUtils.java
index 160a9c2eea..4abfa86cb7 100644
--- a/third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/ElementUtils.java
+++ b/third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/ElementUtils.java
@@ -8,6 +8,7 @@ import static com.sun.tools.javac.code.Flags.ABSTRACT;
import static com.sun.tools.javac.code.Flags.EFFECTIVELY_FINAL;
import static com.sun.tools.javac.code.Flags.FINAL;
+import com.sun.tools.javac.code.Symbol;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collection;
@@ -16,7 +17,7 @@ import java.util.Deque;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
-
+import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.ExecutableElement;
@@ -31,26 +32,23 @@ import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.ElementFilter;
import javax.lang.model.util.Elements;
-import com.sun.tools.javac.code.Symbol;
-
-/**
- * A Utility class for analyzing {@code Element}s.
- */
+/** A Utility class for analyzing {@code Element}s. */
public class ElementUtils {
// Class cannot be instantiated.
- private ElementUtils() { throw new AssertionError("Class ElementUtils cannot be instantiated."); }
+ private ElementUtils() {
+ throw new AssertionError("Class ElementUtils cannot be instantiated.");
+ }
/**
* Returns the innermost type element enclosing the given element
*
* @param elem the enclosed element of a class
- * @return the innermost type element
+ * @return the innermost type element
*/
public static TypeElement enclosingClass(final Element elem) {
Element result = elem;
- while (result != null && !result.getKind().isClass()
- && !result.getKind().isInterface()) {
+ while (result != null && !result.getKind().isClass() && !result.getKind().isInterface()) {
/*@Nullable*/ Element encl = result.getEnclosingElement();
result = encl;
}
@@ -58,13 +56,12 @@ public class ElementUtils {
}
/**
- * Returns the innermost package element enclosing the given element.
- * The same effect as {@link javax.lang.model.util.Elements#getPackageOf(Element)}.
- * Returns the element itself if it is a package.
+ * Returns the innermost package element enclosing the given element. The same effect as {@link
+ * javax.lang.model.util.Elements#getPackageOf(Element)}. Returns the element itself if it is a
+ * package.
*
* @param elem the enclosed element of a package
* @return the innermost package element
- *
*/
public static PackageElement enclosingPackage(final Element elem) {
Element result = elem;
@@ -76,20 +73,21 @@ public class ElementUtils {
}
/**
- * Returns the "parent" package element for the given package element.
- * For package "A.B" it gives "A".
- * For package "A" it gives the default package.
- * For the default package it returns null;
+ * Returns the "parent" package element for the given package element. For package "A.B" it
+ * gives "A". For package "A" it gives the default package. For the default package it returns
+ * null;
*
- * Note that packages are not enclosed within each other, we have to manually climb
- * the namespaces. Calling "enclosingPackage" on a package element returns the
- * package element itself again.
+ * <p>Note that packages are not enclosed within each other, we have to manually climb the
+ * namespaces. Calling "enclosingPackage" on a package element returns the package element
+ * itself again.
*
* @param elem the package to start from
* @return the parent package element
- *
*/
public static PackageElement parentPackage(final Elements e, final PackageElement elem) {
+ // The following might do the same thing:
+ // ((Symbol) elt).owner;
+ // TODO: verify and see whether the change is worth it.
String fqnstart = elem.getQualifiedName().toString();
String fqn = fqnstart;
if (fqn != null && !fqn.isEmpty() && fqn.contains(".")) {
@@ -100,10 +98,9 @@ public class ElementUtils {
}
/**
- * Returns true if the element is a static element: whether it is a static
- * field, static method, or static class
+ * Returns true if the element is a static element: whether it is a static field, static method,
+ * or static class
*
- * @param element
* @return true if element is static
*/
public static boolean isStatic(Element element) {
@@ -111,10 +108,8 @@ public class ElementUtils {
}
/**
- * Returns true if the element is a final element: a final field, final
- * method, or final class
+ * Returns true if the element is a final element: a final field, final method, or final class
*
- * @param element
* @return true if the element is final
*/
public static boolean isFinal(Element element) {
@@ -124,44 +119,39 @@ public class ElementUtils {
/**
* Returns true if the element is a effectively final element.
*
- * @param element
* @return true if the element is effectively final
*/
public static boolean isEffectivelyFinal(Element element) {
Symbol sym = (Symbol) element;
- if (sym.getEnclosingElement().getKind() == ElementKind.METHOD &&
- (sym.getEnclosingElement().flags() & ABSTRACT) != 0) {
+ if (sym.getEnclosingElement().getKind() == ElementKind.METHOD
+ && (sym.getEnclosingElement().flags() & ABSTRACT) != 0) {
return true;
}
return (sym.flags() & (FINAL | EFFECTIVELY_FINAL)) != 0;
}
/**
- * Returns the {@code TypeMirror} for usage of Element as a value. It
- * returns the return type of a method element, the class type of a
- * constructor, or simply the type mirror of the element itself.
+ * Returns the {@code TypeMirror} for usage of Element as a value. It returns the return type of
+ * a method element, the class type of a constructor, or simply the type mirror of the element
+ * itself.
*
- * @param element
- * @return the type for the element used as a value
+ * @return the type for the element used as a value
*/
public static TypeMirror getType(Element element) {
- if (element.getKind() == ElementKind.METHOD)
- return ((ExecutableElement)element).getReturnType();
- else if (element.getKind() == ElementKind.CONSTRUCTOR)
+ if (element.getKind() == ElementKind.METHOD) {
+ return ((ExecutableElement) element).getReturnType();
+ } else if (element.getKind() == ElementKind.CONSTRUCTOR) {
return enclosingClass(element).asType();
- else
+ } else {
return element.asType();
+ }
}
/**
- * Returns the qualified name of the inner most class enclosing
- * the provided {@code Element}
+ * Returns the qualified name of the inner most class enclosing the provided {@code Element}
*
- * @param element
- * an element enclosed by a class, or a
- * {@code TypeElement}
- * @return The qualified {@code Name} of the innermost class
- * enclosing the element
+ * @param element an element enclosed by a class, or a {@code TypeElement}
+ * @return the qualified {@code Name} of the innermost class enclosing the element
*/
public static /*@Nullable*/ Name getQualifiedClassName(Element element) {
if (element.getKind() == ElementKind.PACKAGE) {
@@ -170,18 +160,18 @@ public class ElementUtils {
}
TypeElement elem = enclosingClass(element);
- if (elem == null)
+ if (elem == null) {
return null;
+ }
return elem.getQualifiedName();
}
- /**
- * Returns a verbose name that identifies the element.
- */
+ /** Returns a verbose name that identifies the element. */
public static String getVerboseName(Element elt) {
- if (elt.getKind() == ElementKind.PACKAGE ||
- elt.getKind().isClass()) {
+ if (elt.getKind() == ElementKind.PACKAGE
+ || elt.getKind().isClass()
+ || elt.getKind().isInterface()) {
return getQualifiedClassName(elt).toString();
} else {
return getQualifiedClassName(elt) + "." + elt.toString();
@@ -191,34 +181,33 @@ public class ElementUtils {
/**
* Check if the element is an element for 'java.lang.Object'
*
- * @param element the type element
+ * @param element the type element
* @return true iff the element is java.lang.Object element
*/
public static boolean isObject(TypeElement element) {
return element.getQualifiedName().contentEquals("java.lang.Object");
}
- /**
- * Returns true if the element is a constant time reference
- */
+ /** Returns true if the element is a constant time reference */
public static boolean isCompileTimeConstant(Element elt) {
return elt != null
- && elt.getKind() == ElementKind.FIELD
- && ((VariableElement)elt).getConstantValue() != null;
+ && (elt.getKind() == ElementKind.FIELD
+ || elt.getKind() == ElementKind.LOCAL_VARIABLE)
+ && ((VariableElement) elt).getConstantValue() != null;
}
/**
- * Returns true if the element is declared in ByteCode.
- * Always return false if elt is a package.
+ * Returns true if the element is declared in ByteCode. Always return false if elt is a package.
*/
- public static boolean isElementFromByteCode(Element elt){
- if (elt == null)
+ public static boolean isElementFromByteCode(Element elt) {
+ if (elt == null) {
return false;
+ }
- if (elt instanceof Symbol.ClassSymbol){
+ if (elt instanceof Symbol.ClassSymbol) {
Symbol.ClassSymbol clss = (Symbol.ClassSymbol) elt;
- if (null != clss.classfile){
- //The class file could be a .java file
+ if (null != clss.classfile) {
+ // The class file could be a .java file
return clss.classfile.getName().endsWith(".class");
} else {
return false;
@@ -228,19 +217,19 @@ public class ElementUtils {
}
/**
- * Returns true if the element is declared in ByteCode.
- * Always return false if elt is a package.
+ * Returns true if the element is declared in ByteCode. Always return false if elt is a package.
*/
- private static boolean isElementFromByteCode(Element elt, Element orig){
- if (elt == null)
+ private static boolean isElementFromByteCode(Element elt, Element orig) {
+ if (elt == null) {
return false;
- if (elt instanceof Symbol.ClassSymbol){
+ }
+ if (elt instanceof Symbol.ClassSymbol) {
Symbol.ClassSymbol clss = (Symbol.ClassSymbol) elt;
- if (null != clss.classfile){
+ if (null != clss.classfile) {
// The class file could be a .java file
- return (clss.classfile.getName().endsWith(".class") ||
- clss.classfile.getName().endsWith(".class)") ||
- clss.classfile.getName().endsWith(".class)]"));
+ return (clss.classfile.getName().endsWith(".class")
+ || clss.classfile.getName().endsWith(".class)")
+ || clss.classfile.getName().endsWith(".class)]"));
} else {
return false;
}
@@ -248,11 +237,9 @@ public class ElementUtils {
return isElementFromByteCode(elt.getEnclosingElement(), elt);
}
- /**
- * Returns the field of the class
- */
+ /** Returns the field of the class */
public static VariableElement findFieldInType(TypeElement type, String name) {
- for (VariableElement field: ElementFilter.fieldsIn(type.getEnclosedElements())) {
+ for (VariableElement field : ElementFilter.fieldsIn(type.getEnclosedElements())) {
if (field.getSimpleName().toString().equals(name)) {
return field;
}
@@ -260,9 +247,22 @@ public class ElementUtils {
return null;
}
- public static Set<VariableElement> findFieldsInType(TypeElement type, Collection<String> names) {
+ /**
+ * Returns the elements of the fields whose simple names are {@code names} and are declared in
+ * {@code type}.
+ *
+ * <p>If a field isn't declared in {@code type}, its element isn't included in the returned set.
+ * If none of the fields is declared in {@code type}, the empty set is returned.
+ *
+ * @param type where to look for fields
+ * @param names simple names of fields that might be declared in {@code type}
+ * @return the elements of the fields whose simple names are {@code names} and are declared in
+ * {@code type}
+ */
+ public static Set<VariableElement> findFieldsInType(
+ TypeElement type, Collection<String> names) {
Set<VariableElement> results = new HashSet<VariableElement>();
- for (VariableElement field: ElementFilter.fieldsIn(type.getEnclosedElements())) {
+ for (VariableElement field : ElementFilter.fieldsIn(type.getEnclosedElements())) {
if (names.contains(field.getSimpleName().toString())) {
results.add(field);
}
@@ -270,35 +270,87 @@ public class ElementUtils {
return results;
}
+ /**
+ * Returns non-private field elements, and side-effects {@code names} to remove them. For every
+ * field name in {@code names} that is declared in {@code type} or a supertype, add its element
+ * to the returned set and remove it from {@code names}.
+ *
+ * <p>When this routine returns, the combination of the return value and {@code names} has the
+ * same cardinality, and represents the same fields, as {@code names} did when the method was
+ * called.
+ *
+ * @param type where to look for fields
+ * @param names simple names of fields that might be declared in {@code type} or a supertype.
+ * (Names that are found are removed from this list.)
+ * @return the {@code VariableElement}s for non-private fields that are declared in {@code type}
+ * whose simple names were in {@code names} when the method was called.
+ */
+ public static Set<VariableElement> findFieldsInTypeOrSuperType(
+ TypeMirror type, Collection<String> names) {
+ Set<VariableElement> elements = new HashSet<>();
+ findFieldsInTypeOrSuperType(type, names, elements);
+ return elements;
+ }
+
+ /**
+ * Side-effects both {@code foundFields} (which starts empty) and {@code notFound}, conceptually
+ * moving elements from {@code notFound} to {@code foundFields}.
+ */
+ private static void findFieldsInTypeOrSuperType(
+ TypeMirror type, Collection<String> notFound, Set<VariableElement> foundFields) {
+ if (TypesUtils.isObject(type)) {
+ return;
+ }
+ TypeElement elt = InternalUtils.getTypeElement(type);
+
+ Set<VariableElement> fieldElts = findFieldsInType(elt, notFound);
+ for (VariableElement field : new HashSet<>(fieldElts)) {
+ if (!field.getModifiers().contains(Modifier.PRIVATE)) {
+ notFound.remove(field.getSimpleName().toString());
+ } else {
+ fieldElts.remove(field);
+ }
+ }
+ foundFields.addAll(fieldElts);
+
+ if (!notFound.isEmpty()) {
+ findFieldsInTypeOrSuperType(elt.getSuperclass(), notFound, foundFields);
+ }
+ }
+
public static boolean isError(Element element) {
- return element.getClass().getName().equals("com.sun.tools.javac.comp.Resolve$SymbolNotFoundError");
+ return element.getClass()
+ .getName()
+ .equals("com.sun.tools.javac.comp.Resolve$SymbolNotFoundError");
}
/**
- * Does the given element need a receiver for accesses?
- * For example, an access to a local variable does not require a receiver.
+ * Does the given element need a receiver for accesses? For example, an access to a local
+ * variable does not require a receiver.
*
- * @param element The element to test.
- * @return whether the element requires a receiver for accesses.
+ * @param element the element to test
+ * @return whether the element requires a receiver for accesses
*/
public static boolean hasReceiver(Element element) {
- return element.getKind() != ElementKind.LOCAL_VARIABLE
- && element.getKind() != ElementKind.PARAMETER
- && element.getKind() != ElementKind.PACKAGE
+ return (element.getKind().isField()
+ || element.getKind() == ElementKind.METHOD
+ || element.getKind() == ElementKind.CONSTRUCTOR)
&& !ElementUtils.isStatic(element);
}
/**
- * Determine all type elements for the classes and interfaces referenced
- * in the extends/implements clauses of the given type element.
- * TODO: can we learn from the implementation of
+ * Determine all type elements for the classes and interfaces referenced (directly or
+ * indirectly) in the extends/implements clauses of the given type element.
+ *
+ * <p>TODO: can we learn from the implementation of
* com.sun.tools.javac.model.JavacElements.getAllMembers(TypeElement)?
*/
- public static List<TypeElement> getSuperTypes(TypeElement type) {
+ public static List<TypeElement> getSuperTypes(Elements elements, TypeElement type) {
List<TypeElement> superelems = new ArrayList<TypeElement>();
- if (type == null)
+ if (type == null) {
return superelems;
+ }
// Set up a stack containing type, which is our starting point.
Deque<TypeElement> stack = new ArrayDeque<TypeElement>();
@@ -310,16 +362,27 @@ public class ElementUtils {
// For each direct supertype of the current type element, if it
// hasn't already been visited, push it onto the stack and
// add it to our superelems set.
- TypeMirror supertypecls = current.getSuperclass();
- if (supertypecls.getKind() != TypeKind.NONE) {
- TypeElement supercls = (TypeElement) ((DeclaredType)supertypecls).asElement();
+ TypeMirror supertypecls;
+ try {
+ supertypecls = current.getSuperclass();
+ } catch (com.sun.tools.javac.code.Symbol.CompletionFailure cf) {
+ // Looking up a supertype failed. This sometimes happens
+ // when transitive dependencies are not on the classpath.
+ // As javac didn't complain, let's also not complain.
+ // TODO: Use an expanded ErrorReporter to output a message.
+ supertypecls = null;
+ }
+
+ if (supertypecls != null && supertypecls.getKind() != TypeKind.NONE) {
+ TypeElement supercls = (TypeElement) ((DeclaredType) supertypecls).asElement();
if (!superelems.contains(supercls)) {
stack.push(supercls);
superelems.add(supercls);
}
}
+
for (TypeMirror supertypeitf : current.getInterfaces()) {
- TypeElement superitf = (TypeElement) ((DeclaredType)supertypeitf).asElement();
+ TypeElement superitf = (TypeElement) ((DeclaredType) supertypeitf).asElement();
if (!superelems.contains(superitf)) {
stack.push(superitf);
superelems.add(superitf);
@@ -327,18 +390,24 @@ public class ElementUtils {
}
}
+ // Include java.lang.Object as implicit superclass for all classes and interfaces.
+ TypeElement jlobject = elements.getTypeElement("java.lang.Object");
+ if (!superelems.contains(jlobject)) {
+ superelems.add(jlobject);
+ }
+
return Collections.<TypeElement>unmodifiableList(superelems);
}
/**
- * Return all fields declared in the given type or any superclass/interface.
- * TODO: should this use javax.lang.model.util.Elements.getAllMembers(TypeElement)
- * instead of our own getSuperTypes?
+ * Return all fields declared in the given type or any superclass/interface. TODO: should this
+ * use javax.lang.model.util.Elements.getAllMembers(TypeElement) instead of our own
+ * getSuperTypes?
*/
- public static List<VariableElement> getAllFieldsIn(TypeElement type) {
+ public static List<VariableElement> getAllFieldsIn(Elements elements, TypeElement type) {
List<VariableElement> fields = new ArrayList<VariableElement>();
fields.addAll(ElementFilter.fieldsIn(type.getEnclosedElements()));
- List<TypeElement> alltypes = getSuperTypes(type);
+ List<TypeElement> alltypes = getSuperTypes(elements, type);
for (TypeElement atype : alltypes) {
fields.addAll(ElementFilter.fieldsIn(atype.getEnclosedElements()));
}
@@ -346,16 +415,15 @@ public class ElementUtils {
}
/**
- * Return all methods declared in the given type or any superclass/interface.
- * Note that no constructors will be returned.
- * TODO: should this use javax.lang.model.util.Elements.getAllMembers(TypeElement)
- * instead of our own getSuperTypes?
+ * Return all methods declared in the given type or any superclass/interface. Note that no
+ * constructors will be returned. TODO: should this use
+ * javax.lang.model.util.Elements.getAllMembers(TypeElement) instead of our own getSuperTypes?
*/
- public static List<ExecutableElement> getAllMethodsIn(TypeElement type) {
+ public static List<ExecutableElement> getAllMethodsIn(Elements elements, TypeElement type) {
List<ExecutableElement> meths = new ArrayList<ExecutableElement>();
meths.addAll(ElementFilter.methodsIn(type.getEnclosedElements()));
- List<TypeElement> alltypes = getSuperTypes(type);
+ List<TypeElement> alltypes = getSuperTypes(elements, type);
for (TypeElement atype : alltypes) {
meths.addAll(ElementFilter.methodsIn(atype.getEnclosedElements()));
}
@@ -364,8 +432,8 @@ public class ElementUtils {
public static boolean isTypeDeclaration(Element elt) {
switch (elt.getKind()) {
- // These tree kinds are always declarations. Uses of the declared
- // types have tree kind IDENTIFIER.
+ // These tree kinds are always declarations. Uses of the declared
+ // types have tree kind IDENTIFIER.
case ANNOTATION_TYPE:
case CLASS:
case ENUM:
@@ -381,17 +449,16 @@ public class ElementUtils {
/**
* Check that a method Element matches a signature.
*
- * Note: Matching the receiver type must be done elsewhere as
- * the Element receiver type is only populated when annotated.
+ * <p>Note: Matching the receiver type must be done elsewhere as the Element receiver type is
+ * only populated when annotated.
*
* @param method the method Element
* @param methodName the name of the method
* @param parameters the formal parameters' Classes
* @return true if the method matches
*/
- public static boolean matchesElement(ExecutableElement method,
- String methodName,
- Class<?> ... parameters) {
+ public static boolean matchesElement(
+ ExecutableElement method, String methodName, Class<?>... parameters) {
if (!method.getSimpleName().toString().equals(methodName)) {
return false;
@@ -401,8 +468,11 @@ public class ElementUtils {
return false;
} else {
for (int i = 0; i < method.getParameters().size(); i++) {
- if (!method.getParameters().get(i).asType().toString().equals(
- parameters[i].getName())) {
+ if (!method.getParameters()
+ .get(i)
+ .asType()
+ .toString()
+ .equals(parameters[i].getName())) {
return false;
}
@@ -411,4 +481,12 @@ public class ElementUtils {
return true;
}
+
+ /** Returns true if the given element is, or overrides, method. */
+ public static boolean isMethod(
+ ExecutableElement questioned, ExecutableElement method, ProcessingEnvironment env) {
+ TypeElement enclosing = (TypeElement) questioned.getEnclosingElement();
+ return questioned.equals(method)
+ || env.getElementUtils().overrides(questioned, method, enclosing);
+ }
}
diff --git a/third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/ErrorHandler.java b/third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/ErrorHandler.java
index 3fd0faa475..76ee74eaca 100644
--- a/third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/ErrorHandler.java
+++ b/third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/ErrorHandler.java
@@ -1,16 +1,15 @@
package org.checkerframework.javacutil;
/**
- * An implementation of the ErrorHandler interface can be registered
- * with the ErrorReporter class to change the default behavior on
- * errors.
+ * An implementation of the ErrorHandler interface can be registered with the ErrorReporter class to
+ * change the default behavior on errors.
*/
public interface ErrorHandler {
/**
* Log an error message and abort processing.
*
- * @param msg The error message to log.
+ * @param msg the error message to log
*/
public void errorAbort(String msg);
diff --git a/third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/ErrorReporter.java b/third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/ErrorReporter.java
index 072e1a1031..4ff62e05d1 100644
--- a/third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/ErrorReporter.java
+++ b/third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/ErrorReporter.java
@@ -1,27 +1,24 @@
package org.checkerframework.javacutil;
/**
- * Handle errors detected in utility classes. By default, the error reporter
- * throws a RuntimeException, but clients of the utility library may register
- * a handler to change the behavior. For example, type checkers can direct
- * errors to the org.checkerframework.framework.source.SourceChecker class.
+ * Handle errors detected in utility classes. By default, the error reporter throws a
+ * RuntimeException, but clients of the utility library may register a handler to change the
+ * behavior. For example, type checkers can direct errors to the
+ * org.checkerframework.framework.source.SourceChecker class.
*/
public class ErrorReporter {
protected static ErrorHandler handler = null;
- /**
- * Register a handler to customize error reporting.
- */
+ /** Register a handler to customize error reporting. */
public static void setHandler(ErrorHandler h) {
handler = h;
}
/**
- * Log an error message and abort processing.
- * Call this method instead of raising an exception.
+ * Log an error message and abort processing. Call this method instead of raising an exception.
*
- * @param msg The error message to log.
+ * @param msg the error message to log
*/
public static void errorAbort(String msg) {
if (handler != null) {
@@ -31,6 +28,22 @@ public class ErrorReporter {
}
}
+ /**
+ * Log an error message use {@link String#format(String, Object...)}} and abort processing. Call
+ * this method instead of raising an exception.
+ *
+ * @param format a format string
+ * @param args arguments to the format string
+ */
+ public static void errorAbort(String format, Object... args) {
+ String formattedMsg = String.format(format, args);
+ if (handler != null) {
+ handler.errorAbort(formattedMsg);
+ } else {
+ throw new RuntimeException(formattedMsg, new Throwable());
+ }
+ }
+
public static void errorAbort(String msg, Throwable cause) {
if (handler != null) {
handler.errorAbort(msg, cause);
diff --git a/third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/InternalUtils.java b/third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/InternalUtils.java
index 40cb4747f5..10a48cd719 100644
--- a/third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/InternalUtils.java
+++ b/third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/InternalUtils.java
@@ -1,19 +1,5 @@
package org.checkerframework.javacutil;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-import javax.annotation.processing.ProcessingEnvironment;
-import javax.lang.model.element.AnnotationMirror;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.type.TypeKind;
-import javax.lang.model.type.TypeMirror;
-import javax.lang.model.type.TypeVariable;
-import javax.lang.model.type.WildcardType;
-import javax.lang.model.util.Elements;
-
import com.sun.source.tree.AnnotatedTypeTree;
import com.sun.source.tree.AnnotationTree;
import com.sun.source.tree.ArrayAccessTree;
@@ -29,6 +15,7 @@ import com.sun.tools.javac.code.Flags;
import com.sun.tools.javac.code.Symbol;
import com.sun.tools.javac.code.Symbol.TypeSymbol;
import com.sun.tools.javac.code.Type;
+import com.sun.tools.javac.code.Type.CapturedType;
import com.sun.tools.javac.code.Types;
import com.sun.tools.javac.processing.JavacProcessingEnvironment;
import com.sun.tools.javac.tree.JCTree;
@@ -43,15 +30,29 @@ import com.sun.tools.javac.tree.JCTree.JCNewClass;
import com.sun.tools.javac.tree.JCTree.JCTypeParameter;
import com.sun.tools.javac.tree.TreeInfo;
import com.sun.tools.javac.util.Context;
+import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.TypeKind;
+import javax.lang.model.type.TypeMirror;
+import javax.lang.model.type.TypeVariable;
+import javax.lang.model.type.WildcardType;
+import javax.lang.model.util.Elements;
/*>>>
- import org.checkerframework.checker.nullness.qual.*;
- */
+import org.checkerframework.checker.nullness.qual.*;
+*/
/**
- * Static utility methods used by annotation abstractions in this package. Some
- * methods in this class depend on the use of Sun javac internals; any procedure
- * in the Checker Framework that uses a non-public API should be placed here.
+ * Static utility methods used by annotation abstractions in this package. Some methods in this
+ * class depend on the use of Sun javac internals; any procedure in the Checker Framework that uses
+ * a non-public API should be placed here.
*/
public class InternalUtils {
@@ -64,11 +65,9 @@ public class InternalUtils {
* Gets the {@link Element} ("symbol") for the given Tree API node.
*
* @param tree the {@link Tree} node to get the symbol for
- * @throws IllegalArgumentException
- * if {@code tree} is null or is not a valid javac-internal tree
- * (JCTree)
- * @return the {@code {@link Symbol}} for the given tree, or null if one
- * could not be found
+ * @throws IllegalArgumentException if {@code tree} is null or is not a valid javac-internal
+ * tree (JCTree)
+ * @return the {@link Symbol} for the given tree, or null if one could not be found
*/
public static /*@Nullable*/ Element symbol(Tree tree) {
if (tree == null) {
@@ -95,19 +94,19 @@ public class InternalUtils {
case TYPE_PARAMETER:
return TreeInfo.symbolFor((JCTree) tree);
- // symbol() only works on MethodSelects, so we need to get it manually
- // for method invocations.
+ // symbol() only works on MethodSelects, so we need to get it manually
+ // for method invocations.
case METHOD_INVOCATION:
return TreeInfo.symbol(((JCMethodInvocation) tree).getMethodSelect());
case ASSIGNMENT:
- return TreeInfo.symbol((JCTree)((AssignmentTree)tree).getVariable());
+ return TreeInfo.symbol((JCTree) ((AssignmentTree) tree).getVariable());
case ARRAY_ACCESS:
- return symbol(((ArrayAccessTree)tree).getExpression());
+ return symbol(((ArrayAccessTree) tree).getExpression());
case NEW_CLASS:
- return ((JCNewClass)tree).constructor;
+ return ((JCNewClass) tree).constructor;
case MEMBER_REFERENCE:
// TreeInfo.symbol, which is used in the default case, didn't handle
@@ -120,43 +119,40 @@ public class InternalUtils {
}
/**
- * Determines whether or not the node referred to by the given
- * {@link TreePath} is an anonymous constructor (the constructor for an
- * anonymous class.
+ * Determines whether or not the node referred to by the given {@link TreePath} is an anonymous
+ * constructor (the constructor for an anonymous class.
*
- * @param method the {@link TreePath} for a node that may be an anonymous
- * constructor
- * @return true if the given path points to an anonymous constructor, false
- * if it does not
+ * @param method the {@link TreePath} for a node that may be an anonymous constructor
+ * @return true if the given path points to an anonymous constructor, false if it does not
*/
public static boolean isAnonymousConstructor(final MethodTree method) {
/*@Nullable*/ Element e = InternalUtils.symbol(method);
- if (e == null || !(e instanceof Symbol))
+ if (e == null || !(e instanceof Symbol)) {
return false;
+ }
- if ((((/*@NonNull*/ Symbol)e).flags() & Flags.ANONCONSTR) != 0)
+ if ((((/*@NonNull*/ Symbol) e).flags() & Flags.ANONCONSTR) != 0) {
return true;
+ }
return false;
}
/**
- * indicates whether it should return the constructor that gets invoked
- * in cases of anonymous classes
+ * indicates whether it should return the constructor that gets invoked in cases of anonymous
+ * classes
*/
private static final boolean RETURN_INVOKE_CONSTRUCTOR = true;
/**
- * Determines the symbol for a constructor given an invocation via
- * {@code new}.
+ * Determines the symbol for a constructor given an invocation via {@code new}.
*
- * If the tree is a declaration of an anonymous class, then method returns
- * constructor that gets invoked in the extended class, rather than the
- * anonymous constructor implicitly added by the constructor (JLS 15.9.5.1)
+ * <p>If the tree is a declaration of an anonymous class, then method returns constructor that
+ * gets invoked in the extended class, rather than the anonymous constructor implicitly added by
+ * the constructor (JLS 15.9.5.1)
*
* @param tree the constructor invocation
- * @return the {@link ExecutableElement} corresponding to the constructor
- * call in {@code tree}
+ * @return the {@link ExecutableElement} corresponding to the constructor call in {@code tree}
*/
public static ExecutableElement constructor(NewClassTree tree) {
@@ -178,7 +174,7 @@ public class InternalUtils {
// the method call is guaranteed to return nonnull
JCMethodDecl anonConstructor =
- (JCMethodDecl) TreeInfo.declarationFor(newClassTree.constructor, newClassTree);
+ (JCMethodDecl) TreeInfo.declarationFor(newClassTree.constructor, newClassTree);
assert anonConstructor != null;
assert anonConstructor.body.stats.size() == 1;
JCExpressionStatement stmt = (JCExpressionStatement) anonConstructor.body.stats.head;
@@ -193,22 +189,31 @@ public class InternalUtils {
return (ExecutableElement) e;
}
- public final static List<AnnotationMirror> annotationsFromTypeAnnotationTrees(List<? extends AnnotationTree> annos) {
+ public static final List<AnnotationMirror> annotationsFromTypeAnnotationTrees(
+ List<? extends AnnotationTree> annos) {
List<AnnotationMirror> annotations = new ArrayList<AnnotationMirror>(annos.size());
- for (AnnotationTree anno : annos)
- annotations.add(((JCAnnotation)anno).attribute);
+ for (AnnotationTree anno : annos) {
+ annotations.add(annotationFromAnnotationTree(anno));
+ }
return annotations;
}
- public final static List<? extends AnnotationMirror> annotationsFromTree(AnnotatedTypeTree node) {
- return annotationsFromTypeAnnotationTrees(((JCAnnotatedType)node).annotations);
+ public static AnnotationMirror annotationFromAnnotationTree(AnnotationTree tree) {
+ return ((JCAnnotation) tree).attribute;
+ }
+
+ public static final List<? extends AnnotationMirror> annotationsFromTree(
+ AnnotatedTypeTree node) {
+ return annotationsFromTypeAnnotationTrees(((JCAnnotatedType) node).annotations);
}
- public final static List<? extends AnnotationMirror> annotationsFromTree(TypeParameterTree node) {
- return annotationsFromTypeAnnotationTrees(((JCTypeParameter)node).annotations);
+ public static final List<? extends AnnotationMirror> annotationsFromTree(
+ TypeParameterTree node) {
+ return annotationsFromTypeAnnotationTrees(((JCTypeParameter) node).annotations);
}
- public final static List<? extends AnnotationMirror> annotationsFromArrayCreation(NewArrayTree node, int level) {
+ public static final List<? extends AnnotationMirror> annotationsFromArrayCreation(
+ NewArrayTree node, int level) {
assert node instanceof JCNewArray;
final JCNewArray newArray = ((JCNewArray) node);
@@ -229,32 +234,40 @@ public class InternalUtils {
return ((JCTree) tree).type;
}
- /**
- * Returns whether a TypeVariable represents a captured type.
- */
+ /** Returns whether a TypeVariable represents a captured type. */
public static boolean isCaptured(TypeVariable typeVar) {
- return ((Type.TypeVar) typeVar).isCaptured();
+ return ((Type.TypeVar) TypeAnnotationUtils.unannotatedType(typeVar)).isCaptured();
}
- /**
- * Returns whether a TypeMirror represents a class type.
- */
+ /** If typeVar is a captured wildcard, returns that wildcard; otherwise returns null. */
+ public static WildcardType getCapturedWildcard(TypeVariable typeVar) {
+ if (isCaptured(typeVar)) {
+ return ((CapturedType) TypeAnnotationUtils.unannotatedType(typeVar)).wildcard;
+ }
+ return null;
+ }
+
+ /** Returns whether a TypeMirror represents a class type. */
public static boolean isClassType(TypeMirror type) {
return (type instanceof Type.ClassType);
}
/**
- * Returns the least upper bound of two {@link TypeMirror}s.
+ * Returns the least upper bound of two {@link TypeMirror}s, ignoring any annotations on the
+ * types.
*
- * @param processingEnv The {@link ProcessingEnvironment} to use.
- * @param tm1 A {@link TypeMirror}.
- * @param tm2 A {@link TypeMirror}.
- * @return The least upper bound of {@code tm1} and {@code tm2}.
+ * <p>Wrapper around Types.lub to add special handling for null types, primitives, and
+ * wildcards.
+ *
+ * @param processingEnv the {@link ProcessingEnvironment} to use
+ * @param tm1 a {@link TypeMirror}
+ * @param tm2 a {@link TypeMirror}
+ * @return the least upper bound of {@code tm1} and {@code tm2}.
*/
public static TypeMirror leastUpperBound(
ProcessingEnvironment processingEnv, TypeMirror tm1, TypeMirror tm2) {
- Type t1 = (Type) tm1;
- Type t2 = (Type) tm2;
+ Type t1 = TypeAnnotationUtils.unannotatedType(tm1);
+ Type t2 = TypeAnnotationUtils.unannotatedType(tm2);
JavacProcessingEnvironment javacEnv = (JavacProcessingEnvironment) processingEnv;
Types types = Types.instance(javacEnv.getContext());
if (types.isSameType(t1, t2)) {
@@ -268,16 +281,6 @@ public class InternalUtils {
if (t2.getKind() == TypeKind.NULL) {
return t1;
}
- // Special case for primitives.
- if (TypesUtils.isPrimitive(t1) || TypesUtils.isPrimitive(t2)) {
- if (types.isAssignable(t1, t2)) {
- return t2;
- } else if (types.isAssignable(t2, t1)) {
- return t1;
- } else {
- return processingEnv.getTypeUtils().getNoType(TypeKind.NONE);
- }
- }
if (t1.getKind() == TypeKind.WILDCARD) {
WildcardType wc1 = (WildcardType) t1;
Type bound = (Type) wc1.getExtendsBound();
@@ -298,21 +301,36 @@ public class InternalUtils {
}
t2 = bound;
}
+ // Special case for primitives.
+ if (TypesUtils.isPrimitive(t1) || TypesUtils.isPrimitive(t2)) {
+ if (types.isAssignable(t1, t2)) {
+ return t2;
+ } else if (types.isAssignable(t2, t1)) {
+ return t1;
+ } else {
+ Elements elements = processingEnv.getElementUtils();
+ return elements.getTypeElement("java.lang.Object").asType();
+ }
+ }
return types.lub(t1, t2);
}
/**
- * Returns the greatest lower bound of two {@link TypeMirror}s.
+ * Returns the greatest lower bound of two {@link TypeMirror}s, ignoring any annotations on the
+ * types.
*
- * @param processingEnv The {@link ProcessingEnvironment} to use.
- * @param tm1 A {@link TypeMirror}.
- * @param tm2 A {@link TypeMirror}.
- * @return The greatest lower bound of {@code tm1} and {@code tm2}.
+ * <p>Wrapper around Types.glb to add special handling for null types, primitives, and
+ * wildcards.
+ *
+ * @param processingEnv the {@link ProcessingEnvironment} to use
+ * @param tm1 a {@link TypeMirror}
+ * @param tm2 a {@link TypeMirror}
+ * @return the greatest lower bound of {@code tm1} and {@code tm2}.
*/
public static TypeMirror greatestLowerBound(
ProcessingEnvironment processingEnv, TypeMirror tm1, TypeMirror tm2) {
- Type t1 = (Type) tm1;
- Type t2 = (Type) tm2;
+ Type t1 = TypeAnnotationUtils.unannotatedType(tm1);
+ Type t2 = TypeAnnotationUtils.unannotatedType(tm2);
JavacProcessingEnvironment javacEnv = (JavacProcessingEnvironment) processingEnv;
Types types = Types.instance(javacEnv.getContext());
if (types.isSameType(t1, t2)) {
@@ -345,21 +363,24 @@ public class InternalUtils {
if (t2.getKind() == TypeKind.WILDCARD) {
return t1;
}
+
+ // If neither type is a primitive type, null type, or wildcard
+ // and if the types are not the same, use javac types.glb
return types.glb(t1, t2);
}
/**
- * Returns the return type of a method, where the "raw" return type of that
- * method is given (i.e., the return type might still contain unsubstituted
- * type variables), given the receiver of the method call.
+ * Returns the return type of a method, where the "raw" return type of that method is given
+ * (i.e., the return type might still contain unsubstituted type variables), given the receiver
+ * of the method call.
*/
- public static TypeMirror substituteMethodReturnType(TypeMirror methodType,
- TypeMirror substitutedReceiverType) {
+ public static TypeMirror substituteMethodReturnType(
+ TypeMirror methodType, TypeMirror substitutedReceiverType) {
if (methodType.getKind() != TypeKind.TYPEVAR) {
return methodType;
}
// TODO: find a nicer way to substitute type variables
- String t = methodType.toString();
+ String t = TypeAnnotationUtils.unannotatedType(methodType).toString();
Type finalReceiverType = (Type) substitutedReceiverType;
int i = 0;
for (TypeSymbol typeParam : finalReceiverType.tsym.getTypeParameters()) {
@@ -372,13 +393,91 @@ public class InternalUtils {
return null;
}
- /** Helper function to extract the javac Context from the
- * javac processing environment.
+ /**
+ * Helper function to extract the javac Context from the javac processing environment.
*
* @param env the processing environment
* @return the javac Context
*/
public static Context getJavacContext(ProcessingEnvironment env) {
- return ((JavacProcessingEnvironment)env).getContext();
+ return ((JavacProcessingEnvironment) env).getContext();
+ }
+
+ /**
+ * Returns the type element for {@code type} if {@code type} is a class, interface, annotation
+ * type, or enum. Otherwise, returns null.
+ *
+ * @param type whose element is returned
+ * @return the type element for {@code type} if {@code type} is a class, interface, annotation
+ * type, or enum; otherwise, returns null
+ */
+ public static TypeElement getTypeElement(TypeMirror type) {
+ Element element = ((Type) type).asElement();
+ switch (element.getKind()) {
+ case ANNOTATION_TYPE:
+ case CLASS:
+ case ENUM:
+ case INTERFACE:
+ return (TypeElement) element;
+ default:
+ return null;
+ }
+ }
+
+ /**
+ * Obtain the class loader for {@code clazz}. If that is not available, return the system class
+ * loader.
+ *
+ * @param clazz the class whose class loader to find
+ * @return the class loader used to {@code clazz}, or the system class loader, or null if both
+ * are unavailable
+ */
+ public static ClassLoader getClassLoaderForClass(Class<? extends Object> clazz) {
+ ClassLoader classLoader = clazz.getClassLoader();
+ return classLoader == null ? ClassLoader.getSystemClassLoader() : classLoader;
+ }
+
+ /**
+ * Compares tree1 to tree2 by the position at which a diagnostic (e.g., an error message) for
+ * the tree should be printed.
+ */
+ public static int compareDiagnosticPosition(Tree tree1, Tree tree2) {
+ DiagnosticPosition pos1 = (DiagnosticPosition) tree1;
+ DiagnosticPosition pos2 = (DiagnosticPosition) tree2;
+
+ int preferred = Integer.compare(pos1.getPreferredPosition(), pos2.getPreferredPosition());
+ if (preferred != 0) {
+ return preferred;
+ }
+
+ return Integer.compare(pos1.getStartPosition(), pos2.getStartPosition());
+ }
+
+ /**
+ * Returns whether or not {@code type} is a functional interface type (as defined in JLS 9.8).
+ *
+ * @param type possible functional interface type
+ * @param env ProcessingEnvironment
+ * @return whether or not {@code type} is a functional interface type (as defined in JLS 9.8)
+ */
+ public static boolean isFunctionalInterface(TypeMirror type, ProcessingEnvironment env) {
+ Context ctx = ((JavacProcessingEnvironment) env).getContext();
+ com.sun.tools.javac.code.Types javacTypes = com.sun.tools.javac.code.Types.instance(ctx);
+ return javacTypes.isFunctionalInterface((Type) type);
+ }
+
+ /**
+ * The type of the lambda or method reference tree is a functional interface type. This method
+ * returns the single abstract method declared by that functional interface. (The type of this
+ * method is referred to as the function type.)
+ *
+ * @param tree lambda or member reference tree
+ * @param env ProcessingEnvironment
+ * @return the single abstract method declared by the type of the tree
+ */
+ public static Symbol findFunction(Tree tree, ProcessingEnvironment env) {
+ Context ctx = ((JavacProcessingEnvironment) env).getContext();
+ com.sun.tools.javac.code.Types javacTypes = com.sun.tools.javac.code.Types.instance(ctx);
+ return javacTypes.findDescriptorSymbol(((Type) typeOf(tree)).asElement());
}
}
diff --git a/third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/Pair.java b/third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/Pair.java
index 779c9b34ec..161af82605 100644
--- a/third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/Pair.java
+++ b/third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/Pair.java
@@ -8,7 +8,7 @@ import org.checkerframework.dataflow.qual.SideEffectFree;
/**
* Simple pair class for multiple returns.
*
- * TODO: as class is immutable, use @Covariant annotation.
+ * <p>TODO: as class is immutable, use @Covariant annotation.
*/
public class Pair<V1, V2> {
public final V1 first;
@@ -36,18 +36,21 @@ public class Pair<V1, V2> {
public int hashCode() {
if (hashCode == -1) {
hashCode = 31;
- if (first != null)
+ if (first != null) {
hashCode += 17 * first.hashCode();
- if (second != null)
+ }
+ if (second != null) {
hashCode += 17 * second.hashCode();
+ }
}
return hashCode;
}
@Override
public boolean equals(Object o) {
- if (!(o instanceof Pair))
+ if (!(o instanceof Pair)) {
return false;
+ }
@SuppressWarnings("unchecked")
Pair<V1, V2> other = (Pair<V1, V2>) o;
if (this.first == null) {
diff --git a/third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/Resolver.java b/third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/Resolver.java
index c47566bfa2..361c6aef99 100644
--- a/third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/Resolver.java
+++ b/third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/Resolver.java
@@ -1,22 +1,15 @@
package org.checkerframework.javacutil;
+import static com.sun.tools.javac.code.Kinds.PCK;
+import static com.sun.tools.javac.code.Kinds.TYP;
import static com.sun.tools.javac.code.Kinds.VAR;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Field;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-
-import javax.annotation.processing.ProcessingEnvironment;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.ElementKind;
-import javax.lang.model.element.VariableElement;
-import javax.lang.model.type.TypeMirror;
-
import com.sun.source.util.TreePath;
import com.sun.source.util.Trees;
import com.sun.tools.javac.api.JavacScope;
import com.sun.tools.javac.code.Symbol;
+import com.sun.tools.javac.code.Symbol.ClassSymbol;
+import com.sun.tools.javac.code.Symbol.PackageSymbol;
import com.sun.tools.javac.code.Symbol.TypeSymbol;
import com.sun.tools.javac.code.Type;
import com.sun.tools.javac.comp.AttrContext;
@@ -29,81 +22,184 @@ import com.sun.tools.javac.util.List;
import com.sun.tools.javac.util.Log;
import com.sun.tools.javac.util.Name;
import com.sun.tools.javac.util.Names;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ElementKind;
+import javax.lang.model.element.VariableElement;
+import javax.lang.model.type.TypeMirror;
-/**
- * A Utility class to find symbols corresponding to string references.
- */
+/** A Utility class to find symbols corresponding to string references. */
public class Resolver {
private final Resolve resolve;
private final Names names;
private final Trees trees;
private final Log log;
- private final Method FIND_METHOD;
- private final Method FIND_IDENT_IN_TYPE;
- private final Method FIND_IDENT_IN_PACKAGE;
- private final Method FIND_TYPE;
+ private static final Method FIND_METHOD;
+ private static final Method FIND_VAR;
+ private static final Method FIND_IDENT;
+ private static final Method FIND_IDENT_IN_TYPE;
+ private static final Method FIND_IDENT_IN_PACKAGE;
+ private static final Method FIND_TYPE;
- public Resolver(ProcessingEnvironment env) {
- Context context = ((JavacProcessingEnvironment) env).getContext();
- this.resolve = Resolve.instance(context);
- this.names = Names.instance(context);
- this.trees = Trees.instance(env);
- this.log = Log.instance(context);
+ private static final Class<?> ACCESSERROR;
+ // Note that currently access(...) is defined in InvalidSymbolError, a superclass of AccessError
+ private static final Method ACCESSERROR_ACCESS;
+ static {
try {
- FIND_METHOD = Resolve.class.getDeclaredMethod("findMethod",
- Env.class, Type.class, Name.class, List.class, List.class,
- boolean.class, boolean.class, boolean.class);
+ FIND_METHOD =
+ Resolve.class.getDeclaredMethod(
+ "findMethod",
+ Env.class,
+ Type.class,
+ Name.class,
+ List.class,
+ List.class,
+ boolean.class,
+ boolean.class,
+ boolean.class);
FIND_METHOD.setAccessible(true);
- FIND_IDENT_IN_TYPE = Resolve.class.getDeclaredMethod(
- "findIdentInType", Env.class, Type.class, Name.class,
- int.class);
+ FIND_VAR = Resolve.class.getDeclaredMethod("findVar", Env.class, Name.class);
+ FIND_VAR.setAccessible(true);
+
+ FIND_IDENT =
+ Resolve.class.getDeclaredMethod("findIdent", Env.class, Name.class, int.class);
+ FIND_IDENT.setAccessible(true);
+
+ FIND_IDENT_IN_TYPE =
+ Resolve.class.getDeclaredMethod(
+ "findIdentInType", Env.class, Type.class, Name.class, int.class);
FIND_IDENT_IN_TYPE.setAccessible(true);
- FIND_IDENT_IN_PACKAGE = Resolve.class.getDeclaredMethod(
- "findIdentInPackage", Env.class, TypeSymbol.class, Name.class,
- int.class);
+ FIND_IDENT_IN_PACKAGE =
+ Resolve.class.getDeclaredMethod(
+ "findIdentInPackage",
+ Env.class,
+ TypeSymbol.class,
+ Name.class,
+ int.class);
FIND_IDENT_IN_PACKAGE.setAccessible(true);
- FIND_TYPE = Resolve.class.getDeclaredMethod(
- "findType", Env.class, Name.class);
+ FIND_TYPE = Resolve.class.getDeclaredMethod("findType", Env.class, Name.class);
FIND_TYPE.setAccessible(true);
} catch (Exception e) {
- Error err = new AssertionError(
- "Compiler 'Resolve' class doesn't contain required 'find' method");
+ Error err =
+ new AssertionError(
+ "Compiler 'Resolve' class doesn't contain required 'find' method");
err.initCause(e);
throw err;
}
+
+ try {
+ ACCESSERROR = Class.forName("com.sun.tools.javac.comp.Resolve$AccessError");
+ ACCESSERROR_ACCESS = ACCESSERROR.getMethod("access", Name.class, TypeSymbol.class);
+ ACCESSERROR_ACCESS.setAccessible(true);
+ } catch (ClassNotFoundException e) {
+ ErrorReporter.errorAbort(
+ "Compiler 'Resolve$AccessError' class could not be retrieved.", e);
+ // Unreachable code - needed so the compiler does not warn about a possibly uninitialized final field.
+ throw new AssertionError();
+ } catch (NoSuchMethodException e) {
+ ErrorReporter.errorAbort(
+ "Compiler 'Resolve$AccessError' class doesn't contain required 'access' method",
+ e);
+ // Unreachable code - needed so the compiler does not warn about a possibly uninitialized final field.
+ throw new AssertionError();
+ }
+ }
+
+ public Resolver(ProcessingEnvironment env) {
+ Context context = ((JavacProcessingEnvironment) env).getContext();
+ this.resolve = Resolve.instance(context);
+ this.names = Names.instance(context);
+ this.trees = Trees.instance(env);
+ this.log = Log.instance(context);
+ }
+
+ /**
+ * Determine the environment for the given path.
+ *
+ * @param path the tree path to the local scope
+ * @return the corresponding attribution environment
+ */
+ public Env<AttrContext> getEnvForPath(TreePath path) {
+ TreePath iter = path;
+ JavacScope scope = null;
+ while (scope == null && iter != null) {
+ try {
+ scope = (JavacScope) trees.getScope(iter);
+ } catch (Throwable t) {
+ // Work around Issue #1059 by skipping through the TreePath until something
+ // doesn't crash. This probably returns the class scope, so users might not
+ // get the variables they expect. But that is better than crashing.
+ iter = iter.getParentPath();
+ }
+ }
+ if (scope != null) {
+ return scope.getEnv();
+ } else {
+ ErrorReporter.errorAbort(
+ "Could not determine any possible scope for path: " + path.getLeaf());
+ return null;
+ }
+ }
+
+ /**
+ * Finds the package with name {@code name}.
+ *
+ * @param name the name of the package
+ * @param path the tree path to the local scope
+ * @return the {@code PackageSymbol} for the package if it is found, {@code null} otherwise
+ */
+ public PackageSymbol findPackage(String name, TreePath path) {
+ Log.DiagnosticHandler discardDiagnosticHandler = new Log.DiscardDiagnosticHandler(log);
+ try {
+ Env<AttrContext> env = getEnvForPath(path);
+ Element res =
+ wrapInvocationOnResolveInstance(FIND_IDENT, env, names.fromString(name), PCK);
+ // findIdent will return a PackageSymbol even for a symbol that is not a package,
+ // such as a.b.c.MyClass.myStaticField. "exists()" must be called on it to ensure
+ // that it exists.
+ if (res.getKind() == ElementKind.PACKAGE) {
+ PackageSymbol ps = (PackageSymbol) res;
+ return ps.exists() ? ps : null;
+ } else {
+ return null;
+ }
+ } finally {
+ log.popDiagnosticHandler(discardDiagnosticHandler);
+ }
}
/**
* Finds the field with name {@code name} in a given type.
*
- * <p>
- * The method adheres to all the rules of Java's scoping (while also
- * considering the imports) for name resolution.
+ * <p>The method adheres to all the rules of Java's scoping (while also considering the imports)
+ * for name resolution.
*
- * @param name
- * The name of the field.
- * @param type
- * The type of the receiver (i.e., the type in which to look for
- * the field).
- * @param path
- * The tree path to the local scope.
- * @return The element for the field.
+ * @param name the name of the field
+ * @param type the type of the receiver (i.e., the type in which to look for the field).
+ * @param path the tree path to the local scope
+ * @return the element for the field
*/
public VariableElement findField(String name, TypeMirror type, TreePath path) {
- Log.DiagnosticHandler discardDiagnosticHandler =
- new Log.DiscardDiagnosticHandler(log);
+ Log.DiagnosticHandler discardDiagnosticHandler = new Log.DiscardDiagnosticHandler(log);
try {
- JavacScope scope = (JavacScope) trees.getScope(path);
- Env<AttrContext> env = scope.getEnv();
- Element res = wrapInvocation(FIND_IDENT_IN_TYPE, env, type,
- names.fromString(name), VAR);
+ Env<AttrContext> env = getEnvForPath(path);
+ Element res =
+ wrapInvocationOnResolveInstance(
+ FIND_IDENT_IN_TYPE, env, type, names.fromString(name), VAR);
if (res.getKind() == ElementKind.FIELD) {
return (VariableElement) res;
+ } else if (res.getKind() == ElementKind.OTHER && ACCESSERROR.isInstance(res)) {
+ // Return the inaccessible field that was found
+ return (VariableElement) wrapInvocation(res, ACCESSERROR_ACCESS, null, null);
} else {
// Most likely didn't find the field and the Element is a SymbolNotFoundError
return null;
@@ -114,53 +210,94 @@ public class Resolver {
}
/**
+ * Finds the local variable with name {@code name} in the given scope.
+ *
+ * @param name the name of the local variable
+ * @param path the tree path to the local scope
+ * @return the element for the local variable
+ */
+ public VariableElement findLocalVariableOrParameterOrField(String name, TreePath path) {
+ Log.DiagnosticHandler discardDiagnosticHandler = new Log.DiscardDiagnosticHandler(log);
+ try {
+ Env<AttrContext> env = getEnvForPath(path);
+ Element res = wrapInvocationOnResolveInstance(FIND_VAR, env, names.fromString(name));
+ if (res.getKind() == ElementKind.LOCAL_VARIABLE
+ || res.getKind() == ElementKind.PARAMETER
+ || res.getKind() == ElementKind.FIELD) {
+ return (VariableElement) res;
+ } else {
+ // Most likely didn't find the variable and the Element is a SymbolNotFoundError
+ return null;
+ }
+ } finally {
+ log.popDiagnosticHandler(discardDiagnosticHandler);
+ }
+ }
+
+ /**
* Finds the class literal with name {@code name}.
*
- * <p>
- * The method adheres to all the rules of Java's scoping (while also
- * considering the imports) for name resolution.
+ * <p>The method adheres to all the rules of Java's scoping (while also considering the imports)
+ * for name resolution.
*
- * @param name
- * The name of the class.
- * @param path
- * The tree path to the local scope.
- * @return The element for the class.
+ * @param name the name of the class
+ * @param path the tree path to the local scope
+ * @return the element for the class
*/
public Element findClass(String name, TreePath path) {
- Log.DiagnosticHandler discardDiagnosticHandler =
- new Log.DiscardDiagnosticHandler(log);
+ Log.DiagnosticHandler discardDiagnosticHandler = new Log.DiscardDiagnosticHandler(log);
+ try {
+ Env<AttrContext> env = getEnvForPath(path);
+ return wrapInvocationOnResolveInstance(FIND_TYPE, env, names.fromString(name));
+ } finally {
+ log.popDiagnosticHandler(discardDiagnosticHandler);
+ }
+ }
+
+ /**
+ * Finds the class with name {@code name} in a given package.
+ *
+ * @param name the name of the class
+ * @param pck the PackageSymbol for the package
+ * @param path the tree path to the local scope
+ * @return the {@code ClassSymbol} for the class if it is found, {@code null} otherwise
+ */
+ public ClassSymbol findClassInPackage(String name, PackageSymbol pck, TreePath path) {
+ Log.DiagnosticHandler discardDiagnosticHandler = new Log.DiscardDiagnosticHandler(log);
try {
- JavacScope scope = (JavacScope) trees.getScope(path);
- Env<AttrContext> env = scope.getEnv();
- return wrapInvocation(FIND_TYPE, env, names.fromString(name));
+ Env<AttrContext> env = getEnvForPath(path);
+ Element res =
+ wrapInvocationOnResolveInstance(
+ FIND_IDENT_IN_PACKAGE, env, pck, names.fromString(name), TYP);
+ if (res.getKind() == ElementKind.CLASS) {
+ return (ClassSymbol) res;
+ } else {
+ return null;
+ }
} finally {
log.popDiagnosticHandler(discardDiagnosticHandler);
}
}
/**
- * Finds the method element for a given name and list of expected parameter
- * types.
+ * Finds the method element for a given name and list of expected parameter types.
*
- * <p>
- * The method adheres to all the rules of Java's scoping (while also
- * considering the imports) for name resolution.
+ * <p>The method adheres to all the rules of Java's scoping (while also considering the imports)
+ * for name resolution.
*
- * @param methodName
- * Name of the method to find.
- * @param receiverType
- * Type of the receiver of the method
- * @param path
- * Tree path.
- * @return The method element (if found).
+ * @param methodName name of the method to find
+ * @param receiverType type of the receiver of the method
+ * @param path tree path
+ * @return the method element (if found)
*/
- public Element findMethod(String methodName, TypeMirror receiverType,
- TreePath path, java.util.List<TypeMirror> argumentTypes) {
- Log.DiagnosticHandler discardDiagnosticHandler =
- new Log.DiscardDiagnosticHandler(log);
+ public Element findMethod(
+ String methodName,
+ TypeMirror receiverType,
+ TreePath path,
+ java.util.List<TypeMirror> argumentTypes) {
+ Log.DiagnosticHandler discardDiagnosticHandler = new Log.DiscardDiagnosticHandler(log);
try {
- JavacScope scope = (JavacScope) trees.getScope(path);
- Env<AttrContext> env = scope.getEnv();
+ Env<AttrContext> env = getEnvForPath(path);
Type site = (Type) receiverType;
Name name = names.fromString(methodName);
@@ -179,8 +316,17 @@ public class Resolver {
Object methodContext = buildMethodContext();
Object oldContext = getField(resolve, "currentResolutionContext");
setField(resolve, "currentResolutionContext", methodContext);
- Element result = wrapInvocation(FIND_METHOD, env, site, name, argtypes,
- typeargtypes, allowBoxing, useVarargs, operator);
+ Element result =
+ wrapInvocationOnResolveInstance(
+ FIND_METHOD,
+ env,
+ site,
+ name,
+ argtypes,
+ typeargtypes,
+ allowBoxing,
+ useVarargs,
+ operator);
setField(resolve, "currentResolutionContext", oldContext);
return result;
} catch (Throwable t) {
@@ -193,14 +339,13 @@ public class Resolver {
}
}
- /**
- * Build an instance of {@code Resolve$MethodResolutionContext}.
- */
- protected Object buildMethodContext() throws ClassNotFoundException,
- InstantiationException, IllegalAccessException,
- InvocationTargetException, NoSuchFieldException {
+ /** Build an instance of {@code Resolve$MethodResolutionContext}. */
+ protected Object buildMethodContext()
+ throws ClassNotFoundException, InstantiationException, IllegalAccessException,
+ InvocationTargetException, NoSuchFieldException {
// Class is not accessible, instantiate reflectively.
- Class<?> methCtxClss = Class.forName("com.sun.tools.javac.comp.Resolve$MethodResolutionContext");
+ Class<?> methCtxClss =
+ Class.forName("com.sun.tools.javac.comp.Resolve$MethodResolutionContext");
Constructor<?> constructor = methCtxClss.getDeclaredConstructors()[0];
constructor.setAccessible(true);
Object methodContext = constructor.newInstance(resolve);
@@ -213,25 +358,28 @@ public class Resolver {
}
/** Reflectively set a field. */
- private void setField(Object receiver, String fieldName,
- Object value) throws NoSuchFieldException,
- IllegalAccessException {
+ private void setField(Object receiver, String fieldName, Object value)
+ throws NoSuchFieldException, IllegalAccessException {
Field f = receiver.getClass().getDeclaredField(fieldName);
f.setAccessible(true);
f.set(receiver, value);
}
/** Reflectively get the value of a field. */
- private Object getField(Object receiver, String fieldName) throws NoSuchFieldException,
- IllegalAccessException {
+ private Object getField(Object receiver, String fieldName)
+ throws NoSuchFieldException, IllegalAccessException {
Field f = receiver.getClass().getDeclaredField(fieldName);
f.setAccessible(true);
return f.get(receiver);
}
- private Symbol wrapInvocation(Method method, Object... args) {
+ private Symbol wrapInvocationOnResolveInstance(Method method, Object... args) {
+ return wrapInvocation(resolve, method, args);
+ }
+
+ private Symbol wrapInvocation(Object receiver, Method method, Object... args) {
try {
- return (Symbol) method.invoke(resolve, args);
+ return (Symbol) method.invoke(receiver, args);
} catch (IllegalAccessException e) {
Error err = new AssertionError("Unexpected Reflection error");
err.initCause(e);
diff --git a/third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/TreeUtils.java b/third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/TreeUtils.java
index a3ae88fa31..4da97b400d 100644
--- a/third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/TreeUtils.java
+++ b/third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/TreeUtils.java
@@ -4,25 +4,13 @@ package org.checkerframework.javacutil;
import org.checkerframework.checker.nullness.qual.*;
*/
-import java.util.EnumSet;
-import java.util.Set;
-
-import javax.annotation.processing.ProcessingEnvironment;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.ElementKind;
-import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.element.Name;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.element.VariableElement;
-import javax.lang.model.util.ElementFilter;
-
import com.sun.source.tree.AnnotatedTypeTree;
import com.sun.source.tree.ArrayAccessTree;
-import com.sun.source.tree.AssignmentTree;
import com.sun.source.tree.BinaryTree;
import com.sun.source.tree.BlockTree;
import com.sun.source.tree.ClassTree;
import com.sun.source.tree.CompoundAssignmentTree;
+import com.sun.source.tree.ConditionalExpressionTree;
import com.sun.source.tree.ExpressionStatementTree;
import com.sun.source.tree.ExpressionTree;
import com.sun.source.tree.IdentifierTree;
@@ -30,14 +18,13 @@ import com.sun.source.tree.LiteralTree;
import com.sun.source.tree.MemberSelectTree;
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.ParenthesizedTree;
import com.sun.source.tree.PrimitiveTypeTree;
-import com.sun.source.tree.ReturnTree;
import com.sun.source.tree.StatementTree;
import com.sun.source.tree.Tree;
+import com.sun.source.tree.Tree.Kind;
import com.sun.source.tree.TypeCastTree;
import com.sun.source.tree.VariableTree;
import com.sun.source.util.TreePath;
@@ -45,21 +32,34 @@ import com.sun.source.util.Trees;
import com.sun.tools.javac.code.Flags;
import com.sun.tools.javac.code.Symbol.MethodSymbol;
import com.sun.tools.javac.tree.JCTree;
+import java.util.ArrayList;
+import java.util.EnumSet;
+import java.util.List;
+import java.util.Set;
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ElementKind;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.Modifier;
+import javax.lang.model.element.Name;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.VariableElement;
+import javax.lang.model.type.TypeKind;
+import javax.lang.model.util.ElementFilter;
-/**
- * A utility class made for helping to analyze a given {@code Tree}.
- */
+/** A utility class made for helping to analyze a given {@code Tree}. */
// TODO: This class needs significant restructuring
public final class TreeUtils {
// Class cannot be instantiated.
- private TreeUtils() { throw new AssertionError("Class TreeUtils cannot be instantiated."); }
+ private TreeUtils() {
+ throw new AssertionError("Class TreeUtils cannot be instantiated.");
+ }
/**
* Checks if the provided method is a constructor method or no.
*
- * @param tree
- * a tree defining the method
+ * @param tree a tree defining the method
* @return true iff tree describes a constructor
*/
public static boolean isConstructor(final MethodTree tree) {
@@ -69,39 +69,50 @@ public final class TreeUtils {
/**
* Checks if the method invocation is a call to super.
*
- * @param tree
- * a tree defining a method invocation
- *
+ * @param tree a tree defining a method invocation
* @return true iff tree describes a call to super
*/
public static boolean isSuperCall(MethodInvocationTree tree) {
+ return isNamedMethodCall("super", tree);
+ }
+
+ /**
+ * Checks if the method invocation is a call to this.
+ *
+ * @param tree a tree defining a method invocation
+ * @return true iff tree describes a call to this
+ */
+ public static boolean isThisCall(MethodInvocationTree tree) {
+ return isNamedMethodCall("this", tree);
+ }
+
+ protected static boolean isNamedMethodCall(String name, MethodInvocationTree tree) {
/*@Nullable*/ ExpressionTree mst = tree.getMethodSelect();
assert mst != null; /*nninvariant*/
- if (mst.getKind() == Tree.Kind.IDENTIFIER ) {
- return ((IdentifierTree)mst).getName().contentEquals("super");
+ if (mst.getKind() == Tree.Kind.IDENTIFIER) {
+ return ((IdentifierTree) mst).getName().contentEquals(name);
}
if (mst.getKind() == Tree.Kind.MEMBER_SELECT) {
- MemberSelectTree selectTree = (MemberSelectTree)mst;
+ MemberSelectTree selectTree = (MemberSelectTree) mst;
if (selectTree.getExpression().getKind() != Tree.Kind.IDENTIFIER) {
return false;
}
- return ((IdentifierTree) selectTree.getExpression()).getName()
- .contentEquals("super");
+ return ((IdentifierTree) selectTree.getExpression()).getName().contentEquals(name);
}
return false;
}
/**
- * Returns true if the tree is a tree that 'looks like' either an access
- * of a field or an invocation of a method that are owned by the same
- * accessing instance.
+ * Returns true if the tree is a tree that 'looks like' either an access of a field or an
+ * invocation of a method that are owned by the same accessing instance.
+ *
+ * <p>It would only return true if the access tree is of the form:
*
- * It would only return true if the access tree is of the form:
* <pre>
* field
* this.field
@@ -110,35 +121,37 @@ public final class TreeUtils {
* this.method()
* </pre>
*
- * It does not perform any semantical check to differentiate between
- * fields and local variables; local methods or imported static methods.
+ * It does not perform any semantical check to differentiate between fields and local variables;
+ * local methods or imported static methods.
*
- * @param tree expression tree representing an access to object member
+ * @param tree expression tree representing an access to object member
* @return {@code true} iff the member is a member of {@code this} instance
*/
public static boolean isSelfAccess(final ExpressionTree tree) {
ExpressionTree tr = TreeUtils.skipParens(tree);
// If method invocation check the method select
- if (tr.getKind() == Tree.Kind.ARRAY_ACCESS)
+ if (tr.getKind() == Tree.Kind.ARRAY_ACCESS) {
return false;
+ }
if (tree.getKind() == Tree.Kind.METHOD_INVOCATION) {
- tr = ((MethodInvocationTree)tree).getMethodSelect();
+ tr = ((MethodInvocationTree) tree).getMethodSelect();
}
tr = TreeUtils.skipParens(tr);
- if (tr.getKind() == Tree.Kind.TYPE_CAST)
- tr = ((TypeCastTree)tr).getExpression();
+ if (tr.getKind() == Tree.Kind.TYPE_CAST) {
+ tr = ((TypeCastTree) tr).getExpression();
+ }
tr = TreeUtils.skipParens(tr);
- if (tr.getKind() == Tree.Kind.IDENTIFIER)
+ if (tr.getKind() == Tree.Kind.IDENTIFIER) {
return true;
+ }
if (tr.getKind() == Tree.Kind.MEMBER_SELECT) {
- tr = ((MemberSelectTree)tr).getExpression();
+ tr = ((MemberSelectTree) tr).getExpression();
if (tr.getKind() == Tree.Kind.IDENTIFIER) {
- Name ident = ((IdentifierTree)tr).getName();
- return ident.contentEquals("this") ||
- ident.contentEquals("super");
+ Name ident = ((IdentifierTree) tr).getName();
+ return ident.contentEquals("this") || ident.contentEquals("super");
}
}
@@ -148,8 +161,8 @@ public final class TreeUtils {
/**
* Gets the first enclosing tree in path, of the specified kind.
*
- * @param path the path defining the tree node
- * @param kind the kind of the desired tree
+ * @param path the path defining the tree node
+ * @param kind the kind of the desired tree
* @return the enclosing tree of the given type as given by the path
*/
public static Tree enclosingOfKind(final TreePath path, final Tree.Kind kind) {
@@ -159,8 +172,8 @@ public final class TreeUtils {
/**
* Gets the first enclosing tree in path, with any one of the specified kinds.
*
- * @param path the path defining the tree node
- * @param kinds the set of kinds of the desired tree
+ * @param path the path defining the tree node
+ * @param kinds the set of kinds of the desired tree
* @return the enclosing tree of the given type as given by the path
*/
public static Tree enclosingOfKind(final TreePath path, final Set<Tree.Kind> kinds) {
@@ -169,8 +182,9 @@ public final class TreeUtils {
while (p != null) {
Tree leaf = p.getLeaf();
assert leaf != null; /*nninvariant*/
- if (kinds.contains(leaf.getKind()))
+ if (kinds.contains(leaf.getKind())) {
return leaf;
+ }
p = p.getParentPath();
}
@@ -178,10 +192,10 @@ public final class TreeUtils {
}
/**
- * Gets path to the the first enclosing class tree, where class is
- * defined by the classTreeKinds method.
+ * Gets path to the first enclosing class tree, where class is defined by the classTreeKinds
+ * method.
*
- * @param path the path defining the tree node
+ * @param path the path defining the tree node
* @return the path to the enclosing class tree
*/
public static TreePath pathTillClass(final TreePath path) {
@@ -189,10 +203,10 @@ public final class TreeUtils {
}
/**
- * Gets path to the the first enclosing tree of the specified kind.
+ * Gets path to the first enclosing tree of the specified kind.
*
- * @param path the path defining the tree node
- * @param kind the kind of the desired tree
+ * @param path the path defining the tree node
+ * @param kind the kind of the desired tree
* @return the path to the enclosing tree of the given type
*/
public static TreePath pathTillOfKind(final TreePath path, final Tree.Kind kind) {
@@ -200,10 +214,10 @@ public final class TreeUtils {
}
/**
- * Gets path to the the first enclosing tree with any one of the specified kinds.
+ * Gets path to the first enclosing tree with any one of the specified kinds.
*
- * @param path the path defining the tree node
- * @param kinds the set of kinds of the desired tree
+ * @param path the path defining the tree node
+ * @param kinds the set of kinds of the desired tree
* @return the path to the enclosing tree of the given type
*/
public static TreePath pathTillOfKind(final TreePath path, final Set<Tree.Kind> kinds) {
@@ -212,8 +226,9 @@ public final class TreeUtils {
while (p != null) {
Tree leaf = p.getLeaf();
assert leaf != null; /*nninvariant*/
- if (kinds.contains(leaf.getKind()))
+ if (kinds.contains(leaf.getKind())) {
return p;
+ }
p = p.getParentPath();
}
@@ -223,17 +238,19 @@ public final class TreeUtils {
/**
* Gets the first enclosing tree in path, of the specified class
*
- * @param path the path defining the tree node
+ * @param path the path defining the tree node
* @param treeClass the class of the desired tree
* @return the enclosing tree of the given type as given by the path
*/
- public static <T extends Tree> T enclosingOfClass(final TreePath path, final Class<T> treeClass) {
+ public static <T extends Tree> T enclosingOfClass(
+ final TreePath path, final Class<T> treeClass) {
TreePath p = path;
while (p != null) {
Tree leaf = p.getLeaf();
- if (treeClass.isInstance(leaf))
+ if (treeClass.isInstance(leaf)) {
return treeClass.cast(leaf);
+ }
p = p.getParentPath();
}
@@ -241,22 +258,20 @@ public final class TreeUtils {
}
/**
- * Gets the enclosing class of the tree node defined by the given
- * {@code {@link TreePath}}. It returns a {@link Tree}, from which
- * {@code checkers.types.AnnotatedTypeMirror} or {@link Element} can be
+ * Gets the enclosing class of the tree node defined by the given {@link TreePath}. It returns a
+ * {@link Tree}, from which {@code checkers.types.AnnotatedTypeMirror} or {@link Element} can be
* obtained.
*
* @param path the path defining the tree node
- * @return the enclosing class (or interface) as given by the path, or null
- * if one does not exist.
+ * @return the enclosing class (or interface) as given by the path, or null if one does not
+ * exist
*/
public static /*@Nullable*/ ClassTree enclosingClass(final /*@Nullable*/ TreePath path) {
return (ClassTree) enclosingOfKind(path, classTreeKinds());
}
/**
- * Gets the enclosing variable of a tree node defined by the given
- * {@link TreePath}.
+ * Gets the enclosing variable of a tree node defined by the given {@link TreePath}.
*
* @param path the path defining the tree node
* @return the enclosing variable as given by the path, or null if one does not exist
@@ -266,14 +281,12 @@ public final class TreeUtils {
}
/**
- * Gets the enclosing method of the tree node defined by the given
- * {@code {@link TreePath}}. It returns a {@link Tree}, from which an
- * {@code checkers.types.AnnotatedTypeMirror} or {@link Element} can be
- * obtained.
+ * Gets the enclosing method of the tree node defined by the given {@link TreePath}. It returns
+ * a {@link Tree}, from which an {@code checkers.types.AnnotatedTypeMirror} or {@link Element}
+ * can be obtained.
*
* @param path the path defining the tree node
- * @return the enclosing method as given by the path, or null if one does
- * not exist
+ * @return the enclosing method as given by the path, or null if one does not exist
*/
public static /*@Nullable*/ MethodTree enclosingMethod(final /*@Nullable*/ TreePath path) {
return (MethodTree) enclosingOfKind(path, Tree.Kind.METHOD);
@@ -281,7 +294,7 @@ public final class TreeUtils {
public static /*@Nullable*/ BlockTree enclosingTopLevelBlock(TreePath path) {
TreePath parpath = path.getParentPath();
- while (parpath!=null && parpath.getLeaf().getKind() != Tree.Kind.CLASS) {
+ while (parpath != null && !classTreeKinds.contains(parpath.getLeaf().getKind())) {
path = parpath;
parpath = parpath.getParentPath();
}
@@ -291,61 +304,89 @@ public final class TreeUtils {
return null;
}
-
/**
- * If the given tree is a parenthesized tree, it returns the enclosed
- * non-parenthesized tree. Otherwise, it returns the same tree.
+ * If the given tree is a parenthesized tree, it returns the enclosed non-parenthesized tree.
+ * Otherwise, it returns the same tree.
*
- * @param tree an expression tree
- * @return the outermost non-parenthesized tree enclosed by the given tree
+ * @param tree an expression tree
+ * @return the outermost non-parenthesized tree enclosed by the given tree
*/
public static ExpressionTree skipParens(final ExpressionTree tree) {
ExpressionTree t = tree;
- while (t.getKind() == Tree.Kind.PARENTHESIZED)
- t = ((ParenthesizedTree)t).getExpression();
+ while (t.getKind() == Tree.Kind.PARENTHESIZED) {
+ t = ((ParenthesizedTree) t).getExpression();
+ }
return t;
}
/**
- * Returns the tree with the assignment context for the treePath
- * leaf node.
+ * Returns the tree with the assignment context for the treePath leaf node. (Does not handle
+ * pseudo-assignment of an argument to a parameter or a receiver expression to a receiver.)
+ *
+ * <p>The assignment context for the {@code treePath} is the leaf of its parent, if the parent
+ * is one of the following trees:
*
- * The assignment context for the treepath is the most enclosing
- * tree of type:
* <ul>
- * <li>AssignmentTree </li>
- * <li>CompoundAssignmentTree </li>
- * <li>MethodInvocationTree</li>
- * <li>NewArrayTree</li>
- * <li>NewClassTree</li>
- * <li>ReturnTree</li>
- * <li>VariableTree</li>
+ * <li>AssignmentTree
+ * <li>CompoundAssignmentTree
+ * <li>MethodInvocationTree
+ * <li>NewArrayTree
+ * <li>NewClassTree
+ * <li>ReturnTree
+ * <li>VariableTree
* </ul>
*
- * @param treePath
- * @return the assignment context as described.
+ * If the parent is a ConditionalExpressionTree we need to distinguish two cases: If the leaf is
+ * either the then or else branch of the ConditionalExpressionTree, then recurse on the parent.
+ * If the leaf is the condition of the ConditionalExpressionTree, then return null to not
+ * consider this assignment context.
+ *
+ * <p>If the leaf is a ParenthesizedTree, then recurse on the parent.
+ *
+ * <p>Otherwise, null is returned.
+ *
+ * @return the assignment context as described
*/
public static Tree getAssignmentContext(final TreePath treePath) {
- TreePath path = treePath.getParentPath();
+ TreePath parentPath = treePath.getParentPath();
- if (path == null)
+ if (parentPath == null) {
return null;
- Tree node = path.getLeaf();
- if ((node instanceof AssignmentTree) ||
- (node instanceof CompoundAssignmentTree) ||
- (node instanceof MethodInvocationTree) ||
- (node instanceof NewArrayTree) ||
- (node instanceof NewClassTree) ||
- (node instanceof ReturnTree) ||
- (node instanceof VariableTree))
- return node;
- return null;
+ }
+
+ Tree parent = parentPath.getLeaf();
+ switch (parent.getKind()) {
+ case PARENTHESIZED:
+ return getAssignmentContext(parentPath);
+ case CONDITIONAL_EXPRESSION:
+ ConditionalExpressionTree cet = (ConditionalExpressionTree) parent;
+ if (cet.getCondition() == treePath.getLeaf()) {
+ // The assignment context for the condition is simply boolean.
+ // No point in going on.
+ return null;
+ }
+ // Otherwise use the context of the ConditionalExpressionTree.
+ return getAssignmentContext(parentPath);
+ case ASSIGNMENT:
+ case METHOD_INVOCATION:
+ case NEW_ARRAY:
+ case NEW_CLASS:
+ case RETURN:
+ case VARIABLE:
+ return parent;
+ default:
+ // 11 Tree.Kinds are CompoundAssignmentTrees,
+ // so use instanceof rather than listing all 11.
+ if (parent instanceof CompoundAssignmentTree) {
+ return parent;
+ }
+ return null;
+ }
}
/**
* Gets the element for a class corresponding to a declaration.
*
- * @param node
* @return the element for the given class
*/
public static final TypeElement elementFromDeclaration(ClassTree node) {
@@ -356,7 +397,6 @@ public final class TreeUtils {
/**
* Gets the element for a method corresponding to a declaration.
*
- * @param node
* @return the element for the given method
*/
public static final ExecutableElement elementFromDeclaration(MethodTree node) {
@@ -367,7 +407,6 @@ public final class TreeUtils {
/**
* Gets the element for a variable corresponding to its declaration.
*
- * @param node
* @return the element for the given variable
*/
public static final VariableElement elementFromDeclaration(VariableTree node) {
@@ -376,11 +415,10 @@ public final class TreeUtils {
}
/**
- * Gets the element for the declaration corresponding to this use of an element.
- * To get the element for a declaration, use {@link
- * Trees#getElement(TreePath)} instead.
+ * Gets the element for the declaration corresponding to this use of an element. To get the
+ * element for a declaration, use {@link Trees#getElement(TreePath)} instead.
*
- * TODO: remove this method, as it really doesn't do anything.
+ * <p>TODO: remove this method, as it really doesn't do anything.
*
* @param node the tree corresponding to a use of an element
* @return the element for the corresponding declaration
@@ -390,8 +428,14 @@ public final class TreeUtils {
}
// Specialization for return type.
+ // Might return null if element wasn't found.
public static final ExecutableElement elementFromUse(MethodInvocationTree node) {
- return (ExecutableElement) elementFromUse((ExpressionTree) node);
+ Element el = elementFromUse((ExpressionTree) node);
+ if (el instanceof ExecutableElement) {
+ return (ExecutableElement) el;
+ } else {
+ return null;
+ }
}
// Specialization for return type.
@@ -399,12 +443,11 @@ public final class TreeUtils {
return (ExecutableElement) elementFromUse((ExpressionTree) node);
}
-
/**
* Determine whether the given ExpressionTree has an underlying element.
*
* @param node the ExpressionTree to test
- * @return whether the tree refers to an identifier, member select, or method invocation.
+ * @return whether the tree refers to an identifier, member select, or method invocation
*/
public static final boolean isUseOfElement(ExpressionTree node) {
node = TreeUtils.skipParens(node);
@@ -419,35 +462,35 @@ public final class TreeUtils {
}
}
- /**
- * @return the name of the invoked method
- */
+ /** @return the name of the invoked method */
public static final Name methodName(MethodInvocationTree node) {
ExpressionTree expr = node.getMethodSelect();
- if (expr.getKind() == Tree.Kind.IDENTIFIER)
- return ((IdentifierTree)expr).getName();
- else if (expr.getKind() == Tree.Kind.MEMBER_SELECT)
- return ((MemberSelectTree)expr).getIdentifier();
+ if (expr.getKind() == Tree.Kind.IDENTIFIER) {
+ return ((IdentifierTree) expr).getName();
+ } else if (expr.getKind() == Tree.Kind.MEMBER_SELECT) {
+ return ((MemberSelectTree) expr).getIdentifier();
+ }
ErrorReporter.errorAbort("TreeUtils.methodName: cannot be here: " + node);
return null; // dead code
}
/**
- * @return true if the first statement in the body is a self constructor
- * invocation within a constructor
+ * @return true if the first statement in the body is a self constructor invocation within a
+ * constructor
*/
public static final boolean containsThisConstructorInvocation(MethodTree node) {
- if (!TreeUtils.isConstructor(node)
- || node.getBody().getStatements().isEmpty())
+ if (!TreeUtils.isConstructor(node) || node.getBody().getStatements().isEmpty())
return false;
StatementTree st = node.getBody().getStatements().get(0);
if (!(st instanceof ExpressionStatementTree)
- || !(((ExpressionStatementTree)st).getExpression() instanceof MethodInvocationTree))
+ || !(((ExpressionStatementTree) st).getExpression()
+ instanceof MethodInvocationTree)) {
return false;
+ }
- MethodInvocationTree invocation = (MethodInvocationTree)
- ((ExpressionStatementTree)st).getExpression();
+ MethodInvocationTree invocation =
+ (MethodInvocationTree) ((ExpressionStatementTree) st).getExpression();
return "this".contentEquals(TreeUtils.methodName(invocation));
}
@@ -455,11 +498,12 @@ public final class TreeUtils {
public static final Tree firstStatement(Tree tree) {
Tree first;
if (tree.getKind() == Tree.Kind.BLOCK) {
- BlockTree block = (BlockTree)tree;
- if (block.getStatements().isEmpty())
+ BlockTree block = (BlockTree) tree;
+ if (block.getStatements().isEmpty()) {
first = block;
- else
+ } else {
first = block.getStatements().iterator().next();
+ }
} else {
first = tree;
}
@@ -469,13 +513,13 @@ public final class TreeUtils {
/**
* Determine whether the given class contains an explicit constructor.
*
- * @param node A class tree.
- * @return True, iff there is an explicit constructor.
+ * @param node a class tree
+ * @return true, iff there is an explicit constructor
*/
public static boolean hasExplicitConstructor(ClassTree node) {
TypeElement elem = TreeUtils.elementFromDeclaration(node);
- for ( ExecutableElement ee : ElementFilter.constructorsIn(elem.getEnclosedElements())) {
+ for (ExecutableElement ee : ElementFilter.constructorsIn(elem.getEnclosedElements())) {
MethodSymbol ms = (MethodSymbol) ee;
long mod = ms.flags();
@@ -487,33 +531,31 @@ public final class TreeUtils {
}
/**
- * Returns true if the tree is of a diamond type.
- * In contrast to the implementation in TreeInfo, this version
- * works on Trees.
+ * Returns true if the tree is of a diamond type. In contrast to the implementation in TreeInfo,
+ * this version works on Trees.
*
* @see com.sun.tools.javac.tree.TreeInfo#isDiamond(JCTree)
*/
public static final boolean isDiamondTree(Tree tree) {
switch (tree.getKind()) {
- case ANNOTATED_TYPE: return isDiamondTree(((AnnotatedTypeTree)tree).getUnderlyingType());
- case PARAMETERIZED_TYPE: return ((ParameterizedTypeTree)tree).getTypeArguments().isEmpty();
- case NEW_CLASS: return isDiamondTree(((NewClassTree)tree).getIdentifier());
- default: return false;
+ case ANNOTATED_TYPE:
+ return isDiamondTree(((AnnotatedTypeTree) tree).getUnderlyingType());
+ case PARAMETERIZED_TYPE:
+ return ((ParameterizedTypeTree) tree).getTypeArguments().isEmpty();
+ case NEW_CLASS:
+ return isDiamondTree(((NewClassTree) tree).getIdentifier());
+ default:
+ return false;
}
}
- /**
- * Returns true if the tree represents a {@code String} concatenation
- * operation
- */
+ /** Returns true if the tree represents a {@code String} concatenation operation */
public static final boolean isStringConcatenation(Tree tree) {
return (tree.getKind() == Tree.Kind.PLUS
&& TypesUtils.isString(InternalUtils.typeOf(tree)));
}
- /**
- * Returns true if the compound assignment tree is a string concatenation
- */
+ /** Returns true if the compound assignment tree is a string concatenation */
public static final boolean isStringCompoundConcatenation(CompoundAssignmentTree tree) {
return (tree.getKind() == Tree.Kind.PLUS_ASSIGNMENT
&& TypesUtils.isString(InternalUtils.typeOf(tree)));
@@ -522,18 +564,19 @@ public final class TreeUtils {
/**
* Returns true if the node is a constant-time expression.
*
- * A tree is a constant-time expression if it is:
+ * <p>A tree is a constant-time expression if it is:
+ *
* <ol>
- * <li>a literal tree
- * <li>a reference to a final variable initialized with a compile time
- * constant
- * <li>a String concatenation of two compile time constants
+ * <li>a literal tree
+ * <li>a reference to a final variable initialized with a compile time constant
+ * <li>a String concatenation of two compile time constants
* </ol>
*/
public static boolean isCompileTimeString(ExpressionTree node) {
ExpressionTree tree = TreeUtils.skipParens(node);
- if (tree instanceof LiteralTree)
+ if (tree instanceof LiteralTree) {
return true;
+ }
if (TreeUtils.isUseOfElement(tree)) {
Element elt = TreeUtils.elementFromUse(tree);
@@ -541,15 +584,13 @@ public final class TreeUtils {
} else if (TreeUtils.isStringConcatenation(tree)) {
BinaryTree binOp = (BinaryTree) tree;
return isCompileTimeString(binOp.getLeftOperand())
- && isCompileTimeString(binOp.getRightOperand());
+ && isCompileTimeString(binOp.getRightOperand());
} else {
return false;
}
}
- /**
- * Returns the receiver tree of a field access or a method invocation
- */
+ /** Returns the receiver tree of a field access or a method invocation */
public static ExpressionTree getReceiverTree(ExpressionTree expression) {
ExpressionTree receiver = TreeUtils.skipParens(expression);
@@ -565,13 +606,13 @@ public final class TreeUtils {
// Trying to handle receiver calls to trees of the form
// ((m).getArray())
// returns the type of 'm' in this case
- receiver = ((MethodInvocationTree)receiver).getMethodSelect();
+ receiver = ((MethodInvocationTree) receiver).getMethodSelect();
if (receiver.getKind() == Tree.Kind.IDENTIFIER) {
// It's a method call "m(foo)" without an explicit receiver
return null;
} else if (receiver.getKind() == Tree.Kind.MEMBER_SELECT) {
- receiver = ((MemberSelectTree)receiver).getExpression();
+ receiver = ((MemberSelectTree) receiver).getExpression();
} else {
// Otherwise, e.g. a NEW_CLASS: nothing to do.
}
@@ -579,9 +620,9 @@ public final class TreeUtils {
// It's a field access on implicit this or a local variable/parameter.
return null;
} else if (receiver.getKind() == Tree.Kind.ARRAY_ACCESS) {
- return TreeUtils.skipParens(((ArrayAccessTree)receiver).getExpression());
+ return TreeUtils.skipParens(((ArrayAccessTree) receiver).getExpression());
} else if (receiver.getKind() == Tree.Kind.MEMBER_SELECT) {
- receiver = ((MemberSelectTree)receiver).getExpression();
+ receiver = ((MemberSelectTree) receiver).getExpression();
// Avoid int.class
if (receiver instanceof PrimitiveTypeTree) {
return null;
@@ -596,20 +637,19 @@ public final class TreeUtils {
// Adding Tree.Kind.NEW_CLASS here doesn't work, because then a
// tree gets cast to ClassTree when it is actually a NewClassTree,
// for example in enclosingClass above.
- private final static Set<Tree.Kind> classTreeKinds = EnumSet.of(
- Tree.Kind.CLASS,
- Tree.Kind.ENUM,
- Tree.Kind.INTERFACE,
- Tree.Kind.ANNOTATION_TYPE
- );
+ private static final Set<Tree.Kind> classTreeKinds =
+ EnumSet.of(
+ Tree.Kind.CLASS,
+ Tree.Kind.ENUM,
+ Tree.Kind.INTERFACE,
+ Tree.Kind.ANNOTATION_TYPE);
public static Set<Tree.Kind> classTreeKinds() {
return classTreeKinds;
}
/**
- * Is the given tree kind a class, i.e. a class, enum,
- * interface, or annotation type.
+ * Is the given tree kind a class, i.e. a class, enum, interface, or annotation type.
*
* @param tree the tree to test
* @return true, iff the given kind is a class kind
@@ -618,16 +658,16 @@ public final class TreeUtils {
return classTreeKinds().contains(tree.getKind());
}
- private final static Set<Tree.Kind> typeTreeKinds = EnumSet.of(
- Tree.Kind.PRIMITIVE_TYPE,
- Tree.Kind.PARAMETERIZED_TYPE,
- Tree.Kind.TYPE_PARAMETER,
- Tree.Kind.ARRAY_TYPE,
- Tree.Kind.UNBOUNDED_WILDCARD,
- Tree.Kind.EXTENDS_WILDCARD,
- Tree.Kind.SUPER_WILDCARD,
- Tree.Kind.ANNOTATED_TYPE
- );
+ private static final Set<Tree.Kind> typeTreeKinds =
+ EnumSet.of(
+ Tree.Kind.PRIMITIVE_TYPE,
+ Tree.Kind.PARAMETERIZED_TYPE,
+ Tree.Kind.TYPE_PARAMETER,
+ Tree.Kind.ARRAY_TYPE,
+ Tree.Kind.UNBOUNDED_WILDCARD,
+ Tree.Kind.EXTENDS_WILDCARD,
+ Tree.Kind.SUPER_WILDCARD,
+ Tree.Kind.ANNOTATED_TYPE);
public static Set<Tree.Kind> typeTreeKinds() {
return typeTreeKinds;
@@ -636,8 +676,8 @@ public final class TreeUtils {
/**
* Is the given tree a type instantiation?
*
- * TODO: this is an under-approximation: e.g. an identifier could
- * be either a type use or an expression. How can we distinguish.
+ * <p>TODO: this is an under-approximation: e.g. an identifier could be either a type use or an
+ * expression. How can we distinguish.
*
* @param tree the tree to test
* @return true, iff the given tree is a type
@@ -647,54 +687,60 @@ public final class TreeUtils {
}
/**
- * Returns true if the given element is an invocation of the method, or
- * of any method that overrides that one.
+ * Returns true if the given element is an invocation of the method, or of any method that
+ * overrides that one.
*/
- public static boolean isMethodInvocation(Tree tree, ExecutableElement method, ProcessingEnvironment env) {
- if (!(tree instanceof MethodInvocationTree))
+ public static boolean isMethodInvocation(
+ Tree tree, ExecutableElement method, ProcessingEnvironment env) {
+ if (!(tree instanceof MethodInvocationTree)) {
return false;
- MethodInvocationTree methInvok = (MethodInvocationTree)tree;
+ }
+ MethodInvocationTree methInvok = (MethodInvocationTree) tree;
ExecutableElement invoked = TreeUtils.elementFromUse(methInvok);
- return isMethod(invoked, method, env);
- }
-
- /** Returns true if the given element is, or overrides, method. */
- private static boolean isMethod(ExecutableElement questioned, ExecutableElement method, ProcessingEnvironment env) {
- return (questioned.equals(method)
- || env.getElementUtils().overrides(questioned, method,
- (TypeElement)questioned.getEnclosingElement()));
+ return ElementUtils.isMethod(invoked, method, env);
}
/**
- * Returns the ExecutableElement for a method declaration of
- * methodName, in class typeName, with params parameters.
+ * Returns the ExecutableElement for a method declaration of methodName, in class typeName, with
+ * params parameters.
*
- * TODO: to precisely resolve method overloading, we should use parameter types and not just
+ * <p>TODO: to precisely resolve method overloading, we should use parameter types and not just
* the number of parameters!
*/
- public static ExecutableElement getMethod(String typeName, String methodName, int params, ProcessingEnvironment env) {
- TypeElement mapElt = env.getElementUtils().getTypeElement(typeName);
- for (ExecutableElement exec : ElementFilter.methodsIn(mapElt.getEnclosedElements())) {
+ public static ExecutableElement getMethod(
+ String typeName, String methodName, int params, ProcessingEnvironment env) {
+ TypeElement typeElt = env.getElementUtils().getTypeElement(typeName);
+ for (ExecutableElement exec : ElementFilter.methodsIn(typeElt.getEnclosedElements())) {
if (exec.getSimpleName().contentEquals(methodName)
- && exec.getParameters().size() == params)
+ && exec.getParameters().size() == params) {
return exec;
+ }
}
ErrorReporter.errorAbort("TreeUtils.getMethod: shouldn't be here!");
return null; // dead code
}
+ public static List<ExecutableElement> getMethodList(
+ String typeName, String methodName, int params, ProcessingEnvironment env) {
+ List<ExecutableElement> methods = new ArrayList<>();
+ TypeElement typeElement = env.getElementUtils().getTypeElement(typeName);
+ for (ExecutableElement exec : ElementFilter.methodsIn(typeElement.getEnclosedElements())) {
+ if (exec.getSimpleName().contentEquals(methodName)
+ && exec.getParameters().size() == params) {
+ methods.add(exec);
+ }
+ }
+ return methods;
+ }
+
/**
- * Determine whether the given expression is either "this" or an outer
- * "C.this".
+ * Determine whether the given expression is either "this" or an outer "C.this".
*
- * TODO: Should this also handle "super"?
- *
- * @param tree
- * @return
+ * <p>TODO: Should this also handle "super"?
*/
public static final boolean isExplicitThisDereference(ExpressionTree tree) {
if (tree.getKind() == Tree.Kind.IDENTIFIER
- && ((IdentifierTree)tree).getName().contentEquals("this")) {
+ && ((IdentifierTree) tree).getName().contentEquals("this")) {
// Explicit this reference "this"
return true;
}
@@ -712,16 +758,30 @@ public final class TreeUtils {
}
/**
- * Determine whether <code>tree</code> is a field access expressions, such
- * as
+ * Determine whether {@code tree} is a class literal, such as
+ *
+ * <pre>
+ * <em>Object</em> . <em>class</em>
+ * </pre>
+ *
+ * @return true iff if tree is a class literal
+ */
+ public static boolean isClassLiteral(Tree tree) {
+ if (tree.getKind() != Tree.Kind.MEMBER_SELECT) {
+ return false;
+ }
+ return "class".equals(((MemberSelectTree) tree).getIdentifier().toString());
+ }
+
+ /**
+ * Determine whether {@code tree} is a field access expressions, such as
*
* <pre>
* <em>f</em>
* <em>obj</em> . <em>f</em>
* </pre>
*
- * @return true iff if tree is a field access expression (implicit or
- * explicit).
+ * @return true iff if tree is a field access expression (implicit or explicit)
*/
public static boolean isFieldAccess(Tree tree) {
if (tree.getKind().equals(Tree.Kind.MEMBER_SELECT)) {
@@ -734,17 +794,17 @@ public final class TreeUtils {
IdentifierTree ident = (IdentifierTree) tree;
Element el = TreeUtils.elementFromUse(ident);
return el.getKind().isField()
- && !ident.getName().contentEquals("this") && !ident.getName().contentEquals("super");
+ && !ident.getName().contentEquals("this")
+ && !ident.getName().contentEquals("super");
}
return false;
}
/**
- * Compute the name of the field that the field access <code>tree</code>
- * accesses. Requires <code>tree</code> to be a field access, as determined
- * by <code>isFieldAccess</code>.
+ * Compute the name of the field that the field access {@code tree} accesses. Requires {@code
+ * tree} to be a field access, as determined by {@code isFieldAccess}.
*
- * @return The name of the field accessed by <code>tree</code>.
+ * @return the name of the field accessed by {@code tree}.
*/
public static String getFieldName(Tree tree) {
assert isFieldAccess(tree);
@@ -758,45 +818,39 @@ public final class TreeUtils {
}
/**
- * Determine whether <code>tree</code> refers to a method element, such
- * as
+ * Determine whether {@code tree} refers to a method element, such as
*
* <pre>
* <em>m</em>(...)
* <em>obj</em> . <em>m</em>(...)
* </pre>
*
- * @return true iff if tree is a method access expression (implicit or
- * explicit).
+ * @return true iff if tree is a method access expression (implicit or explicit)
*/
public static boolean isMethodAccess(Tree tree) {
if (tree.getKind().equals(Tree.Kind.MEMBER_SELECT)) {
// explicit method access
MemberSelectTree memberSelect = (MemberSelectTree) tree;
Element el = TreeUtils.elementFromUse(memberSelect);
- return el.getKind() == ElementKind.METHOD
- || el.getKind() == ElementKind.CONSTRUCTOR;
+ return el.getKind() == ElementKind.METHOD || el.getKind() == ElementKind.CONSTRUCTOR;
} else if (tree.getKind().equals(Tree.Kind.IDENTIFIER)) {
// implicit method access
IdentifierTree ident = (IdentifierTree) tree;
// The field "super" and "this" are also legal methods
- if (ident.getName().contentEquals("super")
- || ident.getName().contentEquals("this")) {
+ if (ident.getName().contentEquals("super") || ident.getName().contentEquals("this")) {
return true;
}
Element el = TreeUtils.elementFromUse(ident);
- return el.getKind() == ElementKind.METHOD
- || el.getKind() == ElementKind.CONSTRUCTOR;
+ return el.getKind() == ElementKind.METHOD || el.getKind() == ElementKind.CONSTRUCTOR;
}
return false;
}
/**
- * Compute the name of the method that the method access <code>tree</code>
- * accesses. Requires <code>tree</code> to be a method access, as determined
- * by <code>isMethodAccess</code>.
+ * Compute the name of the method that the method access {@code tree} accesses. Requires {@code
+ * tree} to be a method access, as determined by {@code isMethodAccess}.
*
- * @return The name of the method accessed by <code>tree</code>.
+ * @return the name of the method accessed by {@code tree}.
*/
public static String getMethodName(Tree tree) {
assert isMethodAccess(tree);
@@ -810,19 +864,17 @@ public final class TreeUtils {
}
/**
- * @return {@code true} if and only if {@code tree} can have a type
- * annotation.
- *
- * TODO: is this implementation precise enough? E.g. does
- * a .class literal work correctly?
+ * @return {@code true} if and only if {@code tree} can have a type annotation.
+ * <p>TODO: is this implementation precise enough? E.g. does a .class literal work
+ * correctly?
*/
public static boolean canHaveTypeAnnotation(Tree tree) {
return ((JCTree) tree).type != null;
}
/**
- * Returns true if and only if the given {@code tree} represents a field
- * access of the given {@link VariableElement}.
+ * Returns true if and only if the given {@code tree} represents a field access of the given
+ * {@link VariableElement}.
*/
public static boolean isSpecificFieldAccess(Tree tree, VariableElement var) {
if (tree instanceof MemberSelectTree) {
@@ -841,12 +893,13 @@ public final class TreeUtils {
/**
* Returns the VariableElement for a field declaration.
*
- * @param typeName the class where the field is declared.
- * @param fieldName the name of the field.
- * @param env the processing environment.
+ * @param typeName the class where the field is declared
+ * @param fieldName the name of the field
+ * @param env the processing environment
* @return the VariableElement for typeName.fieldName
*/
- public static VariableElement getField(String typeName, String fieldName, ProcessingEnvironment env) {
+ public static VariableElement getField(
+ String typeName, String fieldName, ProcessingEnvironment env) {
TypeElement mapElt = env.getElementUtils().getTypeElement(typeName);
for (VariableElement var : ElementFilter.fieldsIn(mapElt.getEnclosedElements())) {
if (var.getSimpleName().contentEquals(fieldName)) {
@@ -857,11 +910,12 @@ public final class TreeUtils {
return null; // dead code
}
- /** Determine whether the given tree represents an ExpressionTree.
+ /**
+ * Determine whether the given tree represents an ExpressionTree.
*
- * TODO: is there a nicer way than an instanceof?
+ * <p>TODO: is there a nicer way than an instanceof?
*
- * @param tree the Tree to test.
+ * @param tree the Tree to test
* @return whether the tree is an ExpressionTree
*/
public static boolean isExpressionTree(Tree tree) {
@@ -880,16 +934,17 @@ public final class TreeUtils {
return correctClass && correctMethod;
}
- /** Determine whether the given tree represents a declaration of a type
- * (including type parameters).
+ /**
+ * Determine whether the given tree represents a declaration of a type (including type
+ * parameters).
*
- * @param node the Tree to test
+ * @param node the Tree to test
* @return true if the tree is a type declaration
*/
public static boolean isTypeDeclaration(Tree node) {
switch (node.getKind()) {
- // These tree kinds are always declarations. Uses of the declared
- // types have tree kind IDENTIFIER.
+ // These tree kinds are always declarations. Uses of the declared
+ // types have tree kind IDENTIFIER.
case ANNOTATION_TYPE:
case CLASS:
case ENUM:
@@ -901,4 +956,65 @@ public final class TreeUtils {
return false;
}
}
+
+ /**
+ * @see Object#getClass()
+ * @return true iff invocationTree is an instance of getClass()
+ */
+ public static boolean isGetClassInvocation(MethodInvocationTree invocationTree) {
+ final Element declarationElement = elementFromUse(invocationTree);
+ String ownerName =
+ ElementUtils.getQualifiedClassName(declarationElement.getEnclosingElement())
+ .toString();
+ return ownerName.equals("java.lang.Object")
+ && declarationElement.getSimpleName().toString().equals("getClass");
+ }
+
+ /**
+ * Returns whether or not the leaf of the tree path is in a static scope.
+ *
+ * @param path TreePath whose leaf may or may not be in static scope
+ * @return returns whether or not the leaf of the tree path is in a static scope
+ */
+ public static boolean isTreeInStaticScope(TreePath path) {
+ MethodTree enclosingMethod = TreeUtils.enclosingMethod(path);
+
+ if (enclosingMethod != null) {
+ return enclosingMethod.getModifiers().getFlags().contains(Modifier.STATIC);
+ }
+ // no enclosing method, check for static or initializer block
+ BlockTree block = enclosingTopLevelBlock(path);
+ if (block != null) {
+ return block.isStatic();
+ }
+
+ // check if its in a variable initializer
+ Tree t = enclosingVariable(path);
+ if (t != null) {
+ return ((VariableTree) t).getModifiers().getFlags().contains((Modifier.STATIC));
+ }
+ ClassTree classTree = enclosingClass(path);
+ if (classTree != null) {
+ return classTree.getModifiers().getFlags().contains((Modifier.STATIC));
+ }
+ return false;
+ }
+
+ /**
+ * Returns whether or not tree is an access of array length.
+ *
+ * @param tree tree to check
+ * @return true if tree is an access of array length
+ */
+ public static boolean isArrayLengthAccess(Tree tree) {
+ if (tree.getKind() == Kind.MEMBER_SELECT
+ && isFieldAccess(tree)
+ && getFieldName(tree).equals("length")) {
+ ExpressionTree expressionTree = ((MemberSelectTree) tree).getExpression();
+ if (InternalUtils.typeOf(expressionTree).getKind() == TypeKind.ARRAY) {
+ return true;
+ }
+ }
+ return false;
+ }
}
diff --git a/third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/TypeAnnotationUtils.java b/third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/TypeAnnotationUtils.java
index c166e43f47..b925f91b04 100644
--- a/third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/TypeAnnotationUtils.java
+++ b/third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/TypeAnnotationUtils.java
@@ -1,11 +1,20 @@
package org.checkerframework.javacutil;
-import java.lang.reflect.InvocationTargetException;
+import com.sun.tools.javac.code.Attribute;
+import com.sun.tools.javac.code.Attribute.TypeCompound;
+import com.sun.tools.javac.code.Symbol;
+import com.sun.tools.javac.code.TargetType;
+import com.sun.tools.javac.code.Type;
+import com.sun.tools.javac.code.TypeAnnotationPosition;
+import com.sun.tools.javac.processing.JavacProcessingEnvironment;
+import com.sun.tools.javac.util.Context;
+import com.sun.tools.javac.util.List;
+import com.sun.tools.javac.util.Name;
+import com.sun.tools.javac.util.Pair;
+import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.Map;
-
import javax.annotation.processing.ProcessingEnvironment;
-import javax.lang.model.SourceVersion;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.AnnotationValue;
import javax.lang.model.element.AnnotationValueVisitor;
@@ -18,18 +27,6 @@ import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.Elements;
import javax.lang.model.util.Types;
-import com.sun.tools.javac.code.Attribute;
-import com.sun.tools.javac.code.Attribute.TypeCompound;
-import com.sun.tools.javac.code.Symbol;
-import com.sun.tools.javac.code.TargetType;
-import com.sun.tools.javac.code.Type;
-import com.sun.tools.javac.code.TypeAnnotationPosition;
-import com.sun.tools.javac.processing.JavacProcessingEnvironment;
-import com.sun.tools.javac.tree.JCTree.JCLambda;
-import com.sun.tools.javac.util.Context;
-import com.sun.tools.javac.util.List;
-import com.sun.tools.javac.util.Pair;
-
/**
* A collection of helper methods related to type annotation handling.
*
@@ -38,111 +35,117 @@ import com.sun.tools.javac.util.Pair;
public class TypeAnnotationUtils {
// Class cannot be instantiated.
- private TypeAnnotationUtils() { throw new AssertionError("Class TypeAnnotationUtils cannot be instantiated."); }
+ private TypeAnnotationUtils() {
+ throw new AssertionError("Class TypeAnnotationUtils cannot be instantiated.");
+ }
/**
* Check whether a TypeCompound is contained in a list of TypeCompounds.
*
- * @param list The input list of TypeCompounds.
- * @param tc The TypeCompound to find.
- * @return true, iff a TypeCompound equal to tc is contained in list.
+ * @param list the input list of TypeCompounds
+ * @param tc the TypeCompound to find
+ * @return true, iff a TypeCompound equal to tc is contained in list
*/
- public static boolean isTypeCompoundContained(Types types, List<TypeCompound> list, TypeCompound tc) {
+ public static boolean isTypeCompoundContained(
+ Types types, List<TypeCompound> list, TypeCompound tc) {
for (Attribute.TypeCompound rawat : list) {
- if (rawat.type.tsym.name.contentEquals(tc.type.tsym.name) &&
+ if (contentEquals(rawat.type.tsym.name, tc.type.tsym.name)
// TODO: in previous line, it would be nicer to use reference equality:
// rawat.type == tc.type &&
// or at least "isSameType":
// types.isSameType(rawat.type, tc.type) &&
// but each fails in some cases.
- rawat.values.equals(tc.values) &&
- isSameTAPosition(rawat.position, tc.position)) {
+ && rawat.values.equals(tc.values)
+ && isSameTAPositionExceptTreePos(rawat.position, tc.position)) {
return true;
}
}
return false;
}
+ private static boolean contentEquals(Name n1, Name n2) {
+ // Views of underlying bytes, not copies as with Name#contentEquals
+ ByteBuffer b1 = ByteBuffer.wrap(n1.getByteArray(), n1.getByteOffset(), n1.getByteLength());
+ ByteBuffer b2 = ByteBuffer.wrap(n2.getByteArray(), n2.getByteOffset(), n2.getByteLength());
+
+ return b1.equals(b2);
+ }
+
/**
* Compare two TypeAnnotationPositions for equality.
*
- * @param p1 The first position.
- * @param p2 The second position.
- * @return true, iff the two positions are equal.
+ * @param p1 the first position
+ * @param p2 the second position
+ * @return true, iff the two positions are equal
*/
- public static boolean isSameTAPosition(TypeAnnotationPosition p1,
- TypeAnnotationPosition p2) {
- if (p1.isValidOffset == p2.isValidOffset &&
- p1.bound_index == p2.bound_index &&
- p1.exception_index == p2.exception_index &&
- p1.location.equals(p2.location) &&
- Arrays.equals(p1.lvarIndex, p2.lvarIndex) &&
- Arrays.equals(p1.lvarLength, p2.lvarLength) &&
- Arrays.equals(p1.lvarOffset, p2.lvarOffset) &&
- p1.offset == p2.offset &&
- p1.onLambda == p2.onLambda &&
- p1.parameter_index == p2.parameter_index &&
- p1.pos == p2.pos &&
- p1.type == p2.type &&
- p1.type_index == p2.type_index) {
- return true;
- }
- return false;
+ public static boolean isSameTAPosition(TypeAnnotationPosition p1, TypeAnnotationPosition p2) {
+ return isSameTAPositionExceptTreePos(p1, p2) && p1.pos == p2.pos;
+ }
+
+ public static boolean isSameTAPositionExceptTreePos(
+ TypeAnnotationPosition p1, TypeAnnotationPosition p2) {
+ return p1.isValidOffset == p2.isValidOffset
+ && p1.bound_index == p2.bound_index
+ && p1.exception_index == p2.exception_index
+ && p1.location.equals(p2.location)
+ && Arrays.equals(p1.lvarIndex, p2.lvarIndex)
+ && Arrays.equals(p1.lvarLength, p2.lvarLength)
+ && Arrays.equals(p1.lvarOffset, p2.lvarOffset)
+ && p1.offset == p2.offset
+ && p1.onLambda == p2.onLambda
+ && p1.parameter_index == p2.parameter_index
+ && p1.type == p2.type
+ && p1.type_index == p2.type_index;
}
/**
- * Returns a newly created Attribute.Compound corresponding to an
- * argument AnnotationMirror.
+ * Returns a newly created Attribute.Compound corresponding to an argument AnnotationMirror.
*
- * @param am an AnnotationMirror, which may be part of an AST or an internally
- * created subclass.
- * @return a new Attribute.Compound corresponding to the AnnotationMirror
+ * @param am an AnnotationMirror, which may be part of an AST or an internally created subclass
+ * @return a new Attribute.Compound corresponding to the AnnotationMirror
*/
- public static Attribute.Compound createCompoundFromAnnotationMirror(ProcessingEnvironment env,
- AnnotationMirror am) {
+ public static Attribute.Compound createCompoundFromAnnotationMirror(
+ ProcessingEnvironment env, AnnotationMirror am) {
// Create a new Attribute to match the AnnotationMirror.
List<Pair<Symbol.MethodSymbol, Attribute>> values = List.nil();
for (Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> entry :
- am.getElementValues().entrySet()) {
- Attribute attribute = attributeFromAnnotationValue(env, entry.getKey(), entry.getValue());
- values = values.append(new Pair<>((Symbol.MethodSymbol)entry.getKey(),
- attribute));
+ am.getElementValues().entrySet()) {
+ Attribute attribute =
+ attributeFromAnnotationValue(env, entry.getKey(), entry.getValue());
+ values = values.append(new Pair<>((Symbol.MethodSymbol) entry.getKey(), attribute));
}
- return new Attribute.Compound((Type.ClassType)am.getAnnotationType(), values);
+ return new Attribute.Compound((Type.ClassType) am.getAnnotationType(), values);
}
/**
- * Returns a newly created Attribute.TypeCompound corresponding to an
- * argument AnnotationMirror.
+ * Returns a newly created Attribute.TypeCompound corresponding to an argument AnnotationMirror.
*
- * @param am an AnnotationMirror, which may be part of an AST or an internally
- * created subclass.
- * @param tapos the type annotation position to use.
- * @return a new Attribute.TypeCompound corresponding to the AnnotationMirror
+ * @param am an AnnotationMirror, which may be part of an AST or an internally created subclass
+ * @param tapos the type annotation position to use
+ * @return a new Attribute.TypeCompound corresponding to the AnnotationMirror
*/
- public static Attribute.TypeCompound createTypeCompoundFromAnnotationMirror(ProcessingEnvironment env,
- AnnotationMirror am, TypeAnnotationPosition tapos) {
+ public static Attribute.TypeCompound createTypeCompoundFromAnnotationMirror(
+ ProcessingEnvironment env, AnnotationMirror am, TypeAnnotationPosition tapos) {
// Create a new Attribute to match the AnnotationMirror.
List<Pair<Symbol.MethodSymbol, Attribute>> values = List.nil();
for (Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> entry :
- am.getElementValues().entrySet()) {
- Attribute attribute = attributeFromAnnotationValue(env, entry.getKey(), entry.getValue());
- values = values.append(new Pair<>((Symbol.MethodSymbol)entry.getKey(),
- attribute));
+ am.getElementValues().entrySet()) {
+ Attribute attribute =
+ attributeFromAnnotationValue(env, entry.getKey(), entry.getValue());
+ values = values.append(new Pair<>((Symbol.MethodSymbol) entry.getKey(), attribute));
}
- return new Attribute.TypeCompound((Type.ClassType)am.getAnnotationType(), values, tapos);
+ return new Attribute.TypeCompound((Type.ClassType) am.getAnnotationType(), values, tapos);
}
/**
- * Returns a newly created Attribute corresponding to an argument
- * AnnotationValue.
+ * Returns a newly created Attribute corresponding to an argument AnnotationValue.
*
- * @param meth the ExecutableElement that is assigned the value, needed for empty arrays.
- * @param av an AnnotationValue, which may be part of an AST or an internally
- * created subclass.
- * @return a new Attribute corresponding to the AnnotationValue
+ * @param meth the ExecutableElement that is assigned the value, needed for empty arrays
+ * @param av an AnnotationValue, which may be part of an AST or an internally created subclass
+ * @return a new Attribute corresponding to the AnnotationValue
*/
- public static Attribute attributeFromAnnotationValue(ProcessingEnvironment env, ExecutableElement meth, AnnotationValue av) {
+ public static Attribute attributeFromAnnotationValue(
+ ProcessingEnvironment env, ExecutableElement meth, AnnotationValue av) {
return av.accept(new AttributeCreator(env, meth), null);
}
@@ -156,7 +159,7 @@ public class TypeAnnotationUtils {
public AttributeCreator(ProcessingEnvironment env, ExecutableElement meth) {
this.processingEnv = env;
- Context context = ((JavacProcessingEnvironment)env).getContext();
+ Context context = ((JavacProcessingEnvironment) env).getContext();
this.elements = env.getElementUtils();
this.modelTypes = env.getTypeUtils();
this.javacTypes = com.sun.tools.javac.code.Types.instance(context);
@@ -183,55 +186,55 @@ public class TypeAnnotationUtils {
@Override
public Attribute visitByte(byte b, Void p) {
TypeMirror byteType = modelTypes.getPrimitiveType(TypeKind.BYTE);
- return new Attribute.Constant((Type)byteType, b);
+ return new Attribute.Constant((Type) byteType, b);
}
@Override
public Attribute visitChar(char c, Void p) {
TypeMirror charType = modelTypes.getPrimitiveType(TypeKind.CHAR);
- return new Attribute.Constant((Type)charType, c);
+ return new Attribute.Constant((Type) charType, c);
}
@Override
public Attribute visitDouble(double d, Void p) {
TypeMirror doubleType = modelTypes.getPrimitiveType(TypeKind.DOUBLE);
- return new Attribute.Constant((Type)doubleType, d);
+ return new Attribute.Constant((Type) doubleType, d);
}
@Override
public Attribute visitFloat(float f, Void p) {
TypeMirror floatType = modelTypes.getPrimitiveType(TypeKind.FLOAT);
- return new Attribute.Constant((Type)floatType, f);
+ return new Attribute.Constant((Type) floatType, f);
}
@Override
public Attribute visitInt(int i, Void p) {
TypeMirror intType = modelTypes.getPrimitiveType(TypeKind.INT);
- return new Attribute.Constant((Type)intType, i);
+ return new Attribute.Constant((Type) intType, i);
}
@Override
public Attribute visitLong(long i, Void p) {
TypeMirror longType = modelTypes.getPrimitiveType(TypeKind.LONG);
- return new Attribute.Constant((Type)longType, i);
+ return new Attribute.Constant((Type) longType, i);
}
@Override
public Attribute visitShort(short s, Void p) {
TypeMirror shortType = modelTypes.getPrimitiveType(TypeKind.SHORT);
- return new Attribute.Constant((Type)shortType, s);
+ return new Attribute.Constant((Type) shortType, s);
}
@Override
public Attribute visitString(String s, Void p) {
TypeMirror stringType = elements.getTypeElement("java.lang.String").asType();
- return new Attribute.Constant((Type)stringType, s);
+ return new Attribute.Constant((Type) stringType, s);
}
@Override
public Attribute visitType(TypeMirror t, Void p) {
if (t instanceof Type) {
- return new Attribute.Class(javacTypes, (Type)t);
+ return new Attribute.Class(javacTypes, (Type) t);
}
assert false : "Unexpected type of TypeMirror: " + t.getClass();
@@ -264,7 +267,7 @@ public class TypeAnnotationUtils {
valAttrs = valAttrs.append(av.accept(this, p));
}
ArrayType arrayType = modelTypes.getArrayType(valAttrs.get(0).type);
- return new Attribute.Array((Type)arrayType, valAttrs);
+ return new Attribute.Array((Type) arrayType, valAttrs);
} else {
return new Attribute.Array((Type) meth.getReturnType(), List.<Attribute>nil());
}
@@ -277,338 +280,118 @@ public class TypeAnnotationUtils {
}
}
- /**
- * An interface to abstract a Java 8 and a Java 9 version of how
- * to get a RET reference.
- * These methods must then be implemented using reflection in order to
- * compile in either setting.
- * Note that we cannot use lambda for this as long as we want to
- * support Java 7.
- */
- interface Call8or9<RET> {
- RET call8() throws Throwable;
- RET call9() throws Throwable;
- }
-
- /**
- * Use the SourceVersion to decide whether to call the Java 8 or Java 9 version.
- * Catch all exceptions and abort if one occurs - the reflection code should
- * never break once fully debugged.
- *
- * @param ver The SourceVersion to decide what API to use.
- * @param tc The TAPCall abstraction to encapsulate two methods.
- * @return The created TypeAnnotationPosition.
- */
- private static <RET> RET call8or9(Call8or9<RET> tc) {
- try {
- boolean hasNine;
- try {
- hasNine = SourceVersion.valueOf("RELEASE_9") != null;
- } catch(IllegalArgumentException iae) {
- hasNine = false;
- }
- if (hasNine) {
- return tc.call9();
- } else {
- boolean hasEight;
- try {
- hasEight = SourceVersion.valueOf("RELEASE_8") != null;
- } catch(IllegalArgumentException iae) {
- hasEight = false;
- }
- if (hasEight) {
- return tc.call8();
- } else {
- assert false : "Checker Framework needs a Java 8 or 9 javac.";
- return null;
- }
- }
- } catch (Throwable t) {
- assert false : "Checker Framework internal error: " + t;
- t.printStackTrace();
- return null;
- }
- }
-
public static TypeAnnotationPosition unknownTAPosition() {
- return call8or9(
- new Call8or9<TypeAnnotationPosition>() {
- @Override
- public TypeAnnotationPosition call8() throws InstantiationException, IllegalAccessException {
- return TypeAnnotationPosition.class.newInstance();
- }
- @Override
- public TypeAnnotationPosition call9() throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException {
- return (TypeAnnotationPosition) TypeAnnotationPosition.class
- .getField("unknown")
- .get(null);
- }
- }
- );
+ return new TypeAnnotationPosition();
}
public static TypeAnnotationPosition methodReturnTAPosition(final int pos) {
- return call8or9(
- new Call8or9<TypeAnnotationPosition>() {
- @Override
- public TypeAnnotationPosition call8() throws InstantiationException, IllegalAccessException, IllegalArgumentException, NoSuchFieldException, SecurityException {
- TypeAnnotationPosition tapos = TypeAnnotationPosition.class.newInstance();
- TypeAnnotationPosition.class.getField("type").set(tapos, TargetType.METHOD_RETURN);
- TypeAnnotationPosition.class.getField("pos").set(tapos, pos);
- return tapos;
- }
- @Override
- public TypeAnnotationPosition call9() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
- return (TypeAnnotationPosition) TypeAnnotationPosition.class
- .getMethod("methodReturn", int.class)
- .invoke(null, pos);
- }
- }
- );
+ TypeAnnotationPosition tapos = new TypeAnnotationPosition();
+ tapos.type = TargetType.METHOD_RETURN;
+ tapos.pos = pos;
+ return tapos;
}
public static TypeAnnotationPosition methodReceiverTAPosition(final int pos) {
- return call8or9(
- new Call8or9<TypeAnnotationPosition>() {
- @Override
- public TypeAnnotationPosition call8() throws InstantiationException, IllegalAccessException, IllegalArgumentException, NoSuchFieldException, SecurityException {
- TypeAnnotationPosition tapos = TypeAnnotationPosition.class.newInstance();
- TypeAnnotationPosition.class.getField("type").set(tapos, TargetType.METHOD_RECEIVER);
- TypeAnnotationPosition.class.getField("pos").set(tapos, pos);
- return tapos;
- }
- @Override
- public TypeAnnotationPosition call9() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
- return (TypeAnnotationPosition) TypeAnnotationPosition.class
- .getMethod("methodReceiver", int.class)
- .invoke(null, pos);
- }
- }
- );
+ TypeAnnotationPosition tapos = new TypeAnnotationPosition();
+ tapos.type = TargetType.METHOD_RECEIVER;
+ tapos.pos = pos;
+ return tapos;
}
public static TypeAnnotationPosition methodParameterTAPosition(final int pidx, final int pos) {
- return call8or9(
- new Call8or9<TypeAnnotationPosition>() {
- @Override
- public TypeAnnotationPosition call8() throws InstantiationException, IllegalAccessException, IllegalArgumentException, NoSuchFieldException, SecurityException {
- TypeAnnotationPosition tapos = TypeAnnotationPosition.class.newInstance();
- TypeAnnotationPosition.class.getField("type").set(tapos, TargetType.METHOD_FORMAL_PARAMETER);
- TypeAnnotationPosition.class.getField("parameter_index").set(tapos, pidx);
- TypeAnnotationPosition.class.getField("pos").set(tapos, pos);
- return tapos;
- }
- @Override
- public TypeAnnotationPosition call9() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
- return (TypeAnnotationPosition) TypeAnnotationPosition.class
- .getMethod("methodParameter", int.class, int.class)
- .invoke(null, pidx, pos);
- }
- }
- );
+ TypeAnnotationPosition tapos = new TypeAnnotationPosition();
+ tapos.type = TargetType.METHOD_FORMAL_PARAMETER;
+ tapos.parameter_index = pidx;
+ tapos.pos = pos;
+ return tapos;
}
public static TypeAnnotationPosition methodThrowsTAPosition(final int tidx, final int pos) {
- return call8or9(
- new Call8or9<TypeAnnotationPosition>() {
- @Override
- public TypeAnnotationPosition call8() throws InstantiationException, IllegalAccessException, IllegalArgumentException, NoSuchFieldException, SecurityException {
- TypeAnnotationPosition tapos = TypeAnnotationPosition.class.newInstance();
- TypeAnnotationPosition.class.getField("type").set(tapos, TargetType.THROWS);
- TypeAnnotationPosition.class.getField("type_index").set(tapos, tidx);
- TypeAnnotationPosition.class.getField("pos").set(tapos, pos);
- return tapos;
- }
- @Override
- public TypeAnnotationPosition call9() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException, NoSuchFieldException {
- return (TypeAnnotationPosition) TypeAnnotationPosition.class
- .getMethod("methodThrows", List.class, JCLambda.class, int.class, int.class)
- .invoke(null, TypeAnnotationPosition.class.getField("emptyPath").get(null), null, tidx, pos);
- }
- }
- );
+ TypeAnnotationPosition tapos = new TypeAnnotationPosition();
+ tapos.type = TargetType.THROWS;
+ tapos.type_index = tidx;
+ tapos.pos = pos;
+ return tapos;
}
public static TypeAnnotationPosition fieldTAPosition(final int pos) {
- return call8or9(
- new Call8or9<TypeAnnotationPosition>() {
- @Override
- public TypeAnnotationPosition call8() throws InstantiationException, IllegalAccessException, IllegalArgumentException, NoSuchFieldException, SecurityException {
- TypeAnnotationPosition tapos = TypeAnnotationPosition.class.newInstance();
- TypeAnnotationPosition.class.getField("type").set(tapos, TargetType.FIELD);
- TypeAnnotationPosition.class.getField("pos").set(tapos, pos);
- return tapos;
- }
- @Override
- public TypeAnnotationPosition call9() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
- return (TypeAnnotationPosition) TypeAnnotationPosition.class
- .getMethod("field", int.class)
- .invoke(null, pos);
- }
- }
- );
+ TypeAnnotationPosition tapos = new TypeAnnotationPosition();
+ tapos.type = TargetType.FIELD;
+ tapos.pos = pos;
+ return tapos;
}
public static TypeAnnotationPosition classExtendsTAPosition(final int implidx, final int pos) {
- return call8or9(
- new Call8or9<TypeAnnotationPosition>() {
- @Override
- public TypeAnnotationPosition call8() throws InstantiationException, IllegalAccessException, IllegalArgumentException, NoSuchFieldException, SecurityException {
- TypeAnnotationPosition tapos = TypeAnnotationPosition.class.newInstance();
- TypeAnnotationPosition.class.getField("type").set(tapos, TargetType.CLASS_EXTENDS);
- TypeAnnotationPosition.class.getField("type_index").set(tapos, implidx);
- TypeAnnotationPosition.class.getField("pos").set(tapos, pos);
- return tapos;
- }
- @Override
- public TypeAnnotationPosition call9() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
- return (TypeAnnotationPosition) TypeAnnotationPosition.class
- .getMethod("classExtends", int.class, int.class)
- .invoke(null, implidx, pos);
- }
- }
- );
+ TypeAnnotationPosition tapos = new TypeAnnotationPosition();
+ tapos.type = TargetType.CLASS_EXTENDS;
+ tapos.type_index = implidx;
+ tapos.pos = pos;
+ return tapos;
}
public static TypeAnnotationPosition typeParameterTAPosition(final int tpidx, final int pos) {
- return call8or9(
- new Call8or9<TypeAnnotationPosition>() {
- @Override
- public TypeAnnotationPosition call8() throws InstantiationException, IllegalAccessException, IllegalArgumentException, NoSuchFieldException, SecurityException {
- TypeAnnotationPosition tapos = TypeAnnotationPosition.class.newInstance();
- TypeAnnotationPosition.class.getField("type").set(tapos, TargetType.CLASS_TYPE_PARAMETER);
- TypeAnnotationPosition.class.getField("parameter_index").set(tapos, tpidx);
- TypeAnnotationPosition.class.getField("pos").set(tapos, pos);
- return tapos;
- }
- @Override
- public TypeAnnotationPosition call9() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException, NoSuchFieldException {
- return (TypeAnnotationPosition) TypeAnnotationPosition.class
- .getMethod("typeParameter", List.class, JCLambda.class, int.class, int.class)
- .invoke(null, TypeAnnotationPosition.class.getField("emptyPath").get(null), null, tpidx, pos);
- }
- }
- );
+ TypeAnnotationPosition tapos = new TypeAnnotationPosition();
+ tapos.type = TargetType.CLASS_TYPE_PARAMETER;
+ tapos.parameter_index = tpidx;
+ tapos.pos = pos;
+ return tapos;
}
- public static TypeAnnotationPosition methodTypeParameterTAPosition(final int tpidx, final int pos) {
- return call8or9(
- new Call8or9<TypeAnnotationPosition>() {
- @Override
- public TypeAnnotationPosition call8() throws InstantiationException, IllegalAccessException, IllegalArgumentException, NoSuchFieldException, SecurityException {
- TypeAnnotationPosition tapos = TypeAnnotationPosition.class.newInstance();
- TypeAnnotationPosition.class.getField("type").set(tapos, TargetType.METHOD_TYPE_PARAMETER);
- TypeAnnotationPosition.class.getField("parameter_index").set(tapos, tpidx);
- TypeAnnotationPosition.class.getField("pos").set(tapos, pos);
- return tapos;
- }
- @Override
- public TypeAnnotationPosition call9() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException, NoSuchFieldException {
- return (TypeAnnotationPosition) TypeAnnotationPosition.class
- .getMethod("methodTypeParameter", List.class, JCLambda.class, int.class, int.class)
- .invoke(null, TypeAnnotationPosition.class.getField("emptyPath").get(null), null, tpidx, pos);
- }
- }
- );
+ public static TypeAnnotationPosition methodTypeParameterTAPosition(
+ final int tpidx, final int pos) {
+ TypeAnnotationPosition tapos = new TypeAnnotationPosition();
+ tapos.type = TargetType.METHOD_TYPE_PARAMETER;
+ tapos.parameter_index = tpidx;
+ tapos.pos = pos;
+ return tapos;
}
- public static TypeAnnotationPosition typeParameterBoundTAPosition(final int tpidx, final int bndidx, final int pos) {
- return call8or9(
- new Call8or9<TypeAnnotationPosition>() {
- @Override
- public TypeAnnotationPosition call8() throws InstantiationException, IllegalAccessException, IllegalArgumentException, NoSuchFieldException, SecurityException {
- TypeAnnotationPosition tapos = TypeAnnotationPosition.class.newInstance();
- TypeAnnotationPosition.class.getField("type").set(tapos, TargetType.CLASS_TYPE_PARAMETER_BOUND);
- TypeAnnotationPosition.class.getField("parameter_index").set(tapos, tpidx);
- TypeAnnotationPosition.class.getField("bound_index").set(tapos, bndidx);
- TypeAnnotationPosition.class.getField("pos").set(tapos, pos);
- return tapos;
- }
- @Override
- public TypeAnnotationPosition call9() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException, NoSuchFieldException {
- return (TypeAnnotationPosition) TypeAnnotationPosition.class
- .getMethod("typeParameterBound", List.class, JCLambda.class, int.class, int.class, int.class)
- .invoke(null, TypeAnnotationPosition.class.getField("emptyPath").get(null), null, tpidx, bndidx, pos);
- }
- }
- );
+ public static TypeAnnotationPosition typeParameterBoundTAPosition(
+ final int tpidx, final int bndidx, final int pos) {
+ TypeAnnotationPosition tapos = new TypeAnnotationPosition();
+ tapos.type = TargetType.CLASS_TYPE_PARAMETER_BOUND;
+ tapos.parameter_index = tpidx;
+ tapos.bound_index = bndidx;
+ tapos.pos = pos;
+ return tapos;
}
- public static TypeAnnotationPosition methodTypeParameterBoundTAPosition(final int tpidx, final int bndidx, final int pos) {
- return call8or9(
- new Call8or9<TypeAnnotationPosition>() {
- @Override
- public TypeAnnotationPosition call8() throws InstantiationException, IllegalAccessException, IllegalArgumentException, NoSuchFieldException, SecurityException {
- TypeAnnotationPosition tapos = TypeAnnotationPosition.class.newInstance();
- TypeAnnotationPosition.class.getField("type").set(tapos, TargetType.METHOD_TYPE_PARAMETER_BOUND);
- TypeAnnotationPosition.class.getField("parameter_index").set(tapos, tpidx);
- TypeAnnotationPosition.class.getField("bound_index").set(tapos, bndidx);
- TypeAnnotationPosition.class.getField("pos").set(tapos, pos);
- return tapos;
- }
- @Override
- public TypeAnnotationPosition call9() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException, NoSuchFieldException {
- return (TypeAnnotationPosition) TypeAnnotationPosition.class
- .getMethod("methodTypeParameterBound", List.class, JCLambda.class, int.class, int.class, int.class)
- .invoke(null, TypeAnnotationPosition.class.getField("emptyPath").get(null), null, tpidx, bndidx, pos);
- }
- }
- );
+ public static TypeAnnotationPosition methodTypeParameterBoundTAPosition(
+ final int tpidx, final int bndidx, final int pos) {
+ TypeAnnotationPosition tapos = new TypeAnnotationPosition();
+ tapos.type = TargetType.METHOD_TYPE_PARAMETER_BOUND;
+ tapos.parameter_index = tpidx;
+ tapos.bound_index = bndidx;
+ tapos.pos = pos;
+ return tapos;
}
public static TypeAnnotationPosition copyTAPosition(final TypeAnnotationPosition tapos) {
- return call8or9(
- new Call8or9<TypeAnnotationPosition>() {
- @Override
- public TypeAnnotationPosition call8() throws InstantiationException, IllegalAccessException, IllegalArgumentException, NoSuchFieldException, SecurityException {
- return copyTAPosition8(tapos);
- }
- @Override
- public TypeAnnotationPosition call9() throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException, InvocationTargetException, NoSuchMethodException {
- return (TypeAnnotationPosition) TypeAnnotationPosition.class
- .getMethod("copy", TypeAnnotationPosition.class)
- .invoke(null, tapos);
- }
- }
- );
- }
-
- private static TypeAnnotationPosition copyTAPosition8(TypeAnnotationPosition tapos) throws InstantiationException, IllegalAccessException, IllegalArgumentException, NoSuchFieldException, SecurityException {
- TypeAnnotationPosition res = TypeAnnotationPosition.class.newInstance();
+ TypeAnnotationPosition res = new TypeAnnotationPosition();
res.isValidOffset = tapos.isValidOffset;
- TypeAnnotationPosition.class.getField("bound_index").set(res, tapos.bound_index);
+ res.bound_index = tapos.bound_index;
res.exception_index = tapos.exception_index;
res.location = List.from(tapos.location);
- if (tapos.lvarIndex != null)
+ if (tapos.lvarIndex != null) {
res.lvarIndex = Arrays.copyOf(tapos.lvarIndex, tapos.lvarIndex.length);
- if (tapos.lvarLength != null)
+ }
+ if (tapos.lvarLength != null) {
res.lvarLength = Arrays.copyOf(tapos.lvarLength, tapos.lvarLength.length);
- if (tapos.lvarOffset != null)
+ }
+ if (tapos.lvarOffset != null) {
res.lvarOffset = Arrays.copyOf(tapos.lvarOffset, tapos.lvarOffset.length);
+ }
res.offset = tapos.offset;
- TypeAnnotationPosition.class.getField("onLambda").set(res, tapos.onLambda);
- TypeAnnotationPosition.class.getField("parameter_index").set(res, tapos.parameter_index);
- TypeAnnotationPosition.class.getField("pos").set(res, tapos.pos);
- TypeAnnotationPosition.class.getField("type").set(res, tapos.type);
- TypeAnnotationPosition.class.getField("type_index").set(res, tapos.type_index);
+ res.onLambda = tapos.onLambda;
+ res.parameter_index = tapos.parameter_index;
+ res.pos = tapos.pos;
+ res.type = tapos.type;
+ res.type_index = tapos.type_index;
return res;
}
- public static Type unannotatedType(final Type in) {
- return call8or9(
- new Call8or9<Type>() {
- @Override
- public Type call8() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
- return (Type) Type.class
- .getMethod("unannotatedType")
- .invoke(in);
- }
- @Override
- public Type call9() {
- return in;
- }
- }
- );
+ public static Type unannotatedType(final TypeMirror in) {
+ final Type impl = (Type) in;
+ return impl.unannotatedType();
}
-
-} \ No newline at end of file
+}
diff --git a/third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/TypesUtils.java b/third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/TypesUtils.java
index f024a60feb..fe7456f6d2 100644
--- a/third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/TypesUtils.java
+++ b/third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/TypesUtils.java
@@ -1,8 +1,19 @@
package org.checkerframework.javacutil;
+import static com.sun.tools.javac.code.TypeTag.WILDCARD;
+
+import com.sun.tools.javac.code.Symtab;
+import com.sun.tools.javac.code.Type;
+import com.sun.tools.javac.code.TypeTag;
+import com.sun.tools.javac.model.JavacTypes;
+import com.sun.tools.javac.processing.JavacProcessingEnvironment;
+import com.sun.tools.javac.util.Context;
import javax.annotation.processing.ProcessingEnvironment;
+import javax.lang.model.element.Element;
import javax.lang.model.element.Name;
+import javax.lang.model.element.NestingKind;
import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.TypeParameterElement;
import javax.lang.model.type.ArrayType;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.TypeKind;
@@ -12,26 +23,18 @@ import javax.lang.model.type.WildcardType;
import javax.lang.model.util.Elements;
import javax.lang.model.util.Types;
-import com.sun.tools.javac.code.Symtab;
-import com.sun.tools.javac.code.Type;
-import com.sun.tools.javac.code.TypeTag;
-import com.sun.tools.javac.model.JavacTypes;
-import com.sun.tools.javac.processing.JavacProcessingEnvironment;
-import com.sun.tools.javac.util.Context;
-
-/**
- * A utility class that helps with {@link TypeMirror}s.
- *
- */
+/** A utility class that helps with {@link TypeMirror}s. */
// TODO: This class needs significant restructuring
public final class TypesUtils {
// Class cannot be instantiated
- private TypesUtils() { throw new AssertionError("Class TypesUtils cannot be instantiated."); }
+ private TypesUtils() {
+ throw new AssertionError("Class TypesUtils cannot be instantiated.");
+ }
/**
- * Gets the fully qualified name for a provided type. It returns an empty
- * name if type is an anonymous type.
+ * Gets the fully qualified name for a provided type. It returns an empty name if type is an
+ * anonymous type.
*
* @param type the declared type
* @return the name corresponding to that type
@@ -44,7 +47,7 @@ public final class TypesUtils {
/**
* Checks if the type represents a java.lang.Object declared type.
*
- * @param type the type
+ * @param type the type
* @return true iff type represents java.lang.Object
*/
public static boolean isObject(TypeMirror type) {
@@ -54,7 +57,7 @@ public final class TypesUtils {
/**
* Checks if the type represents a java.lang.Class declared type.
*
- * @param type the type
+ * @param type the type
* @return true iff type represents java.lang.Class
*/
public static boolean isClass(TypeMirror type) {
@@ -62,11 +65,11 @@ public final class TypesUtils {
}
/**
- * Checks if the type represents a java.lang.String declared type.
- * TODO: it would be cleaner to use String.class.getCanonicalName(), but
- * the two existing methods above don't do that, I guess for performance reasons.
+ * Checks if the type represents a java.lang.String declared type. TODO: it would be cleaner to
+ * use String.class.getCanonicalName(), but the two existing methods above don't do that, I
+ * guess for performance reasons.
*
- * @param type the type
+ * @param type the type
* @return true iff type represents java.lang.String
*/
public static boolean isString(TypeMirror type) {
@@ -74,8 +77,8 @@ public final class TypesUtils {
}
/**
- * Checks if the type represents a boolean type, that is either boolean
- * (primitive type) or java.lang.Boolean.
+ * Checks if the type represents a boolean type, that is either boolean (primitive type) or
+ * java.lang.Boolean.
*
* @param type the type to test
* @return true iff type represents a boolean type
@@ -93,14 +96,15 @@ public final class TypesUtils {
*/
public static boolean isDeclaredOfName(TypeMirror type, CharSequence qualifiedName) {
return type.getKind() == TypeKind.DECLARED
- && getQualifiedName((DeclaredType)type).contentEquals(qualifiedName);
+ && getQualifiedName((DeclaredType) type).contentEquals(qualifiedName);
}
public static boolean isBoxedPrimitive(TypeMirror type) {
- if (type.getKind() != TypeKind.DECLARED)
+ if (type.getKind() != TypeKind.DECLARED) {
return false;
+ }
- String qualifiedName = getQualifiedName((DeclaredType)type).toString();
+ String qualifiedName = getQualifiedName((DeclaredType) type).toString();
return (qualifiedName.equals("java.lang.Boolean")
|| qualifiedName.equals("java.lang.Byte")
@@ -112,44 +116,57 @@ public final class TypesUtils {
|| qualifiedName.equals("java.lang.Float"));
}
- /** @return type represents a Throwable type (e.g. Exception, Error) **/
+ /** @return type represents a Throwable type (e.g. Exception, Error) */
public static boolean isThrowable(TypeMirror type) {
while (type != null && type.getKind() == TypeKind.DECLARED) {
DeclaredType dt = (DeclaredType) type;
TypeElement elem = (TypeElement) dt.asElement();
Name name = elem.getQualifiedName();
- if ("java.lang.Throwable".contentEquals(name))
+ if ("java.lang.Throwable".contentEquals(name)) {
return true;
+ }
type = elem.getSuperclass();
}
return false;
}
/**
+ * Returns true iff the argument is an anonymous type.
+ *
+ * @return whether the argument is an anonymous type
+ */
+ public static boolean isAnonymous(TypeMirror type) {
+ return (type instanceof DeclaredType)
+ && (((TypeElement) ((DeclaredType) type).asElement())
+ .getNestingKind()
+ .equals(NestingKind.ANONYMOUS));
+ }
+
+ /**
* Returns true iff the argument is a primitive type.
*
- * @return whether the argument is a primitive type
+ * @return whether the argument is a primitive type
*/
public static boolean isPrimitive(TypeMirror type) {
switch (type.getKind()) {
- case BOOLEAN:
- case BYTE:
- case CHAR:
- case DOUBLE:
- case FLOAT:
- case INT:
- case LONG:
- case SHORT:
- return true;
- default:
- return false;
+ case BOOLEAN:
+ case BYTE:
+ case CHAR:
+ case DOUBLE:
+ case FLOAT:
+ case INT:
+ case LONG:
+ case SHORT:
+ return true;
+ default:
+ return false;
}
}
/**
* Returns true iff the arguments are both the same primitive types.
*
- * @return whether the arguments are the same primitive types
+ * @return whether the arguments are the same primitive types
*/
public static boolean areSamePrimitiveTypes(TypeMirror left, TypeMirror right) {
if (!isPrimitive(left) || !isPrimitive(right)) {
@@ -162,65 +179,64 @@ public final class TypesUtils {
/**
* Returns true iff the argument is a primitive numeric type.
*
- * @return whether the argument is a primitive numeric type
+ * @return whether the argument is a primitive numeric type
*/
public static boolean isNumeric(TypeMirror type) {
switch (type.getKind()) {
- case BYTE:
- case CHAR:
- case DOUBLE:
- case FLOAT:
- case INT:
- case LONG:
- case SHORT:
- return true;
- default:
- return false;
+ case BYTE:
+ case CHAR:
+ case DOUBLE:
+ case FLOAT:
+ case INT:
+ case LONG:
+ case SHORT:
+ return true;
+ default:
+ return false;
}
}
/**
* Returns true iff the argument is an integral type.
*
- * @return whether the argument is an integral type
+ * @return whether the argument is an integral type
*/
public static boolean isIntegral(TypeMirror type) {
switch (type.getKind()) {
- case BYTE:
- case CHAR:
- case INT:
- case LONG:
- case SHORT:
- return true;
- default:
- return false;
+ case BYTE:
+ case CHAR:
+ case INT:
+ case LONG:
+ case SHORT:
+ return true;
+ default:
+ return false;
}
}
/**
* Returns true iff the argument is a floating point type.
*
- * @return whether the argument is a floating point type
+ * @return whether the argument is a floating point type
*/
public static boolean isFloating(TypeMirror type) {
switch (type.getKind()) {
- case DOUBLE:
- case FLOAT:
- return true;
- default:
- return false;
+ case DOUBLE:
+ case FLOAT:
+ return true;
+ default:
+ return false;
}
}
/**
- * Returns the widened numeric type for an arithmetic operation
- * performed on a value of the left type and the right type.
- * Defined in JLS 5.6.2. We return a {@link TypeKind} because
- * creating a {@link TypeMirror} requires a {@link Types} object
- * from the {@link javax.annotation.processing.ProcessingEnvironment}.
+ * Returns the widened numeric type for an arithmetic operation performed on a value of the left
+ * type and the right type. Defined in JLS 5.6.2. We return a {@link TypeKind} because creating
+ * a {@link TypeMirror} requires a {@link Types} object from the {@link
+ * javax.annotation.processing.ProcessingEnvironment}.
*
- * @return the result of widening numeric conversion, or NONE when
- * the conversion cannot be performed
+ * @return the result of widening numeric conversion, or NONE when the conversion cannot be
+ * performed
*/
public static TypeKind widenedNumericType(TypeMirror left, TypeMirror right) {
if (!isNumeric(left) || !isNumeric(right)) {
@@ -246,13 +262,12 @@ public final class TypesUtils {
}
/**
- * If the argument is a bounded TypeVariable or WildcardType,
- * return its non-variable, non-wildcard upper bound. Otherwise,
- * return the type itself.
+ * If the argument is a bounded TypeVariable or WildcardType, return its non-variable,
+ * non-wildcard upper bound. Otherwise, return the type itself.
*
- * @param type a type
- * @return the non-variable, non-wildcard upper bound of a type,
- * if it has one, or itself if it has no bounds
+ * @param type a type
+ * @return the non-variable, non-wildcard upper bound of a type, if it has one, or itself if it
+ * has no bounds
*/
public static TypeMirror upperBound(TypeMirror type) {
do {
@@ -277,8 +292,28 @@ public final class TypesUtils {
return type;
}
- // Version of com.sun.tools.javac.code.Types.wildUpperBound(Type)
- // that works with both jdk8 (called upperBound there) and jdk8u.
+ /**
+ * Get the type parameter for this wildcard from the underlying type's bound field This field is
+ * sometimes null, in that case this method will return null
+ *
+ * @return the TypeParameterElement the wildcard is an argument to
+ */
+ public static TypeParameterElement wildcardToTypeParam(final Type.WildcardType wildcard) {
+
+ final Element typeParamElement;
+ if (wildcard.bound != null) {
+ typeParamElement = wildcard.bound.asElement();
+ } else {
+ typeParamElement = null;
+ }
+
+ return (TypeParameterElement) typeParamElement;
+ }
+
+ /**
+ * Version of com.sun.tools.javac.code.Types.wildUpperBound(Type) that works with both jdk8
+ * (called upperBound there) and jdk8u.
+ */
// TODO: contrast to upperBound.
public static Type wildUpperBound(ProcessingEnvironment env, TypeMirror tm) {
Type t = (Type) tm;
@@ -291,15 +326,27 @@ public final class TypesUtils {
} else {
return wildUpperBound(env, w.type);
}
- }
- else {
+ } else {
return TypeAnnotationUtils.unannotatedType(t);
}
}
/**
- * Returns the {@link TypeMirror} for a given {@link Class}.
+ * Version of com.sun.tools.javac.code.Types.wildLowerBound(Type) that works with both jdk8
+ * (called upperBound there) and jdk8u.
*/
+ public static Type wildLowerBound(ProcessingEnvironment env, TypeMirror tm) {
+ Type t = (Type) tm;
+ if (t.hasTag(WILDCARD)) {
+ Context context = ((JavacProcessingEnvironment) env).getContext();
+ Symtab syms = Symtab.instance(context);
+ Type.WildcardType w = (Type.WildcardType) TypeAnnotationUtils.unannotatedType(t);
+ return w.isExtendsBound() ? syms.botType : wildLowerBound(env, w.type);
+ } else {
+ return TypeAnnotationUtils.unannotatedType(t);
+ }
+ }
+ /** Returns the {@link TypeMirror} for a given {@link Class}. */
public static TypeMirror typeFromClass(Types types, Elements elements, Class<?> clazz) {
if (clazz == void.class) {
return types.getNoType(TypeKind.VOID);
@@ -320,11 +367,86 @@ public final class TypesUtils {
}
}
- /**
- * Returns an {@link ArrayType} with elements of type {@code componentType}.
- */
+ /** Returns an {@link ArrayType} with elements of type {@code componentType}. */
public static ArrayType createArrayType(Types types, TypeMirror componentType) {
JavacTypes t = (JavacTypes) types;
return t.getArrayType(componentType);
}
+
+ /**
+ * Returns true if declaredType is a Class that is used to box primitive type (e.g.
+ * declaredType=java.lang.Double and primitiveType=22.5d )
+ */
+ public static boolean isBoxOf(TypeMirror declaredType, TypeMirror primitiveType) {
+ if (declaredType.getKind() != TypeKind.DECLARED) {
+ return false;
+ }
+
+ final String qualifiedName = getQualifiedName((DeclaredType) declaredType).toString();
+ switch (primitiveType.getKind()) {
+ case BOOLEAN:
+ return qualifiedName.equals("java.lang.Boolean");
+ case BYTE:
+ return qualifiedName.equals("java.lang.Byte");
+ case CHAR:
+ return qualifiedName.equals("java.lang.Character");
+ case DOUBLE:
+ return qualifiedName.equals("java.lang.Double");
+ case FLOAT:
+ return qualifiedName.equals("java.lang.Float");
+ case INT:
+ return qualifiedName.equals("java.lang.Integer");
+ case LONG:
+ return qualifiedName.equals("java.lang.Long");
+ case SHORT:
+ return qualifiedName.equals("java.lang.Short");
+
+ default:
+ return false;
+ }
+ }
+
+ /**
+ * Given a bounded type (wildcard or typevar) get the concrete type of its upper bound. If the
+ * bounded type extends other bounded types, this method will iterate through their bounds until
+ * a class, interface, or intersection is found.
+ *
+ * @return a type that is not a wildcard or typevar, or null if this type is an unbounded
+ * wildcard
+ */
+ public static TypeMirror findConcreteUpperBound(final TypeMirror boundedType) {
+ TypeMirror effectiveUpper = boundedType;
+ outerLoop:
+ while (true) {
+ switch (effectiveUpper.getKind()) {
+ case WILDCARD:
+ effectiveUpper =
+ ((javax.lang.model.type.WildcardType) effectiveUpper).getExtendsBound();
+ if (effectiveUpper == null) {
+ return null;
+ }
+ break;
+
+ case TYPEVAR:
+ effectiveUpper = ((TypeVariable) effectiveUpper).getUpperBound();
+ break;
+
+ default:
+ break outerLoop;
+ }
+ }
+ return effectiveUpper;
+ }
+
+ /**
+ * Returns true if the erased type of subtype is a subtype of the erased type of supertype.
+ *
+ * @param types Types
+ * @param subtype possible subtype
+ * @param supertype possible supertype
+ * @return true if the erased type of subtype is a subtype of the erased type of supertype
+ */
+ public static boolean isErasedSubtype(Types types, TypeMirror subtype, TypeMirror supertype) {
+ return types.isSubtype(types.erasure(subtype), types.erasure(supertype));
+ }
}
diff --git a/third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/dist/ManualTaglet.java b/third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/dist/ManualTaglet.java
index ade653e13b..01f35485e5 100644
--- a/third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/dist/ManualTaglet.java
+++ b/third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/dist/ManualTaglet.java
@@ -1,22 +1,20 @@
package org.checkerframework.javacutil.dist;
-import java.util.Map;
-
import com.sun.javadoc.Tag;
import com.sun.tools.doclets.Taglet;
+import java.util.Map;
/**
* A taglet for processing the {@code @checker_framework.manual} javadoc block tag, which inserts
* references to the Checker Framework manual into javadoc.
*
- * <p>
- *
- * The {@code @checker_framework.manual} tag is used as follows:
+ * <p>The {@code @checker_framework.manual} tag is used as follows:
*
* <ul>
- * <li>{@code @checker_framework.manual #} expands to a top-level link to the Checker Framework manual
- * <li>{@code @checker_framework.manual #anchor text} expands to a link with some text to a
- * particular part of the manual
+ * <li>{@code @checker_framework.manual #} expands to a top-level link to the Checker Framework
+ * manual
+ * <li>{@code @checker_framework.manual #anchor text} expands to a link with some text to a
+ * particular part of the manual
* </ul>
*/
public class ManualTaglet implements Taglet {
@@ -65,8 +63,8 @@ public class ManualTaglet implements Taglet {
* Formats a link, given an array of tokens.
*
* @param parts the array of tokens
- * @return a link to the manual top-level if the array size is one, or a
- * link to a part of the manual if it's larger than one
+ * @return a link to the manual top-level if the array size is one, or a link to a part of the
+ * manual if it's larger than one
*/
private String formatLink(String[] parts) {
String anchor, text;
@@ -78,21 +76,18 @@ public class ManualTaglet implements Taglet {
text = parts[1];
}
return String.format(
- "<A HREF=\"http://types.cs.washington.edu/checker-framework/current/checker-framework-manual.html%s\">%s</A>",
- anchor, text);
+ "<A HREF=\"https://checkerframework.org/manual/%s\">%s</A>", anchor, text);
}
/**
- * Formats the {@code @checker_framework.manual} tag, prepending the tag header to the
- * tag content.
+ * Formats the {@code @checker_framework.manual} tag, prepending the tag header to the tag
+ * content.
*
* @param text the tag content
* @return the formatted tag
*/
private String formatHeader(String text) {
- return String.format(
- "<DT><B>See the Checker Framework Manual:</B><DD>%s<BR>",
- text);
+ return String.format("<DT><B>See the Checker Framework Manual:</B><DD>%s<BR>", text);
}
@Override
@@ -103,19 +98,21 @@ public class ManualTaglet implements Taglet {
@Override
public String toString(Tag[] tags) {
- if (tags.length == 0)
+ if (tags.length == 0) {
return "";
+ }
StringBuilder sb = new StringBuilder();
for (Tag t : tags) {
String[] split = t.text().split(" ", 2);
- if (t != tags[0])
+ if (t != tags[0]) {
sb.append(", ");
+ }
sb.append(formatLink(split));
}
return formatHeader(sb.toString());
}
- @SuppressWarnings({ "unchecked", "rawtypes" })
+ @SuppressWarnings({"unchecked", "rawtypes"})
public static void register(Map tagletMap) {
ManualTaglet tag = new ManualTaglet();
Taglet t = (Taglet) tagletMap.get(tag.getName());
diff --git a/third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/trees/DetachedVarSymbol.java b/third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/trees/DetachedVarSymbol.java
index 0edf3944e3..43d79cc710 100644
--- a/third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/trees/DetachedVarSymbol.java
+++ b/third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/trees/DetachedVarSymbol.java
@@ -10,35 +10,26 @@ import org.checkerframework.checker.nullness.qual.Nullable;
*/
/**
- * A DetachedVarSymbol represents a variable that is not part of any
- * AST Tree. DetachedVarSymbols are created when desugaring source
- * code constructs and they carry important type information, but some
- * methods such as TreeInfo.declarationFor do not work on them.
+ * A DetachedVarSymbol represents a variable that is not part of any AST Tree. DetachedVarSymbols
+ * are created when desugaring source code constructs and they carry important type information, but
+ * some methods such as TreeInfo.declarationFor do not work on them.
*/
-
public class DetachedVarSymbol extends Symbol.VarSymbol {
protected /*@Nullable*/ VariableTree decl;
- /**
- * Construct a detached variable symbol, given its flags, name,
- * type and owner.
- */
+ /** Construct a detached variable symbol, given its flags, name, type and owner. */
public DetachedVarSymbol(long flags, Name name, Type type, Symbol owner) {
super(flags, name, type, owner);
this.decl = null;
}
- /**
- * Set the declaration tree for the variable.
- */
+ /** Set the declaration tree for the variable. */
public void setDeclaration(VariableTree decl) {
this.decl = decl;
}
- /**
- * Get the declaration tree for the variable.
- */
+ /** Get the declaration tree for the variable. */
public /*@Nullable*/ VariableTree getDeclaration() {
return decl;
}
diff --git a/third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/trees/TreeBuilder.java b/third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/trees/TreeBuilder.java
index 2623f2f2e7..eab005dea8 100644
--- a/third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/trees/TreeBuilder.java
+++ b/third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/trees/TreeBuilder.java
@@ -1,24 +1,5 @@
package org.checkerframework.javacutil.trees;
-import java.util.List;
-
-import javax.annotation.processing.ProcessingEnvironment;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.element.Name;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.element.VariableElement;
-import javax.lang.model.type.ArrayType;
-import javax.lang.model.type.DeclaredType;
-import javax.lang.model.type.TypeKind;
-import javax.lang.model.type.TypeMirror;
-import javax.lang.model.util.ElementFilter;
-import javax.lang.model.util.Elements;
-import javax.lang.model.util.Types;
-
-import org.checkerframework.javacutil.InternalUtils;
-import org.checkerframework.javacutil.TypesUtils;
-
import com.sun.source.tree.ArrayAccessTree;
import com.sun.source.tree.AssignmentTree;
import com.sun.source.tree.BinaryTree;
@@ -40,12 +21,27 @@ import com.sun.tools.javac.tree.TreeInfo;
import com.sun.tools.javac.tree.TreeMaker;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.Names;
+import java.util.List;
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.Name;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.VariableElement;
+import javax.lang.model.type.ArrayType;
+import javax.lang.model.type.DeclaredType;
+import javax.lang.model.type.TypeKind;
+import javax.lang.model.type.TypeMirror;
+import javax.lang.model.util.ElementFilter;
+import javax.lang.model.util.Elements;
+import javax.lang.model.util.Types;
+import org.checkerframework.javacutil.InternalUtils;
+import org.checkerframework.javacutil.TypesUtils;
/**
- * The TreeBuilder permits the creation of new AST Trees using the
- * non-public Java compiler API TreeMaker.
+ * The TreeBuilder permits the creation of new AST Trees using the non-public Java compiler API
+ * TreeMaker.
*/
-
public class TreeBuilder {
protected final Elements elements;
protected final Types modelTypes;
@@ -57,7 +53,7 @@ public class TreeBuilder {
public TreeBuilder(ProcessingEnvironment env) {
this.env = env;
- Context context = ((JavacProcessingEnvironment)env).getContext();
+ Context context = ((JavacProcessingEnvironment) env).getContext();
elements = env.getElementUtils();
modelTypes = env.getTypeUtils();
javacTypes = com.sun.tools.javac.code.Types.instance(context);
@@ -67,66 +63,63 @@ public class TreeBuilder {
}
/**
- * Builds an AST Tree to access the iterator() method of some iterable
- * expression.
+ * Builds an AST Tree to access the iterator() method of some iterable expression.
*
- * @param iterableExpr an expression whose type is a subtype of Iterable
- * @return a MemberSelectTree that accesses the iterator() method of
- * the expression
+ * @param iterableExpr an expression whose type is a subtype of Iterable
+ * @return a MemberSelectTree that accesses the iterator() method of the expression
*/
public MemberSelectTree buildIteratorMethodAccess(ExpressionTree iterableExpr) {
DeclaredType exprType =
- (DeclaredType)TypesUtils.upperBound(InternalUtils.typeOf(iterableExpr));
+ (DeclaredType) TypesUtils.upperBound(InternalUtils.typeOf(iterableExpr));
assert exprType != null : "expression must be of declared type Iterable<>";
- TypeElement exprElement = (TypeElement)exprType.asElement();
+ TypeElement exprElement = (TypeElement) exprType.asElement();
// Find the iterator() method of the iterable type
Symbol.MethodSymbol iteratorMethod = null;
for (ExecutableElement method :
- ElementFilter.methodsIn(elements.getAllMembers(exprElement))) {
+ ElementFilter.methodsIn(elements.getAllMembers(exprElement))) {
Name methodName = method.getSimpleName();
if (method.getParameters().size() == 0) {
if (methodName.contentEquals("iterator")) {
- iteratorMethod = (Symbol.MethodSymbol)method;
+ iteratorMethod = (Symbol.MethodSymbol) method;
}
}
}
assert iteratorMethod != null : "no iterator method declared for expression type";
- Type.MethodType methodType = (Type.MethodType)iteratorMethod.asType();
+ Type.MethodType methodType = (Type.MethodType) iteratorMethod.asType();
Symbol.TypeSymbol methodClass = methodType.asElement();
- DeclaredType iteratorType = (DeclaredType)methodType.getReturnType();
+ DeclaredType iteratorType = (DeclaredType) methodType.getReturnType();
TypeMirror elementType;
if (iteratorType.getTypeArguments().size() > 0) {
elementType = iteratorType.getTypeArguments().get(0);
// Remove captured type from a wildcard.
if (elementType instanceof Type.CapturedType) {
- elementType = ((Type.CapturedType)elementType).wildcard;
+ elementType = ((Type.CapturedType) elementType).wildcard;
}
iteratorType =
- modelTypes.getDeclaredType((TypeElement)modelTypes.asElement(iteratorType),
- elementType);
+ modelTypes.getDeclaredType(
+ (TypeElement) modelTypes.asElement(iteratorType), elementType);
}
-
// Replace the iterator method's generic return type with
// the actual element type of the expression.
Type.MethodType updatedMethodType =
- new Type.MethodType(com.sun.tools.javac.util.List.<Type>nil(),
- (Type)iteratorType,
- com.sun.tools.javac.util.List.<Type>nil(),
- methodClass);
+ new Type.MethodType(
+ com.sun.tools.javac.util.List.<Type>nil(),
+ (Type) iteratorType,
+ com.sun.tools.javac.util.List.<Type>nil(),
+ methodClass);
JCTree.JCFieldAccess iteratorAccess =
- (JCTree.JCFieldAccess)
- maker.Select((JCTree.JCExpression)iterableExpr,
- iteratorMethod);
+ (JCTree.JCFieldAccess)
+ maker.Select((JCTree.JCExpression) iterableExpr, iteratorMethod);
iteratorAccess.setType(updatedMethodType);
return iteratorAccess;
@@ -135,26 +128,25 @@ public class TreeBuilder {
/**
* Builds an AST Tree to access the hasNext() method of an iterator.
*
- * @param iteratorExpr an expression whose type is a subtype of Iterator
- * @return a MemberSelectTree that accesses the hasNext() method of
- * the expression
+ * @param iteratorExpr an expression whose type is a subtype of Iterator
+ * @return a MemberSelectTree that accesses the hasNext() method of the expression
*/
public MemberSelectTree buildHasNextMethodAccess(ExpressionTree iteratorExpr) {
- DeclaredType exprType = (DeclaredType)InternalUtils.typeOf(iteratorExpr);
+ DeclaredType exprType = (DeclaredType) InternalUtils.typeOf(iteratorExpr);
assert exprType != null : "expression must be of declared type Iterator<>";
- TypeElement exprElement = (TypeElement)exprType.asElement();
+ TypeElement exprElement = (TypeElement) exprType.asElement();
// Find the hasNext() method of the iterator type
Symbol.MethodSymbol hasNextMethod = null;
for (ExecutableElement method :
- ElementFilter.methodsIn(elements.getAllMembers(exprElement))) {
+ ElementFilter.methodsIn(elements.getAllMembers(exprElement))) {
Name methodName = method.getSimpleName();
if (method.getParameters().size() == 0) {
if (methodName.contentEquals("hasNext")) {
- hasNextMethod = (Symbol.MethodSymbol)method;
+ hasNextMethod = (Symbol.MethodSymbol) method;
}
}
}
@@ -162,9 +154,8 @@ public class TreeBuilder {
assert hasNextMethod != null : "no hasNext method declared for expression type";
JCTree.JCFieldAccess hasNextAccess =
- (JCTree.JCFieldAccess)
- maker.Select((JCTree.JCExpression)iteratorExpr,
- hasNextMethod);
+ (JCTree.JCFieldAccess)
+ maker.Select((JCTree.JCExpression) iteratorExpr, hasNextMethod);
hasNextAccess.setType(hasNextMethod.asType());
return hasNextAccess;
@@ -173,38 +164,37 @@ public class TreeBuilder {
/**
* Builds an AST Tree to access the next() method of an iterator.
*
- * @param iteratorExpr an expression whose type is a subtype of Iterator
- * @return a MemberSelectTree that accesses the next() method of
- * the expression
+ * @param iteratorExpr an expression whose type is a subtype of Iterator
+ * @return a MemberSelectTree that accesses the next() method of the expression
*/
public MemberSelectTree buildNextMethodAccess(ExpressionTree iteratorExpr) {
- DeclaredType exprType = (DeclaredType)InternalUtils.typeOf(iteratorExpr);
+ DeclaredType exprType = (DeclaredType) InternalUtils.typeOf(iteratorExpr);
assert exprType != null : "expression must be of declared type Iterator<>";
- TypeElement exprElement = (TypeElement)exprType.asElement();
+ TypeElement exprElement = (TypeElement) exprType.asElement();
// Find the next() method of the iterator type
Symbol.MethodSymbol nextMethod = null;
for (ExecutableElement method :
- ElementFilter.methodsIn(elements.getAllMembers(exprElement))) {
+ ElementFilter.methodsIn(elements.getAllMembers(exprElement))) {
Name methodName = method.getSimpleName();
if (method.getParameters().size() == 0) {
if (methodName.contentEquals("next")) {
- nextMethod = (Symbol.MethodSymbol)method;
+ nextMethod = (Symbol.MethodSymbol) method;
}
}
}
assert nextMethod != null : "no next method declared for expression type";
- Type.MethodType methodType = (Type.MethodType)nextMethod.asType();
+ Type.MethodType methodType = (Type.MethodType) nextMethod.asType();
Symbol.TypeSymbol methodClass = methodType.asElement();
Type elementType;
if (exprType.getTypeArguments().size() > 0) {
- elementType = (Type)exprType.getTypeArguments().get(0);
+ elementType = (Type) exprType.getTypeArguments().get(0);
} else {
elementType = symtab.objectType;
}
@@ -212,15 +202,14 @@ public class TreeBuilder {
// Replace the next method's generic return type with
// the actual element type of the expression.
Type.MethodType updatedMethodType =
- new Type.MethodType(com.sun.tools.javac.util.List.<Type>nil(),
- elementType,
- com.sun.tools.javac.util.List.<Type>nil(),
- methodClass);
+ new Type.MethodType(
+ com.sun.tools.javac.util.List.<Type>nil(),
+ elementType,
+ com.sun.tools.javac.util.List.<Type>nil(),
+ methodClass);
JCTree.JCFieldAccess nextAccess =
- (JCTree.JCFieldAccess)
- maker.Select((JCTree.JCExpression)iteratorExpr,
- nextMethod);
+ (JCTree.JCFieldAccess) maker.Select((JCTree.JCExpression) iteratorExpr, nextMethod);
nextAccess.setType(updatedMethodType);
return nextAccess;
@@ -229,82 +218,80 @@ public class TreeBuilder {
/**
* Builds an AST Tree to dereference the length field of an array
*
- * @param expression the array expression whose length is being accessed
- * @return a MemberSelectTree to dereference the length of the array
+ * @param expression the array expression whose length is being accessed
+ * @return a MemberSelectTree to dereference the length of the array
*/
public MemberSelectTree buildArrayLengthAccess(ExpressionTree expression) {
return (JCTree.JCFieldAccess)
- maker.Select((JCTree.JCExpression)expression, symtab.lengthVar);
+ maker.Select((JCTree.JCExpression) expression, symtab.lengthVar);
}
/**
* Builds an AST Tree to call a method designated by the argument expression.
*
- * @param methodExpr an expression denoting a method with no arguments
- * @return a MethodInvocationTree to call the argument method
+ * @param methodExpr an expression denoting a method with no arguments
+ * @return a MethodInvocationTree to call the argument method
*/
public MethodInvocationTree buildMethodInvocation(ExpressionTree methodExpr) {
- return maker.App((JCTree.JCExpression)methodExpr);
+ return maker.App((JCTree.JCExpression) methodExpr);
}
/**
- * Builds an AST Tree to call a method designated by methodExpr,
- * with one argument designated by argExpr.
+ * Builds an AST Tree to call a method designated by methodExpr, with one argument designated by
+ * argExpr.
*
- * @param methodExpr an expression denoting a method with one argument
- * @param argExpr an expression denoting an argument to the method
- * @return a MethodInvocationTree to call the argument method
+ * @param methodExpr an expression denoting a method with one argument
+ * @param argExpr an expression denoting an argument to the method
+ * @return a MethodInvocationTree to call the argument method
*/
- public MethodInvocationTree buildMethodInvocation(ExpressionTree methodExpr,
- ExpressionTree argExpr) {
- return maker.App((JCTree.JCExpression)methodExpr,
- com.sun.tools.javac.util.List.of((JCTree.JCExpression)argExpr));
+ public MethodInvocationTree buildMethodInvocation(
+ ExpressionTree methodExpr, ExpressionTree argExpr) {
+ return maker.App(
+ (JCTree.JCExpression) methodExpr,
+ com.sun.tools.javac.util.List.of((JCTree.JCExpression) argExpr));
}
/**
* Builds an AST Tree to declare and initialize a variable, with no modifiers.
*
- * @param type the type of the variable
- * @param name the name of the variable
- * @param owner the element containing the new symbol
- * @param initializer the initializer expression
- * @return a VariableDeclTree declaring the new variable
+ * @param type the type of the variable
+ * @param name the name of the variable
+ * @param owner the element containing the new symbol
+ * @param initializer the initializer expression
+ * @return a VariableDeclTree declaring the new variable
*/
- public VariableTree buildVariableDecl(TypeMirror type,
- String name,
- Element owner,
- ExpressionTree initializer) {
+ public VariableTree buildVariableDecl(
+ TypeMirror type, String name, Element owner, ExpressionTree initializer) {
DetachedVarSymbol sym =
- new DetachedVarSymbol(0, names.fromString(name),
- (Type)type, (Symbol)owner);
- VariableTree tree = maker.VarDef(sym, (JCTree.JCExpression)initializer);
+ new DetachedVarSymbol(0, names.fromString(name), (Type) type, (Symbol) owner);
+ VariableTree tree = maker.VarDef(sym, (JCTree.JCExpression) initializer);
sym.setDeclaration(tree);
return tree;
}
/**
- * Builds an AST Tree to declare and initialize a variable. The
- * type of the variable is specified by a Tree.
+ * Builds an AST Tree to declare and initialize a variable. The type of the variable is
+ * specified by a Tree.
*
- * @param type the type of the variable, as a Tree
- * @param name the name of the variable
- * @param owner the element containing the new symbol
- * @param initializer the initializer expression
- * @return a VariableDeclTree declaring the new variable
+ * @param type the type of the variable, as a Tree
+ * @param name the name of the variable
+ * @param owner the element containing the new symbol
+ * @param initializer the initializer expression
+ * @return a VariableDeclTree declaring the new variable
*/
- public VariableTree buildVariableDecl(Tree type,
- String name,
- Element owner,
- ExpressionTree initializer) {
- Type typeMirror = (Type)InternalUtils.typeOf(type);
+ public VariableTree buildVariableDecl(
+ Tree type, String name, Element owner, ExpressionTree initializer) {
+ Type typeMirror = (Type) InternalUtils.typeOf(type);
DetachedVarSymbol sym =
- new DetachedVarSymbol(0, names.fromString(name),
- typeMirror, (Symbol)owner);
+ new DetachedVarSymbol(0, names.fromString(name), typeMirror, (Symbol) owner);
JCTree.JCModifiers mods = maker.Modifiers(0);
- JCTree.JCVariableDecl decl = maker.VarDef(mods, sym.name,
- (JCTree.JCExpression)type,
- (JCTree.JCExpression)initializer);
+ JCTree.JCVariableDecl decl =
+ maker.VarDef(
+ mods,
+ sym.name,
+ (JCTree.JCExpression) type,
+ (JCTree.JCExpression) initializer);
decl.setType(typeMirror);
decl.sym = sym;
sym.setDeclaration(decl);
@@ -314,57 +301,49 @@ public class TreeBuilder {
/**
* Builds an AST Tree to refer to a variable.
*
- * @param decl the declaration of the variable
- * @return an IdentifierTree to refer to the variable
+ * @param decl the declaration of the variable
+ * @return an IdentifierTree to refer to the variable
*/
public IdentifierTree buildVariableUse(VariableTree decl) {
- return (IdentifierTree)maker.Ident((JCTree.JCVariableDecl)decl);
+ return (IdentifierTree) maker.Ident((JCTree.JCVariableDecl) decl);
}
/**
* Builds an AST Tree to cast the type of an expression.
*
- * @param type the type to cast to
- * @param expr the expression to be cast
- * @return a cast of the expression to the type
+ * @param type the type to cast to
+ * @param expr the expression to be cast
+ * @return a cast of the expression to the type
*/
- public TypeCastTree buildTypeCast(TypeMirror type,
- ExpressionTree expr) {
- return maker.TypeCast((Type)type, (JCTree.JCExpression)expr);
+ public TypeCastTree buildTypeCast(TypeMirror type, ExpressionTree expr) {
+ return maker.TypeCast((Type) type, (JCTree.JCExpression) expr);
}
/**
* Builds an AST Tree to assign an expression to a variable.
*
- * @param variable the declaration of the variable to assign to
- * @param expr the expression to be assigned
- * @return a statement assigning the expression to the variable
+ * @param variable the declaration of the variable to assign to
+ * @param expr the expression to be assigned
+ * @return a statement assigning the expression to the variable
*/
- public StatementTree buildAssignment(VariableTree variable,
- ExpressionTree expr) {
- return maker.Assignment(TreeInfo.symbolFor((JCTree)variable),
- (JCTree.JCExpression)expr);
+ public StatementTree buildAssignment(VariableTree variable, ExpressionTree expr) {
+ return maker.Assignment(TreeInfo.symbolFor((JCTree) variable), (JCTree.JCExpression) expr);
}
/**
* Builds an AST Tree to assign an RHS expression to an LHS expression.
*
- * @param lhs the expression to be assigned to
- * @param rhs the expression to be assigned
- * @return a statement assigning the expression to the variable
+ * @param lhs the expression to be assigned to
+ * @param rhs the expression to be assigned
+ * @return a statement assigning the expression to the variable
*/
- public AssignmentTree buildAssignment(ExpressionTree lhs,
- ExpressionTree rhs) {
- JCTree.JCAssign assign =
- maker.Assign((JCTree.JCExpression)lhs, (JCTree.JCExpression)rhs);
- assign.setType((Type)InternalUtils.typeOf(lhs));
+ public AssignmentTree buildAssignment(ExpressionTree lhs, ExpressionTree rhs) {
+ JCTree.JCAssign assign = maker.Assign((JCTree.JCExpression) lhs, (JCTree.JCExpression) rhs);
+ assign.setType((Type) InternalUtils.typeOf(lhs));
return assign;
}
- /**
- * Builds an AST Tree representing a literal value of primitive
- * or String type.
- */
+ /** Builds an AST Tree representing a literal value of primitive or String type. */
public LiteralTree buildLiteral(Object value) {
return maker.Literal(value);
}
@@ -372,51 +351,48 @@ public class TreeBuilder {
/**
* Builds an AST Tree to compare two operands with less than.
*
- * @param left the left operand tree
- * @param right the right operand tree
- * @return a Tree representing "left &lt; right"
+ * @param left the left operand tree
+ * @param right the right operand tree
+ * @return a Tree representing "left &lt; right"
*/
public BinaryTree buildLessThan(ExpressionTree left, ExpressionTree right) {
JCTree.JCBinary binary =
- maker.Binary(JCTree.Tag.LT, (JCTree.JCExpression)left,
- (JCTree.JCExpression)right);
- binary.setType((Type)modelTypes.getPrimitiveType(TypeKind.BOOLEAN));
+ maker.Binary(
+ JCTree.Tag.LT, (JCTree.JCExpression) left, (JCTree.JCExpression) right);
+ binary.setType((Type) modelTypes.getPrimitiveType(TypeKind.BOOLEAN));
return binary;
}
/**
* Builds an AST Tree to dereference an array.
*
- * @param array the array to dereference
- * @param index the index at which to dereference
- * @return a Tree representing the dereference
+ * @param array the array to dereference
+ * @param index the index at which to dereference
+ * @return a Tree representing the dereference
*/
- public ArrayAccessTree buildArrayAccess(ExpressionTree array,
- ExpressionTree index) {
- ArrayType arrayType = (ArrayType)InternalUtils.typeOf(array);
+ public ArrayAccessTree buildArrayAccess(ExpressionTree array, ExpressionTree index) {
+ ArrayType arrayType = (ArrayType) InternalUtils.typeOf(array);
JCTree.JCArrayAccess access =
- maker.Indexed((JCTree.JCExpression)array, (JCTree.JCExpression)index);
- access.setType((Type)arrayType.getComponentType());
+ maker.Indexed((JCTree.JCExpression) array, (JCTree.JCExpression) index);
+ access.setType((Type) arrayType.getComponentType());
return access;
}
/**
* Builds an AST Tree to refer to a class name.
*
- * @param elt an element representing the class
- * @return an IdentifierTree referring to the class
+ * @param elt an element representing the class
+ * @return an IdentifierTree referring to the class
*/
public IdentifierTree buildClassUse(Element elt) {
- return maker.Ident((Symbol)elt);
+ return maker.Ident((Symbol) elt);
}
/**
- * Builds an AST Tree to access the valueOf() method of boxed type
- * such as Short or Float.
+ * Builds an AST Tree to access the valueOf() method of boxed type such as Short or Float.
*
- * @param expr an expression whose type is a boxed type
- * @return a MemberSelectTree that accesses the valueOf() method of
- * the expression
+ * @param expr an expression whose type is a boxed type
+ * @return a MemberSelectTree that accesses the valueOf() method of the expression
*/
public MemberSelectTree buildValueOfMethodAccess(Tree expr) {
TypeMirror boxedType = InternalUtils.typeOf(expr);
@@ -426,32 +402,31 @@ public class TreeBuilder {
// Find the valueOf(unboxedType) method of the boxed type
Symbol.MethodSymbol valueOfMethod = getValueOfMethod(env, boxedType);
- Type.MethodType methodType = (Type.MethodType)valueOfMethod.asType();
+ Type.MethodType methodType = (Type.MethodType) valueOfMethod.asType();
JCTree.JCFieldAccess valueOfAccess =
- (JCTree.JCFieldAccess)
- maker.Select((JCTree.JCExpression)expr, valueOfMethod);
+ (JCTree.JCFieldAccess) maker.Select((JCTree.JCExpression) expr, valueOfMethod);
valueOfAccess.setType(methodType);
return valueOfAccess;
}
- /**
- * Returns the valueOf method of a boxed type such as Short or Float.
- */
- public static Symbol.MethodSymbol getValueOfMethod(ProcessingEnvironment env, TypeMirror boxedType) {
+ /** Returns the valueOf method of a boxed type such as Short or Float. */
+ public static Symbol.MethodSymbol getValueOfMethod(
+ ProcessingEnvironment env, TypeMirror boxedType) {
Symbol.MethodSymbol valueOfMethod = null;
TypeMirror unboxedType = env.getTypeUtils().unboxedType(boxedType);
- TypeElement boxedElement = (TypeElement)((DeclaredType)boxedType).asElement();
+ TypeElement boxedElement = (TypeElement) ((DeclaredType) boxedType).asElement();
for (ExecutableElement method :
- ElementFilter.methodsIn(env.getElementUtils().getAllMembers(boxedElement))) {
+ ElementFilter.methodsIn(env.getElementUtils().getAllMembers(boxedElement))) {
Name methodName = method.getSimpleName();
if (methodName.contentEquals("valueOf")) {
List<? extends VariableElement> params = method.getParameters();
- if (params.size() == 1 && env.getTypeUtils().isSameType(params.get(0).asType(), unboxedType)) {
- valueOfMethod = (Symbol.MethodSymbol)method;
+ if (params.size() == 1
+ && env.getTypeUtils().isSameType(params.get(0).asType(), unboxedType)) {
+ valueOfMethod = (Symbol.MethodSymbol) method;
}
}
}
@@ -461,17 +436,15 @@ public class TreeBuilder {
}
/**
- * Builds an AST Tree to access the *Value() method of a
- * boxed type such as Short or Float, where * is the corresponding
- * primitive type (i.e. shortValue or floatValue).
+ * Builds an AST Tree to access the *Value() method of a boxed type such as Short or Float,
+ * where * is the corresponding primitive type (i.e. shortValue or floatValue).
*
- * @param expr an expression whose type is a boxed type
- * @return a MemberSelectTree that accesses the *Value() method of
- * the expression
+ * @param expr an expression whose type is a boxed type
+ * @return a MemberSelectTree that accesses the *Value() method of the expression
*/
public MemberSelectTree buildPrimValueMethodAccess(Tree expr) {
TypeMirror boxedType = InternalUtils.typeOf(expr);
- TypeElement boxedElement = (TypeElement)((DeclaredType)boxedType).asElement();
+ TypeElement boxedElement = (TypeElement) ((DeclaredType) boxedType).asElement();
assert TypesUtils.isBoxedPrimitive(boxedType);
TypeMirror unboxedType = modelTypes.unboxedType(boxedType);
@@ -481,207 +454,202 @@ public class TreeBuilder {
Symbol.MethodSymbol primValueMethod = null;
for (ExecutableElement method :
- ElementFilter.methodsIn(elements.getAllMembers(boxedElement))) {
+ ElementFilter.methodsIn(elements.getAllMembers(boxedElement))) {
Name methodName = method.getSimpleName();
- if (methodName.contentEquals(primValueName) &&
- method.getParameters().size() == 0) {
- primValueMethod = (Symbol.MethodSymbol)method;
+ if (methodName.contentEquals(primValueName) && method.getParameters().size() == 0) {
+ primValueMethod = (Symbol.MethodSymbol) method;
}
}
assert primValueMethod != null : "no *Value method declared for boxed type";
- Type.MethodType methodType = (Type.MethodType)primValueMethod.asType();
+ Type.MethodType methodType = (Type.MethodType) primValueMethod.asType();
JCTree.JCFieldAccess primValueAccess =
- (JCTree.JCFieldAccess)
- maker.Select((JCTree.JCExpression)expr, primValueMethod);
+ (JCTree.JCFieldAccess) maker.Select((JCTree.JCExpression) expr, primValueMethod);
primValueAccess.setType(methodType);
return primValueAccess;
}
- /**
- * Map public AST Tree.Kinds to internal javac JCTree.Tags.
- */
+ /** Map public AST Tree.Kinds to internal javac JCTree.Tags. */
public JCTree.Tag kindToTag(Tree.Kind kind) {
switch (kind) {
- case AND:
- return JCTree.Tag.BITAND;
- case AND_ASSIGNMENT:
- return JCTree.Tag.BITAND_ASG;
- case ANNOTATION:
- return JCTree.Tag.ANNOTATION;
- case ANNOTATION_TYPE:
- return JCTree.Tag.TYPE_ANNOTATION;
- case ARRAY_ACCESS:
- return JCTree.Tag.INDEXED;
- case ARRAY_TYPE:
- return JCTree.Tag.TYPEARRAY;
- case ASSERT:
- return JCTree.Tag.ASSERT;
- case ASSIGNMENT:
- return JCTree.Tag.ASSIGN;
- case BITWISE_COMPLEMENT:
- return JCTree.Tag.COMPL;
- case BLOCK:
- return JCTree.Tag.BLOCK;
- case BREAK:
- return JCTree.Tag.BREAK;
- case CASE:
- return JCTree.Tag.CASE;
- case CATCH:
- return JCTree.Tag.CATCH;
- case CLASS:
- return JCTree.Tag.CLASSDEF;
- case CONDITIONAL_AND:
- return JCTree.Tag.AND;
- case CONDITIONAL_EXPRESSION:
- return JCTree.Tag.CONDEXPR;
- case CONDITIONAL_OR:
- return JCTree.Tag.OR;
- case CONTINUE:
- return JCTree.Tag.CONTINUE;
- case DIVIDE:
- return JCTree.Tag.DIV;
- case DIVIDE_ASSIGNMENT:
- return JCTree.Tag.DIV_ASG;
- case DO_WHILE_LOOP:
- return JCTree.Tag.DOLOOP;
- case ENHANCED_FOR_LOOP:
- return JCTree.Tag.FOREACHLOOP;
- case EQUAL_TO:
- return JCTree.Tag.EQ;
- case EXPRESSION_STATEMENT:
- return JCTree.Tag.EXEC;
- case FOR_LOOP:
- return JCTree.Tag.FORLOOP;
- case GREATER_THAN:
- return JCTree.Tag.GT;
- case GREATER_THAN_EQUAL:
- return JCTree.Tag.GE;
- case IDENTIFIER:
- return JCTree.Tag.IDENT;
- case IF:
- return JCTree.Tag.IF;
- case IMPORT:
- return JCTree.Tag.IMPORT;
- case INSTANCE_OF:
- return JCTree.Tag.TYPETEST;
- case LABELED_STATEMENT:
- return JCTree.Tag.LABELLED;
- case LEFT_SHIFT:
- return JCTree.Tag.SL;
- case LEFT_SHIFT_ASSIGNMENT:
- return JCTree.Tag.SL_ASG;
- case LESS_THAN:
- return JCTree.Tag.LT;
- case LESS_THAN_EQUAL:
- return JCTree.Tag.LE;
- case LOGICAL_COMPLEMENT:
- return JCTree.Tag.NOT;
- case MEMBER_SELECT:
- return JCTree.Tag.SELECT;
- case METHOD:
- return JCTree.Tag.METHODDEF;
- case METHOD_INVOCATION:
- return JCTree.Tag.APPLY;
- case MINUS:
- return JCTree.Tag.MINUS;
- case MINUS_ASSIGNMENT:
- return JCTree.Tag.MINUS_ASG;
- case MODIFIERS:
- return JCTree.Tag.MODIFIERS;
- case MULTIPLY:
- return JCTree.Tag.MUL;
- case MULTIPLY_ASSIGNMENT:
- return JCTree.Tag.MUL_ASG;
- case NEW_ARRAY:
- return JCTree.Tag.NEWARRAY;
- case NEW_CLASS:
- return JCTree.Tag.NEWCLASS;
- case NOT_EQUAL_TO:
- return JCTree.Tag.NE;
- case OR:
- return JCTree.Tag.BITOR;
- case OR_ASSIGNMENT:
- return JCTree.Tag.BITOR_ASG;
- case PARENTHESIZED:
- return JCTree.Tag.PARENS;
- case PLUS:
- return JCTree.Tag.PLUS;
- case PLUS_ASSIGNMENT:
- return JCTree.Tag.PLUS_ASG;
- case POSTFIX_DECREMENT:
- return JCTree.Tag.POSTDEC;
- case POSTFIX_INCREMENT:
- return JCTree.Tag.POSTINC;
- case PREFIX_DECREMENT:
- return JCTree.Tag.PREDEC;
- case PREFIX_INCREMENT:
- return JCTree.Tag.PREINC;
- case REMAINDER:
- return JCTree.Tag.MOD;
- case REMAINDER_ASSIGNMENT:
- return JCTree.Tag.MOD_ASG;
- case RETURN:
- return JCTree.Tag.RETURN;
- case RIGHT_SHIFT:
- return JCTree.Tag.SR;
- case RIGHT_SHIFT_ASSIGNMENT:
- return JCTree.Tag.SR_ASG;
- case SWITCH:
- return JCTree.Tag.SWITCH;
- case SYNCHRONIZED:
- return JCTree.Tag.SYNCHRONIZED;
- case THROW:
- return JCTree.Tag.THROW;
- case TRY:
- return JCTree.Tag.TRY;
- case TYPE_CAST:
- return JCTree.Tag.TYPECAST;
- case TYPE_PARAMETER:
- return JCTree.Tag.TYPEPARAMETER;
- case UNARY_MINUS:
- return JCTree.Tag.NEG;
- case UNARY_PLUS:
- return JCTree.Tag.POS;
- case UNION_TYPE:
- return JCTree.Tag.TYPEUNION;
- case UNSIGNED_RIGHT_SHIFT:
- return JCTree.Tag.USR;
- case UNSIGNED_RIGHT_SHIFT_ASSIGNMENT:
- return JCTree.Tag.USR_ASG;
- case VARIABLE:
- return JCTree.Tag.VARDEF;
- case WHILE_LOOP:
- return JCTree.Tag.WHILELOOP;
- case XOR:
- return JCTree.Tag.BITXOR;
- case XOR_ASSIGNMENT:
- return JCTree.Tag.BITXOR_ASG;
- default:
- return JCTree.Tag.NO_TAG;
+ case AND:
+ return JCTree.Tag.BITAND;
+ case AND_ASSIGNMENT:
+ return JCTree.Tag.BITAND_ASG;
+ case ANNOTATION:
+ return JCTree.Tag.ANNOTATION;
+ case ANNOTATION_TYPE:
+ return JCTree.Tag.TYPE_ANNOTATION;
+ case ARRAY_ACCESS:
+ return JCTree.Tag.INDEXED;
+ case ARRAY_TYPE:
+ return JCTree.Tag.TYPEARRAY;
+ case ASSERT:
+ return JCTree.Tag.ASSERT;
+ case ASSIGNMENT:
+ return JCTree.Tag.ASSIGN;
+ case BITWISE_COMPLEMENT:
+ return JCTree.Tag.COMPL;
+ case BLOCK:
+ return JCTree.Tag.BLOCK;
+ case BREAK:
+ return JCTree.Tag.BREAK;
+ case CASE:
+ return JCTree.Tag.CASE;
+ case CATCH:
+ return JCTree.Tag.CATCH;
+ case CLASS:
+ return JCTree.Tag.CLASSDEF;
+ case CONDITIONAL_AND:
+ return JCTree.Tag.AND;
+ case CONDITIONAL_EXPRESSION:
+ return JCTree.Tag.CONDEXPR;
+ case CONDITIONAL_OR:
+ return JCTree.Tag.OR;
+ case CONTINUE:
+ return JCTree.Tag.CONTINUE;
+ case DIVIDE:
+ return JCTree.Tag.DIV;
+ case DIVIDE_ASSIGNMENT:
+ return JCTree.Tag.DIV_ASG;
+ case DO_WHILE_LOOP:
+ return JCTree.Tag.DOLOOP;
+ case ENHANCED_FOR_LOOP:
+ return JCTree.Tag.FOREACHLOOP;
+ case EQUAL_TO:
+ return JCTree.Tag.EQ;
+ case EXPRESSION_STATEMENT:
+ return JCTree.Tag.EXEC;
+ case FOR_LOOP:
+ return JCTree.Tag.FORLOOP;
+ case GREATER_THAN:
+ return JCTree.Tag.GT;
+ case GREATER_THAN_EQUAL:
+ return JCTree.Tag.GE;
+ case IDENTIFIER:
+ return JCTree.Tag.IDENT;
+ case IF:
+ return JCTree.Tag.IF;
+ case IMPORT:
+ return JCTree.Tag.IMPORT;
+ case INSTANCE_OF:
+ return JCTree.Tag.TYPETEST;
+ case LABELED_STATEMENT:
+ return JCTree.Tag.LABELLED;
+ case LEFT_SHIFT:
+ return JCTree.Tag.SL;
+ case LEFT_SHIFT_ASSIGNMENT:
+ return JCTree.Tag.SL_ASG;
+ case LESS_THAN:
+ return JCTree.Tag.LT;
+ case LESS_THAN_EQUAL:
+ return JCTree.Tag.LE;
+ case LOGICAL_COMPLEMENT:
+ return JCTree.Tag.NOT;
+ case MEMBER_SELECT:
+ return JCTree.Tag.SELECT;
+ case METHOD:
+ return JCTree.Tag.METHODDEF;
+ case METHOD_INVOCATION:
+ return JCTree.Tag.APPLY;
+ case MINUS:
+ return JCTree.Tag.MINUS;
+ case MINUS_ASSIGNMENT:
+ return JCTree.Tag.MINUS_ASG;
+ case MODIFIERS:
+ return JCTree.Tag.MODIFIERS;
+ case MULTIPLY:
+ return JCTree.Tag.MUL;
+ case MULTIPLY_ASSIGNMENT:
+ return JCTree.Tag.MUL_ASG;
+ case NEW_ARRAY:
+ return JCTree.Tag.NEWARRAY;
+ case NEW_CLASS:
+ return JCTree.Tag.NEWCLASS;
+ case NOT_EQUAL_TO:
+ return JCTree.Tag.NE;
+ case OR:
+ return JCTree.Tag.BITOR;
+ case OR_ASSIGNMENT:
+ return JCTree.Tag.BITOR_ASG;
+ case PARENTHESIZED:
+ return JCTree.Tag.PARENS;
+ case PLUS:
+ return JCTree.Tag.PLUS;
+ case PLUS_ASSIGNMENT:
+ return JCTree.Tag.PLUS_ASG;
+ case POSTFIX_DECREMENT:
+ return JCTree.Tag.POSTDEC;
+ case POSTFIX_INCREMENT:
+ return JCTree.Tag.POSTINC;
+ case PREFIX_DECREMENT:
+ return JCTree.Tag.PREDEC;
+ case PREFIX_INCREMENT:
+ return JCTree.Tag.PREINC;
+ case REMAINDER:
+ return JCTree.Tag.MOD;
+ case REMAINDER_ASSIGNMENT:
+ return JCTree.Tag.MOD_ASG;
+ case RETURN:
+ return JCTree.Tag.RETURN;
+ case RIGHT_SHIFT:
+ return JCTree.Tag.SR;
+ case RIGHT_SHIFT_ASSIGNMENT:
+ return JCTree.Tag.SR_ASG;
+ case SWITCH:
+ return JCTree.Tag.SWITCH;
+ case SYNCHRONIZED:
+ return JCTree.Tag.SYNCHRONIZED;
+ case THROW:
+ return JCTree.Tag.THROW;
+ case TRY:
+ return JCTree.Tag.TRY;
+ case TYPE_CAST:
+ return JCTree.Tag.TYPECAST;
+ case TYPE_PARAMETER:
+ return JCTree.Tag.TYPEPARAMETER;
+ case UNARY_MINUS:
+ return JCTree.Tag.NEG;
+ case UNARY_PLUS:
+ return JCTree.Tag.POS;
+ case UNION_TYPE:
+ return JCTree.Tag.TYPEUNION;
+ case UNSIGNED_RIGHT_SHIFT:
+ return JCTree.Tag.USR;
+ case UNSIGNED_RIGHT_SHIFT_ASSIGNMENT:
+ return JCTree.Tag.USR_ASG;
+ case VARIABLE:
+ return JCTree.Tag.VARDEF;
+ case WHILE_LOOP:
+ return JCTree.Tag.WHILELOOP;
+ case XOR:
+ return JCTree.Tag.BITXOR;
+ case XOR_ASSIGNMENT:
+ return JCTree.Tag.BITXOR_ASG;
+ default:
+ return JCTree.Tag.NO_TAG;
}
}
/**
* Builds an AST Tree to perform a binary operation.
*
- * @param type result type of the operation
- * @param op AST Tree operator
- * @param left the left operand tree
- * @param right the right operand tree
- * @return a Tree representing "left &lt; right"
+ * @param type result type of the operation
+ * @param op AST Tree operator
+ * @param left the left operand tree
+ * @param right the right operand tree
+ * @return a Tree representing "left &lt; right"
*/
- public BinaryTree buildBinary(TypeMirror type, Tree.Kind op, ExpressionTree left, ExpressionTree right) {
+ public BinaryTree buildBinary(
+ TypeMirror type, Tree.Kind op, ExpressionTree left, ExpressionTree right) {
JCTree.Tag jcOp = kindToTag(op);
JCTree.JCBinary binary =
- maker.Binary(jcOp, (JCTree.JCExpression)left,
- (JCTree.JCExpression)right);
- binary.setType((Type)type);
+ maker.Binary(jcOp, (JCTree.JCExpression) left, (JCTree.JCExpression) right);
+ binary.setType((Type) type);
return binary;
}
-
}
diff --git a/third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/trees/TreeParser.java b/third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/trees/TreeParser.java
index ea7f67f69e..9ea545e55c 100644
--- a/third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/trees/TreeParser.java
+++ b/third_party/checker_framework_javacutil/java/org/checkerframework/javacutil/trees/TreeParser.java
@@ -1,9 +1,5 @@
package org.checkerframework.javacutil.trees;
-import java.util.StringTokenizer;
-
-import javax.annotation.processing.ProcessingEnvironment;
-
import com.sun.source.tree.ExpressionTree;
import com.sun.tools.javac.processing.JavacProcessingEnvironment;
import com.sun.tools.javac.tree.JCTree.JCExpression;
@@ -12,27 +8,28 @@ import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.List;
import com.sun.tools.javac.util.ListBuffer;
import com.sun.tools.javac.util.Names;
+import java.util.StringTokenizer;
+import javax.annotation.processing.ProcessingEnvironment;
/**
- * A Utility class for parsing Java expression snippets, and converting them
- * to proper Javac AST nodes.
+ * A Utility class for parsing Java expression snippets, and converting them to proper Javac AST
+ * nodes.
+ *
+ * <p>This is useful for parsing {@code EnsuresNonNull*}, and {@code KeyFor} values.
*
- * This is useful for parsing {@code EnsuresNonNull*},
- * and {@code KeyFor} values.
+ * <p>Currently, it handles four tree types only:
*
- * Currently, it handles four tree types only:
* <ul>
- * <li>Identifier tree (e.g. {@code id})</li>
- * <li>Literal tree (e.g. 2, 3)</li>
- * <li>Method invocation tree (e.g. {@code method(2, 3)})</li>
- * <li>Member select tree (e.g. {@code Class.field}, {@code instance.method()})
- * <li>Array access tree (e.g. {@code array[id]})</li>
+ * <li>Identifier tree (e.g. {@code id})
+ * <li>Literal tree (e.g. 2, 3)
+ * <li>Method invocation tree (e.g. {@code method(2, 3)})
+ * <li>Member select tree (e.g. {@code Class.field}, {@code instance.method()})
+ * <li>Array access tree (e.g. {@code array[id]})
* </ul>
*
- * Notable limitation: Doesn't handle spaces, or non-method-argument
- * parenthesis.
+ * Notable limitation: Doesn't handle spaces, or non-method-argument parenthesis.
*
- * It's implemented via a Recursive-Descend parser.
+ * <p>It's implemented via a Recursive-Descend parser.
*/
public class TreeParser {
private static final String DELIMS = ".[](),";
@@ -42,17 +39,16 @@ public class TreeParser {
private final Names names;
public TreeParser(ProcessingEnvironment env) {
- Context context = ((JavacProcessingEnvironment)env).getContext();
+ Context context = ((JavacProcessingEnvironment) env).getContext();
maker = TreeMaker.instance(context);
names = Names.instance(context);
}
/**
- * Parses the snippet in the string as an internal Javac AST expression
- * node
+ * Parses the snippet in the string as an internal Javac AST expression node
*
* @param s the java snippet
- * @return the AST corresponding to the snippet
+ * @return the AST corresponding to the snippet
*/
public ExpressionTree parseTree(String s) {
tokenizer = new StringTokenizer(s, DELIMS, true);
@@ -84,15 +80,19 @@ public class TreeParser {
return maker.Literal(false);
}
- if (Character.isLetter(token.charAt(0)))
+ if (Character.isLetter(token.charAt(0))) {
return maker.Ident(names.fromString(token));
+ }
Object value = null;
try {
value = Integer.valueOf(token);
- } catch (Exception e2) { try {
- value = Double.valueOf(token);
- } catch (Exception ef) {}}
+ } catch (Exception e2) {
+ try {
+ value = Double.valueOf(token);
+ } catch (Exception ef) {
+ }
+ }
assert value != null;
return maker.Literal(value);
}
@@ -104,21 +104,20 @@ public class TreeParser {
String delim = nextToken();
if (".".equals(delim)) {
nextToken();
- tree = maker.Select(tree,
- names.fromString(token));
+ tree = maker.Select(tree, names.fromString(token));
} else if ("(".equals(delim)) {
nextToken();
ListBuffer<JCExpression> args = new ListBuffer<>();
while (!")".equals(token)) {
JCExpression arg = parseExpression();
args.append(arg);
- if (",".equals(token))
+ if (",".equals(token)) {
nextToken();
+ }
}
// For now, handle empty args only
assert ")".equals(token);
- tree = maker.Apply(List.<JCExpression>nil(),
- tree, args.toList());
+ tree = maker.Apply(List.<JCExpression>nil(), tree, args.toList());
} else if ("[".equals(token)) {
nextToken();
JCExpression index = parseExpression();
@@ -132,7 +131,7 @@ public class TreeParser {
return tree;
}
- class ParseError extends RuntimeException {
+ private static class ParseError extends RuntimeException {
private static final long serialVersionUID = 1887754619522101929L;
ParseError(Throwable cause) {