/** Removes the message argument if it is present. */ private void removeMessageArgumentIfPresent(VisitorState state, List<Type> argumentTypes) { if (argumentTypes.size() == 2) { return; } Types types = state.getTypes(); Type firstType = argumentTypes.get(0); if (types.isSameType(firstType, state.getSymtab().stringType)) { argumentTypes.remove(0); } }
@Override public boolean matches(BinaryTree tree, VisitorState state) { Type leftType = ((JCTree) tree.getLeftOperand()).type; Types types = state.getTypes(); Symtab symtab = state.getSymtab(); if (!(types.isSameType(leftType, symtab.intType)) && !(types.isSameType(leftType, symtab.byteType)) && !(types.isSameType(leftType, symtab.shortType)) && !(types.isSameType(leftType, symtab.charType))) { return false; } ExpressionTree rightOperand = tree.getRightOperand(); if (rightOperand instanceof LiteralTree) { Object rightValue = ((LiteralTree) rightOperand).getValue(); if (rightValue instanceof Number) { int intValue = ((Number) rightValue).intValue(); return intValue < 0 || intValue > 31; } } return false; } };
private DoubleAndFloatStatus doubleAndFloatStatus( VisitorState state, Type recieverType, Type argType) { Types types = state.getTypes(); if (!types.isSameType(recieverType, state.getSymtab().floatType)) { return DoubleAndFloatStatus.NONE; } if (types.isSameType(argType, types.boxedClass(state.getSymtab().doubleType).type)) { return DoubleAndFloatStatus.BOXED_DOUBLE_INTO_FLOAT; } if (types.isSameType(argType, state.getSymtab().doubleType)) { return DoubleAndFloatStatus.PRIMITIVE_DOUBLE_INTO_FLOAT; } return DoubleAndFloatStatus.NONE; }
private static TreeSet<Type> typeSet(VisitorState state) { return new TreeSet<>( (t1, t2) -> state.getTypes().isSameType(t1, t2) ? 0 : t1.toString().compareTo(t2.toString())); } }
private static boolean hasInitialStringParameter(MethodSymbol sym, VisitorState state) { Types types = state.getTypes(); List<VarSymbol> parameters = sym.getParameters(); return !parameters.isEmpty() && types.isSameType(parameters.get(0).type, state.getSymtab().stringType); }
private static boolean isEqualsMethod( MemberName calleeName, List<Node> arguments, Types types, Symtab symtab) { // we don't care about class name -- we're matching against Object.equals(Object) // this implies that non-overriding methods are assumed to be null-guaranteeing. // Also see http://errorprone.info/bugpattern/NonOverridingEquals if (!calleeName.member.equals("equals") || arguments.size() != 1) { return false; } if (!(getOnlyElement(arguments).getTree() instanceof JCIdent)) { return false; } Symbol sym = ((JCIdent) getOnlyElement(arguments).getTree()).sym; if (sym == null || sym.type == null) { return false; } return types.isSameType(sym.type, symtab.objectType) && (!variablesAtIndexes(ImmutableSet.of(0), arguments).isEmpty()); }
private static ImmutableMap<TypeVariableSymbol, Type> getInstantiation( Types types, Type methodType) { List<Type> to = new ArrayList<>(); ArrayList<Type> from = new ArrayList<>(); getSubst(getMapping(methodType), from, to); Map<TypeVariableSymbol, Type> mapping = new LinkedHashMap<>(); Streams.forEachPair( from.stream(), to.stream(), (f, t) -> { Type existing = mapping.put((TypeVariableSymbol) f.asElement(), t); if (existing != null && !types.isSameType(t, existing)) { throw new AssertionError( String.format("%s instantiated as both %s and %s", f.asElement(), t, existing)); } }); return ImmutableMap.copyOf(mapping); }
@Override public boolean matches(T t, VisitorState state) { Type type = getType(t); return type != null && state.getTypes().isSameType(type, state.getSymtab().voidType); } };
static boolean equivalentExprs(Unifier unifier, JCExpression expr1, JCExpression expr2) { return expr1.type != null && expr2.type != null && Types.instance(unifier.getContext()).isSameType(expr2.type, expr1.type) && expr2.toString().equals(expr1.toString()); }
/** Returns true if {@code erasure(s) == erasure(t)}. */ public static boolean isSameType(Type s, Type t, VisitorState state) { if (s == null || t == null) { return false; } Types types = state.getTypes(); return types.isSameType(types.erasure(s), types.erasure(t)); }
/** Return true if the given type is 'void' or 'Void'. */ public static boolean isVoidType(Type type, VisitorState state) { if (type == null) { return false; } return type.getKind() == TypeKind.VOID || state.getTypes().isSameType(Suppliers.JAVA_LANG_VOID_TYPE.get(state), type); }
private Multimap<Type, VariableTree> partitionParametersByType( List<VariableTree> parameters, VisitorState state) { Types types = state.getTypes(); Multimap<Type, VariableTree> multimap = LinkedListMultimap.create(); variables: for (VariableTree node : parameters) { // Normalize Integer => int Type type = types.unboxedTypeOrType(ASTHelpers.getType(node)); for (Type existingType : multimap.keySet()) { if (types.isSameType(existingType, type)) { multimap.put(existingType, node); continue variables; } } // A new type for the map. multimap.put(type, node); } return multimap; } }
private boolean isIgnoredReturnType(JCMethodDecl method, VisitorState state) { Type returnType = method.sym.getReturnType(); // Methods returning a primitive cannot return null. Also ignore Void-returning methods as // the only valid Void value is null, so it's implied. // TODO(kmb): Technically we should assume NULL when we see a call to a method that returns Void return returnType.isPrimitiveOrVoid() || state.getTypes().isSameType(returnType, state.getTypeFromString("java.lang.Void")); }
@Override public Description matchMethodInvocation(MethodInvocationTree tree, VisitorState state) { if (!MATCHER.matches(tree, state)) { return NO_MATCH; } List<? extends ExpressionTree> arguments = tree.getArguments(); Symtab syms = state.getSymtab(); Types types = state.getTypes(); if (types.isSameType(types.unboxedTypeOrType(getType(arguments.get(0))), syms.intType) && types.isSameType(types.unboxedTypeOrType(getType(arguments.get(1))), syms.charType)) { return describeMatch( tree, SuggestedFix.builder() .replace(arguments.get(0), state.getSourceForNode(arguments.get(1))) .replace(arguments.get(1), state.getSourceForNode(arguments.get(0))) .build()); } return NO_MATCH; } }
@Override public Description matchMethodInvocation(MethodInvocationTree tree, VisitorState state) { if (!MATCHER.matches(tree, state)) { return NO_MATCH; } List<? extends ExpressionTree> arguments = tree.getArguments(); Symtab syms = state.getSymtab(); Types types = state.getTypes(); if (types.isSameType(types.unboxedTypeOrType(getType(arguments.get(1))), syms.intType) && types.isSameType(types.unboxedTypeOrType(getType(arguments.get(0))), syms.charType)) { return describeMatch( tree, SuggestedFix.builder() .replace(arguments.get(0), state.getSourceForNode(arguments.get(1))) .replace(arguments.get(1), state.getSourceForNode(arguments.get(0))) .build()); } return NO_MATCH; } }
private boolean isStringConcat(Tree tree, VisitorState state) { return (tree.getKind() == Kind.PLUS || tree.getKind() == Kind.PLUS_ASSIGNMENT) && state.getTypes().isSameType(ASTHelpers.getType(tree), state.getSymtab().stringType); }
boolean isKnownCheckedException(VisitorState state, Type type) { Types types = state.getTypes(); Symtab symtab = state.getSymtab(); // Check erasure for generics. type = types.erasure(type); return // Has to be some Exception: A variable of type Throwable might be an Error. types.isSubtype(type, symtab.exceptionType) // Has to be some subtype: A variable of type Exception might be a RuntimeException. && !types.isSameType(type, symtab.exceptionType) // Can't be of type RuntimeException. && !types.isSubtype(type, symtab.runtimeExceptionType); } };
/** * Return true if this parameter is assignable to the target parameter. This will consider * subclassing, autoboxing and null. */ boolean isAssignableTo(Parameter target, VisitorState state) { if (state.getTypes().isSameType(type(), Type.noType) || state.getTypes().isSameType(target.type(), Type.noType)) { return false; } try { return state.getTypes().isAssignable(type(), target.type()); } catch (CompletionFailure e) { // Report completion errors to avoid e.g. https://github.com/bazelbuild/bazel/issues/4105 Check.instance(state.context) .completionError((DiagnosticPosition) state.getPath().getLeaf(), e); return false; } }
@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); } };
/** 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(); }