private String generateFix(MethodInvocationTree methodInvocation, boolean negated) { String methodName = ASTHelpers.getSymbol(methodInvocation).getQualifiedName().toString(); String countMethod = methodName + "Count"; return String.format( "%s.%s() %s %s", getReceiver(methodInvocation), countMethod, negated ? "<=" : ">", getOnlyElement(methodInvocation.getArguments())); } },
fullyQualifiedClazz); List<String> topLevelPath = Splitter.on('.').splitToList(topLevelClazz); String topClazz = Iterables.getLast(topLevelPath); List<String> qualifiedPath = Splitter.on('.').splitToList(fullyQualifiedClazz); boolean importTopLevelClazz = false, conflictTopLevelClazz = false; if (!importTopLevelClazz) { conflictTopLevelClazz |= topClazz.equals(Iterables.getLast(Splitter.on('.').split(importName))); if (currentPackage == null || !currentPackage.getQualifiedName().contentEquals(packge)) {
/** Gets a human-friendly name for the given {@link Symbol} to use in diagnostics. */ public String getPrettyName(Symbol sym) { if (!sym.getSimpleName().isEmpty()) { return sym.getSimpleName().toString(); } if (sym.getKind() == ElementKind.ENUM) { // anonymous classes for enum constants are identified by the enclosing constant // declaration return sym.owner.getSimpleName().toString(); } // anonymous classes have an empty name, but a recognizable superclass or interface // e.g. refer to `new Runnable() { ... }` as "Runnable" Type superType = state.getTypes().supertype(sym.type); if (state.getTypes().isSameType(superType, state.getSymtab().objectType)) { superType = Iterables.getFirst(state.getTypes().interfaces(sym.type), superType); } return superType.tsym.getSimpleName().toString(); }
/** Returns true if the given symbol has static modifier and is all upper case. */ private static boolean isUpperCaseAndStatic(Symbol symbol) { return symbol.isStatic() && symbol.name.contentEquals(Ascii.toUpperCase(symbol.name.toString())); }
private static boolean knownNonNullMethod( MethodSymbol methodSymbol, ClassSymbol clazzSymbol, @Nullable Types types) { if (types == null) { return false; } // Proto getters are not null if (methodSymbol.name.toString().startsWith("get") && methodSymbol.params().isEmpty() && !methodSymbol.isStatic()) { Type type = clazzSymbol.type; while (type != null) { TypeSymbol typeSymbol = type.asElement(); if (typeSymbol == null) { break; } if (typeSymbol .getQualifiedName() .contentEquals("com.google.protobuf.AbstractMessageLite")) { return true; } type = types.supertype(type); } } return false; }
private static Set<Modifier> getIncompatibleModifiers(AnnotationTree tree, VisitorState state) { for (Attribute.Compound c : ASTHelpers.getSymbol(tree).getAnnotationMirrors()) { if (((TypeElement) c.getAnnotationType().asElement()) .getQualifiedName() .contentEquals(GUAVA_ANNOTATION)) { @SuppressWarnings("unchecked") List<Attribute.Enum> modifiers = (List<Attribute.Enum>) c.member(state.getName("value")).getValue(); return ImmutableSet.copyOf( Iterables.transform( modifiers, (Attribute.Enum input) -> Modifier.valueOf(input.getValue().name.toString()))); } } IncompatibleModifiers annotation = ASTHelpers.getAnnotation(tree, IncompatibleModifiers.class); if (annotation != null) { return ImmutableSet.copyOf(annotation.value()); } return ImmutableSet.of(); }
MethodSymbol symbol = ASTHelpers.getSymbol(invocation); Symtab symtab = state.getSymtab(); List<? extends ExpressionTree> args = invocation.getArguments(); switch (symbol.getSimpleName().toString()) { case "expect": Type type = ASTHelpers.getType(getOnlyElement(invocation.getArguments())); if (isSubtype(type, symtab.classType, state)) { ExpressionTree arg = getOnlyElement(args); exceptionClassExpr = state.getSourceForNode(arg); ExpressionTree exceptionClassTree; Type matcherType = state.getTypes().asSuper(type, state.getSymbolFromString("org.hamcrest.Matcher")); if (!matcherType.getTypeArguments().isEmpty()) { Type matchType = getOnlyElement(matcherType.getTypeArguments()); if (isSubtype(matchType, symtab.throwableType, state)) { exceptionClassName = SuggestedFixes.qualifyType(state, fix, matchType); ExpressionTree matcher = getOnlyElement(invocation.getArguments()); if (IS_A.matches(matcher, state)) { fix.addStaticImport("com.google.common.truth.Truth.assertThat"); case "expectMessage": if (isSubtype( getOnlyElement(symbol.getParameters()).asType(), symtab.stringType, state)) {
.map( param -> Iterables.tryFind( enclosingTypes, sym -> Streams.stream(Iterables.concat(env.info.getLocalElements(), enclosingTypes)) .map(sym -> sym.getSimpleName().toString()) .collect(ImmutableSet.toImmutableSet()); .filter(tv -> TypeParameterNamingClassification.classify(tv.name.toString()).isValidName()) .map( tv ->
private static String getFullyQualifiedName(JCCompilationUnit tree) { Iterator<JCClassDecl> types = Iterables.filter(tree.getTypeDecls(), JCClassDecl.class).iterator(); if (types.hasNext()) { return Iterators.getOnlyElement(types).sym.getQualifiedName().toString(); } // Fallback: if no class is declared, then assume we're looking at a `package-info.java`. return tree.getPackage().packge.package_info.toString(); }
/** Ignore some common ThreadLocal type arguments that are fine to have per-instance copies of. */ private boolean wellKnownTypeArgument(NewClassTree tree, VisitorState state) { Type type = getType(tree); if (type == null) { return false; } type = state.getTypes().asSuper(type, state.getSymbolFromString("java.lang.ThreadLocal")); if (type == null) { return false; } if (type.getTypeArguments().isEmpty()) { return false; } Type argType = getOnlyElement(type.getTypeArguments()); if (WELL_KNOWN_TYPES.contains(argType.asElement().getQualifiedName().toString())) { return true; } if (isSubtype(argType, state.getTypeFromString("java.text.DateFormat"), state)) { return true; } return false; } }
public static Collection<? extends CodeTransformer> extractRules( ClassTree tree, Context context) { ClassSymbol sym = ASTHelpers.getSymbol(tree); RefasterRuleBuilderScanner scanner = new RefasterRuleBuilderScanner(context); // visit abstract methods first List<MethodTree> methods = new Ordering<MethodTree>() { @Override public int compare(MethodTree l, MethodTree r) { return Boolean.compare( l.getModifiers().getFlags().contains(Modifier.ABSTRACT), r.getModifiers().getFlags().contains(Modifier.ABSTRACT)); } }.reverse().immutableSortedCopy(Iterables.filter(tree.getMembers(), MethodTree.class)); scanner.visit(methods, null); UTemplater templater = new UTemplater(context); List<UType> types = templater.templateTypes(sym.type.getTypeArguments()); return scanner.createMatchers( Iterables.filter(types, UTypeVar.class), sym.getQualifiedName().toString(), UTemplater.annotationMap(sym)); }
if (annotationQualifiedName.contentEquals(PROVIDES_CLASS_NAME) || annotationQualifiedName.contentEquals(PRODUCES_CLASS_NAME)) { List<JCExpression> arguments = annotation.getArguments(); if (!arguments.isEmpty()) { JCExpression argument = Iterables.getOnlyElement(arguments); checkState(argument.getKind().equals(ASSIGNMENT)); JCAssign assignment = (JCAssign) argument; checkState(getSymbol(assignment.getVariable()).getSimpleName().contentEquals("type")); String typeName = getSymbol(assignment.getExpression()).getSimpleName().toString(); switch (typeName) { case "SET":
private static HeldLockSet handleMonitorGuards(VisitorState state, HeldLockSet locks) { JCNewClass newClassTree = ASTHelpers.findEnclosingNode(state.getPath(), JCNewClass.class); if (newClassTree == null) { return locks; } Symbol clazzSym = ASTHelpers.getSymbol(newClassTree.clazz); if (!(clazzSym instanceof ClassSymbol)) { return locks; } if (!((ClassSymbol) clazzSym).fullname.contentEquals(MONITOR_GUARD_CLASS)) { return locks; } Optional<GuardedByExpression> lockExpression = GuardedByBinder.bindExpression( Iterables.getOnlyElement(newClassTree.getArguments()), state); if (!lockExpression.isPresent()) { return locks; } return locks.plus(lockExpression.get()); }
private void fixThrows(VisitorState state, SuggestedFix.Builder fix) { MethodTree methodTree = state.findEnclosing(MethodTree.class); if (methodTree == null || methodTree.getThrows().isEmpty()) { return; } ImmutableMap.Builder<Type, ExpressionTree> thrown = ImmutableMap.builder(); for (ExpressionTree e : methodTree.getThrows()) { thrown.put(ASTHelpers.getType(e), e); } UnhandledResult<ExpressionTree> result = unhandled(thrown.build(), state); if (result.unhandled.isEmpty()) { return; } List<String> newThrows = new ArrayList<>(); for (Type handle : result.unhandled) { newThrows.add(handle.tsym.getSimpleName().toString()); } Collections.sort(newThrows); fix.postfixWith( Iterables.getLast(methodTree.getThrows()), ", " + Joiner.on(", ").join(newThrows)); // the other exceptions are in java.lang fix.addImport("java.lang.reflect.InvocationTargetException"); }
private ClassAndField(VarSymbol symbol) { this.symbol = symbol; this.clazz = symbol.owner.getQualifiedName().toString(); this.field = symbol.getSimpleName().toString(); }
private static Fix adjustHashCodeCall(MethodInvocationTree tree, VisitorState state) { String argumentClass = state .getTypes() .boxedTypeOrType(ASTHelpers.getType(tree.getArguments().get(0))) .tsym .getSimpleName() .toString(); return SuggestedFix.builder() .prefixWith(tree, argumentClass + ".hashCode(") .replace(tree, state.getSourceForNode(tree.getArguments().get(0))) .postfixWith(tree, ")") .build(); } }
Set<String> containerTypeParameters, AnnotationInfo annotation, Type type) { if (!annotation.containerOf().isEmpty() && type.tsym.getTypeParameters().size() != type.getTypeArguments().size()) { return Violation.of( String.format( getPrettyName(type.tsym), Joiner.on(", ").join(annotation.containerOf()))); for (int i = 0; i < type.tsym.getTypeParameters().size(); i++) { TypeVariableSymbol typaram = type.tsym.getTypeParameters().get(i); boolean immutableTypeParameter = hasThreadSafeTypeParameterAnnotation(typaram); if (annotation.containerOf().contains(typaram.getSimpleName().toString()) || immutableTypeParameter) { Type tyarg = type.getTypeArguments().get(i); if (suppressAnnotation != null && tyarg.getAnnotationMirrors().stream() .anyMatch( a -> ((ClassSymbol) a.getAnnotationType().asElement()) .flatName() .contentEquals(suppressAnnotation.getName()))) { continue;
String name = classdecl.getSimpleName().toString(); if (context.hasClassNameMapping(classdecl.sym)) { name = context.getClassNameMapping(classdecl.sym); if (context.lookupDecoratorAnnotation(classdecl.sym.getQualifiedName().toString()) != null) { JCTree[] globalDecoratorFunction = context .lookupGlobalMethod(classdecl.sym.getQualifiedName().toString()); if (globalDecoratorFunction == null) { report(classdecl, JSweetProblem.CANNOT_FIND_GLOBAL_DECORATOR_FUNCTION, boolean globals = JSweetConfig.GLOBALS_CLASS_NAME.equals(classdecl.name.toString()); if (globals && classdecl.extending != null) { report(classdecl, JSweetProblem.GLOBALS_CLASS_CANNOT_HAVE_SUPERCLASS); .equals(classdecl.extending.type.tsym.getSimpleName().toString())) { report(classdecl, JSweetProblem.GLOBALS_CLASS_CANNOT_BE_SUBCLASSED); return; && classdecl.extending.type.tsym.getQualifiedName().toString() .equals(Iterable.class.getName())) { removeIterable = true; if (itf.type.tsym.getQualifiedName().toString().equals(Iterable.class.getName())) { implementing.remove(itf); entry.getValue().getName().toString(), (MethodType) entry.getValue().type); if (s == null || s == entry.getValue().sym) { getAdapter().typeVariablesToErase
private static String getMethodName(ExpressionTree tree) { MethodInvocationTree method = (MethodInvocationTree) tree; ExpressionTree expressionTree = method.getMethodSelect(); JCFieldAccess access = (JCFieldAccess) expressionTree; return access.sym.getQualifiedName().toString(); }