private static List<JavaType> expandVarArgsToFitSize(List<JavaType> m1ArgTypes, int size) { List<JavaType> newArgTypes = new ArrayList<>(m1ArgTypes); int m1ArgTypesSize = newArgTypes.size(); int m1ArgTypesLast = m1ArgTypesSize - 1; Type lastElementType = ((Type.ArrayType) newArgTypes.get(m1ArgTypesLast)).elementType(); // replace last element type from GivenType[] to GivenType newArgTypes.set(m1ArgTypesLast, (JavaType) lastElementType); // if m1ArgTypes smaller than size pad it with lastElementType for (int i = m1ArgTypesSize; i < size - 1; i++) { if (i < newArgTypes.size()) { newArgTypes.set(i, (JavaType) lastElementType); } else { newArgTypes.add((JavaType) lastElementType); } } return newArgTypes; }
private void checkInvokedMethod(JavaSymbol.MethodJavaSymbol methodSymbol, @Nullable MethodJavaType methodType, ExpressionTree lastArg) { if (methodSymbol.isVarArgs() && lastArg.is(Tree.Kind.NEW_ARRAY)) { if (lastParamHasSameType(methodSymbol, methodType, lastArg.symbolType())) { String message = "Remove this array creation"; NewArrayTree newArrayTree = (NewArrayTree) lastArg; if (newArrayTree.openBraceToken() == null) { ExpressionTree expression = newArrayTree.dimensions().get(0).expression(); Integer literalValue = LiteralUtils.intLiteralValue(expression); if (literalValue == null || literalValue != 0 || isCallingOverload(methodSymbol, lastArg)) { return; } } else if (!newArrayTree.initializers().isEmpty()) { message += " and simply pass the elements"; } reportIssue(lastArg, message + "."); } else { String type = ((Type.ArrayType) getLastParameterType(methodSymbol.parameterTypes())).elementType().name(); reportIssue(lastArg, "Disambiguate this call by either casting as \"" + type + "\" or \"" + type + "[]\"."); } } }
private void checkInvokedMethod(JavaSymbol.MethodJavaSymbol methodSymbol, @Nullable MethodJavaType methodType, ExpressionTree lastArg) { if (methodSymbol.isVarArgs() && lastArg.is(Tree.Kind.NEW_ARRAY)) { if (lastParamHasSameType(methodSymbol, methodType, lastArg.symbolType())) { String message = "Remove this array creation"; NewArrayTree newArrayTree = (NewArrayTree) lastArg; if (newArrayTree.openBraceToken() == null) { ExpressionTree expression = newArrayTree.dimensions().get(0).expression(); Integer literalValue = LiteralUtils.intLiteralValue(expression); if (literalValue == null || literalValue != 0 || isCallingOverload(methodSymbol, lastArg)) { return; } } else if (!newArrayTree.initializers().isEmpty()) { message += " and simply pass the elements"; } reportIssue(lastArg, message + "."); } else { String type = ((Type.ArrayType) getLastParameterType(methodSymbol.parameterTypes())).elementType().name(); reportIssue(lastArg, "Disambiguate this call by either casting as \"" + type + "\" or \"" + type + "[]\"."); } } }
@Override public boolean isSubtypeOf(Type superType) { JavaType supType = (JavaType) superType; if (isTagged(ARRAY)) { //Handle covariance of arrays. if(supType.isTagged(ARRAY)) { return ((ArrayType) this).elementType().isSubtypeOf(((ArrayType) supType).elementType()); } //Only possibility to be supertype of array without being an array is to be Object. return "java.lang.Object".equals(supType.fullyQualifiedName()); } else if(isTagged(TYPEVAR)) { if (supType.isTagged(WILDCARD)) { return ((WildCardType) supType).isSubtypeOfBound(this); } return this.equals(superType) || erasure().isSubtypeOf(superType.erasure()); } return false; }
private static List<JavaType> expandVarArgsToFitSize(List<JavaType> m1ArgTypes, int size) { List<JavaType> newArgTypes = new ArrayList<>(m1ArgTypes); int m1ArgTypesSize = newArgTypes.size(); int m1ArgTypesLast = m1ArgTypesSize - 1; Type lastElementType = ((Type.ArrayType) newArgTypes.get(m1ArgTypesLast)).elementType(); // replace last element type from GivenType[] to GivenType newArgTypes.set(m1ArgTypesLast, (JavaType) lastElementType); // if m1ArgTypes smaller than size pad it with lastElementType for (int i = m1ArgTypesSize; i < size - 1; i++) { if (i < newArgTypes.size()) { newArgTypes.set(i, (JavaType) lastElementType); } else { newArgTypes.add((JavaType) lastElementType); } } return newArgTypes; }
@Override public boolean isSubtypeOf(Type superType) { JavaType supType = (JavaType) superType; if (isTagged(ARRAY)) { //Handle covariance of arrays. if(supType.isTagged(ARRAY)) { return ((ArrayType) this).elementType().isSubtypeOf(((ArrayType) supType).elementType()); } //Only possibility to be supertype of array without being an array is to be Object. return "java.lang.Object".equals(supType.fullyQualifiedName()); } else if(isTagged(TYPEVAR)) { return this.equals(superType) || erasure().isSubtypeOf(superType.erasure()); } return false; }
private static List<JavaType> expandVarArgsToFitSize(List<JavaType> m1ArgTypes, int size) { List<JavaType> newArgTypes = new ArrayList<>(m1ArgTypes); int m1ArgTypesSize = newArgTypes.size(); int m1ArgTypesLast = m1ArgTypesSize - 1; Type lastElementType = ((Type.ArrayType) newArgTypes.get(m1ArgTypesLast)).elementType(); // replace last element type from GivenType[] to GivenType newArgTypes.set(m1ArgTypesLast, (JavaType) lastElementType); // if m1ArgTypes smaller than size pad it with lastElementType for (int i = m1ArgTypesSize; i < size - 1; i++) { if (i < newArgTypes.size()) { newArgTypes.set(i, (JavaType) lastElementType); } else { newArgTypes.add((JavaType) lastElementType); } } return newArgTypes; }
private boolean implementsSerializable(@Nullable Type type) { if (type == null || type.isUnknown()) { return false; } if (type.isPrimitive()) { return true; } if (type.isArray()) { return implementsSerializable(((Type.ArrayType) type).elementType()); } if (type.isClass() || ((JavaType) type).isTagged(JavaType.TYPEVAR)) { return type.erasure().isSubtypeOf("java.io.Serializable"); } return false; }
private static String getMessage(VariableTree variableTree) { Type varType = variableTree.type().symbolType(); if (varType.isArray()) { String atomicType = "Reference"; Type elementType = ((Type.ArrayType) varType).elementType(); if (elementType.isPrimitive(Type.Primitives.LONG)) { atomicType = "Long"; } else if (elementType.isPrimitive(Type.Primitives.INT)) { atomicType = "Integer"; } return String.format(ARRAY_MESSAGE, atomicType); } return REF_MESSAGE; } }
private static boolean isSerializableArray(Type type) { return type.isArray() && isSerializable(((Type.ArrayType) type).elementType()); }
private static Type getRootElementType(Type type) { return type.isArray() ? getRootElementType(((ArrayType) type).elementType()) : type; }
private static String getMessage(VariableTree variableTree) { Type varType = variableTree.type().symbolType(); if (varType.isArray()) { String atomicType = "Reference"; Type elementType = ((Type.ArrayType) varType).elementType(); if (elementType.isPrimitive(Type.Primitives.LONG)) { atomicType = "Long"; } else if (elementType.isPrimitive(Type.Primitives.INT)) { atomicType = "Integer"; } return String.format(ARRAY_MESSAGE, atomicType); } return REF_MESSAGE; } }
@Override public boolean isSubtypeOf(Type superType) { JavaType supType = (JavaType) superType; // Handle covariance of arrays. if (supType.isTagged(ARRAY)) { return elementType.isSubtypeOf(((ArrayType) supType).elementType()); } if (supType.isTagged(WILDCARD)) { return ((WildCardType) superType).isSubtypeOfBound(this); } // Only possibility to be supertype of array without being an array is to be Object. return "java.lang.Object".equals(supType.fullyQualifiedName()); }
private static Type getRootElementType(Type type) { return type.isArray() ? getRootElementType(((ArrayType) type).elementType()) : type; }
private static boolean isSerializableArray(Type type) { return type.isArray() && isSerializable(((Type.ArrayType) type).elementType()); }
private static boolean implementsSerializable(@Nullable Type type) { if (type == null || type.isUnknown() || type.isPrimitive()) { // do not raise an issue if type is unknown return true; } if (type.isArray()) { return implementsSerializable(((Type.ArrayType) type).elementType()); } if (type.isClass() || ((JavaType) type).isTagged(JavaType.TYPEVAR)) { return type.erasure().isSubtypeOf("java.io.Serializable"); } return false; }
private Type getExpectedType(Type providedType, List<Type> parametersTypes, int index, boolean varargs) { int lastParameterIndex = parametersTypes.size() - 1; Type lastParameterType = parametersTypes.get(lastParameterIndex); Type lastExpectedType = varargs ? ((Type.ArrayType) lastParameterType).elementType() : lastParameterType; if (index > lastParameterIndex || (index == lastParameterIndex && varargs && !providedType.isArray())) { return lastExpectedType; } return parametersTypes.get(index); }
@Override public boolean isSubtypeOf(Type superType) { JavaType supType = (JavaType) superType; // Handle covariance of arrays. if (supType.isTagged(ARRAY)) { return elementType.isSubtypeOf(((ArrayType) supType).elementType()); } if (supType.isTagged(WILDCARD)) { return ((WildCardType) superType).isSubtypeOfBound(this); } // Only possibility to be supertype of array without being an array is to be Object. return "java.lang.Object".equals(supType.fullyQualifiedName()); }
private static boolean implementsSerializable(@Nullable Type type) { if (type == null || type.isUnknown() || type.isPrimitive()) { // do not raise an issue if type is unknown return true; } if (type.isArray()) { return implementsSerializable(((Type.ArrayType) type).elementType()); } if (type.isClass() || ((JavaType) type).isTagged(JavaType.TYPEVAR)) { return type.erasure().isSubtypeOf("java.io.Serializable"); } return false; }
private void checkCast(Type type, MethodInvocationTree mit) { if (type.isArray() && !type.is("java.lang.Object[]")) { Type elementType = ((Type.ArrayType) type).elementType(); if (!((JavaType) elementType).isTagged(JavaType.TYPEVAR)) { reportIssue(mit, "Pass \"new " + elementType.name() + "[0]\" as argument to \"toArray\"."); } } } }