Resolution in generic classes fixed

This commit is contained in:
Andrey Breslav
2011-03-10 17:13:19 +03:00
parent 5472df794b
commit c1677055b0
14 changed files with 120 additions and 29 deletions
@@ -52,7 +52,7 @@ public class ClassDescriptorResolver {
@Nullable
public void resolveMutableClassDescriptor(@NotNull JetScope scope, @NotNull JetClass classElement, @NotNull MutableClassDescriptor descriptor) {
WritableScope parameterScope = new WritableScope(scope);
WritableScope parameterScope = descriptor.getUnsubstitutedMemberScope();
// This call has side-effects on the parameterScope (fills it in)
List<TypeParameterDescriptor> typeParameters
@@ -157,17 +157,21 @@ public class ClassDescriptorResolver {
JetParameter valueParameter = valueParameters.get(i);
JetTypeReference typeReference = valueParameter.getTypeReference();
assert typeReference != null : "Parameters without type annotations are not supported"; // TODO
Type type;
if (typeReference == null) {
semanticServices.getErrorHandler().structuralError(valueParameter.getNode(), "A type annotation is required on a value parameter " + valueParameter.getName());
type = ErrorType.createErrorType("Type annotation was missing");
} else {
type = typeResolver.resolveType(parameterScope, typeReference);
}
ValueParameterDescriptor valueParameterDescriptor = new ValueParameterDescriptorImpl(
i,
AttributeResolver.INSTANCE.resolveAttributes(valueParameter.getModifierList()),
valueParameter.getName(),
typeResolver.resolveType(parameterScope, typeReference),
type,
valueParameter.getDefaultValue() != null,
false // TODO : varargs
);
// TODO : Default values???
result.add(valueParameterDescriptor);
@@ -197,6 +201,7 @@ public class ClassDescriptorResolver {
: Collections.singleton(typeResolver.resolveType(extensibleScope, extendsBound))
);
extensibleScope.addTypeParameterDescriptor(typeParameterDescriptor);
trace.recordDeclarationResolution(typeParameter, typeParameterDescriptor);
return typeParameterDescriptor;
}
@@ -1,10 +1,7 @@
package org.jetbrains.jet.lang.resolve;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.types.Attribute;
import org.jetbrains.jet.lang.types.ClassDescriptor;
import org.jetbrains.jet.lang.types.TypeConstructor;
import org.jetbrains.jet.lang.types.TypeProjection;
import org.jetbrains.jet.lang.types.*;
import java.util.List;
import java.util.Map;
@@ -49,4 +46,9 @@ public class LazySubstitutingClassDescriptor implements ClassDescriptor {
public String getName() {
return original.getName();
}
@Override
public DeclarationDescriptor getOriginal() {
return original.getOriginal();
}
}
@@ -24,4 +24,9 @@ public class MutableDeclarationDescriptor implements DeclarationDescriptor {
public void setName(String name) {
this.name = name;
}
@Override
public DeclarationDescriptor getOriginal() {
return this;
}
}
@@ -60,6 +60,10 @@ public class SubstitutingScope implements JetScope {
@NotNull
@Override
public FunctionGroup getFunctionGroup(@NotNull String name) {
return new LazySubstitutingFunctionGroup(substitutionContext, workerScope.getFunctionGroup(name));
FunctionGroup functionGroup = workerScope.getFunctionGroup(name);
if (substitutionContext.isEmpty()) {
return functionGroup;
}
return new LazySubstitutingFunctionGroup(substitutionContext, functionGroup);
}
}
@@ -4,4 +4,11 @@ package org.jetbrains.jet.lang.types;
* @author abreslav
*/
public interface DeclarationDescriptor extends Annotated, Named {
/**
* @return The descriptor that corresponds to the original declaration of this element.
* A descriptor can be obtained from its original by substituting type arguments (of the declaring class
* or of the element itself).
* returns <code>this</code> object if the current descriptor is original itself
*/
DeclarationDescriptor getOriginal();
}
@@ -18,4 +18,9 @@ public abstract class DeclarationDescriptorImpl extends AnnotatedImpl implements
public String getName() {
return name;
}
@Override
public DeclarationDescriptor getOriginal() {
return this;
}
}
@@ -18,12 +18,6 @@ public interface FunctionDescriptor extends DeclarationDescriptor {
@NotNull
Type getUnsubstitutedReturnType();
/**
* @return The descriptor that corresponds to the original declaration of this function.
* A descriptor can be obtained from its original by substituting type arguments (of the declaring class
* or of the function itself).
* null if the current descriptor is original itself
*/
@Nullable
FunctionDescriptor getOriginal();
}
@@ -2,9 +2,8 @@ package org.jetbrains.jet.lang.types;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.psi.JetFunction;
import java.util.*;
import java.util.List;
/**
* @author abreslav
@@ -27,7 +26,7 @@ public class FunctionDescriptorImpl extends DeclarationDescriptorImpl implements
@NotNull List<ValueParameterDescriptor> unsubstitutedValueParameters,
@NotNull Type unsubstitutedReturnType) {
super(attributes, name);
this.original = original;
this.original = original == null ? this : original;
this.typeParameters = typeParameters;
this.unsubstitutedValueParameters = unsubstitutedValueParameters;
this.unsubstitutedReturnType = unsubstitutedReturnType;
@@ -16,7 +16,9 @@ import org.jetbrains.jet.lang.resolve.TopDownAnalyzer;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
@@ -46,6 +48,7 @@ public class JetStandardLibrary {
private final ClassDescriptor doubleClass;
private final ClassDescriptor booleanClass;
private final ClassDescriptor stringClass;
private final ClassDescriptor arrayClass;
private final Type byteType;
private final Type charType;
@@ -82,6 +85,7 @@ public class JetStandardLibrary {
this.doubleClass = libraryScope.getClass("Double");
this.booleanClass = libraryScope.getClass("Boolean");
this.stringClass = libraryScope.getClass("String");
this.arrayClass = libraryScope.getClass("Array");
this.byteType = new TypeImpl(getByte());
this.charType = new TypeImpl(getChar());
@@ -146,39 +150,71 @@ public class JetStandardLibrary {
return stringClass;
}
@NotNull
public ClassDescriptor getArray() {
return arrayClass;
}
@NotNull
public Type getIntType() {
return intType;
}
@NotNull
public Type getLongType() {
return longType;
}
@NotNull
public Type getDoubleType() {
return doubleType;
}
@NotNull
public Type getFloatType() {
return floatType;
}
@NotNull
public Type getCharType() {
return charType;
}
@NotNull
public Type getBooleanType() {
return booleanType;
}
@NotNull
public Type getStringType() {
return stringType;
}
@NotNull
public Type getByteType() {
return byteType;
}
@NotNull
public Type getShortType() {
return shortType;
}
@NotNull
public Type getArrayType(@NotNull Type argument) {
Variance variance = Variance.INVARIANT;
return getArrayType(variance, argument);
}
@NotNull
public Type getArrayType(@NotNull Variance variance, @NotNull Type argument) {
List<TypeProjection> types = Collections.singletonList(new TypeProjection(variance, argument));
return new TypeImpl(
Collections.<Attribute>emptyList(),
getArray().getTypeConstructor(),
false,
types,
getArray().getMemberScope(types)
);
}
}
@@ -36,4 +36,9 @@ public class LazySubstitutedPropertyDescriptorImpl implements PropertyDescriptor
public String getName() {
return propertyDescriptor.getName();
}
@Override
public DeclarationDescriptor getOriginal() {
return propertyDescriptor.getOriginal();
}
}
@@ -60,7 +60,7 @@ public class LazySubstitutingFunctionDescriptor implements FunctionDescriptor {
@Override
public FunctionDescriptor getOriginal() {
return functionDescriptor;
return functionDescriptor.getOriginal();
}
@Override
@@ -73,5 +73,7 @@ public class LazySubstitutingFunctionDescriptor implements FunctionDescriptor {
public String getName() {
return functionDescriptor.getName();
}
}
+5
View File
@@ -1,6 +1,11 @@
import `java::java`java.*
import `java::java.util`util.*
fun foo(~a~a : `std::Array`Array<`std::Int`Int>) : `java::java.util.List`List {
`a`a.`std::Array.get(Int)`get(1)
`a`a.`std::Array.set(Int, Int)`set(1, 1)
}
fun foo(o : `java::java.lang.Object`Object, l : `java::java.util`util.`java::java.util.List`List) : `java::java.util.List`List {}
~A~class A {
@@ -120,7 +120,7 @@ public class ExpectedResolveData {
JetTypeReference typeReference = getAncestorOfType(JetTypeReference.class, element);
if (expectedDescriptor != null) {
DeclarationDescriptor actual = bindingContext.resolveReferenceExpression(reference);
assertSame(expectedDescriptor, actual);
assertSame("Expected: " + name, expectedDescriptor.getOriginal(), actual == null ? null : actual.getOriginal());
continue;
}
@@ -9,6 +9,7 @@ import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.search.GlobalSearchScope;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.types.*;
import org.jetbrains.jet.parsing.JetParsingTest;
@@ -28,6 +29,11 @@ public class JetResolveTest extends ExtensibleResolveTestCase {
JetStandardLibrary lib = JetStandardLibrary.getJetStandardLibrary(project);
Map<String, DeclarationDescriptor> nameToDescriptor = new HashMap<String, DeclarationDescriptor>();
nameToDescriptor.put("std::Int.plus(Int)", standardFunction(lib.getInt(), "plus", lib.getIntType()));
FunctionDescriptor descriptorForGet = standardFunction(lib.getArray(), Collections.singletonList(new TypeProjection(lib.getIntType())), "get", lib.getIntType());
nameToDescriptor.put("std::Array.get(Int)", descriptorForGet.getOriginal());
@NotNull
FunctionDescriptor descriptorForSet = standardFunction(lib.getArray(), Collections.singletonList(new TypeProjection(lib.getIntType())), "set", lib.getIntType(), lib.getIntType());
nameToDescriptor.put("std::Array.set(Int, Int)", descriptorForSet.getOriginal());
Map<String,PsiElement> nameToDeclaration = new HashMap<String, PsiElement>();
nameToDeclaration.put("java::java.util.Collections.emptyList()", findMethod(findClass("java.util.Collections"), "emptyList"));
@@ -43,20 +49,22 @@ public class JetResolveTest extends ExtensibleResolveTestCase {
nameToDeclaration.put("java::java.io.PrintStream.print(Int)", methods[2]);
nameToDeclaration.put("java::java.lang.System.out", findClass("java.lang.System").findFieldByName("out", true));
return new ExpectedResolveData(nameToDescriptor, nameToDeclaration);
}
@NotNull
private PsiElement findPackage(String qualifiedName) {
JavaPsiFacade javaFacade = JavaPsiFacade.getInstance(getProject());
return javaFacade.findPackage(qualifiedName);
}
@NotNull
private PsiMethod findMethod(PsiClass psiClass, String name) {
PsiMethod[] emptyLists = psiClass.findMethodsByName(name, true);
return emptyLists[0];
}
@NotNull
private PsiClass findClass(String qualifiedName) {
Project project = getProject();
JavaPsiFacade javaFacade = JavaPsiFacade.getInstance(project);
@@ -64,15 +72,27 @@ public class JetResolveTest extends ExtensibleResolveTestCase {
return javaFacade.findClass(qualifiedName, javaSearchScope);
}
private DeclarationDescriptor standardFunction(ClassDescriptor classDescriptor, String name, Type parameterType) {
FunctionGroup functionGroup = classDescriptor.getMemberScope(Collections.<TypeProjection>emptyList()).getFunctionGroup(name);
Collection<FunctionDescriptor> functions = functionGroup.getPossiblyApplicableFunctions(Collections.<Type>emptyList(), Collections.singletonList(parameterType));
@NotNull
private FunctionDescriptor standardFunction(ClassDescriptor classDescriptor, String name, Type parameterType) {
List<TypeProjection> typeArguments = Collections.emptyList();
return standardFunction(classDescriptor, typeArguments, name, parameterType);
}
@NotNull
private FunctionDescriptor standardFunction(ClassDescriptor classDescriptor, List<TypeProjection> typeArguments, String name, Type... parameterType) {
FunctionGroup functionGroup = classDescriptor.getMemberScope(typeArguments).getFunctionGroup(name);
List<Type> parameterTypeList = Arrays.asList(parameterType);
Collection<FunctionDescriptor> functions = functionGroup.getPossiblyApplicableFunctions(Collections.<Type>emptyList(), parameterTypeList);
for (FunctionDescriptor function : functions) {
if (function.getUnsubstitutedValueParameters().get(0).getType().equals(parameterType)) {
return function;
List<ValueParameterDescriptor> unsubstitutedValueParameters = function.getUnsubstitutedValueParameters();
for (int i = 0, unsubstitutedValueParametersSize = unsubstitutedValueParameters.size(); i < unsubstitutedValueParametersSize; i++) {
ValueParameterDescriptor unsubstitutedValueParameter = unsubstitutedValueParameters.get(i);
if (unsubstitutedValueParameter.getType().equals(parameterType[i])) {
return function;
}
}
}
throw new IllegalArgumentException("Not found: std::" + classDescriptor.getName() + "." + name + "(" + parameterType + ")");
throw new IllegalArgumentException("Not found: std::" + classDescriptor.getName() + "." + name + "(" + parameterTypeList + ")");
}
@Override
@@ -84,7 +104,9 @@ public class JetResolveTest extends ExtensibleResolveTestCase {
protected Sdk getProjectJDK() {
Properties properties = new Properties();
try {
properties.load(new FileReader(getHomeDirectory() + "/idea/idea.properties"));
FileReader reader = new FileReader(getHomeDirectory() + "/idea/idea.properties");
properties.load(reader);
reader.close();
} catch (IOException e) {
throw new RuntimeException(e);
}