public TypeVariableJavaSymbol(String name, JavaSymbol owner) { super(0, name, owner); this.type = new TypeVariableJavaType(this); this.members = new Scope(this); }
@Override public boolean isSubtypeOf(String fullyQualifiedName) { return erasure().isSubtypeOf(fullyQualifiedName); }
private static boolean subtypeOfTypeVar(JavaType arg, TypeVariableJavaType formal) { for (JavaType bound : formal.bounds()) { if ((bound.isTagged(JavaType.TYPEVAR) && !subtypeOfTypeVar(arg, (TypeVariableJavaType) bound)) || !arg.isSubtypeOf(bound)) { return false; } } return true; }
private static boolean subtypeOfTypeVar(JavaType arg, TypeVariableJavaType formal) { for (JavaType bound : formal.bounds()) { if ((bound.isTagged(JavaType.TYPEVAR) && !subtypeOfTypeVar(arg, (TypeVariableJavaType) bound)) || !arg.isSubtypeOf(bound)) { return false; } } return true; }
@Override public boolean isSubtypeOf(Type superType) { JavaType supType = (JavaType) superType; if (supType.isTagged(WILDCARD)) { return ((WildCardType) supType).isSubtypeOfBound(this); } if (supType == this) { return true; } for (JavaType bound : bounds()) { if (bound.isSubtypeOf(supType) || (supType.isParameterized() && bound == supType.erasure())) { return true; } } return false; } }
public TypeVariableJavaSymbol(String name, JavaSymbol owner) { super(0, name, owner); this.type = new TypeVariableJavaType(this); this.members = new Scope(this); }
@Override public boolean isSubtypeOf(String fullyQualifiedName) { return erasure().isSubtypeOf(fullyQualifiedName); }
@Override public boolean isSubtypeOf(Type superType) { JavaType supType = (JavaType) superType; if (supType.isTagged(WILDCARD)) { return ((WildCardType) supType).isSubtypeOfBound(this); } if (supType == this) { return true; } for (JavaType bound : bounds()) { if (bound.isSubtypeOf(supType) || (supType.isParameterized() && bound == supType.erasure())) { return true; } } return false; } }
private JavaType substituteInTypeVar(TypeVariableJavaType typevar, TypeSubstitution substitution) { // completing owner of type var to ensure type var's bounds have been computed typevar.symbol.owner().complete(); if(typevarExplored.contains(typevar.symbol) || typevar.bounds == null) { return typevar; } typevarExplored.push((JavaSymbol.TypeVariableJavaSymbol) typevar.symbol); List<JavaType> substitutedBounds = typevar.bounds.stream().map(t -> applySubstitution(t, substitution)).collect(Collectors.toList()); typevarExplored.pop(); if(substitutedBounds.equals(typevar.bounds)) { return typevar; } TypeVariableJavaType typeVariableJavaType = new TypeVariableJavaType((JavaSymbol.TypeVariableJavaSymbol) typevar.symbol); typeVariableJavaType.bounds = substitutedBounds; return typeVariableJavaType; }
@VisibleForTesting Set<Type> supertypes(JavaType type) { List<Type> result = new ArrayList<>(); result.add(type); Symbol.TypeSymbol symbol = type.symbol(); TypeSubstitution substitution = getTypeSubstitution(type); if(substitution.size() == 0 && !((JavaSymbol.TypeJavaSymbol) symbol).typeVariableTypes.isEmpty()) { // raw type : let's create a substitution based on erasures TypeSubstitution ts = new TypeSubstitution(); ((JavaSymbol.TypeJavaSymbol) symbol).typeVariableTypes.forEach(t -> ts.add(t, t.erasure())); substitution = ts; } result.addAll(interfacesWithSubstitution(symbol, substitution)); Type superClass = symbol.superClass(); while (superClass != null) { JavaType substitutedSuperClass = applySubstitution(superClass, substitution); result.add(substitutedSuperClass); substitution = getTypeSubstitution(substitutedSuperClass); JavaSymbol.TypeJavaSymbol superClassSymbol = substitutedSuperClass.getSymbol(); result.addAll(interfacesWithSubstitution(superClassSymbol, substitution)); superClass = superClassSymbol.superClass(); } return new LinkedHashSet<>(result); }
private static boolean requiredForMemberAccess(TypeCastTree typeCastTree) { ExpressionTree expression = typeCastTree.expression(); if (!expression.is(Tree.Kind.METHOD_INVOCATION)) { Tree parent = typeCastTree.parent(); return expression.is(Tree.Kind.METHOD_REFERENCE) && parent != null && skipParentheses(parent).is(Tree.Kind.MEMBER_SELECT); } Symbol symbol = ((MethodInvocationTree) expression).symbol(); if (!symbol.isMethodSymbol()) { return false; } Type returnType = ((Symbol.MethodSymbol) symbol).returnType().type(); if (!(returnType instanceof TypeVariableJavaType) || ((TypeVariableJavaType) returnType).bounds().get(0).is("java.lang.Object")) { return false; } // consider REQUIRED as soon as the parent expression is a member access (killing the noise), without checking if cast could have been avoided // as the member accessed could have also been part of initial type return skipParentheses(typeCastTree.parent()).is(Tree.Kind.MEMBER_SELECT); }
private JavaType substituteInTypeVar(TypeVariableJavaType typevar, TypeSubstitution substitution) { // completing owner of type var to ensure type var's bounds have been computed typevar.symbol.owner().complete(); if(typevarExplored.contains(typevar.symbol) || typevar.bounds == null) { return typevar; } typevarExplored.push((JavaSymbol.TypeVariableJavaSymbol) typevar.symbol); List<JavaType> substitutedBounds = typevar.bounds.stream().map(t -> applySubstitution(t, substitution)).collect(Collectors.toList()); typevarExplored.pop(); if(substitutedBounds.equals(typevar.bounds)) { return typevar; } TypeVariableJavaType typeVariableJavaType = new TypeVariableJavaType((JavaSymbol.TypeVariableJavaSymbol) typevar.symbol); typeVariableJavaType.bounds = substitutedBounds; return typeVariableJavaType; }
@VisibleForTesting Set<Type> supertypes(JavaType type) { List<Type> result = new ArrayList<>(); result.add(type); Symbol.TypeSymbol symbol = type.symbol(); TypeSubstitution substitution = getTypeSubstitution(type); if(substitution.size() == 0 && !((JavaSymbol.TypeJavaSymbol) symbol).typeVariableTypes.isEmpty()) { // raw type : let's create a substitution based on erasures TypeSubstitution ts = new TypeSubstitution(); ((JavaSymbol.TypeJavaSymbol) symbol).typeVariableTypes.forEach(t -> ts.add(t, t.erasure())); substitution = ts; } result.addAll(interfacesWithSubstitution(symbol, substitution)); Type superClass = symbol.superClass(); while (superClass != null) { JavaType substitutedSuperClass = applySubstitution(superClass, substitution); result.add(substitutedSuperClass); substitution = getTypeSubstitution(substitutedSuperClass); JavaSymbol.TypeJavaSymbol superClassSymbol = substitutedSuperClass.getSymbol(); result.addAll(interfacesWithSubstitution(superClassSymbol, substitution)); superClass = superClassSymbol.superClass(); } return new LinkedHashSet<>(result); }
private static boolean requiredForMemberAccess(TypeCastTree typeCastTree) { ExpressionTree expression = typeCastTree.expression(); if (!expression.is(Tree.Kind.METHOD_INVOCATION)) { Tree parent = typeCastTree.parent(); return expression.is(Tree.Kind.METHOD_REFERENCE) && parent != null && skipParentheses(parent).is(Tree.Kind.MEMBER_SELECT); } Symbol symbol = ((MethodInvocationTree) expression).symbol(); if (!symbol.isMethodSymbol()) { return false; } Type returnType = ((Symbol.MethodSymbol) symbol).returnType().type(); if (!(returnType instanceof TypeVariableJavaType) || ((TypeVariableJavaType) returnType).bounds().get(0).is("java.lang.Object")) { return false; } // consider REQUIRED as soon as the parent expression is a member access (killing the noise), without checking if cast could have been avoided // as the member accessed could have also been part of initial type return skipParentheses(typeCastTree.parent()).is(Tree.Kind.MEMBER_SELECT); }