private List<JavaSymbol.MethodJavaSymbol> abstractMethodsOfType(JavaType javaType) { return javaType.symbol().memberSymbols().stream().filter(Resolve::isAbstractMethod).map(JavaSymbol.MethodJavaSymbol.class::cast) .filter(m -> !isObjectMethod(m)) .collect(Collectors.toList()); }
private List<JavaSymbol.MethodJavaSymbol> abstractMethodsOfType(JavaType javaType) { return javaType.symbol().memberSymbols().stream().filter(Resolve::isAbstractMethod).map(JavaSymbol.MethodJavaSymbol.class::cast) .filter(m -> !isObjectMethod(m)) .collect(Collectors.toList()); }
@Override public List<JavaType> getInterfaces() { List<JavaType> bounds = bounds(); if (bounds.get(0).symbol().isInterface()) { return bounds; } return bounds.subList(1, bounds.size()); }
@Override public List<JavaType> getInterfaces() { List<JavaType> bounds = bounds(); if (bounds.get(0).symbol().isInterface()) { return bounds; } return bounds.subList(1, bounds.size()); }
@Override @Nullable public JavaType getSuperclass() { JavaType firstBound = bounds().get(0); if (!firstBound.symbol().isInterface()) { return firstBound; } return getObjectType(firstBound); }
@Override @Nullable public JavaType getSuperclass() { JavaType firstBound = bounds().get(0); if (!firstBound.symbol().isInterface()) { return firstBound; } return getObjectType(firstBound); }
private static JavaType getObjectType(JavaType type) { JavaType superClass = (JavaType) type.symbol().superClass(); if (superClass == null) { return type; } return getObjectType(superClass); }
private static JavaType getObjectType(JavaType type) { JavaType superClass = (JavaType) type.symbol().superClass(); if (superClass == null) { return type; } return getObjectType(superClass); }
private static boolean hasEnumKey(Type symbolType) { Type type = symbolType; if (type instanceof MethodJavaType) { type = ((MethodJavaType) type).resultType(); } if (type instanceof ParametrizedTypeJavaType) { ParametrizedTypeJavaType parametrizedTypeJavaType = (ParametrizedTypeJavaType) type; List<TypeVariableJavaType> typeParameters = parametrizedTypeJavaType.typeParameters(); if (!typeParameters.isEmpty()) { return parametrizedTypeJavaType.substitution(typeParameters.get(0)).symbol().isEnum(); } } return false; }
private static boolean hasEnumKey(Type symbolType) { Type type = symbolType; if (type instanceof MethodJavaType) { type = ((MethodJavaType) type).resultType(); } if (type instanceof ParametrizedTypeJavaType) { ParametrizedTypeJavaType parametrizedTypeJavaType = (ParametrizedTypeJavaType) type; List<TypeVariableJavaType> typeParameters = parametrizedTypeJavaType.typeParameters(); if (!typeParameters.isEmpty()) { return parametrizedTypeJavaType.substitution(typeParameters.get(0)).symbol().isEnum(); } } return false; }
private JavaType refinedTypeForConstructor(JavaType capturedReturnType, JavaType refinedReturnType) { JavaType sanitizedCaptured = capturedReturnType; JavaType refinedConstructorType = refinedReturnType; if (refinedConstructorType.symbol().isTypeSymbol() && !((JavaSymbol.TypeJavaSymbol) refinedConstructorType.symbol()).typeParameters().scopeSymbols().isEmpty()) { refinedConstructorType = parametrizedTypeCache.getParametrizedTypeType(refinedConstructorType.symbol, new TypeSubstitution()); } if (sanitizedCaptured.isTagged(JavaType.TYPEVAR)) { sanitizedCaptured = ((TypeVariableJavaType) sanitizedCaptured).bounds.get(0); } if (refinedConstructorType.isParameterized()) { refinedConstructorType = resolve.resolveTypeSubstitutionWithDiamondOperator((ParametrizedTypeJavaType) refinedConstructorType, sanitizedCaptured); } return refinedConstructorType; }
private JavaType refinedTypeForConstructor(JavaType capturedReturnType, JavaType refinedReturnType) { JavaType sanitizedCaptured = capturedReturnType; JavaType refinedConstructorType = refinedReturnType; if (refinedConstructorType.symbol().isTypeSymbol() && !((JavaSymbol.TypeJavaSymbol) refinedConstructorType.symbol()).typeParameters().scopeSymbols().isEmpty()) { refinedConstructorType = parametrizedTypeCache.getParametrizedTypeType(refinedConstructorType.symbol, new TypeSubstitution()); } if (sanitizedCaptured.isTagged(JavaType.TYPEVAR)) { sanitizedCaptured = ((TypeVariableJavaType) sanitizedCaptured).bounds.get(0); } if (refinedConstructorType.isParameterized()) { refinedConstructorType = resolve.resolveTypeSubstitutionWithDiamondOperator((ParametrizedTypeJavaType) refinedConstructorType, sanitizedCaptured); } return refinedConstructorType; }
private boolean isValidSubstitution(TypeSubstitution candidate, TypeVariableJavaType typeVar, JavaType typeParam, JavaType site) { for (JavaType bound : typeVar.bounds) { JavaType currentBound = applySubstitution(bound, candidate); while (currentBound.isTagged(JavaType.TYPEVAR) && !currentBound.symbol().owner().isMethodSymbol()) { JavaType newBound = candidate.substitutedType(currentBound); if (newBound == null && site.isParameterized()) { newBound = ((ParametrizedTypeJavaType) site).typeSubstitution.substitutedType(currentBound); } if (newBound == null) { return ((JavaSymbol.TypeJavaSymbol) site.symbol()).typeVariableTypes.contains(currentBound); } if (currentBound.equals(newBound)) { // exploring the same substitution, we cannot deduce anything break; } currentBound = newBound; } if (!isUnboundedWildcard(typeParam) && !typeParam.isSubtypeOf(currentBound)) { return false; } } return true; }
@Override public void visitNode(Tree tree) { MethodTree methodTree = (MethodTree) tree; if (hasSemantic() && isCompareToMethod(methodTree) && Boolean.FALSE.equals(methodTree.isOverriding())) { ClassJavaType ownerType = (ClassJavaType) methodTree.symbol().owner().type(); ownerType.superTypes().stream().filter(supertype -> supertype.is("java.lang.Comparable")).findFirst().ifPresent( comparableType -> { String name = "Object"; if (comparableType.isParameterized()) { ParametrizedTypeJavaType ptjt = (ParametrizedTypeJavaType) comparableType; name = ptjt.substitution(ptjt.typeParameters().get(0)).symbol().name(); } reportIssue(methodTree.parameters().get(0), "Refactor this method so that its argument is of type '" + name + "'."); }); } }
@Override public void visitNode(Tree tree) { MethodTree methodTree = (MethodTree) tree; if (hasSemantic() && isCompareToMethod(methodTree) && Boolean.FALSE.equals(methodTree.isOverriding())) { ClassJavaType ownerType = (ClassJavaType) methodTree.symbol().owner().type(); ownerType.superTypes().stream().filter(supertype -> supertype.is("java.lang.Comparable")).findFirst().ifPresent( comparableType -> { String name = "Object"; if (comparableType.isParameterized()) { ParametrizedTypeJavaType ptjt = (ParametrizedTypeJavaType) comparableType; name = ptjt.substitution(ptjt.typeParameters().get(0)).symbol().name(); } reportIssue(methodTree.parameters().get(0), "Refactor this method so that its argument is of type '" + name + "'."); }); } }
private JavaType getAnonymousClassType(JavaType identifierType, JavaType constructedType, ClassTree classBody) { JavaType parentType = (constructedType.isTagged(JavaType.DEFERRED) || identifierType.symbol().isInterface()) ? identifierType : constructedType; ClassJavaType anonymousClassType = (ClassJavaType) classBody.symbol().type(); if (parentType.getSymbol().isInterface()) { anonymousClassType.interfaces = ImmutableList.of(parentType); anonymousClassType.supertype = symbols.objectType; } else { anonymousClassType.supertype = parentType; anonymousClassType.interfaces = ImmutableList.of(); } anonymousClassType.symbol.members.enter(new JavaSymbol.VariableJavaSymbol(Flags.FINAL, "super", anonymousClassType.supertype, anonymousClassType.symbol)); scan(classBody); return anonymousClassType; }
private JavaType getAnonymousClassType(JavaType identifierType, JavaType constructedType, ClassTree classBody) { JavaType parentType = (constructedType.isTagged(JavaType.DEFERRED) || identifierType.symbol().isInterface()) ? identifierType : constructedType; ClassJavaType anonymousClassType = (ClassJavaType) classBody.symbol().type(); if (parentType.getSymbol().isInterface()) { anonymousClassType.interfaces = ImmutableList.of(parentType); anonymousClassType.supertype = symbols.objectType; } else { anonymousClassType.supertype = parentType; anonymousClassType.interfaces = ImmutableList.of(); } anonymousClassType.symbol.members.enter(new JavaSymbol.VariableJavaSymbol(Flags.FINAL, "super", anonymousClassType.supertype, anonymousClassType.symbol)); scan(classBody); return anonymousClassType; }
@Override public void visitNode(Tree tree) { if (!hasSemantic()) { return; } Type type = ((NewClassTree) tree).symbolType(); if (type instanceof ParametrizedTypeJavaType && useHashDataStructure(type)) { ParametrizedTypeJavaType ptt = (ParametrizedTypeJavaType) type; Symbol.TypeSymbol symbol = ptt.substitution(ptt.typeParameters().get(0)).symbol(); if (implementsEquals(symbol) && !implementsHashCode(symbol)) { reportIssue(tree, "Add a \"hashCode()\" method to \"" + symbol.name() + "\" or remove it from this hash."); } } }
@Override public void visitNode(Tree tree) { if (!hasSemantic()) { return; } Type type = ((NewClassTree) tree).symbolType(); if (type instanceof ParametrizedTypeJavaType && useHashDataStructure(type)) { ParametrizedTypeJavaType ptt = (ParametrizedTypeJavaType) type; Symbol.TypeSymbol symbol = ptt.substitution(ptt.typeParameters().get(0)).symbol(); if (implementsEquals(symbol) && !implementsHashCode(symbol)) { reportIssue(tree, "Add a \"hashCode()\" method to \"" + symbol.name() + "\" or remove it from this hash."); } } }
private void populateSuperclass(JavaSymbol.TypeJavaSymbol symbol, Resolve.Env env, ClassJavaType type) { ClassTree tree = symbol.declaration; Tree superClassTree = tree.superClass(); if (superClassTree != null) { type.supertype = resolveType(env, superClassTree); checkHierarchyCycles(symbol.type); } else if (tree.is(Tree.Kind.ENUM)) { // JLS8 8.9: The direct superclass of an enum type E is Enum<E>. Scope enumParameters = ((JavaSymbol.TypeJavaSymbol) symbols.enumType.symbol()).typeParameters(); TypeVariableJavaType enumParameter = (TypeVariableJavaType) enumParameters.lookup("E").get(0).type(); type.supertype = parametrizedTypeCache.getParametrizedTypeType(symbols.enumType.symbol, new TypeSubstitution().add(enumParameter, type)); } else if (tree.is(Tree.Kind.CLASS, Tree.Kind.INTERFACE)) { // For CLASS JLS8 8.1.4: the direct superclass of the class type C<F1,...,Fn> is // the type given in the extends clause of the declaration of C // if an extends clause is present, or Object otherwise. // For INTERFACE JLS8 9.1.3: While every class is an extension of class Object, there is no single interface of which all interfaces are // extensions. // but we can call object method on any interface type. type.supertype = symbols.objectType; } }