use of com.sun.source.tree.MethodTree in project checker-framework by typetools.
the class TypesIntoElements method store.
/**
* The entry point.
*
* @param processingEnv the environment
* @param atypeFactory the type factory
* @param tree the ClassTree to process
*/
public static void store(ProcessingEnvironment processingEnv, AnnotatedTypeFactory atypeFactory, ClassTree tree) {
Symbol.ClassSymbol csym = (Symbol.ClassSymbol) TreeUtils.elementFromDeclaration(tree);
Types types = processingEnv.getTypeUtils();
storeTypeParameters(processingEnv, types, atypeFactory, tree.getTypeParameters(), csym);
for (Tree mem : tree.getMembers()) {
if (mem.getKind() == Tree.Kind.METHOD) {
storeMethod(processingEnv, types, atypeFactory, (MethodTree) mem);
} else if (mem.getKind() == Tree.Kind.VARIABLE) {
storeVariable(processingEnv, types, atypeFactory, (VariableTree) mem);
} else {
// System.out.println("Unhandled member tree: " + mem);
}
}
}
use of com.sun.source.tree.MethodTree in project checker-framework by typetools.
the class CFAbstractTransfer method initialStore.
/**
* The initial store maps method formal parameters to their currently most refined type.
*/
@Override
public S initialStore(UnderlyingAST underlyingAST, List<LocalVariableNode> parameters) {
if (underlyingAST.getKind() != UnderlyingAST.Kind.LAMBDA && underlyingAST.getKind() != UnderlyingAST.Kind.METHOD) {
if (fixedInitialStore != null) {
return fixedInitialStore;
} else {
return analysis.createEmptyStore(sequentialSemantics);
}
}
S store;
if (underlyingAST.getKind() == UnderlyingAST.Kind.METHOD) {
if (fixedInitialStore != null) {
// copy knowledge
store = analysis.createCopiedStore(fixedInitialStore);
} else {
store = analysis.createEmptyStore(sequentialSemantics);
}
AnnotatedTypeFactory factory = analysis.getTypeFactory();
for (LocalVariableNode p : parameters) {
AnnotatedTypeMirror anno = factory.getAnnotatedType(p.getElement());
store.initializeMethodParameter(p, analysis.createAbstractValue(anno));
}
// add properties known through precondition
CFGMethod method = (CFGMethod) underlyingAST;
MethodTree methodDeclTree = method.getMethod();
ExecutableElement methodElem = TreeUtils.elementFromDeclaration(methodDeclTree);
addInformationFromPreconditions(store, factory, method, methodDeclTree, methodElem);
addInitialFieldValues(store, method.getClassTree(), methodDeclTree);
addFinalLocalValues(store, methodElem);
if (shouldPerformWholeProgramInference(methodDeclTree, methodElem)) {
Map<AnnotatedDeclaredType, ExecutableElement> overriddenMethods = AnnotatedTypes.overriddenMethods(analysis.atypeFactory.getElementUtils(), analysis.atypeFactory, methodElem);
for (Map.Entry<AnnotatedDeclaredType, ExecutableElement> pair : overriddenMethods.entrySet()) {
AnnotatedExecutableType overriddenMethod = AnnotatedTypes.asMemberOf(analysis.atypeFactory.getProcessingEnv().getTypeUtils(), analysis.atypeFactory, pair.getKey(), pair.getValue());
// Infers parameter and receiver types of the method based
// on the overridden method.
analysis.atypeFactory.getWholeProgramInference().updateFromOverride(methodDeclTree, methodElem, overriddenMethod);
}
}
} else if (underlyingAST.getKind() == UnderlyingAST.Kind.LAMBDA) {
// Create a copy and keep only the field values (nothing else applies).
store = analysis.createCopiedStore(fixedInitialStore);
// Allow that local variables are retained; they are effectively final,
// otherwise Java wouldn't allow access from within the lambda.
// TODO: what about the other information? Can code further down be simplified?
// store.localVariableValues.clear();
store.classValues.clear();
store.arrayValues.clear();
store.methodValues.clear();
AnnotatedTypeFactory factory = analysis.getTypeFactory();
for (LocalVariableNode p : parameters) {
AnnotatedTypeMirror anno = factory.getAnnotatedType(p.getElement());
store.initializeMethodParameter(p, analysis.createAbstractValue(anno));
}
CFGLambda lambda = (CFGLambda) underlyingAST;
// used in == tests
@SuppressWarnings("interning:assignment") @InternedDistinct Tree enclosingTree = TreePathUtil.enclosingOfKind(factory.getPath(lambda.getLambdaTree()), new HashSet<>(Arrays.asList(Tree.Kind.METHOD, // Tree.Kind for which TreeUtils.isClassTree is true
Tree.Kind.CLASS, Tree.Kind.INTERFACE, Tree.Kind.ANNOTATION_TYPE, Tree.Kind.ENUM)));
Element enclosingElement = null;
if (enclosingTree.getKind() == Tree.Kind.METHOD) {
// If it is in an initializer, we need to use locals from the initializer.
enclosingElement = TreeUtils.elementFromTree(enclosingTree);
} else if (TreeUtils.isClassTree(enclosingTree)) {
// Try to find an enclosing initializer block.
// Would love to know if there was a better way.
// Find any enclosing element of the lambda (using trees).
// Then go up the elements to find an initializer element (which can't be found with the
// tree).
TreePath loopTree = factory.getPath(lambda.getLambdaTree()).getParentPath();
Element anEnclosingElement = null;
while (loopTree.getLeaf() != enclosingTree) {
Element sym = TreeUtils.elementFromTree(loopTree.getLeaf());
if (sym != null) {
anEnclosingElement = sym;
break;
}
loopTree = loopTree.getParentPath();
}
while (anEnclosingElement != null && !anEnclosingElement.equals(TreeUtils.elementFromTree(enclosingTree))) {
if (anEnclosingElement.getKind() == ElementKind.INSTANCE_INIT || anEnclosingElement.getKind() == ElementKind.STATIC_INIT) {
enclosingElement = anEnclosingElement;
break;
}
anEnclosingElement = anEnclosingElement.getEnclosingElement();
}
}
if (enclosingElement != null) {
addFinalLocalValues(store, enclosingElement);
}
// We want the initialization stuff, but need to throw out any refinements.
Map<FieldAccess, V> fieldValuesClone = new HashMap<>(store.fieldValues);
for (Map.Entry<FieldAccess, V> fieldValue : fieldValuesClone.entrySet()) {
AnnotatedTypeMirror declaredType = factory.getAnnotatedType(fieldValue.getKey().getField());
V lubbedValue = analysis.createAbstractValue(declaredType).leastUpperBound(fieldValue.getValue());
store.fieldValues.put(fieldValue.getKey(), lubbedValue);
}
} else {
assert false : "Unexpected tree: " + underlyingAST;
store = null;
}
return store;
}
use of com.sun.source.tree.MethodTree in project checker-framework by typetools.
the class CFAbstractTransfer method addInformationFromPreconditions.
/**
* Add the information from all the preconditions of a method to the initial store in the method
* body.
*
* @param initialStore the initial store for the method body
* @param factory the type factory
* @param methodAst the AST for a method declaration
* @param methodDeclTree the declaration of the method; is a field of {@code methodAst}
* @param methodElement the element for the method
*/
protected void addInformationFromPreconditions(S initialStore, AnnotatedTypeFactory factory, CFGMethod methodAst, MethodTree methodDeclTree, ExecutableElement methodElement) {
ContractsFromMethod contractsUtils = analysis.atypeFactory.getContractsFromMethod();
Set<Precondition> preconditions = contractsUtils.getPreconditions(methodElement);
StringToJavaExpression stringToJavaExpr = stringExpr -> StringToJavaExpression.atMethodBody(stringExpr, methodDeclTree, analysis.checker);
for (Precondition p : preconditions) {
String stringExpr = p.expressionString;
AnnotationMirror annotation = p.viewpointAdaptDependentTypeAnnotation(analysis.atypeFactory, stringToJavaExpr, /*errorTree=*/
null);
JavaExpression exprJe;
try {
// TODO: currently, these expressions are parsed at the declaration (i.e. here) and for
// every use. this could be optimized to store the result the first time.
// (same for other annotations)
exprJe = StringToJavaExpression.atMethodBody(stringExpr, methodDeclTree, analysis.checker);
} catch (JavaExpressionParseException e) {
// Errors are reported by BaseTypeVisitor.checkContractsAtMethodDeclaration().
continue;
}
initialStore.insertValuePermitNondeterministic(exprJe, annotation);
}
}
use of com.sun.source.tree.MethodTree in project checker-framework by typetools.
the class ExpectedTreesVisitor method visitClass.
@Override
public Void visitClass(ClassTree tree, Void p) {
defaultAction(tree);
scan(tree.getModifiers(), p);
scan(tree.getTypeParameters(), p);
scan(tree.getExtendsClause(), p);
scan(tree.getImplementsClause(), p);
if (tree.getKind() == Tree.Kind.ENUM) {
// instance of an enum.
for (Tree member : tree.getMembers()) {
member.accept(this, p);
if (member.getKind() != Tree.Kind.VARIABLE) {
continue;
}
VariableTree variable = (VariableTree) member;
ExpressionTree initializer = variable.getInitializer();
if (initializer == null || initializer.getKind() != Tree.Kind.NEW_CLASS) {
continue;
}
NewClassTree constructor = (NewClassTree) initializer;
if (constructor.getIdentifier().getKind() != Tree.Kind.IDENTIFIER) {
continue;
}
IdentifierTree name = (IdentifierTree) constructor.getIdentifier();
if (name.getName().contentEquals(tree.getSimpleName())) {
trees.remove(variable.getType());
trees.remove(constructor);
trees.remove(constructor.getIdentifier());
}
}
// RECORD was added in Java 14, so use string comparison to be JDK 8,11 compatible:
} else if (tree.getKind().name().equals("RECORD")) {
// A record like:
// record MyRec(String myField) {}
// will be expanded by javac to:
// class MyRec {
// MyRec(String myField) {
// super();
// }
// private final String myField;
// }
// So the constructor and the field declarations have no matching trees in the JavaParser
// node, and we must remove those trees (and their subtrees) from the `trees` field.
TreeScannerWithDefaults removeAllVisitor = new TreeScannerWithDefaults() {
@Override
public void defaultAction(Tree node) {
trees.remove(node);
}
};
for (Tree member : tree.getMembers()) {
scan(member, p);
if (TreeUtils.isAutoGeneratedRecordMember(member)) {
member.accept(removeAllVisitor, null);
} else {
// the parameters. These trees also don't have a match:
if (member.getKind() == Tree.Kind.METHOD) {
MethodTree methodTree = (MethodTree) member;
if (TreeUtils.isCompactCanonicalRecordConstructor(methodTree)) {
for (VariableTree canonicalParameter : methodTree.getParameters()) {
canonicalParameter.accept(removeAllVisitor, null);
}
}
}
}
}
} else {
scan(tree.getMembers(), p);
}
return null;
}
use of com.sun.source.tree.MethodTree in project checker-framework by typetools.
the class ExpectedTreesVisitor method visitNewClass.
@Override
public Void visitNewClass(NewClassTree tree, Void p) {
defaultAction(tree);
if (tree.getEnclosingExpression() != null) {
tree.getEnclosingExpression().accept(this, p);
}
tree.getIdentifier().accept(this, p);
for (Tree typeArgument : tree.getTypeArguments()) {
typeArgument.accept(this, p);
}
for (Tree arg : tree.getTypeArguments()) {
arg.accept(this, p);
}
if (tree.getClassBody() == null) {
return null;
}
// Anonymous class bodies require special handling. There isn't a corresponding JavaParser
// node, and synthetic constructors must be skipped.
ClassTree body = tree.getClassBody();
scan(body.getModifiers(), p);
scan(body.getTypeParameters(), p);
scan(body.getImplementsClause(), p);
for (Tree member : body.getMembers()) {
// Constructors cannot be declared in an anonymous class, so don't add them.
if (member.getKind() == Tree.Kind.METHOD) {
MethodTree methodTree = (MethodTree) member;
if (methodTree.getName().contentEquals("<init>")) {
continue;
}
}
member.accept(this, p);
}
return null;
}
Aggregations