use of org.checkerframework.dataflow.expression.FieldAccess in project checker-framework by typetools.
the class GenericAnnotatedTypeFactory method performFlowAnalysis.
/**
* Perform a org.checkerframework.dataflow analysis over a single class tree and its nested
* classes.
*
* @param classTree the class to analyze
*/
protected void performFlowAnalysis(ClassTree classTree) {
if (flowResult == null) {
regularExitStores = new IdentityHashMap<>();
exceptionalExitStores = new IdentityHashMap<>();
returnStatementStores = new IdentityHashMap<>();
flowResult = new AnalysisResult<>(flowResultAnalysisCaches);
}
// no need to scan annotations
if (classTree.getKind() == Tree.Kind.ANNOTATION_TYPE) {
// Mark finished so that default annotations will be applied.
scannedClasses.put(classTree, ScanState.FINISHED);
return;
}
Queue<Pair<ClassTree, Store>> queue = new ArrayDeque<>();
List<FieldInitialValue<Value>> fieldValues = new ArrayList<>();
// No captured store for top-level classes.
queue.add(Pair.of(classTree, null));
while (!queue.isEmpty()) {
final Pair<ClassTree, Store> qel = queue.remove();
final ClassTree ct = qel.first;
final Store capturedStore = qel.second;
scannedClasses.put(ct, ScanState.IN_PROGRESS);
TreePath preTreePath = getVisitorTreePath();
// Don't use getPath, because that depends on the assignmentContext path.
setVisitorTreePath(TreePath.getPath(this.root, ct));
// start with the captured store as initialization store
initializationStaticStore = capturedStore;
initializationStore = capturedStore;
Queue<Pair<LambdaExpressionTree, Store>> lambdaQueue = new ArrayDeque<>();
try {
List<CFGMethod> methods = new ArrayList<>();
List<? extends Tree> members = ct.getMembers();
if (!Ordering.from(sortVariablesFirst).isOrdered(members)) {
members = new ArrayList<>(members);
// Process variables before methods, so all field initializers are observed before the
// constructor is analyzed and reports uninitialized variables.
members.sort(sortVariablesFirst);
}
for (Tree m : members) {
switch(TreeUtils.getKindRecordAsClass(m)) {
case METHOD:
MethodTree mt = (MethodTree) m;
// Skip abstract and native methods because they have no body.
Set<Modifier> flags = mt.getModifiers().getFlags();
if (flags.contains(Modifier.ABSTRACT) || flags.contains(Modifier.NATIVE)) {
break;
}
// ABSTRACT flag.
if (mt.getBody() == null) {
break;
}
// Wait with scanning the method until all other members
// have been processed.
CFGMethod met = new CFGMethod(mt, ct);
methods.add(met);
break;
case VARIABLE:
VariableTree vt = (VariableTree) m;
ExpressionTree initializer = vt.getInitializer();
AnnotatedTypeMirror declaredType = getAnnotatedTypeLhs(vt);
Value declaredValue = analysis.createAbstractValue(declaredType);
FieldAccess fieldExpr = (FieldAccess) JavaExpression.fromVariableTree(vt);
// analyze initializer if present
if (initializer != null) {
boolean isStatic = vt.getModifiers().getFlags().contains(Modifier.STATIC);
analyze(queue, lambdaQueue, new CFGStatement(vt, ct), fieldValues, classTree, true, true, isStatic, capturedStore);
Value initializerValue = flowResult.getValue(initializer);
if (initializerValue != null) {
fieldValues.add(new FieldInitialValue<>(fieldExpr, declaredValue, initializerValue));
break;
}
}
fieldValues.add(new FieldInitialValue<>(fieldExpr, declaredValue, null));
break;
// Including RECORD
case CLASS:
case ANNOTATION_TYPE:
case INTERFACE:
case ENUM:
// Visit inner and nested class trees.
// TODO: Use no store for them? What can be captured?
queue.add(Pair.of((ClassTree) m, capturedStore));
break;
case BLOCK:
BlockTree b = (BlockTree) m;
analyze(queue, lambdaQueue, new CFGStatement(b, ct), fieldValues, ct, true, true, b.isStatic(), capturedStore);
break;
default:
assert false : "Unexpected member: " + m.getKind();
break;
}
}
// fields of superclasses.
for (CFGMethod met : methods) {
analyze(queue, lambdaQueue, met, fieldValues, classTree, TreeUtils.isConstructor(met.getMethod()), false, false, capturedStore);
}
while (!lambdaQueue.isEmpty()) {
Pair<LambdaExpressionTree, Store> lambdaPair = lambdaQueue.poll();
MethodTree mt = (MethodTree) TreePathUtil.enclosingOfKind(getPath(lambdaPair.first), Tree.Kind.METHOD);
analyze(queue, lambdaQueue, new CFGLambda(lambdaPair.first, classTree, mt), fieldValues, classTree, false, false, false, lambdaPair.second);
}
// See InitializationVisitor.visitClass().
if (initializationStaticStore == null) {
regularExitStores.put(ct, emptyStore);
} else {
regularExitStores.put(ct, initializationStaticStore);
}
} finally {
setVisitorTreePath(preTreePath);
}
scannedClasses.put(ct, ScanState.FINISHED);
}
}
Aggregations