use of com.sun.source.tree.MethodTree in project error-prone by google.
the class MustBeClosedChecker method matchNewClassOrMethodInvocation.
/**
* Check that constructors and methods annotated with {@link MustBeClosed} occur within the
* resource variable initializer of a try-with-resources statement.
*
* @param name The name of the method or constructor.
*/
private Description matchNewClassOrMethodInvocation(String name, Tree tree, VisitorState state) {
if (!HAS_MUST_BE_CLOSED_ANNOTATION.matches(tree, state)) {
// {@link MustBeClosed}.
return NO_MATCH;
}
String errorMessage = String.format("%s must be called within the resource variable initializer of a try-with-resources" + " statement.", name);
MethodTree callerMethodTree = enclosingMethod(state);
if (state.getPath().getParentPath().getLeaf().getKind() == Tree.Kind.RETURN && callerMethodTree != null) {
if (HAS_MUST_BE_CLOSED_ANNOTATION.matches(callerMethodTree, state)) {
// statement of an annotated caller method, since invocations of the caller are enforced.
return NO_MATCH;
}
// enforced. Suggest fixing this by annotating the caller method.
return buildDescription(tree).addFix(SuggestedFix.builder().prefixWith(callerMethodTree, "@MustBeClosed\n").addImport(MustBeClosed.class.getCanonicalName()).build()).setMessage(errorMessage).build();
}
if (!inTWR(state)) {
// initializer of a try-with-resources statement.
return buildDescription(tree).setMessage(errorMessage).build();
}
return NO_MATCH;
}
use of com.sun.source.tree.MethodTree in project checker-framework by typetools.
the class JavaSource2CFGDOT method getMethodTreeAndCompilationUnit.
/**
* @return the AST of a specific method in a specific class as well as the {@link
* CompilationUnitTree} in a specific file (or null they do not exist).
*/
public static Entry<@Nullable MethodTree, @Nullable CompilationUnitTree> getMethodTreeAndCompilationUnit(String file, final String method, String clas) {
final MethodTree[] m = { null };
final CompilationUnitTree[] c = { null };
BasicTypeProcessor typeProcessor = new BasicTypeProcessor() {
@Override
protected TreePathScanner<?, ?> createTreePathScanner(CompilationUnitTree root) {
c[0] = root;
return new TreePathScanner<Void, Void>() {
@Override
public Void visitMethod(MethodTree node, Void p) {
ExecutableElement el = TreeUtils.elementFromDeclaration(node);
if (el.getSimpleName().contentEquals(method)) {
m[0] = node;
// compilation).
throw new RuntimeException();
}
return null;
}
};
}
};
Context context = new Context();
Options.instance(context).put("compilePolicy", "ATTR_ONLY");
JavaCompiler javac = new JavaCompiler(context);
JavacFileManager fileManager = (JavacFileManager) context.get(JavaFileManager.class);
JavaFileObject l = fileManager.getJavaFileObjectsFromStrings(List.of(file)).iterator().next();
PrintStream err = System.err;
try {
// redirect syserr to nothing (and prevent the compiler from issuing
// warnings about our exception.
System.setErr(new PrintStream(new OutputStream() {
@Override
public void write(int b) throws IOException {
}
}));
javac.compile(List.of(l), List.of(clas), List.of(typeProcessor));
} catch (Throwable e) {
// ok
} finally {
System.setErr(err);
}
return new Entry<MethodTree, CompilationUnitTree>() {
@Override
public CompilationUnitTree setValue(CompilationUnitTree value) {
return null;
}
@Override
public CompilationUnitTree getValue() {
return c[0];
}
@Override
public MethodTree getKey() {
return m[0];
}
};
}
use of com.sun.source.tree.MethodTree in project checker-framework by typetools.
the class AnnotatedTypeFactory method getSelfType.
/**
* Returns the type of {@code this} in the current location, which can be used if {@code this}
* has a special semantics (e.g. {@code this} is non-null).
*
* <p>The parameter is an arbitrary tree and does not have to mention "this", neither explicitly
* nor implicitly. This method should be overridden for type-system specific behavior.
*
* <p>TODO: in 1.8.2, handle all receiver type annotations. TODO: handle enclosing classes
* correctly.
*/
public AnnotatedDeclaredType getSelfType(Tree tree) {
TreePath path = getPath(tree);
ClassTree enclosingClass = TreeUtils.enclosingClass(path);
if (enclosingClass == null) {
// I hope this only happens when tree is a fake tree that
// we created, e.g. when desugaring enhanced-for-loops.
enclosingClass = getCurrentClassTree(tree);
}
AnnotatedDeclaredType type = getAnnotatedType(enclosingClass);
MethodTree enclosingMethod = TreeUtils.enclosingMethod(path);
if (enclosingClass.getSimpleName().length() != 0 && enclosingMethod != null) {
AnnotatedDeclaredType methodReceiver;
if (TreeUtils.isConstructor(enclosingMethod)) {
methodReceiver = (AnnotatedDeclaredType) getAnnotatedType(enclosingMethod).getReturnType();
} else {
methodReceiver = getAnnotatedType(enclosingMethod).getReceiverType();
}
if (shouldTakeFromReceiver(methodReceiver)) {
// TODO what about all annotations on the receiver?
// Code is also duplicated above.
type.clearAnnotations();
type.addAnnotations(methodReceiver.getAnnotations());
}
}
return type;
}
use of com.sun.source.tree.MethodTree in project checker-framework by typetools.
the class DependentTypesHelper method standardizeVariable.
public void standardizeVariable(Tree node, AnnotatedTypeMirror type, Element ele) {
if (!hasDependentType(type)) {
return;
}
TreePath path = factory.getPath(node);
if (path == null) {
return;
}
switch(ele.getKind()) {
case PARAMETER:
Tree enclTree = TreeUtils.enclosingOfKind(path, new HashSet<>(Arrays.asList(Kind.METHOD, Kind.LAMBDA_EXPRESSION)));
if (enclTree.getKind() == Kind.METHOD) {
// If the most enclosing tree is a method, the parameter is a method parameter
MethodTree methodTree = (MethodTree) enclTree;
TypeMirror enclosingType = ElementUtils.enclosingClass(ele).asType();
FlowExpressionContext parameterContext = FlowExpressionContext.buildContextForMethodDeclaration(methodTree, enclosingType, factory.getContext());
standardizeDoNotUseLocals(parameterContext, path, type);
} else {
// Otherwise, the parameter is a lambda parameter
LambdaExpressionTree lambdaTree = (LambdaExpressionTree) enclTree;
FlowExpressionContext parameterContext = FlowExpressionContext.buildContextForLambda(lambdaTree, path, factory.getContext());
// TODO: test this.
// TODO: use path.getParentPath to prevent a StackOverflowError, see Issue
// #1027.
standardizeUseLocals(parameterContext, path.getParentPath(), type);
}
break;
case LOCAL_VARIABLE:
case RESOURCE_VARIABLE:
case EXCEPTION_PARAMETER:
TypeMirror enclosingType = ElementUtils.enclosingClass(ele).asType();
FlowExpressions.Receiver receiver = FlowExpressions.internalReprOfPseudoReceiver(path, enclosingType);
List<Receiver> params = FlowExpressions.getParametersOfEnclosingMethod(factory, path);
FlowExpressionContext localContext = new FlowExpressionContext(receiver, params, factory.getContext());
standardizeUseLocals(localContext, path, type);
break;
case FIELD:
FlowExpressions.Receiver receiverF;
if (node.getKind() == Tree.Kind.IDENTIFIER) {
FlowExpressions.Receiver r = FlowExpressions.internalReprOf(factory, (IdentifierTree) node);
receiverF = r instanceof FlowExpressions.FieldAccess ? ((FlowExpressions.FieldAccess) r).getReceiver() : r;
} else {
receiverF = FlowExpressions.internalReprOfImplicitReceiver(ele);
}
FlowExpressionContext fieldContext = new FlowExpressionContext(receiverF, null, factory.getContext());
standardizeDoNotUseLocals(fieldContext, path, type);
break;
default:
}
}
use of com.sun.source.tree.MethodTree in project checker-framework by typetools.
the class BaseTypeVisitor method resolveContracts.
/**
* Takes a set of contracts identified by their expression and annotation strings and resolves
* them to the correct {@link Receiver} and {@link AnnotationMirror}.
*/
private Set<Pair<Receiver, AnnotationMirror>> resolveContracts(Set<? extends Contract> contractSet, AnnotatedExecutableType method) {
Set<Pair<Receiver, AnnotationMirror>> result = new HashSet<>();
MethodTree methodTree = visitorState.getMethodTree();
TreePath path = atypeFactory.getPath(methodTree);
FlowExpressionContext flowExprContext = null;
for (Contract p : contractSet) {
String expression = p.expression;
AnnotationMirror annotation = p.annotation;
if (flowExprContext == null) {
flowExprContext = FlowExpressionContext.buildContextForMethodDeclaration(methodTree, method.getReceiverType().getUnderlyingType(), checker.getContext());
}
annotation = standardizeAnnotationFromContract(annotation, flowExprContext, path);
try {
// TODO: currently, these expressions are parsed many times.
// this could
// be optimized to store the result the first time.
// (same for other annotations)
FlowExpressions.Receiver expr = FlowExpressionParseUtil.parse(expression, flowExprContext, path, false);
result.add(Pair.of(expr, annotation));
} catch (FlowExpressionParseException e) {
// report errors here
checker.report(e.getResult(), methodTree);
}
}
return result;
}
Aggregations