private static boolean isValueOfInvocation(ExpressionTree abstractTypedTree) { if (!abstractTypedTree.is(Kind.METHOD_INVOCATION)) { return false; } Type type = abstractTypedTree.symbolType(); MethodMatcher valueOfMatcher = MethodMatcher.create() .typeDefinition(type.fullyQualifiedName()) .name("valueOf") .addParameter(((JavaType) type).primitiveType().fullyQualifiedName()); return valueOfMatcher.matches((MethodInvocationTree) abstractTypedTree); }
@Override public void visitNode(Tree tree) { ListTree<TypeTree> thrownList = ((MethodTree) tree).throwsClauses(); Set<String> reported = new HashSet<>(); for (TypeTree typeTree : thrownList) { Type symbolType = typeTree.symbolType(); String fullyQualifiedName = symbolType.fullyQualifiedName(); if (!reported.contains(fullyQualifiedName)) { String superTypeName = isSubclassOfAny(symbolType, thrownList); if (superTypeName != null) { addIssue( typeTree, "Remove the declaration of thrown exception '" + fullyQualifiedName + "' which is a subclass of '" + superTypeName + "'."); } else if (symbolType.isSubtypeOf("java.lang.RuntimeException")) { addIssue( typeTree, "Remove the declaration of thrown exception '" + fullyQualifiedName + "' which is a runtime exception."); } else if (declaredMoreThanOnce(fullyQualifiedName, thrownList)) { addIssue( typeTree, "Remove the redundant '" + fullyQualifiedName + "' thrown exception declaration(s)."); } reported.add(fullyQualifiedName); } } }
private static boolean superClassHasOnlyStaticMethods(Symbol.TypeSymbol newClassTypeSymbol) { Type superClass = newClassTypeSymbol.superClass(); if (superClass != null && !superClass.is("java.lang.Object")) { return hasOnlyStaticMethods(superClass.symbol()); } return true; }
@Override protected void onMethodInvocationFound(MethodInvocationTree mit) { Type symbolType = mit.arguments().get(0).symbolType(); if (!(symbolType.is("long") || symbolType.is("java.lang.Long"))) { reportIssue(MethodsHelper.methodName(mit), "Remove this \"Double.longBitsToDouble\" call."); } }
private static String isSubclassOfAny(Type type, ListTree<TypeTree> thrownList) { for (TypeTree thrown : thrownList) { String name = thrown.symbolType().fullyQualifiedName(); if (!type.is(name) && type.isSubtypeOf(name)) { return name; } } return null; }
private static boolean isNanTest(BinaryExpressionTree tree) { Type leftOperandType = tree.leftOperand().symbolType(); if (tree.is(Tree.Kind.NOT_EQUAL_TO) && (leftOperandType.isPrimitive(Type.Primitives.FLOAT) || leftOperandType.isPrimitive(Type.Primitives.DOUBLE))) { return true; } return false; }
@Override public void visitAssignmentExpression(AssignmentExpressionTree tree) { Type wrapper = ((JavaType) tree.expression().symbolType()).primitiveWrapperType(); if (tree.is(Kind.PLUS_ASSIGNMENT) && tree.variable().symbolType().is("java.lang.String") && wrapper != null) { createIssue(tree, wrapper.name()); } super.visitAssignmentExpression(tree); }
private SymbolicValue createIdentifierSymbolicValue(IdentifierTree identifier) { final Type type = identifier.symbol().type(); if (type != null && type.is("java.lang.Boolean")) { if ("TRUE".equals(identifier.name())) { return SymbolicValue.TRUE_LITERAL; } else if ("FALSE".equals(identifier.name())) { return SymbolicValue.FALSE_LITERAL; } } return createDefaultSymbolicValue(); }
private void checkConcatenation( Tree tree, ExpressionTree leftOperand, ExpressionTree rightOperand) { Type wrapper = null; if (isEmptyString(leftOperand)) { wrapper = ((JavaType) rightOperand.symbolType()).primitiveWrapperType(); } else if (isEmptyString(rightOperand)) { wrapper = ((JavaType) leftOperand.symbolType()).primitiveWrapperType(); } if (wrapper != null) { createIssue(tree, wrapper.name()); } }
private static List<Symbol> retrieveMembers(Symbol.TypeSymbol classSymbol) { List<Symbol> results = Lists.newLinkedList(); results.addAll(extractMembers(classSymbol, false)); for (Type parentInterface : classSymbol.interfaces()) { results.addAll(extractMembers(parentInterface.symbol(), true)); } Type superClass = classSymbol.superClass(); if (superClass != null) { results.addAll(extractMembers(superClass.symbol(), true)); } return results; }
private void checkExpression(ExpressionTree expression, Type implicitType) { if (implicitType.isPrimitive()) { checkForBoxing(expression); } else { checkForUnboxing(expression); } }
@Override protected void onMethodInvocationFound(MethodInvocationTree tree) { Type argumentType = tree.arguments().get(0).symbolType(); Type collectionType = getMethodOwner(tree); // can be null when using raw types Type collectionParameterType = getTypeParameter(collectionType); if (collectionParameterType != null && !collectionParameterType.isUnknown() && !isArgumentCompatible(argumentType, collectionParameterType)) { addIssue( tree, MessageFormat.format( "A \"{0}<{1}>\" cannot contain a \"{2}\"", collectionType, collectionParameterType, argumentType)); } }
private static boolean needsClosing(Type type) { for (String ignoredTypes : IGNORED_CLOSEABLE_SUBTYPES) { if (type.is(ignoredTypes)) { return false; } } return isCloseable(type); }
private static boolean hasOneAbstractMethod(ClassTree classTree) { TypeSymbol symbol = classTree.symbol(); if (symbol != null) { List<Type> types = symbol.interfaces(); for (Type type : types) { if (!type.symbol().memberSymbols().isEmpty()) { return false; } } } int methods = 0; for (Tree member : classTree.members()) { boolean isMethod = member.is(Tree.Kind.METHOD); if (!isMethod) { return false; } if (isNotObjectMethod((MethodTree) member) && isNonStaticNonDefaultMethod(member)) { methods++; } } return methods == 1; }
private static boolean autoboxing(Type argumentType, Type collectionParameterType) { return argumentType.isPrimitive() && ((JavaType) collectionParameterType).isPrimitiveWrapper() && isSubtypeOf(((JavaType) argumentType).primitiveWrapperType(), collectionParameterType); }
private static boolean isSubtypeOf(Type type, Type superType) { return type.isSubtypeOf(superType); }
private static boolean isArgumentCompatible(Type argumentType, Type collectionParameterType) { return isSubtypeOf(argumentType.erasure(), collectionParameterType.erasure()) || isSubtypeOf(collectionParameterType.erasure(), argumentType.erasure()) || autoboxing(argumentType, collectionParameterType); }
private static boolean isCloseable(Type type) { return type.isSubtypeOf(JAVA_IO_AUTO_CLOSEABLE) || type.isSubtypeOf(JAVA_IO_CLOSEABLE); }
private boolean instantiateOwnClass(Tree identifier, Symbol.TypeSymbol newClassTypeSymbol) { Type enclosingClassType = getSemanticModel().getEnclosingClass(identifier).type(); return enclosingClassType.equals(newClassTypeSymbol.type()); }
private static Type getRootElementType(Type type) { return type.isArray() ? getRootElementType(((ArrayType) type).elementType()) : type; }
private static boolean isIntegerOrLongExpected(Type type) { return type.isPrimitive(Primitives.INT) || type.isPrimitive(Primitives.LONG); }
private static boolean dissimilarPrimitiveTypeWrappers(Type trueExprType, Type falseExprType) { return isPrimitiveWrapper(trueExprType) && isPrimitiveWrapper(falseExprType) && !trueExprType.equals(falseExprType); }