private Type leastSpecificType() { if (chains == null) { return startType; } chains.forEach(c -> c.removeIf(t -> !t.symbol().isPublic())); if (chains.stream().allMatch(List::isEmpty)) { return startType; } // pick longest chain, if multiple have same length, prefer interface, if multiple choices, choose alphabetically chains.sort(Comparator.<List<Type>>comparingInt(List::size) .thenComparing(chain -> chain.get(0).symbol().isInterface(), Boolean::compare) .thenComparing(chain -> chain.get(0), Comparator.comparing(Type::fullyQualifiedName).reversed()) .reversed()); List<Type> longestChain = chains.get(0); return longestChain.get(0); }
private Type leastSpecificType() { if (chains == null) { return startType; } chains.forEach(c -> c.removeIf(t -> !t.symbol().isPublic())); if (chains.stream().allMatch(List::isEmpty)) { return startType; } // pick longest chain, if multiple have same length, prefer interface, if multiple choices, choose alphabetically chains.sort(Comparator.<List<Type>>comparingInt(List::size) .thenComparing(chain -> chain.get(0).symbol().isInterface(), Boolean::compare) .thenComparing(chain -> chain.get(0), Comparator.comparing(Type::fullyQualifiedName).reversed()) .reversed()); List<Type> longestChain = chains.get(0); return longestChain.get(0); }
public Optional<JavaSymbol.MethodJavaSymbol> getSamMethod(JavaType lambdaType) { List<JavaSymbol.MethodJavaSymbol> methodSymbols = abstractMethodsOfType(lambdaType); if (methodSymbols.size() > 1) { return Optional.empty(); } if (methodSymbols.size() == 1) { JavaSymbol.MethodJavaSymbol override = methodSymbols.get(0).overriddenSymbol(); Optional<JavaSymbol.MethodJavaSymbol> otherAbstractMethod = lambdaType.symbol.superTypes() .stream() .filter(t -> t.symbol().isInterface()) .flatMap(t -> abstractMethodsOfType(t).stream()) .filter(m -> override == null || !override.equals(m)) .findFirst(); if (otherAbstractMethod.isPresent()) { return Optional.empty(); } else { return Optional.of(methodSymbols.get(0)); } } else { // FIXME if list of supertypes define multiple abstract methods we might end up with a wrong samMethod from a non-functional interface return lambdaType.symbol.superTypes() .stream() .flatMap(t -> abstractMethodsOfType(t).stream()) .findFirst(); } }
@VisibleForTesting static Type best(List<Type> minimalCandidates) { Collections.sort(minimalCandidates, (t1, t2) -> { // Sort minimal candidates by name with classes before interfaces, to guarantee always the same type is returned when approximated. Symbol.TypeSymbol t1Symbol = t1.symbol(); Symbol.TypeSymbol t2Symbol = t2.symbol(); if (t1Symbol.isInterface() && t2Symbol.isInterface()) { return t1.name().compareTo(t2.name()); } else if (t1Symbol.isInterface()) { return 1; } else if (t2Symbol.isInterface()) { return -1; } return t1.name().compareTo(t2.name()); }); // FIXME SONARJAVA-1632 should return union of types return minimalCandidates.get(0); }
@VisibleForTesting static Type best(List<Type> minimalCandidates) { Collections.sort(minimalCandidates, (t1, t2) -> { // Sort minimal candidates by name with classes before interfaces, to guarantee always the same type is returned when approximated. Symbol.TypeSymbol t1Symbol = t1.symbol(); Symbol.TypeSymbol t2Symbol = t2.symbol(); if (t1Symbol.isInterface() && t2Symbol.isInterface()) { return t1.name().compareTo(t2.name()); } else if (t1Symbol.isInterface()) { return 1; } else if (t2Symbol.isInterface()) { return -1; } return t1.name().compareTo(t2.name()); }); // FIXME SONARJAVA-1632 should return union of types return minimalCandidates.get(0); }
private static boolean isUnserializableCollection(Type type) { return !type.symbol().isInterface() && isSubtypeOfCollectionApi(type) && !implementsSerializable(type); }
private void checkRedundancy(TypeTree currentInterface, List<Type> superInterfacesTypes, Set<ClassJavaType> superTypes) { Type interfaceType = currentInterface.symbolType(); for (ClassJavaType superType : superTypes) { TypeSymbol superTypeSymbol = superType.symbol(); if (superTypeSymbol.interfaces().contains(interfaceType)) { String typeOfParentMsg = "implemented by a super class"; if (superTypeSymbol.isInterface() && superInterfacesTypes.contains(superType)) { typeOfParentMsg = "already extended by \"" + superTypeSymbol.name() + "\""; } reportIssue(currentInterface, "\"" + interfaceType.name() + "\" is " + typeOfParentMsg + "; there is no need to implement it here."); break; } } }
private static Type best(List<Type> minimalCandidates) { Type result = Symbols.unknownType; for (Type type : minimalCandidates) { if (!type.symbol().isInterface()) { // first type which is not a interface return type; } else if (result.isUnknown()) { // save first interface result = type; } } // huge approximation: should be the bound of all the minimalCandidates, not only the first type return result; }
private static boolean areNeitherInterfaces(Type ownerType, Type argumentType) { return !ownerType.symbol().isInterface() && !argumentType.symbol().isInterface(); }
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 static boolean areTypesFinalClassAndInterface(Type ownerType, Type argumentType) { return (ownerType.symbol().isInterface() && argumentType.symbol().isFinal()) || (argumentType.symbol().isInterface() && ownerType.symbol().isFinal()); }
private static boolean areTypesFinalClassAndInterface(Type ownerType, Type argumentType) { return (ownerType.symbol().isInterface() && argumentType.symbol().isFinal()) || (argumentType.symbol().isInterface() && ownerType.symbol().isFinal()); }
private static boolean areNeitherInterfaces(Type ownerType, Type argumentType) { return !ownerType.symbol().isInterface() && !argumentType.symbol().isInterface(); }
private static boolean isUnserializableCollection(Type type) { return !type.symbol().isInterface() && isSubtypeOfCollectionApi(type) && !implementsSerializable(type); }
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 void checkRedundancy(TypeTree currentInterface, List<Type> superInterfacesTypes, Set<ClassJavaType> superTypes) { Type interfaceType = currentInterface.symbolType(); for (ClassJavaType superType : superTypes) { TypeSymbol superTypeSymbol = superType.symbol(); if (superTypeSymbol.interfaces().contains(interfaceType)) { String typeOfParentMsg = "implemented by a super class"; if (superTypeSymbol.isInterface() && superInterfacesTypes.contains(superType)) { typeOfParentMsg = "already extended by \"" + superTypeSymbol.name() + "\""; } reportIssue(currentInterface, "\"" + interfaceType.name() + "\" is " + typeOfParentMsg + "; there is no need to implement it here."); break; } } }
@Override @Nullable public JavaType getSuperclass() { JavaType firstBound = bounds().get(0); if (!firstBound.symbol().isInterface()) { return firstBound; } return getObjectType(firstBound); }
@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 public List<JavaType> getInterfaces() { List<JavaType> bounds = bounds(); if (bounds.get(0).symbol().isInterface()) { return bounds; } return bounds.subList(1, bounds.size()); }