JET-72 Type inference doesn't work when iterating over ArrayList:
substitutions fixed for methods inherited from generic superclasses
This commit is contained in:
@@ -81,7 +81,7 @@ public class TypeParameterDescriptor extends DeclarationDescriptorImpl implement
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return typeConstructor.toString();
|
||||
return getContainingDeclaration() + "::" + typeConstructor.toString();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -91,4 +91,9 @@ public class JavaClassDescriptor extends MutableDeclarationDescriptor implements
|
||||
public <R, D> R accept(DeclarationDescriptorVisitor<R, D> visitor, D data) {
|
||||
return visitor.visitClassDescriptor(this, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "java class " + typeConstructor;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,7 +110,11 @@ public class JavaClassMembersScope implements JetScope {
|
||||
public FunctionGroup getFunctionGroup(@NotNull String name) {
|
||||
FunctionGroup functionGroup = functionGroups.get(name);
|
||||
if (functionGroup == null) {
|
||||
functionGroup = semanticServices.getDescriptorResolver().resolveFunctionGroup(psiClass, name, staticMembers);
|
||||
functionGroup = semanticServices.getDescriptorResolver().resolveFunctionGroup(
|
||||
psiClass,
|
||||
staticMembers ? null : (ClassDescriptor) containingDeclaration,
|
||||
name,
|
||||
staticMembers);
|
||||
functionGroups.put(name, functionGroup);
|
||||
}
|
||||
return functionGroup;
|
||||
|
||||
@@ -26,7 +26,7 @@ public class JavaDescriptorResolver {
|
||||
|
||||
@Override
|
||||
public <R, D> R accept(DeclarationDescriptorVisitor<R, D> visitor, D data) {
|
||||
throw new UnsupportedOperationException(); // TODO
|
||||
return visitor.visitDeclarationDescriptor(this, data);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -73,7 +73,6 @@ public class JavaDescriptorResolver {
|
||||
classDescriptorCache.put(psiClass.getQualifiedName(), null); // TODO
|
||||
|
||||
String name = psiClass.getName();
|
||||
PsiModifierList modifierList = psiClass.getModifierList();
|
||||
JavaClassDescriptor classDescriptor = new JavaClassDescriptor(
|
||||
JAVA_ROOT
|
||||
);
|
||||
@@ -86,7 +85,7 @@ public class JavaDescriptorResolver {
|
||||
// TODO
|
||||
psiClass.hasModifierProperty(PsiModifier.FINAL),
|
||||
name,
|
||||
resolveTypeParameters(psiClass.getTypeParameters()),
|
||||
resolveTypeParameters(classDescriptor, psiClass.getTypeParameters()),
|
||||
supertypes
|
||||
|
||||
));
|
||||
@@ -124,10 +123,10 @@ public class JavaDescriptorResolver {
|
||||
return classDescriptor;
|
||||
}
|
||||
|
||||
private List<TypeParameterDescriptor> resolveTypeParameters(@NotNull PsiTypeParameter[] typeParameters) {
|
||||
private List<TypeParameterDescriptor> resolveTypeParameters(@NotNull DeclarationDescriptor containingDeclaration, @NotNull PsiTypeParameter[] typeParameters) {
|
||||
List<TypeParameterDescriptor> result = Lists.newArrayList();
|
||||
for (PsiTypeParameter typeParameter : typeParameters) {
|
||||
TypeParameterDescriptor typeParameterDescriptor = resolveTypeParameter(typeParameter);
|
||||
TypeParameterDescriptor typeParameterDescriptor = resolveTypeParameter(containingDeclaration, typeParameter);
|
||||
result.add(typeParameterDescriptor);
|
||||
}
|
||||
return result;
|
||||
@@ -158,11 +157,11 @@ public class JavaDescriptorResolver {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public TypeParameterDescriptor resolveTypeParameter(@NotNull PsiTypeParameter psiTypeParameter) {
|
||||
public TypeParameterDescriptor resolveTypeParameter(@NotNull DeclarationDescriptor containingDeclaration, @NotNull PsiTypeParameter psiTypeParameter) {
|
||||
TypeParameterDescriptor typeParameterDescriptor = typeParameterDescriptorCache.get(psiTypeParameter);
|
||||
if (typeParameterDescriptor == null) {
|
||||
typeParameterDescriptor = createJavaTypeParameterDescriptor(JAVA_ROOT, psiTypeParameter);
|
||||
// Tis is done inside the method: typeParameterDescriptorCache.put(psiTypeParameter, typeParameterDescriptor);
|
||||
typeParameterDescriptor = createJavaTypeParameterDescriptor(containingDeclaration, psiTypeParameter);
|
||||
// This is done inside the method: typeParameterDescriptorCache.put(psiTypeParameter, typeParameterDescriptor);
|
||||
}
|
||||
return typeParameterDescriptor;
|
||||
}
|
||||
@@ -245,9 +244,16 @@ public class JavaDescriptorResolver {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public FunctionGroup resolveFunctionGroup(@NotNull PsiClass psiClass, @NotNull String methodName, boolean staticMembers) {
|
||||
public FunctionGroup resolveFunctionGroup(@NotNull PsiClass psiClass, @Nullable ClassDescriptor classDescriptor, @NotNull String methodName, boolean staticMembers) {
|
||||
WritableFunctionGroup writableFunctionGroup = new WritableFunctionGroup(methodName);
|
||||
final Collection<HierarchicalMethodSignature> signatures = psiClass.getVisibleSignatures();
|
||||
TypeSubstitutor typeSubstitutor;
|
||||
if (classDescriptor != null) {
|
||||
typeSubstitutor = TypeUtils.buildDeepSubstitutor(classDescriptor.getDefaultType());
|
||||
}
|
||||
else {
|
||||
typeSubstitutor = TypeSubstitutor.EMPTY;
|
||||
}
|
||||
for (HierarchicalMethodSignature signature: signatures) {
|
||||
PsiMethod method = signature.getMethod();
|
||||
if (method.hasModifierProperty(PsiModifier.STATIC) != staticMembers) {
|
||||
@@ -258,6 +264,9 @@ public class JavaDescriptorResolver {
|
||||
}
|
||||
FunctionDescriptor functionDescriptor = methodDescriptorCache.get(method);
|
||||
if (functionDescriptor != null) {
|
||||
if (method.getContainingClass() != psiClass) {
|
||||
functionDescriptor = functionDescriptor.substitute(typeSubstitutor);
|
||||
}
|
||||
writableFunctionGroup.addFunction(functionDescriptor);
|
||||
continue;
|
||||
}
|
||||
@@ -270,12 +279,18 @@ public class JavaDescriptorResolver {
|
||||
);
|
||||
functionDescriptorImpl.initialize(
|
||||
null,
|
||||
resolveTypeParameters(method.getTypeParameters()),
|
||||
resolveTypeParameters(functionDescriptorImpl, method.getTypeParameters()),
|
||||
semanticServices.getDescriptorResolver().resolveParameterDescriptors(functionDescriptorImpl, parameters),
|
||||
semanticServices.getTypeTransformer().transformToType(method.getReturnType())
|
||||
);
|
||||
semanticServices.getTrace().recordDeclarationResolution(method, functionDescriptorImpl);
|
||||
writableFunctionGroup.addFunction(functionDescriptorImpl);
|
||||
FunctionDescriptor substitutedFunctionDescriptor = functionDescriptorImpl;
|
||||
if (method.getContainingClass() != psiClass) {
|
||||
substitutedFunctionDescriptor = functionDescriptorImpl.substitute(typeSubstitutor);
|
||||
}
|
||||
if (substitutedFunctionDescriptor != null) {
|
||||
writableFunctionGroup.addFunction(substitutedFunctionDescriptor);
|
||||
}
|
||||
methodDescriptorCache.put(method, functionDescriptorImpl);
|
||||
}
|
||||
return writableFunctionGroup;
|
||||
|
||||
@@ -70,7 +70,7 @@ public class JavaTypeTransformer {
|
||||
|
||||
if (psiClass instanceof PsiTypeParameter) {
|
||||
PsiTypeParameter typeParameter = (PsiTypeParameter) psiClass;
|
||||
TypeParameterDescriptor typeParameterDescriptor = resolver.resolveTypeParameter(typeParameter);
|
||||
TypeParameterDescriptor typeParameterDescriptor = resolver.resolveTypeParameter(JavaDescriptorResolver.JAVA_ROOT, typeParameter);
|
||||
return typeParameterDescriptor.getDefaultType();
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -5,13 +5,18 @@ import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
|
||||
import org.jetbrains.jet.lang.resolve.SubstitutingScope;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
public class TypeSubstitutor {
|
||||
|
||||
public static final TypeSubstitutor EMPTY = create(Collections.<TypeConstructor, TypeProjection>emptyMap());
|
||||
|
||||
public static final class SubstitutionException extends Exception {
|
||||
public SubstitutionException(String message) {
|
||||
super(message);
|
||||
@@ -176,6 +181,10 @@ public class TypeSubstitutor {
|
||||
return new TypeProjection(effectiveProjectionKindValue, specializeType(effectiveTypeValue, effectiveContextVariance));
|
||||
}
|
||||
|
||||
/*package*/ void addSubstitution(@NotNull TypeConstructor typeConstructor, @NotNull TypeProjection typeProjection) {
|
||||
substitutionContext.put(typeConstructor, typeProjection);
|
||||
}
|
||||
|
||||
private static Variance asymmetricOr(Variance a, Variance b) {
|
||||
return a == Variance.INVARIANT ? b : a;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.jetbrains.jet.lang.types;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -185,15 +186,46 @@ public class TypeUtils {
|
||||
return buildSubstitutionContext(context.getConstructor().getParameters(), context.getArguments());
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a context with all the supertypes' parameters substituted
|
||||
*/
|
||||
@NotNull
|
||||
public static TypeSubstitutor buildDeepSubstitutor(@NotNull JetType type) {
|
||||
TypeSubstitutor typeSubstitutor = TypeSubstitutor.create(Maps.<TypeConstructor, TypeProjection>newHashMap());
|
||||
fillInDeepSubstitutor(type, typeSubstitutor);
|
||||
return typeSubstitutor;
|
||||
}
|
||||
|
||||
private static void fillInDeepSubstitutor(JetType context, TypeSubstitutor substitutor) {
|
||||
List<TypeParameterDescriptor> parameters = context.getConstructor().getParameters();
|
||||
List<TypeProjection> arguments = context.getArguments();
|
||||
for (int i = 0; i < arguments.size(); i++) {
|
||||
TypeProjection argument = arguments.get(i);
|
||||
TypeParameterDescriptor typeParameterDescriptor = parameters.get(i);
|
||||
|
||||
JetType substitute = substitutor.substitute(argument.getType(), Variance.INVARIANT);
|
||||
assert substitute != null;
|
||||
TypeProjection substitutedTypeProjection = new TypeProjection(argument.getProjectionKind(), substitute);
|
||||
substitutor.addSubstitution(typeParameterDescriptor.getTypeConstructor(), substitutedTypeProjection);
|
||||
}
|
||||
for (JetType supertype : context.getConstructor().getSupertypes()) {
|
||||
fillInDeepSubstitutor(supertype, substitutor);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Map<TypeConstructor, TypeProjection> buildSubstitutionContext(@NotNull List<TypeParameterDescriptor> parameters, @NotNull List<TypeProjection> contextArguments) {
|
||||
Map<TypeConstructor, TypeProjection> parameterValues = new HashMap<TypeConstructor, TypeProjection>();
|
||||
fillInSubstitutionContext(parameters, contextArguments, parameterValues);
|
||||
return parameterValues;
|
||||
}
|
||||
|
||||
private static void fillInSubstitutionContext(List<TypeParameterDescriptor> parameters, List<TypeProjection> contextArguments, Map<TypeConstructor, TypeProjection> parameterValues) {
|
||||
for (int i = 0, parametersSize = parameters.size(); i < parametersSize; i++) {
|
||||
TypeParameterDescriptor parameter = parameters.get(i);
|
||||
TypeProjection value = contextArguments.get(i);
|
||||
parameterValues.put(parameter.getTypeConstructor(), value);
|
||||
}
|
||||
return parameterValues;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
// JET-72 Type inference doesn't work when iterating over ArrayList
|
||||
|
||||
import java.util.ArrayList
|
||||
|
||||
class Item(val room: Object) {
|
||||
val name : String
|
||||
}
|
||||
|
||||
val items: ArrayList<Item> = new ArrayList<Item>
|
||||
|
||||
fun test(room : Object) {
|
||||
for(val item: Item in items) {
|
||||
if (item.room === room) {
|
||||
System.out?.println("You see " + item.name)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user