Skip to content

Commit d59282a

Browse files
authored
Avoid reading type info from trees that are not being processed (#385)
1 parent d6c7e61 commit d59282a

File tree

6 files changed

+62
-47
lines changed

6 files changed

+62
-47
lines changed

src/checkers/inference/DefaultSlotManager.java

Lines changed: 36 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
package checkers.inference;
22

33
import checkers.inference.util.SlotDefaultTypeResolver;
4+
import com.sun.source.tree.ClassTree;
45
import com.sun.source.tree.CompilationUnitTree;
56
import com.sun.source.tree.Tree;
7+
import com.sun.source.util.TreePath;
68
import com.sun.tools.javac.code.Symbol;
79
import org.checkerframework.checker.nullness.qual.Nullable;
810
import org.checkerframework.common.basetype.BaseAnnotatedTypeFactory;
@@ -11,6 +13,7 @@
1113
import org.checkerframework.javacutil.AnnotationBuilder;
1214
import org.checkerframework.javacutil.AnnotationUtils;
1315
import org.checkerframework.javacutil.BugInCF;
16+
import org.checkerframework.javacutil.TreeUtils;
1417
import org.checkerframework.javacutil.TypeKindUtils;
1518
import org.checkerframework.javacutil.TypesUtils;
1619

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

208+
@Override
209+
public void setTopLevelClass(ClassTree classTree) {
210+
// If the top level has changed, we refresh our cache with the new scope.
211+
defaultAnnotationsCache.clear();
212+
213+
Map<Tree, AnnotatedTypeMirror> defaultTypes = SlotDefaultTypeResolver.resolve(
214+
classTree,
215+
InferenceMain.getInstance().getRealTypeFactory()
216+
);
217+
218+
// find default types in the current hierarchy and save them to the cache
219+
for (Map.Entry<Tree, AnnotatedTypeMirror> entry : defaultTypes.entrySet()) {
220+
defaultAnnotationsCache.put(
221+
entry.getKey(),
222+
entry.getValue().getAnnotationInHierarchy(this.realTop)
223+
);
224+
}
225+
}
226+
205227
/**
206228
* Returns the next unique variable id. These id's are monotonically increasing.
207229
* @return the next variable id to be used in VariableCreation
@@ -347,25 +369,6 @@ public int getNumberOfSlots() {
347369
return nextId - 1;
348370
}
349371

350-
@Override
351-
public void setRoot(CompilationUnitTree compilationUnit) {
352-
this.defaultAnnotationsCache.clear();
353-
354-
BaseAnnotatedTypeFactory realTypeFactory = InferenceMain.getInstance().getRealTypeFactory();
355-
Map<Tree, AnnotatedTypeMirror> defaultTypes = SlotDefaultTypeResolver.resolve(
356-
compilationUnit,
357-
realTypeFactory
358-
);
359-
360-
for (Map.Entry<Tree, AnnotatedTypeMirror> entry : defaultTypes.entrySet()) {
361-
// find default types in the current hierarchy and save them to the cache
362-
this.defaultAnnotationsCache.put(
363-
entry.getKey(),
364-
entry.getValue().getAnnotationInHierarchy(this.realTop)
365-
);
366-
}
367-
}
368-
369372
@Override
370373
public SourceVariableSlot createSourceVariableSlot(AnnotationLocation location, TypeMirror type) {
371374
AnnotationMirror defaultAnnotation = null;
@@ -424,13 +427,20 @@ public SourceVariableSlot createSourceVariableSlot(AnnotationLocation location,
424427
throw new BugInCF("Unable to find default annotation for location " + location);
425428
}
426429

427-
AnnotationMirror realAnnotation = null;
428-
if (tree != null) {
429-
realAnnotation = this.defaultAnnotationsCache.get(tree);
430-
if (realAnnotation == null) {
431-
// If its default type can't be found in the cache, we can
432-
// fallback to the simplest method.
433-
realAnnotation = realTypeFactory.getAnnotatedType(tree).getAnnotationInHierarchy(this.realTop);
430+
AnnotationMirror realAnnotation = defaultAnnotationsCache.get(tree);
431+
if (tree != null && realAnnotation == null) {
432+
// If its default type can't be found in the cache, we can
433+
// fallback to the simplest method.
434+
// TODO: If the tree is not under the current top-level tree
435+
// that's being processed, the type factory may crash due
436+
// to lack of information. We may want to investigate if
437+
// this issue ever happens.
438+
if (TreeUtils.isTypeTree(tree)) {
439+
realAnnotation = realTypeFactory.getAnnotatedTypeFromTypeTree(tree)
440+
.getAnnotationInHierarchy(this.realTop);
441+
} else {
442+
realAnnotation = realTypeFactory.getAnnotatedType(tree)
443+
.getAnnotationInHierarchy(this.realTop);
434444
}
435445
}
436446
return realAnnotation;

src/checkers/inference/InferenceAnnotatedTypeFactory.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import checkers.inference.model.ConstantSlot;
44
import checkers.inference.model.Slot;
5+
import com.sun.source.util.TreePath;
56
import org.checkerframework.common.basetype.BaseAnnotatedTypeFactory;
67
import org.checkerframework.framework.flow.CFAbstractAnalysis;
78
import org.checkerframework.framework.flow.CFAnalysis;
@@ -536,7 +537,6 @@ public void addComputedTypeAnnotations(final Element element, final AnnotatedTyp
536537
treeAnnotator.visit(declaration, type);
537538
} else {
538539
bytecodeTypeAnnotator.annotate(element, type);
539-
540540
}
541541
}
542542
}
@@ -550,7 +550,6 @@ public void setRoot(final CompilationUnitTree root) {
550550
compilationUnitsHandled += 1;
551551
this.realTypeFactory.setRoot( root );
552552
this.variableAnnotator.clearTreeInfo();
553-
this.slotManager.setRoot(root);
554553
super.setRoot(root);
555554
}
556555

src/checkers/inference/InferenceChecker.java

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
package checkers.inference;
22

3-
import java.util.Properties;
4-
53
import org.checkerframework.common.basetype.BaseTypeChecker;
64
import org.checkerframework.common.basetype.BaseTypeVisitor;
75

@@ -23,13 +21,4 @@ public void initChecker() {
2321
protected BaseTypeVisitor<?> createSourceVisitor() {
2422
return null;
2523
}
26-
27-
@Override
28-
public Properties getMessagesProperties() {
29-
// Add the messages.properties file defined in the same location as
30-
// InferenceChecker
31-
Properties messages = super.getMessagesProperties();
32-
messages.putAll(getProperties(this.getClass(), MSGS_FILE, true));
33-
return messages;
34-
}
3524
}

src/checkers/inference/InferenceVisitor.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package checkers.inference;
22

3+
import com.sun.source.tree.ClassTree;
4+
import com.sun.source.util.TreePath;
35
import org.checkerframework.checker.compilermsgs.qual.CompilerMessageKey;
46
import org.checkerframework.common.basetype.BaseAnnotatedTypeFactory;
57
import org.checkerframework.common.basetype.BaseTypeVisitor;
@@ -61,7 +63,7 @@
6163
* That is, the methods from BaseTypeVisiotr should be migrated here and InferenceVisitor
6264
* should replace it in the Visitor hierarchy.
6365
*/
64-
// TODO(Zhiping): new logics from BaseTypeVisiotr should be migrated here
66+
// TODO(Zhiping): new logics from BaseTypeVisitor should be migrated here
6567
public class InferenceVisitor<Checker extends InferenceChecker,
6668
Factory extends BaseAnnotatedTypeFactory>
6769
extends BaseTypeVisitor<Factory> {
@@ -90,6 +92,15 @@ protected Factory createTypeFactory() {
9092
return (Factory)((BaseInferrableChecker)checker).getTypeFactory();
9193
}
9294

95+
@Override
96+
public void visit(TreePath path) {
97+
if (infer) {
98+
final SlotManager slotManager = InferenceMain.getInstance().getSlotManager();
99+
slotManager.setTopLevelClass((ClassTree) path.getLeaf());
100+
}
101+
super.visit(path);
102+
}
103+
93104
public void doesNotContain(AnnotatedTypeMirror ty, AnnotationMirror mod, String msgkey, Tree node) {
94105
doesNotContain(ty, new AnnotationMirror[] {mod}, msgkey, node);
95106
}

src/checkers/inference/SlotManager.java

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package checkers.inference;
22

33
import checkers.inference.model.LubVariableSlot;
4+
import com.sun.source.tree.ClassTree;
45
import com.sun.source.tree.CompilationUnitTree;
56
import org.checkerframework.framework.type.AnnotatedTypeMirror;
67

@@ -221,10 +222,13 @@ ArithmeticVariableSlot createArithmeticVariableSlot(
221222
List<ConstantSlot> getConstantSlots();
222223

223224
/**
224-
* Informs this manager that we are working on a new file, so
225-
* it can preprocess and cache useful information.
225+
* This method informs slot manager of the current top level class tree that's being type processed.
226+
* Slot manager can then preprocess this information by clearing caches, resolving slot default
227+
* types, etc.
226228
*
227-
* @param compilationUnit the current compilation tree
229+
* Note that trees that are not within this tree may be missing some information
230+
* (in the JCTree implementation), and this is because they are either not fully
231+
* initialized or being garbage-recycled.
228232
*/
229-
void setRoot(CompilationUnitTree compilationUnit);
233+
void setTopLevelClass(ClassTree classTree);
230234
}

src/checkers/inference/util/SlotDefaultTypeResolver.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
import com.sun.source.tree.AnnotatedTypeTree;
44
import com.sun.source.tree.ArrayTypeTree;
55
import com.sun.source.tree.ClassTree;
6-
import com.sun.source.tree.CompilationUnitTree;
76
import com.sun.source.tree.ParameterizedTypeTree;
87
import com.sun.source.tree.PrimitiveTypeTree;
98
import com.sun.source.tree.Tree;
@@ -38,11 +37,11 @@
3837
public class SlotDefaultTypeResolver {
3938

4039
public static Map<Tree, AnnotatedTypeMirror> resolve(
41-
CompilationUnitTree root,
40+
ClassTree classTree,
4241
BaseAnnotatedTypeFactory realTypeFactory
4342
) {
4443
DefaultTypeFinder finder = new DefaultTypeFinder(realTypeFactory);
45-
finder.scan(root, null);
44+
finder.scan(classTree, null);
4645

4746
return finder.defaultTypes;
4847
}
@@ -89,6 +88,9 @@ private AnnotatedTypeMirror getDefaultTypeFor(Tree tree) {
8988

9089
@Override
9190
public Void visitClass(ClassTree tree, Void unused) {
91+
// stores the default type of the class tree
92+
getDefaultTypeFor(tree);
93+
9294
Tree ext = tree.getExtendsClause();
9395
if (ext != null) {
9496
defaultTypes.put(ext, realTypeFactory.getTypeOfExtendsImplements(ext));

0 commit comments

Comments
 (0)