use of com.google.errorprone.VisitorState in project error-prone by google.
the class JavaLangClash method check.
private Description check(Tree tree, Name simpleName, VisitorState state) {
Symtab symtab = state.getSymtab();
PackageSymbol javaLang = symtab.enterPackage(symtab.java_base, Names.instance(state.context).java_lang);
Symbol other = getFirst(javaLang.members().getSymbolsByName(simpleName, s -> s.getModifiers().contains(PUBLIC)), null);
Symbol symbol = ASTHelpers.getSymbol(tree);
if (other == null || other.equals(symbol)) {
return NO_MATCH;
}
return buildDescription(tree).setMessage(String.format("%s clashes with %s\n", symbol, other)).build();
}
use of com.google.errorprone.VisitorState in project error-prone by google.
the class LambdaFunctionalInterface method matchMethod.
/**
* Identifies methods with parameters that have a generic argument with Int, Long, or Double. If
* pre-conditions are met, it refactors them to the primitive specializations.
*
* <pre>PreConditions:
* (1): The method declaration has to be private (to do a safe refactoring)
* (2): Its parameters have to meet the following conditions:
* 2.1 Contain type java.util.function.Function
* 2.2 At least one argument type of the Function must be subtype of Number
* (3): All its invocations in the top-level enclosing class have to meet the following
* conditions as well:
* 3.1: lambda argument of Kind.LAMBDA_EXPRESSION
* 3.2: same as 2.1
* 3.3: same as 2.2
* </pre>
*
* <pre>
* Refactoring Changes for matched methods:
* (1) Add the imports
* (2) Change the method signature to use utility function instead of Function
* (3) Find and change the 'apply' calls to the corresponding applyAsT
* </pre>
*/
@Override
public Description matchMethod(MethodTree tree, VisitorState state) {
MethodSymbol methodSym = ASTHelpers.getSymbol(tree);
// precondition (1)
if (!methodSym.getModifiers().contains(Modifier.PRIVATE)) {
return Description.NO_MATCH;
}
ImmutableList<Tree> params = tree.getParameters().stream().filter(param -> hasFunctionAsArg(param, state)).filter(param -> isFunctionArgSubtypeOf(param, 0, state.getTypeFromString(JAVA_LANG_NUMBER), state) || isFunctionArgSubtypeOf(param, 1, state.getTypeFromString(JAVA_LANG_NUMBER), state)).collect(toImmutableList());
// preconditions (2) and (3)
if (params.isEmpty() || !methodCallsMeetConditions(methodSym, state)) {
return Description.NO_MATCH;
}
SuggestedFix.Builder fixBuilder = SuggestedFix.builder();
for (Tree param : params) {
getMappingForFunctionFromTree(param).ifPresent(mappedFunction -> {
fixBuilder.addImport(getImportName(mappedFunction));
fixBuilder.replace(param, getFunctionName(mappedFunction) + " " + ASTHelpers.getSymbol(param).name);
refactorInternalApplyMethods(tree, fixBuilder, param, mappedFunction);
});
}
return describeMatch(tree, fixBuilder.build());
}
use of com.google.errorprone.VisitorState in project error-prone by google.
the class FindIdentifiers method findAllIdents.
/**
* Finds the set of all bare variable identifiers in scope at the current location. Identifiers
* are ordered by ascending distance/scope count from the current location to match shadowing
* rules. That is, if two variables with the same simple names appear in the set, the one that
* appears first in iteration order is the one you get if you use the bare name in the source
* code.
*
* <p>We do not report variables that would require a qualfied access. We also do not handle
* wildcard imports.
*/
public static LinkedHashSet<VarSymbol> findAllIdents(VisitorState state) {
ImmutableSet.Builder<VarSymbol> result = new ImmutableSet.Builder<>();
Tree prev = state.getPath().getLeaf();
for (Tree curr : state.getPath().getParentPath()) {
switch(curr.getKind()) {
case BLOCK:
for (StatementTree stmt : ((BlockTree) curr).getStatements()) {
if (stmt.equals(prev)) {
break;
}
addIfVariable(stmt, result);
}
break;
case METHOD:
for (VariableTree param : ((MethodTree) curr).getParameters()) {
result.add(ASTHelpers.getSymbol(param));
}
break;
case CATCH:
result.add(ASTHelpers.getSymbol(((CatchTree) curr).getParameter()));
break;
case CLASS:
case INTERFACE:
case ENUM:
case ANNOTATION_TYPE:
// field is referred to by qualified name, but we don't support that.
for (Tree member : ((ClassTree) curr).getMembers()) {
if (member.equals(prev)) {
break;
}
addIfVariable(member, result);
}
// Collect inherited fields.
Type classType = ASTHelpers.getType(curr);
List<Type> classTypeClosure = state.getTypes().closure(classType);
List<Type> superTypes = classTypeClosure.size() <= 1 ? Collections.emptyList() : classTypeClosure.subList(1, classTypeClosure.size());
for (Type type : superTypes) {
Scope scope = type.tsym.members();
ImmutableList.Builder<VarSymbol> varsList = ImmutableList.builder();
for (Symbol var : scope.getSymbols(VarSymbol.class::isInstance)) {
varsList.add((VarSymbol) var);
}
result.addAll(varsList.build().reverse());
}
break;
case FOR_LOOP:
addAllIfVariable(((ForLoopTree) curr).getInitializer(), result);
break;
case ENHANCED_FOR_LOOP:
result.add(ASTHelpers.getSymbol(((EnhancedForLoopTree) curr).getVariable()));
break;
case TRY:
TryTree tryTree = (TryTree) curr;
boolean inResources = false;
for (Tree resource : tryTree.getResources()) {
if (resource.equals(prev)) {
inResources = true;
break;
}
}
if (inResources) {
// Case 1: we're in one of the resource declarations
for (Tree resource : tryTree.getResources()) {
if (resource.equals(prev)) {
break;
}
addIfVariable(resource, result);
}
} else if (tryTree.getBlock().equals(prev)) {
// Case 2: We're in the block (not a catch or finally)
addAllIfVariable(tryTree.getResources(), result);
}
break;
case COMPILATION_UNIT:
for (ImportTree importTree : ((CompilationUnitTree) curr).getImports()) {
if (importTree.isStatic() && importTree.getQualifiedIdentifier().getKind() == Kind.MEMBER_SELECT) {
MemberSelectTree memberSelectTree = (MemberSelectTree) importTree.getQualifiedIdentifier();
Scope scope = state.getTypes().membersClosure(ASTHelpers.getType(memberSelectTree.getExpression()), /* skipInterface= */
false);
for (Symbol var : scope.getSymbols(sym -> sym instanceof VarSymbol && sym.getSimpleName().equals(memberSelectTree.getIdentifier()))) {
result.add((VarSymbol) var);
}
}
}
break;
default:
// other node types don't introduce variables
break;
}
prev = curr;
}
// TODO(eaftan): switch out collector for ImmutableSet.toImmutableSet()
return result.build().stream().filter(var -> isVisible(var, state.getPath())).collect(Collectors.toCollection(LinkedHashSet::new));
}
use of com.google.errorprone.VisitorState in project error-prone by google.
the class Matchers method inSynchronized.
/**
* Matches if this Tree is enclosed by either a synchronized block or a synchronized method.
*/
public static final <T extends Tree> Matcher<T> inSynchronized() {
return new Matcher<T>() {
@Override
public boolean matches(T tree, VisitorState state) {
SynchronizedTree synchronizedTree = ASTHelpers.findEnclosingNode(state.getPath(), SynchronizedTree.class);
if (synchronizedTree != null) {
return true;
}
MethodTree methodTree = ASTHelpers.findEnclosingNode(state.getPath(), MethodTree.class);
return methodTree != null && methodTree.getModifiers().getFlags().contains(Modifier.SYNCHRONIZED);
}
};
}
use of com.google.errorprone.VisitorState in project error-prone by google.
the class Matchers method inLoop.
/**
* Matches if the given tree is inside a loop.
*/
public static <T extends Tree> Matcher<T> inLoop() {
return new Matcher<T>() {
@Override
public boolean matches(Tree tree, VisitorState state) {
TreePath path = state.getPath().getParentPath();
Tree node = path.getLeaf();
while (path != null) {
switch(node.getKind()) {
case METHOD:
case CLASS:
return false;
case WHILE_LOOP:
case FOR_LOOP:
case ENHANCED_FOR_LOOP:
case DO_WHILE_LOOP:
return true;
default:
path = path.getParentPath();
node = path.getLeaf();
break;
}
}
return false;
}
};
}
Aggregations