forked from opprop/checker-framework-inference
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathRefValInferenceTreeAnnotator.java
More file actions
155 lines (135 loc) · 6.46 KB
/
Copy pathRefValInferenceTreeAnnotator.java
File metadata and controls
155 lines (135 loc) · 6.46 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
package refval;
import org.checkerframework.framework.type.AnnotatedTypeFactory;
import org.checkerframework.framework.type.AnnotatedTypeMirror;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedArrayType;
import org.checkerframework.javacutil.AnnotationBuilder;
import org.checkerframework.javacutil.ElementUtils;
import org.checkerframework.javacutil.TreeUtils;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import checkers.inference.InferenceAnnotatedTypeFactory;
import checkers.inference.InferenceMain;
import checkers.inference.InferenceTreeAnnotator;
import checkers.inference.InferrableChecker;
import checkers.inference.SlotManager;
import checkers.inference.VariableAnnotator;
import checkers.inference.model.ConstantSlot;
import checkers.inference.qual.VarAnnot;
import com.sun.source.tree.LiteralTree;
import com.sun.source.tree.MethodInvocationTree;
import com.sun.source.tree.NewArrayTree;
import com.sun.source.tree.NewClassTree;
import com.sun.source.tree.ParameterizedTypeTree;
import com.sun.source.tree.Tree;
import com.sun.source.tree.Tree.Kind;
import com.sun.source.util.TreePath;
import refval.util.RefValUtils;
/**
* RefValInferenceTreeAnnotator creates constant slot for base cases.
*
* @author jianchu
*
*/
public class RefValInferenceTreeAnnotator extends InferenceTreeAnnotator {
private final VariableAnnotator variableAnnotator;
private final AnnotatedTypeFactory realTypeFactory;
private final SlotManager slotManager;
public RefValInferenceTreeAnnotator(InferenceAnnotatedTypeFactory atypeFactory,
InferrableChecker realChecker, AnnotatedTypeFactory realAnnotatedTypeFactory,
VariableAnnotator variableAnnotator, SlotManager slotManager) {
super(atypeFactory, realChecker, realAnnotatedTypeFactory, variableAnnotator, slotManager);
this.variableAnnotator = variableAnnotator;
this.realTypeFactory = realAnnotatedTypeFactory;
this.slotManager = InferenceMain.getInstance().getSlotManager();
}
@Override
public Void visitLiteral(final LiteralTree literalTree, final AnnotatedTypeMirror atm) {
if (!literalTree.getKind().equals(Kind.NULL_LITERAL)) {
AnnotationMirror anno = RefValUtils.generateRefValAnnoFromLiteral(literalTree,
this.realTypeFactory.getProcessingEnv());
replaceATM(atm, anno);
} else {
super.visitLiteral(literalTree, atm);
}
return null;
}
@Override
public Void visitNewClass(final NewClassTree newClassTree, final AnnotatedTypeMirror atm) {
TypeMirror tm = atm.getUnderlyingType();
((RefValAnnotatedTypeFactory) this.realTypeFactory).getTypeNameMap().put(tm.toString(), tm);
AnnotationMirror anno = RefValUtils.generateRefValAnnoFromNewClass(atm,
this.realTypeFactory.getProcessingEnv());
replaceATM(atm, anno);
variableAnnotator.visit(atm, newClassTree.getIdentifier());
return null;
}
@Override
public Void visitParameterizedType(final ParameterizedTypeTree param, final AnnotatedTypeMirror atm) {
TreePath path = atypeFactory.getPath(param);
if (path != null) {
final TreePath parentPath = path.getParentPath();
final Tree parentNode = parentPath.getLeaf();
if (!parentNode.getKind().equals(Kind.NEW_CLASS)) {
variableAnnotator.visit(atm, param);
}
}
return null;
}
@Override
public Void visitNewArray(final NewArrayTree newArrayTree, final AnnotatedTypeMirror atm) {
TypeMirror tm = atm.getUnderlyingType();
((RefValAnnotatedTypeFactory) this.realTypeFactory).getTypeNameMap().put(tm.toString(), tm);
AnnotationMirror anno = RefValUtils.generateRefValAnnoFromNewClass(atm,
this.realTypeFactory.getProcessingEnv());
replaceATM(atm, anno);
return null;
}
@Override
public Void visitMethodInvocation(MethodInvocationTree methodInvocationTree,
final AnnotatedTypeMirror atm) {
ExecutableElement methodElement = TreeUtils.elementFromUse(methodInvocationTree);
boolean isBytecode = ElementUtils.isElementFromByteCode(methodElement);
if (isBytecode) {
TypeMirror tm = atm.getUnderlyingType();
((RefValAnnotatedTypeFactory) this.realTypeFactory).getTypeNameMap()
.put(tm.toString(), tm);
AnnotationMirror anno = RefValUtils.generateRefValAnnoFromByteCode(atm,
this.realTypeFactory.getProcessingEnv());
if (atm.getKind() == TypeKind.ARRAY) {
// If the return type of a byte code method is Array type,
// also generated RefVal Annotation on Array component type.
replaceArrayComponentATM((AnnotatedArrayType) atm);
}
replaceATM(atm, anno);
return null;
} else {
return super.visitMethodInvocation(methodInvocationTree, atm);
}
}
private void replaceATM(AnnotatedTypeMirror atm, AnnotationMirror refValAM) {
final ConstantSlot cs = slotManager.createConstantSlot(refValAM);
AnnotationBuilder ab = new AnnotationBuilder(realTypeFactory.getProcessingEnv(), VarAnnot.class);
ab.setValue("value", cs.getId());
AnnotationMirror varAnno = ab.build();
atm.replaceAnnotation(varAnno);
}
/**
* Add the bytecode default RefVal annotation for component type of the given {@link AnnotatedArrayType}.
*
* <p> For multi-dimensional array, this method will recursively add bytecode default RefVal annotation to array's component type.
*
* @param arrayAtm the given {@link AnnotatedArrayType}, whose component type will be added the bytecode default.
*/
private void replaceArrayComponentATM(AnnotatedArrayType arrayAtm) {
AnnotatedTypeMirror componentAtm = arrayAtm.getComponentType();
AnnotationMirror componentAnno = RefValUtils.generateRefValAnnoFromByteCode(componentAtm,
this.realTypeFactory.getProcessingEnv());
replaceATM(componentAtm, componentAnno);
if (componentAtm.getKind() == TypeKind.ARRAY) {
// if component is also an array type, then recursively annotate its component also.
replaceArrayComponentATM((AnnotatedArrayType) componentAtm);
}
}
}