提交 97de457f 编写于 作者: A Andrey Breslav

JET-72 Type inference doesn't work when iterating over ArrayList:

substitutions fixed for methods inherited from generic superclasses
上级 dc25c7bb
......@@ -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;
}
......
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
......
// 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)
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册