use of com.sun.source.tree.ClassTree in project checker-framework by typetools.
the class AnnotatedTypeFactory method fromElement.
// **********************************************************************
// Factories for annotated types that do not account for default qualifiers.
// They only include qualifiers explicitly inserted by the user.
// **********************************************************************
/**
* Creates an AnnotatedTypeMirror for {@code elt} that includes: annotations explicitly written on
* the element and annotations from stub files.
*
* <p>Does not include default qualifiers. To obtain them, use {@link #getAnnotatedType(Element)}.
*
* <p>Does not include fake overrides from the stub file.
*
* @param elt the element
* @return AnnotatedTypeMirror of the element with explicitly-written and stub file annotations
*/
public AnnotatedTypeMirror fromElement(Element elt) {
if (shouldCache && elementCache.containsKey(elt)) {
return elementCache.get(elt).deepCopy();
}
if (elt.getKind() == ElementKind.PACKAGE) {
return toAnnotatedType(elt.asType(), false);
}
AnnotatedTypeMirror type;
// Because of a bug in Java 8, annotations on type parameters are not stored in elements, so get
// explicit annotations from the tree. (This bug has been fixed in Java 9.) Also, since
// annotations computed by the AnnotatedTypeFactory are stored in the element, the annotations
// have to be retrieved from the tree so that only explicit annotations are returned.
Tree decl = declarationFromElement(elt);
if (decl == null) {
type = stubTypes.getAnnotatedTypeMirror(elt);
if (type == null) {
type = toAnnotatedType(elt.asType(), ElementUtils.isTypeDeclaration(elt));
ElementAnnotationApplier.apply(type, elt, this);
}
} else if (decl instanceof ClassTree) {
type = fromClass((ClassTree) decl);
} else if (decl instanceof VariableTree) {
type = fromMember(decl);
} else if (decl instanceof MethodTree) {
type = fromMember(decl);
} else if (decl.getKind() == Tree.Kind.TYPE_PARAMETER) {
type = fromTypeTree(decl);
} else {
throw new BugInCF("AnnotatedTypeFactory.fromElement: cannot be here. decl: " + decl.getKind() + " elt: " + elt);
}
type = mergeAnnotationFileAnnosIntoType(type, elt, ajavaTypes);
if (currentFileAjavaTypes != null) {
type = mergeAnnotationFileAnnosIntoType(type, elt, currentFileAjavaTypes);
}
if (checker.hasOption("mergeStubsWithSource")) {
if (debugStubParser) {
System.out.printf("fromElement: mergeStubsIntoType(%s, %s)", type, elt);
}
type = mergeAnnotationFileAnnosIntoType(type, elt, stubTypes);
if (debugStubParser) {
System.out.printf(" => %s%n", type);
}
}
// method before the annotation files are fully read can return incorrect results.
if (shouldCache && !stubTypes.isParsing() && !ajavaTypes.isParsing() && (currentFileAjavaTypes == null || !currentFileAjavaTypes.isParsing())) {
elementCache.put(elt, type.deepCopy());
}
return type;
}
use of com.sun.source.tree.ClassTree in project checker-framework by typetools.
the class AnnotatedTypeFactory method getCurrentMethodReceiver.
/**
* Returns the receiver type of the method enclosing {@code tree}.
*
* <p>The method uses the parameter only if the most enclosing method cannot be found directly.
*
* @param tree the tree used to find the enclosing method.
* @return receiver type of the most enclosing method being visited
* @deprecated Use {@link #getSelfType(Tree)} instead.
*/
@Deprecated
@Nullable
protected final AnnotatedDeclaredType getCurrentMethodReceiver(Tree tree) {
TreePath path = getPath(tree);
if (path == null) {
return null;
}
// used for == test
@SuppressWarnings("interning:assignment") @InternedDistinct MethodTree enclosingMethod = TreePathUtil.enclosingMethod(path);
ClassTree enclosingClass = TreePathUtil.enclosingClass(path);
boolean found = false;
for (Tree member : enclosingClass.getMembers()) {
if (member.getKind() == Tree.Kind.METHOD) {
if (member == enclosingMethod) {
found = true;
}
}
}
if (found && enclosingMethod != null) {
AnnotatedExecutableType method = getAnnotatedType(enclosingMethod);
return method.getReceiverType();
} else {
// We are within an anonymous class or field initializer
return this.getAnnotatedType(enclosingClass);
}
}
use of com.sun.source.tree.ClassTree 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);
}
}
use of com.sun.source.tree.ClassTree in project checker-framework by typetools.
the class GenericAnnotatedTypeFactory method analyze.
/**
* Analyze the AST {@code ast} and store the result. Additional operations that should be
* performed after analysis should be implemented in {@link #postAnalyze(ControlFlowGraph)}.
*
* @param queue the queue for encountered class trees and their initial stores
* @param lambdaQueue the queue for encountered lambda expression trees and their initial stores
* @param ast the AST to analyze
* @param fieldValues the abstract values for all fields of the same class
* @param currentClass the class we are currently looking at
* @param isInitializationCode are we analyzing a (static/non-static) initializer block of a class
* @param updateInitializationStore should the initialization store be updated
* @param isStatic are we analyzing a static construct
* @param capturedStore the input Store to use for captured variables, e.g. in a lambda
* @see #postAnalyze(org.checkerframework.dataflow.cfg.ControlFlowGraph)
*/
protected void analyze(Queue<Pair<ClassTree, Store>> queue, Queue<Pair<LambdaExpressionTree, Store>> lambdaQueue, UnderlyingAST ast, List<FieldInitialValue<Value>> fieldValues, ClassTree currentClass, boolean isInitializationCode, boolean updateInitializationStore, boolean isStatic, Store capturedStore) {
ControlFlowGraph cfg = CFCFGBuilder.build(root, ast, checker, this, processingEnv);
if (isInitializationCode) {
Store initStore = !isStatic ? initializationStore : initializationStaticStore;
if (initStore != null) {
// we have already seen initialization code and analyzed it, and
// the analysis ended with the store initStore.
// use it to start the next analysis.
transfer.setFixedInitialStore(initStore);
} else {
transfer.setFixedInitialStore(capturedStore);
}
} else {
transfer.setFixedInitialStore(capturedStore);
}
analysis.performAnalysis(cfg, fieldValues);
AnalysisResult<Value, Store> result = analysis.getResult();
// store result
flowResult.combine(result);
if (ast.getKind() == UnderlyingAST.Kind.METHOD) {
// store exit store (for checking postconditions)
CFGMethod mast = (CFGMethod) ast;
MethodTree method = mast.getMethod();
Store regularExitStore = analysis.getRegularExitStore();
if (regularExitStore != null) {
regularExitStores.put(method, regularExitStore);
}
Store exceptionalExitStore = analysis.getExceptionalExitStore();
if (exceptionalExitStore != null) {
exceptionalExitStores.put(method, exceptionalExitStore);
}
returnStatementStores.put(method, analysis.getReturnStatementStores());
} else if (ast.getKind() == UnderlyingAST.Kind.ARBITRARY_CODE) {
CFGStatement block = (CFGStatement) ast;
Store regularExitStore = analysis.getRegularExitStore();
if (regularExitStore != null) {
regularExitStores.put(block.getCode(), regularExitStore);
}
Store exceptionalExitStore = analysis.getExceptionalExitStore();
if (exceptionalExitStore != null) {
exceptionalExitStores.put(block.getCode(), exceptionalExitStore);
}
} else if (ast.getKind() == UnderlyingAST.Kind.LAMBDA) {
// TODO: Postconditions?
CFGLambda block = (CFGLambda) ast;
Store regularExitStore = analysis.getRegularExitStore();
if (regularExitStore != null) {
regularExitStores.put(block.getCode(), regularExitStore);
}
Store exceptionalExitStore = analysis.getExceptionalExitStore();
if (exceptionalExitStore != null) {
exceptionalExitStores.put(block.getCode(), exceptionalExitStore);
}
} else {
assert false : "Unexpected AST kind: " + ast.getKind();
}
if (isInitializationCode && updateInitializationStore) {
Store newInitStore = analysis.getRegularExitStore();
if (!isStatic) {
initializationStore = newInitStore;
} else {
initializationStaticStore = newInitStore;
}
}
// add classes declared in CFG
for (ClassTree cls : cfg.getDeclaredClasses()) {
queue.add(Pair.of(cls, getStoreBefore(cls)));
}
// add lambdas declared in CFG
for (LambdaExpressionTree lambda : cfg.getDeclaredLambdas()) {
lambdaQueue.add(Pair.of(lambda, getStoreBefore(lambda)));
}
postAnalyze(cfg);
}
use of com.sun.source.tree.ClassTree in project checker-framework by typetools.
the class BaseTypeVisitor method processClassTree.
/**
* Type-check classTree. Subclasses should override this method instead of {@link
* #visitClass(ClassTree, Void)}.
*
* @param classTree class to check
*/
public void processClassTree(ClassTree classTree) {
checkFieldInvariantDeclarations(classTree);
if (!TreeUtils.hasExplicitConstructor(classTree)) {
checkDefaultConstructor(classTree);
}
AnnotatedDeclaredType classType = atypeFactory.getAnnotatedType(classTree);
atypeFactory.getDependentTypesHelper().checkClassForErrorExpressions(classTree, classType);
validateType(classTree, classType);
Tree ext = classTree.getExtendsClause();
if (ext != null) {
for (AnnotatedDeclaredType superType : classType.directSupertypes()) {
if (superType.getUnderlyingType().asElement().getKind().isClass()) {
validateType(ext, superType);
break;
}
}
}
List<? extends Tree> impls = classTree.getImplementsClause();
if (impls != null) {
for (Tree im : impls) {
for (AnnotatedDeclaredType superType : classType.directSupertypes()) {
if (superType.getUnderlyingType().asElement().getKind().isInterface() && types.isSameType(superType.getUnderlyingType(), TreeUtils.typeOf(im))) {
validateType(im, superType);
break;
}
}
}
}
checkForPolymorphicQualifiers(classTree);
checkExtendsImplements(classTree);
checkQualifierParameter(classTree);
super.visitClass(classTree, null);
}
Aggregations