public BlockTemplateMatch(JCBlock block, Unifier unifier, int start, int end) { super(checkNotNull(block).getStatements().get(start), unifier); this.statements = ImmutableList.copyOf(block.getStatements().subList(start, end)); }
private static boolean isFunctionArgSubtypeOf( Tree param, int argIndex, Type type, VisitorState state) { return ASTHelpers.isSubtype( ASTHelpers.getType(param).getTypeArguments().get(argIndex), type, state); }
/** * Extracts the appropriate type argument from a specific supertype of the given {@code type}. * This handles the case when a subtype has different type arguments than the expected type. For * example, {@code ClassToInstanceMap<T>} implements {@code Map<Class<? extends T>, T>}. * * @param type the (sub)type from which to extract the type argument * @param superTypeSym the symbol of the supertype on which the type parameter is defined * @param typeArgIndex the index of the type argument to extract from the supertype * @param types the {@link Types} utility class from the {@link VisitorState} * @return the type argument, if defined, or null otherwise */ @Nullable protected static final Type extractTypeArgAsMemberOfSupertype( Type type, Symbol superTypeSym, int typeArgIndex, Types types) { Type collectionType = types.asSuper(type, superTypeSym); if (collectionType == null) { return null; } com.sun.tools.javac.util.List<Type> tyargs = collectionType.getTypeArguments(); if (tyargs.size() <= typeArgIndex) { // Collection is raw, nothing we can do. return null; } return tyargs.get(typeArgIndex); } }
@Override public void visitApply(JCMethodInvocation tree) { JCExpression select = tree.getMethodSelect(); if (select != null && select.toString().equals("Refaster.emitCommentBefore")) { String commentLiteral = (String) ((JCLiteral) tree.getArguments().get(0)).getValue(); JCExpression expr = tree.getArguments().get(1); try { print("/* " + commentLiteral + " */ "); } catch (IOException e) { throw new RuntimeException(e); } expr.accept(this); } else { super.visitApply(tree); } }
JCTree inlineBody(Inliner inliner) throws CouldNotResolveImportException { if (getBody() instanceof UPlaceholderExpression) { UPlaceholderExpression body = (UPlaceholderExpression) getBody(); Optional<List<JCStatement>> blockBinding = inliner.getOptionalBinding(body.placeholder().blockKey()); if (blockBinding.isPresent()) { // this lambda is of the form args -> blockPlaceholder(); List<JCStatement> blockInlined = UPlaceholderExpression.copier(body.arguments(), inliner) .copy(blockBinding.get(), inliner); if (blockInlined.size() == 1) { if (blockInlined.get(0) instanceof JCReturn) { return ((JCReturn) blockInlined.get(0)).getExpression(); } else if (blockInlined.get(0) instanceof JCExpressionStatement) { return ((JCExpressionStatement) blockInlined.get(0)).getExpression(); } } return inliner.maker().Block(0, blockInlined); } } return getBody().inline(inliner); }
@Override public Type get(VisitorState state) { JCExpression jcExpression = (JCExpression) expressionSupplier.get(state); if (jcExpression.type.getTypeArguments().size() <= n) { return state.getSymtab().objectType; } return jcExpression.type.getTypeArguments().get(n); } };
@Override public Type get(VisitorState state) { Type type = typeSupplier.get(state); if (type.getTypeArguments().size() <= n) { return state.getSymtab().objectType; } return type.getTypeArguments().get(n); } };
/** * Works for method parameters defined either in source or in class files * * @param symbol the method symbol * @param paramInd index of the parameter * @return all declaration and type-use annotations for the parameter */ public static Stream<? extends AnnotationMirror> getAllAnnotationsForParameter( Symbol.MethodSymbol symbol, int paramInd) { Symbol.VarSymbol varSymbol = symbol.getParameters().get(paramInd); return Stream.concat( varSymbol.getAnnotationMirrors().stream(), symbol .getRawTypeAttributes() .stream() .filter( t -> t.position.type.equals(TargetType.METHOD_FORMAL_PARAMETER) && t.position.parameter_index == paramInd)); }
@Override public Description matchMethod(MethodTree node, VisitorState state) { Symbol.MethodSymbol method = ASTHelpers.getSymbol(node); if (method == null) { return Description.NO_MATCH; } List<Integer> compileTimeConstantAnnotationIndexes = new ArrayList<>(); for (int i = 0; i < method.getParameters().size(); i++) { if (hasCompileTimeConstantAnnotation(state, method.getParameters().get(i))) { compileTimeConstantAnnotationIndexes.add(i); } } if (compileTimeConstantAnnotationIndexes.isEmpty()) { return Description.NO_MATCH; } for (Symbol.MethodSymbol superMethod : ASTHelpers.findSuperMethods(method, state.getTypes())) { for (Integer index : compileTimeConstantAnnotationIndexes) { if (!hasCompileTimeConstantAnnotation(state, superMethod.getParameters().get(index))) { return buildDescription(node) .setMessage( "Method with @CompileTimeConstant parameter can't override method without it.") .build(); } } } return Description.NO_MATCH; }
public void addShadowType(TypeElement shadowType, TypeElement actualType, TypeElement shadowPickerType) { TypeElement shadowBaseType = null; if (shadowPickerType != null) { TypeMirror iface = helpers.findInterface(shadowPickerType, ShadowPicker.class); if (iface != null) { com.sun.tools.javac.code.Type type = ((com.sun.tools.javac.code.Type.ClassType) iface) .allparams().get(0); String baseClassName = type.asElement().getQualifiedName().toString(); shadowBaseType = helpers.getTypeElement(baseClassName); } } ShadowInfo shadowInfo = new ShadowInfo(shadowType, actualType, shadowPickerType, shadowBaseType); if (shadowInfo.isInAndroidSdk()) { registerType(shadowInfo.shadowType); registerType(shadowInfo.actualType); registerType(shadowInfo.shadowBaseClass); } shadowTypes.put(shadowType.getQualifiedName().toString(), shadowInfo); }
@Override public void printStat(JCTree tree) throws IOException { if (tree instanceof JCExpressionStatement && ((JCExpressionStatement) tree).getExpression() instanceof JCMethodInvocation) { JCMethodInvocation invocation = (JCMethodInvocation) ((JCExpressionStatement) tree).getExpression(); JCExpression select = invocation.getMethodSelect(); if (select != null && select.toString().equals("Refaster.emitComment")) { String commentLiteral = (String) ((JCLiteral) invocation.getArguments().get(0)).getValue(); print("// " + commentLiteral); return; } } super.printStat(tree); }
@Nullable private Type visitMethodInvocationOrNewClass( List<? extends ExpressionTree> arguments, MethodSymbol sym, Type type) { int idx = arguments.indexOf(current); if (idx == -1) { return null; } if (type.getParameterTypes().size() <= idx) { if (!sym.isVarArgs()) { if ((sym.flags() & Flags.HYPOTHETICAL) != 0) { // HYPOTHETICAL is also used for signature-polymorphic methods return null; } throw new IllegalStateException( String.format( "saw %d formal parameters and %d actual parameters on non-varargs method %s\n", type.getParameterTypes().size(), arguments.size(), sym)); } idx = type.getParameterTypes().size() - 1; } Type argType = type.getParameterTypes().get(idx); if (sym.isVarArgs() && idx == type.getParameterTypes().size() - 1) { argType = state.getTypes().elemtype(argType); } return argType; }
@Override public boolean matches(ExpressionTree t, VisitorState state) { Type type = ((JCTree) t).type; // Expect a class type. if (!(type instanceof ClassType)) { return false; } // Expect one type argument, the type of the JUnit class runner to use. com.sun.tools.javac.util.List<Type> typeArgs = ((ClassType) type).getTypeArguments(); if (typeArgs.size() != 1) { return false; } Type runnerType = typeArgs.get(0); for (String testRunner : TEST_RUNNERS) { Symbol parent = state.getSymbolFromString(testRunner); if (parent == null) { continue; } if (runnerType.tsym.isSubClass(parent, state.getTypes())) { return true; } } return false; } };
public Description describe(MethodTree tree, VisitorState state) { SuggestedFix.Builder builder = null; MethodSymbol method = ASTHelpers.getSymbol(tree); if (supermethod == null) { throw new IllegalStateException("Matching supermethod was not found"); } for (int x = 0; x < method.params().size(); x++) { Type methodParamType = method.params().get(x).type; Type supermethodParamType = supermethod.params().get(x).type; if (methodParamType.tsym.name.contentEquals(supermethodParamType.tsym.name) && !state.getTypes().isSameType(methodParamType, supermethodParamType)) { VariableTree param = tree.getParameters().get(x); // TODO(user): Name is most likely more qualified than necessary. Name replacement = supermethodParamType.tsym.getQualifiedName(); if (builder == null) { builder = SuggestedFix.builder(); } builder.replace(param, replacement + " " + param.getName()); } } return (builder != null) ? describeMatch(tree, builder.build()) : describeMatch(tree); } }
@Override public boolean apply(MethodSymbol methodSymbol) { return !methodSymbol.isStatic() && ((methodSymbol.flags() & Flags.SYNTHETIC) == 0) && ((methodSymbol.flags() & Flags.ABSTRACT) == 0) && methodSymbol.getParameters().size() == 1 && types.isSameType( methodSymbol.getParameters().get(0).type, state.getSymtab().objectType); } };
/** Tokenizes as little of the {@code tree} as possible to ensure we grab all the annotations. */ private static ImmutableList<ErrorProneToken> annotationTokens( Tree tree, VisitorState state, int annotationEnd) { int endPos; if (tree instanceof JCMethodDecl) { JCMethodDecl methodTree = (JCMethodDecl) tree; endPos = methodTree.getBody() == null ? state.getEndPosition(methodTree) : methodTree.getBody().getStartPosition(); } else if (tree instanceof JCVariableDecl) { endPos = ((JCVariableDecl) tree).getType().getStartPosition(); } else if (tree instanceof JCClassDecl) { JCClassDecl classTree = (JCClassDecl) tree; endPos = classTree.getMembers().isEmpty() ? state.getEndPosition(classTree) : classTree.getMembers().get(0).getStartPosition(); } else { throw new AssertionError(); } return ErrorProneTokens.getTokens( state.getSourceCode().subSequence(annotationEnd, endPos).toString(), state.context); }
try { boolean exactlyOneParamWithNoType = lambda.params.size() == 1 && lambda.params.get(0).vartype == null; if (!exactlyOneParamWithNoType) { print("(");
@Override public Description matchMemberReference(MemberReferenceTree tree, VisitorState state) { Type predicateType = predicateType(ASTHelpers.getType(tree), state); if (predicateType == null) { return NO_MATCH; } Type receiverType = ASTHelpers.getReceiverType(tree); if (tree.getName().contentEquals("equals") && !EqualsIncompatibleType.compatibilityOfTypes(receiverType, predicateType, state) .compatible()) { return buildMessage(receiverType, predicateType, tree); } if (tree.getName().contentEquals("isInstance") && ASTHelpers.isSameType(receiverType, state.getSymtab().classType, state) && !receiverType.getTypeArguments().isEmpty()) { Type argumentType = receiverType.getTypeArguments().get(0); Type upperBound = ASTHelpers.getUpperBound(predicateType, state.getTypes()); if (!EqualsIncompatibleType.compatibilityOfTypes(upperBound, argumentType, state) .compatible()) { return buildMessage(upperBound, argumentType, tree); } } return NO_MATCH; }
static Type getTargetType(VisitorState state) { Tree parent = state.getPath().getParentPath().getLeaf(); Type type; if (parent instanceof VariableTree || parent instanceof AssignmentTree) { type = ASTHelpers.getType(parent); } else if (parent instanceof ReturnTree || parent instanceof LambdaExpressionTree) { type = getMethodOrLambdaReturnType(state); } else if (parent instanceof MethodInvocationTree) { MethodInvocationTree tree = (MethodInvocationTree) parent; int idx = tree.getArguments().indexOf(state.getPath().getLeaf()); if (idx == -1) { return null; } Type methodType = ASTHelpers.getType(tree.getMethodSelect()); if (idx >= methodType.getParameterTypes().size()) { return null; } return methodType.getParameterTypes().get(idx); } else { return null; } Tree tree = state.getPath().getLeaf(); if (tree instanceof MemberReferenceTree) { type = state.getTypes().findDescriptorType(ASTHelpers.getType(tree)).getReturnType(); } return type; }
private static void replaceAssert( SuggestedFix.Builder fix, AssertTree foundAssert, VisitorState state) { ExpressionTree expr = foundAssert.getCondition(); expr = (ExpressionTree) TreeInfo.skipParens((JCTree) expr); // case: "assert !expr" if (expr.getKind().equals(LOGICAL_COMPLEMENT)) { addFix(fix, ((JCUnary) expr).getExpression(), foundAssert, state, IS_FALSE); return; } // case: "assert expr1.equals(expr2)" if (instanceMethod().onClass(Any.INSTANCE).named("equals").matches(expr, state)) { JCMethodInvocation equalsCall = ((JCMethodInvocation) expr); JCExpression expr1 = ((JCFieldAccess) ((JCMethodInvocation) expr).meth).selected; JCExpression expr2 = equalsCall.getArguments().get(0); addFix( fix, expr1, foundAssert, state, String.format(IS_EQUAL_TO, normalizedSourceForExpression(expr2, state))); return; } // case: "assert expr1 == expr2" or "assert expr1 != expr2" if (expr.getKind().equals(Kind.EQUAL_TO) || expr.getKind().equals(Kind.NOT_EQUAL_TO)) { suggestFixForSameReference(fix, foundAssert, state, expr.getKind().equals(Kind.EQUAL_TO)); return; } // case: "assert expr", which didn't match any of the previous cases. addFix(fix, (JCExpression) expr, foundAssert, state, IS_TRUE); }