Skip to content

Commit

Permalink
Avoid reading type info from trees that are not being processed (#385)
Browse files Browse the repository at this point in the history
  • Loading branch information
zcai1 authored Mar 1, 2022
1 parent d6c7e61 commit d59282a
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 47 deletions.
62 changes: 36 additions & 26 deletions src/checkers/inference/DefaultSlotManager.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package checkers.inference;

import checkers.inference.util.SlotDefaultTypeResolver;
import com.sun.source.tree.ClassTree;
import com.sun.source.tree.CompilationUnitTree;
import com.sun.source.tree.Tree;
import com.sun.source.util.TreePath;
import com.sun.tools.javac.code.Symbol;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.checkerframework.common.basetype.BaseAnnotatedTypeFactory;
Expand All @@ -11,6 +13,7 @@
import org.checkerframework.javacutil.AnnotationBuilder;
import org.checkerframework.javacutil.AnnotationUtils;
import org.checkerframework.javacutil.BugInCF;
import org.checkerframework.javacutil.TreeUtils;
import org.checkerframework.javacutil.TypeKindUtils;
import org.checkerframework.javacutil.TypesUtils;

Expand Down Expand Up @@ -202,6 +205,25 @@ public int compare(Class<? extends Annotation> o1, Class<? extends Annotation> o
return set;
}

@Override
public void setTopLevelClass(ClassTree classTree) {
// If the top level has changed, we refresh our cache with the new scope.
defaultAnnotationsCache.clear();

Map<Tree, AnnotatedTypeMirror> defaultTypes = SlotDefaultTypeResolver.resolve(
classTree,
InferenceMain.getInstance().getRealTypeFactory()
);

// find default types in the current hierarchy and save them to the cache
for (Map.Entry<Tree, AnnotatedTypeMirror> entry : defaultTypes.entrySet()) {
defaultAnnotationsCache.put(
entry.getKey(),
entry.getValue().getAnnotationInHierarchy(this.realTop)
);
}
}

/**
* Returns the next unique variable id. These id's are monotonically increasing.
* @return the next variable id to be used in VariableCreation
Expand Down Expand Up @@ -347,25 +369,6 @@ public int getNumberOfSlots() {
return nextId - 1;
}

@Override
public void setRoot(CompilationUnitTree compilationUnit) {
this.defaultAnnotationsCache.clear();

BaseAnnotatedTypeFactory realTypeFactory = InferenceMain.getInstance().getRealTypeFactory();
Map<Tree, AnnotatedTypeMirror> defaultTypes = SlotDefaultTypeResolver.resolve(
compilationUnit,
realTypeFactory
);

for (Map.Entry<Tree, AnnotatedTypeMirror> entry : defaultTypes.entrySet()) {
// find default types in the current hierarchy and save them to the cache
this.defaultAnnotationsCache.put(
entry.getKey(),
entry.getValue().getAnnotationInHierarchy(this.realTop)
);
}
}

@Override
public SourceVariableSlot createSourceVariableSlot(AnnotationLocation location, TypeMirror type) {
AnnotationMirror defaultAnnotation = null;
Expand Down Expand Up @@ -424,13 +427,20 @@ public SourceVariableSlot createSourceVariableSlot(AnnotationLocation location,
throw new BugInCF("Unable to find default annotation for location " + location);
}

AnnotationMirror realAnnotation = null;
if (tree != null) {
realAnnotation = this.defaultAnnotationsCache.get(tree);
if (realAnnotation == null) {
// If its default type can't be found in the cache, we can
// fallback to the simplest method.
realAnnotation = realTypeFactory.getAnnotatedType(tree).getAnnotationInHierarchy(this.realTop);
AnnotationMirror realAnnotation = defaultAnnotationsCache.get(tree);
if (tree != null && realAnnotation == null) {
// If its default type can't be found in the cache, we can
// fallback to the simplest method.
// TODO: If the tree is not under the current top-level tree
// that's being processed, the type factory may crash due
// to lack of information. We may want to investigate if
// this issue ever happens.
if (TreeUtils.isTypeTree(tree)) {
realAnnotation = realTypeFactory.getAnnotatedTypeFromTypeTree(tree)
.getAnnotationInHierarchy(this.realTop);
} else {
realAnnotation = realTypeFactory.getAnnotatedType(tree)
.getAnnotationInHierarchy(this.realTop);
}
}
return realAnnotation;
Expand Down
3 changes: 1 addition & 2 deletions src/checkers/inference/InferenceAnnotatedTypeFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import checkers.inference.model.ConstantSlot;
import checkers.inference.model.Slot;
import com.sun.source.util.TreePath;
import org.checkerframework.common.basetype.BaseAnnotatedTypeFactory;
import org.checkerframework.framework.flow.CFAbstractAnalysis;
import org.checkerframework.framework.flow.CFAnalysis;
Expand Down Expand Up @@ -536,7 +537,6 @@ public void addComputedTypeAnnotations(final Element element, final AnnotatedTyp
treeAnnotator.visit(declaration, type);
} else {
bytecodeTypeAnnotator.annotate(element, type);

}
}
}
Expand All @@ -550,7 +550,6 @@ public void setRoot(final CompilationUnitTree root) {
compilationUnitsHandled += 1;
this.realTypeFactory.setRoot( root );
this.variableAnnotator.clearTreeInfo();
this.slotManager.setRoot(root);
super.setRoot(root);
}

Expand Down
11 changes: 0 additions & 11 deletions src/checkers/inference/InferenceChecker.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package checkers.inference;

import java.util.Properties;

import org.checkerframework.common.basetype.BaseTypeChecker;
import org.checkerframework.common.basetype.BaseTypeVisitor;

Expand All @@ -23,13 +21,4 @@ public void initChecker() {
protected BaseTypeVisitor<?> createSourceVisitor() {
return null;
}

@Override
public Properties getMessagesProperties() {
// Add the messages.properties file defined in the same location as
// InferenceChecker
Properties messages = super.getMessagesProperties();
messages.putAll(getProperties(this.getClass(), MSGS_FILE, true));
return messages;
}
}
13 changes: 12 additions & 1 deletion src/checkers/inference/InferenceVisitor.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package checkers.inference;

import com.sun.source.tree.ClassTree;
import com.sun.source.util.TreePath;
import org.checkerframework.checker.compilermsgs.qual.CompilerMessageKey;
import org.checkerframework.common.basetype.BaseAnnotatedTypeFactory;
import org.checkerframework.common.basetype.BaseTypeVisitor;
Expand Down Expand Up @@ -61,7 +63,7 @@
* That is, the methods from BaseTypeVisiotr should be migrated here and InferenceVisitor
* should replace it in the Visitor hierarchy.
*/
// TODO(Zhiping): new logics from BaseTypeVisiotr should be migrated here
// TODO(Zhiping): new logics from BaseTypeVisitor should be migrated here
public class InferenceVisitor<Checker extends InferenceChecker,
Factory extends BaseAnnotatedTypeFactory>
extends BaseTypeVisitor<Factory> {
Expand Down Expand Up @@ -90,6 +92,15 @@ protected Factory createTypeFactory() {
return (Factory)((BaseInferrableChecker)checker).getTypeFactory();
}

@Override
public void visit(TreePath path) {
if (infer) {
final SlotManager slotManager = InferenceMain.getInstance().getSlotManager();
slotManager.setTopLevelClass((ClassTree) path.getLeaf());
}
super.visit(path);
}

public void doesNotContain(AnnotatedTypeMirror ty, AnnotationMirror mod, String msgkey, Tree node) {
doesNotContain(ty, new AnnotationMirror[] {mod}, msgkey, node);
}
Expand Down
12 changes: 8 additions & 4 deletions src/checkers/inference/SlotManager.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package checkers.inference;

import checkers.inference.model.LubVariableSlot;
import com.sun.source.tree.ClassTree;
import com.sun.source.tree.CompilationUnitTree;
import org.checkerframework.framework.type.AnnotatedTypeMirror;

Expand Down Expand Up @@ -221,10 +222,13 @@ ArithmeticVariableSlot createArithmeticVariableSlot(
List<ConstantSlot> getConstantSlots();

/**
* Informs this manager that we are working on a new file, so
* it can preprocess and cache useful information.
* This method informs slot manager of the current top level class tree that's being type processed.
* Slot manager can then preprocess this information by clearing caches, resolving slot default
* types, etc.
*
* @param compilationUnit the current compilation tree
* Note that trees that are not within this tree may be missing some information
* (in the JCTree implementation), and this is because they are either not fully
* initialized or being garbage-recycled.
*/
void setRoot(CompilationUnitTree compilationUnit);
void setTopLevelClass(ClassTree classTree);
}
8 changes: 5 additions & 3 deletions src/checkers/inference/util/SlotDefaultTypeResolver.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import com.sun.source.tree.AnnotatedTypeTree;
import com.sun.source.tree.ArrayTypeTree;
import com.sun.source.tree.ClassTree;
import com.sun.source.tree.CompilationUnitTree;
import com.sun.source.tree.ParameterizedTypeTree;
import com.sun.source.tree.PrimitiveTypeTree;
import com.sun.source.tree.Tree;
Expand Down Expand Up @@ -38,11 +37,11 @@
public class SlotDefaultTypeResolver {

public static Map<Tree, AnnotatedTypeMirror> resolve(
CompilationUnitTree root,
ClassTree classTree,
BaseAnnotatedTypeFactory realTypeFactory
) {
DefaultTypeFinder finder = new DefaultTypeFinder(realTypeFactory);
finder.scan(root, null);
finder.scan(classTree, null);

return finder.defaultTypes;
}
Expand Down Expand Up @@ -89,6 +88,9 @@ private AnnotatedTypeMirror getDefaultTypeFor(Tree tree) {

@Override
public Void visitClass(ClassTree tree, Void unused) {
// stores the default type of the class tree
getDefaultTypeFor(tree);

Tree ext = tree.getExtendsClause();
if (ext != null) {
defaultTypes.put(ext, realTypeFactory.getTypeOfExtendsImplements(ext));
Expand Down

0 comments on commit d59282a

Please sign in to comment.