use of com.google.errorprone.VisitorState in project error-prone by google.
the class TypeParameterShadowing method renameTypeVariable.
private static SuggestedFix renameTypeVariable(Tree sourceTree, List<? extends TypeParameterTree> typeParameters, Name typeVariable, String typeVarReplacement, VisitorState state) {
TypeParameterTree matchingTypeParam = typeParameters.stream().filter(t -> t.getName().contentEquals(typeVariable)).collect(MoreCollectors.onlyElement());
Symbol typeVariableSymbol = ASTHelpers.getSymbol(matchingTypeParam);
// replace only the type parameter name (and not any upper bounds)
String name = matchingTypeParam.getName().toString();
int pos = ((JCTree) matchingTypeParam).getStartPosition();
SuggestedFix.Builder fixBuilder = SuggestedFix.builder().replace(pos, pos + name.length(), typeVarReplacement);
((JCTree) sourceTree).accept(new TreeScanner() {
@Override
public void visitIdent(JCTree.JCIdent tree) {
Symbol identSym = ASTHelpers.getSymbol(tree);
if (Objects.equal(identSym, typeVariableSymbol)) {
// }
if (Objects.equal(state.getSourceForNode(tree), name)) {
fixBuilder.replace(tree, typeVarReplacement);
}
}
}
});
return fixBuilder.build();
}
use of com.google.errorprone.VisitorState in project error-prone by google.
the class AbstractArgumentParameterChecker method findReplacements.
private Description findReplacements(List<? extends ExpressionTree> args, com.sun.tools.javac.util.List<VarSymbol> params, boolean isVarArgs, VisitorState state, Tree tree) {
if (args.isEmpty()) {
return Description.NO_MATCH;
}
ImmutableSet<PotentialReplacement> potentialReplacements = potentialReplacementsFunction.apply(state.withPath(new TreePath(state.getPath(), args.get(0))));
SuggestedFix.Builder fix = SuggestedFix.builder();
// Don't suggest for the varargs parameter.
// TODO(eaftan): Reconsider this, especially if the argument is of array type or is itself
// a varargs parameter.
int maxArg = isVarArgs ? params.size() - 1 : params.size();
for (int i = 0; i < maxArg; i++) {
ExpressionTree arg = args.get(i);
VarSymbol param = params.get(i);
if (!validKinds.contains(arg.getKind()) || !parameterPredicate.test(param)) {
continue;
}
String extractedArgumentName = extractArgumentName(arg);
if (extractedArgumentName == null) {
continue;
}
double currSimilarity = similarityMetric.applyAsDouble(extractedArgumentName, param.getSimpleName().toString());
if (1.0 - currSimilarity < beta) {
// No way for any replacement to be at least BETA better than the current argument
continue;
}
ReplacementWithSimilarity bestReplacement = potentialReplacements.stream().filter(replacement -> !replacement.sym().equals(ASTHelpers.getSymbol(arg))).filter(replacement -> isSubtypeHandleCompletionFailures(replacement.sym(), param, state)).map(replacement -> ReplacementWithSimilarity.create(replacement, similarityMetric.applyAsDouble(replacement.argumentName(), param.getSimpleName().toString()))).max(Comparator.comparingDouble(ReplacementWithSimilarity::similarity)).orElse(null);
if ((bestReplacement != null) && (bestReplacement.similarity() - currSimilarity >= beta)) {
fix.replace(arg, bestReplacement.replacement().replacementString());
}
}
if (fix.isEmpty()) {
return Description.NO_MATCH;
} else {
return describeMatch(tree, fix.build());
}
}
use of com.google.errorprone.VisitorState in project error-prone by google.
the class AmbiguousMethodReference method matchClass.
@Override
public Description matchClass(ClassTree tree, VisitorState state) {
ClassSymbol origin = getSymbol(tree);
Types types = state.getTypes();
Iterable<Symbol> members = types.membersClosure(getType(tree), /*skipInterface=*/
false).getSymbols();
// collect declared and inherited methods, grouped by reference descriptor
Map<String, List<MethodSymbol>> methods = stream(members.spliterator(), false).filter(MethodSymbol.class::isInstance).map(MethodSymbol.class::cast).filter(m -> m.isConstructor() || m.owner.equals(origin)).collect(groupingBy(m -> methodReferenceDescriptor(types, m), toCollection(ArrayList::new)));
// look for groups of ambiguous method references
for (Tree member : tree.getMembers()) {
if (!(member instanceof MethodTree)) {
continue;
}
MethodSymbol msym = getSymbol((MethodTree) member);
if (isSuppressed(msym)) {
continue;
}
List<MethodSymbol> clash = methods.remove(methodReferenceDescriptor(types, msym));
if (clash == null) {
continue;
}
clash.remove(msym);
// ignore overridden inherited methods and hidden interface methods
clash.removeIf(m -> types.isSubSignature(msym.type, m.type));
if (clash.isEmpty()) {
continue;
}
String message = String.format("This method's reference is ambiguous, its name and functional interface type" + " are the same as: %s", clash.stream().map(m -> Signatures.prettyMethodSignature(origin, m)).collect(joining(", ")));
state.reportMatch(buildDescription(member).setMessage(message).build());
}
return NO_MATCH;
}
use of com.google.errorprone.VisitorState in project error-prone by google.
the class CompileTimeConstantExpressionMatcherTest method assertCompilerMatchesOnAssignment.
// Helper methods.
private void assertCompilerMatchesOnAssignment(final Map<String, Boolean> expectedMatches, String... lines) {
final Matcher<ExpressionTree> matcher = new CompileTimeConstantExpressionMatcher();
final Scanner scanner = new Scanner() {
@Override
public Void visitAssignment(AssignmentTree t, VisitorState state) {
ExpressionTree lhs = t.getVariable();
if (expectedMatches.containsKey(lhs.toString())) {
boolean matches = matcher.matches(t.getExpression(), state);
if (expectedMatches.get(lhs.toString())) {
assertTrue("Matcher should match expression" + t.getExpression(), matches);
} else {
assertFalse("Matcher should not match expression" + t.getExpression(), matches);
}
}
return super.visitAssignment(t, state);
}
};
CompilationTestHelper.newInstance(ScannerSupplier.fromScanner(scanner), getClass()).expectResult(Result.OK).addSourceLines("test/CompileTimeConstantExpressionMatcherTestCase.java", lines).doTest();
}
use of com.google.errorprone.VisitorState in project error-prone by google.
the class ThreadSafety method getAnnotation.
private AnnotationInfo getAnnotation(Symbol sym, VisitorState state, String annotation, @Nullable Class<? extends Annotation> elementAnnotation) {
if (sym == null) {
return null;
}
Symbol annosym = state.getSymbolFromString(annotation);
Optional<Compound> attr = sym.getAnnotationMirrors().stream().filter(a -> a.getAnnotationType().asElement().equals(annosym)).findAny();
if (attr.isPresent()) {
ImmutableList<String> containerElements = containerOf(state, attr.get());
if (elementAnnotation != null && containerElements.isEmpty()) {
containerElements = sym.getTypeParameters().stream().filter(p -> p.getAnnotation(elementAnnotation) != null).map(p -> p.getSimpleName().toString()).collect(toImmutableList());
}
return AnnotationInfo.create(sym.getQualifiedName().toString(), containerElements);
}
// @ThreadSafe is inherited from supertypes
if (!(sym instanceof ClassSymbol)) {
return null;
}
Type superClass = ((ClassSymbol) sym).getSuperclass();
AnnotationInfo superAnnotation = getInheritedAnnotation(superClass.asElement(), state);
if (superAnnotation == null) {
return null;
}
// If an annotated super-type was found, look for any type arguments to the super-type that
// are in the super-type's containerOf spec, and where the arguments are type parameters
// of the current class.
// E.g. for `Foo<X> extends Super<X>` if `Super<Y>` is annotated
// `@ThreadSafeContainerAnnotation Y`
// then `Foo<X>` is has X implicitly annotated `@ThreadSafeContainerAnnotation X`
ImmutableList.Builder<String> containerOf = ImmutableList.builder();
for (int i = 0; i < superClass.getTypeArguments().size(); i++) {
Type arg = superClass.getTypeArguments().get(i);
TypeVariableSymbol formal = superClass.asElement().getTypeParameters().get(i);
if (!arg.hasTag(TypeTag.TYPEVAR)) {
continue;
}
TypeSymbol argSym = arg.asElement();
if (argSym.owner == sym && superAnnotation.containerOf().contains(formal.getSimpleName().toString())) {
containerOf.add(argSym.getSimpleName().toString());
}
}
return AnnotationInfo.create(superAnnotation.typeName(), containerOf.build());
}
Aggregations