use of com.sun.source.util.TreeScanner in project error-prone by google.
the class InconsistentCapitalization method matchClass.
@Override
public Description matchClass(ClassTree tree, VisitorState state) {
ImmutableSet<Symbol> fields = FieldScanner.findFields(tree);
if (fields.isEmpty()) {
return Description.NO_MATCH;
}
ImmutableMap<String, Symbol> fieldNamesMap = fields.stream().collect(toImmutableMap(symbol -> symbol.toString().toLowerCase(), identity()));
ImmutableMap<TreePath, Symbol> matchedParameters = MatchingParametersScanner.findMatchingParameters(fieldNamesMap, state.getPath());
if (matchedParameters.isEmpty()) {
return Description.NO_MATCH;
}
for (Entry<TreePath, Symbol> entry : matchedParameters.entrySet()) {
TreePath parameterPath = entry.getKey();
Symbol field = entry.getValue();
String fieldName = field.getSimpleName().toString();
VariableTree parameterTree = (VariableTree) parameterPath.getLeaf();
SuggestedFix.Builder fix = SuggestedFix.builder().merge(SuggestedFixes.renameVariable(parameterTree, fieldName, state));
if (parameterPath.getParentPath() != null) {
String qualifiedName = getExplicitQualification(parameterPath, tree, state) + field.getSimpleName();
// If the field was accessed in a non-qualified way, by renaming the parameter this may
// cause clashes with it. Thus, it is required to qualify all uses of the field within the
// parameter's scope just in case.
parameterPath.getParentPath().getLeaf().accept(new TreeScanner<Void, Void>() {
@Override
public Void visitIdentifier(IdentifierTree tree, Void unused) {
if (field.equals(ASTHelpers.getSymbol(tree))) {
fix.replace(tree, qualifiedName);
}
return null;
}
}, null);
}
state.reportMatch(buildDescription(parameterPath.getLeaf()).setMessage(String.format("Found the field '%s' with the same name as the parameter '%s' but with " + "different capitalization.", fieldName, ((VariableTree) parameterPath.getLeaf()).getName())).addFix(fix.build()).build());
}
return Description.NO_MATCH;
}
use of com.sun.source.util.TreeScanner in project error-prone by google.
the class StreamResourceLeak method addFix.
@Override
protected void addFix(Description.Builder description, ExpressionTree tree, VisitorState state) {
TreePath parentPath = state.getPath().getParentPath();
Tree parent = parentPath.getLeaf();
SuggestedFix.Builder fix = SuggestedFix.builder();
String streamType = SuggestedFixes.prettyType(state, fix, ASTHelpers.getReturnType(tree));
if (parent instanceof MemberSelectTree) {
StatementTree statement = state.findEnclosing(StatementTree.class);
if (statement instanceof VariableTree) {
// Variables need to be declared outside the try-with-resources:
// e.g. `int count = Files.lines(p).count();`
// -> `int count; try (Stream<String> stream = Files.lines(p)) { count = stream.count(); }`
VariableTree var = (VariableTree) statement;
int pos = ((JCTree) var).getStartPosition();
int initPos = ((JCTree) var.getInitializer()).getStartPosition();
int eqPos = pos + state.getSourceForNode(var).substring(0, initPos - pos).lastIndexOf('=');
fix.replace(eqPos, initPos, String.format(";\ntry (%s stream = %s) {\n%s =", streamType, state.getSourceForNode(tree), var.getName().toString()));
} else {
// the non-variable case, e.g. `return Files.lines(p).count()`
// -> try (Stream<Stream> stream = Files.lines(p)) { return stream.count(); }`
fix.prefixWith(statement, String.format("try (%s stream = %s) {\n", streamType, state.getSourceForNode(tree)));
}
fix.replace(tree, "stream");
fix.postfixWith(statement, "}");
description.addFix(fix.build());
} else if (parent instanceof VariableTree) {
// If the stream is assigned to a variable, wrap the variable in a try-with-resources
// that includes all statements in the same block that reference the variable.
Tree grandParent = parentPath.getParentPath().getLeaf();
if (!(grandParent instanceof BlockTree)) {
return;
}
List<? extends StatementTree> statements = ((BlockTree) grandParent).getStatements();
int idx = statements.indexOf(parent);
int lastUse = idx;
for (int i = idx + 1; i < statements.size(); i++) {
boolean[] found = { false };
statements.get(i).accept(new TreeScanner<Void, Void>() {
@Override
public Void visitIdentifier(IdentifierTree tree, Void unused) {
if (Objects.equals(ASTHelpers.getSymbol(tree), ASTHelpers.getSymbol(parent))) {
found[0] = true;
}
return null;
}
}, null);
if (found[0]) {
lastUse = i;
}
}
fix.prefixWith(parent, "try (");
fix.replace(state.getEndPosition(((VariableTree) parent).getInitializer()), state.getEndPosition(parent), ") {");
fix.postfixWith(statements.get(lastUse), "}");
description.addFix(fix.build());
} else if (parent instanceof EnhancedForLoopTree) {
// If the stream is used in a loop (e.g. directory streams), wrap the loop in
// try-with-resources.
fix.prefixWith(parent, String.format("try (%s stream = %s) {\n", streamType, state.getSourceForNode(tree)));
fix.replace(tree, "stream");
fix.postfixWith(parent, "}");
description.addFix(fix.build());
} else if (parent instanceof MethodInvocationTree) {
// If the stream is used in a method that is called in an expression statement, wrap it in
// try-with-resources.
Tree grandParent = parentPath.getParentPath().getLeaf();
if (!(grandParent instanceof ExpressionStatementTree)) {
return;
}
fix.prefixWith(parent, String.format("try (%s stream = %s) {\n", streamType, state.getSourceForNode(tree)));
fix.replace(tree, "stream");
fix.postfixWith(grandParent, "}");
description.addFix(fix.build());
}
}
use of com.sun.source.util.TreeScanner in project error-prone by google.
the class UnsafeFinalization method matchMethodInvocation.
@Override
public Description matchMethodInvocation(MethodInvocationTree tree, VisitorState state) {
MethodSymbol sym = ASTHelpers.getSymbol(tree);
// Match invocations of static native methods.
if (sym == null || !sym.isStatic() || !Flags.asFlagSet(sym.flags()).contains(Flag.NATIVE)) {
return NO_MATCH;
}
// Find the enclosing method declaration where the invocation occurs.
MethodTree method = enclosingMethod(state);
if (method == null) {
return NO_MATCH;
}
// Don't check native methods called from static methods and constructors:
// static methods don't have an instance to finalize, and we shouldn't need to worry about
// finalization during construction.
MethodSymbol enclosing = ASTHelpers.getSymbol(method);
if (enclosing == null || enclosing.isStatic() || enclosing.isConstructor()) {
return NO_MATCH;
}
// Check if any arguments of the static native method are members (e.g. fields) of the enclosing
// class. We're only looking for cases where the static native uses state of the enclosing class
// that may become invalid after finalization.
ImmutableList<Symbol> arguments = tree.getArguments().stream().map(ASTHelpers::getSymbol).filter(x -> x != null).collect(toImmutableList());
if (arguments.stream().filter(x -> EnumSet.of(TypeKind.INT, TypeKind.LONG).contains(state.getTypes().unboxedTypeOrType(x.asType()).getKind())).noneMatch(arg -> arg.isMemberOf(enclosing.enclClass(), state.getTypes()))) {
// no instance state is passed to the native method
return NO_MATCH;
}
if (arguments.stream().anyMatch(arg -> arg.getSimpleName().contentEquals("this") && arg.isMemberOf(enclosing.enclClass(), state.getTypes()))) {
// the instance is passed to the native method
return NO_MATCH;
}
Symbol finalizeSym = getFinalizer(state, enclosing.enclClass());
if (finalizeSym.equals(enclosing)) {
// Don't check native methods called from within the implementation of finalize.
return NO_MATCH;
}
if (finalizeSym.enclClass().equals(state.getSymtab().objectType.asElement())) {
// Inheriting finalize from Object doesn't count.
return NO_MATCH;
}
boolean[] sawFence = { false };
new TreeScanner<Void, Void>() {
@Override
public Void visitMethodInvocation(MethodInvocationTree tree, Void unused) {
if (FENCE_MATCHER.matches(tree, state)) {
sawFence[0] = true;
}
return null;
}
}.scan(state.getPath().getCompilationUnit(), null);
if (sawFence[0]) {
// Ignore methods that contain a use of reachabilityFence.
return NO_MATCH;
}
return describeMatch(tree);
}
use of com.sun.source.util.TreeScanner in project ceylon-compiler by ceylon.
the class TestPos method main.
public static void main(String... args) throws IOException {
final boolean[] sawError = { false };
final StringBuilder log = new StringBuilder();
class MyFileObject extends SimpleJavaFileObject {
MyFileObject() {
super(URI.create("myfo:///Test.java"), SOURCE);
}
@Override
public String getCharContent(boolean ignoreEncodingErrors) {
// 0123456789012345678901234567890123456789012345678901234
return "class Test { { Object[] o = new <T,e,s,t>Object[0]; } }";
}
}
class Scanner extends TreeScanner<Void, Trees> {
CompilationUnitTree toplevel = null;
@Override
public Void visitCompilationUnit(CompilationUnitTree node, Trees trees) {
toplevel = node;
return super.visitCompilationUnit(node, trees);
}
@Override
public Void visitErroneous(ErroneousTree node, Trees trees) {
sawError[0] = true;
long startPos = trees.getSourcePositions().getStartPosition(toplevel, node);
long endPos = trees.getSourcePositions().getEndPosition(toplevel, node);
log.append(String.format("begin=%s, end=%s : %s%n", startPos, endPos, node.getErrorTrees()));
if (startPos != 28)
error("Start pos for %s is incorrect (%s)!", node, startPos);
if (endPos != 50)
error("End pos for %s is incorrect (%s)!", node, endPos);
return null;
}
}
JavaCompiler javac = ToolProvider.getSystemJavaCompiler();
List<JavaFileObject> compilationUnits = Collections.<JavaFileObject>singletonList(new MyFileObject());
DiagnosticListener<JavaFileObject> dl = new DiagnosticListener<JavaFileObject>() {
public void report(Diagnostic<? extends JavaFileObject> diag) {
log.append(String.format("%s @ %s%n", diag.getCode(), diag.getPosition()));
if (!diag.getCode().equals(errCode))
error("unexpected error");
if (diag.getPosition() != 33)
error("Error pos for %s is incorrect (%s)!", diag.getCode(), diag.getPosition());
sawError[0] = true;
}
};
JavacTask task = (JavacTask) javac.getTask(null, null, dl, null, null, compilationUnits);
Trees trees = Trees.instance(task);
Iterable<? extends Tree> toplevels = task.parse();
if (!sawError[0])
error("No parse error detected");
sawError[0] = false;
new Scanner().scan(toplevels, trees);
if (!sawError[0])
error("No error tree detected");
if (!log.toString().equals(expected))
error("Unexpected log message: %n%s%n", log);
System.out.print(log);
System.out.flush();
}
Aggregations