@Test public void parametrizedTypeType_methods_tests() { JavaSymbol.PackageJavaSymbol packageSymbol = new JavaSymbol.PackageJavaSymbol("org.foo.bar", null); JavaSymbol.TypeJavaSymbol typeSymbol = new JavaSymbol.TypeJavaSymbol(Flags.PUBLIC, "MyType", packageSymbol); JavaSymbol.TypeVariableJavaSymbol typeVariableSymbol = new JavaSymbol.TypeVariableJavaSymbol("E", typeSymbol); ClassJavaType classType = (ClassJavaType) typeSymbol.type; TypeVariableJavaType typeVariableType = (TypeVariableJavaType) typeVariableSymbol.type; TypeSubstitution typeSubstitution = new TypeSubstitution(); typeSubstitution.add(typeVariableType, classType); ParametrizedTypeJavaType ptt = new ParametrizedTypeJavaType(typeSymbol, typeSubstitution); assertThat(ptt.substitution(typeVariableType)).isEqualTo(classType); assertThat( ptt.substitution( new TypeVariableJavaType(new JavaSymbol.TypeVariableJavaSymbol("F", typeSymbol)))) .isNull(); assertThat(ptt.typeParameters()).hasSize(1); assertThat(ptt.typeParameters()).contains(typeVariableType); ptt = new ParametrizedTypeJavaType(typeSymbol, null); assertThat(ptt.substitution(typeVariableType)).isNull(); assertThat(ptt.typeParameters()).isEmpty(); assertThat(ptt.isClass()).isTrue(); assertThat(ptt.isParameterized()).isTrue(); assertThat(ptt.rawType.isClass()).isTrue(); assertThat(ptt.rawType.isParameterized()).isFalse(); }
private JavaType handleTypeArguments( List<JavaType> typeParams, JavaType type, JavaSymbol.MethodJavaSymbol methodSymbol) { if (!typeParams.isEmpty() && methodSymbol.typeVariableTypes.size() == typeParams.size()) { TypeSubstitution typeSubstitution = new TypeSubstitution(); int i = 0; for (JavaType.TypeVariableJavaType typeVariableType : methodSymbol.typeVariableTypes) { typeSubstitution.add(typeVariableType, typeParams.get(i)); i++; } return substituteTypeParameter(type, typeSubstitution); } return type; }
@Override public void visitEnd() { if (!typeArguments.isEmpty()) { JavaSymbol.TypeJavaSymbol readSymbol = typeRead.symbol; readSymbol.complete(); // Mismatch between type variable and type arguments means we are lacking some pieces of // bytecode to resolve substitution properly. if (typeArguments.size() == readSymbol.typeVariableTypes.size()) { TypeSubstitution substitution = new TypeSubstitution(); int i = 0; for (JavaType typeArgument : typeArguments) { substitution.add(readSymbol.typeVariableTypes.get(i), typeArgument); i++; } typeRead = parametrizedTypeCache.getParametrizedTypeType(readSymbol, substitution); } } }
private JavaType substituteTypeParameter(JavaType type, TypeSubstitution substitution) { JavaType substitutedType = substitution.substitutedType(type); if (substitutedType != null) { return substitutedType; } if (type instanceof JavaType.ParametrizedTypeJavaType) { JavaType.ParametrizedTypeJavaType ptt = (JavaType.ParametrizedTypeJavaType) type; TypeSubstitution newSubstitution = new TypeSubstitution(); for (Map.Entry<JavaType.TypeVariableJavaType, JavaType> entry : ptt.typeSubstitution.substitutionEntries()) { newSubstitution.add( entry.getKey(), substituteTypeParameter(entry.getValue(), substitution)); } return parametrizedTypeCache.getParametrizedTypeType( ptt.rawType.getSymbol(), newSubstitution); } return type; }
@Test public void erasure_of_type_variable() { JavaSymbol.TypeJavaSymbol typeSymbol = new JavaSymbol.TypeJavaSymbol( Flags.PUBLIC, "MyType", new JavaSymbol.PackageJavaSymbol("org.foo.bar", null)); TypeSubstitution typeSubstitution = new TypeSubstitution(); typeSubstitution.add( (TypeVariableJavaType) new JavaSymbol.TypeVariableJavaSymbol("T", typeSymbol).type, typeSymbol.type); ParametrizedTypeJavaType parametrizedType = new ParametrizedTypeJavaType(typeSymbol, typeSubstitution); TypeVariableJavaType typeVariableType = (TypeVariableJavaType) new JavaSymbol.TypeVariableJavaSymbol("X", typeSymbol).type; typeVariableType.bounds = ImmutableList.<JavaType>of(parametrizedType); assertThat(typeVariableType.erasure()).isNotEqualTo(parametrizedType); assertThat(typeVariableType.erasure()).isEqualTo(parametrizedType.erasure()); }