Resolution in generic classes fixed
This commit is contained in:
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user