diff --git a/idea/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java b/idea/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java index ee17da72625..9fb1dbb0bc0 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java @@ -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 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; } diff --git a/idea/src/org/jetbrains/jet/lang/resolve/LazySubstitutingClassDescriptor.java b/idea/src/org/jetbrains/jet/lang/resolve/LazySubstitutingClassDescriptor.java index bdefdaec84d..e16eb02fe4a 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/LazySubstitutingClassDescriptor.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/LazySubstitutingClassDescriptor.java @@ -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(); + } } diff --git a/idea/src/org/jetbrains/jet/lang/resolve/MutableDeclarationDescriptor.java b/idea/src/org/jetbrains/jet/lang/resolve/MutableDeclarationDescriptor.java index 26d9afbbb91..1743c1dc651 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/MutableDeclarationDescriptor.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/MutableDeclarationDescriptor.java @@ -24,4 +24,9 @@ public class MutableDeclarationDescriptor implements DeclarationDescriptor { public void setName(String name) { this.name = name; } + + @Override + public DeclarationDescriptor getOriginal() { + return this; + } } diff --git a/idea/src/org/jetbrains/jet/lang/resolve/SubstitutingScope.java b/idea/src/org/jetbrains/jet/lang/resolve/SubstitutingScope.java index 6b89c581740..0a73b23edcf 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/SubstitutingScope.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/SubstitutingScope.java @@ -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); } } diff --git a/idea/src/org/jetbrains/jet/lang/types/DeclarationDescriptor.java b/idea/src/org/jetbrains/jet/lang/types/DeclarationDescriptor.java index 64a16665add..0b17173f856 100644 --- a/idea/src/org/jetbrains/jet/lang/types/DeclarationDescriptor.java +++ b/idea/src/org/jetbrains/jet/lang/types/DeclarationDescriptor.java @@ -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 this object if the current descriptor is original itself + */ + DeclarationDescriptor getOriginal(); } diff --git a/idea/src/org/jetbrains/jet/lang/types/DeclarationDescriptorImpl.java b/idea/src/org/jetbrains/jet/lang/types/DeclarationDescriptorImpl.java index bcba0d187ad..e8143ec8f2d 100644 --- a/idea/src/org/jetbrains/jet/lang/types/DeclarationDescriptorImpl.java +++ b/idea/src/org/jetbrains/jet/lang/types/DeclarationDescriptorImpl.java @@ -18,4 +18,9 @@ public abstract class DeclarationDescriptorImpl extends AnnotatedImpl implements public String getName() { return name; } + + @Override + public DeclarationDescriptor getOriginal() { + return this; + } } diff --git a/idea/src/org/jetbrains/jet/lang/types/FunctionDescriptor.java b/idea/src/org/jetbrains/jet/lang/types/FunctionDescriptor.java index 72902232c47..0e0c46bd32a 100644 --- a/idea/src/org/jetbrains/jet/lang/types/FunctionDescriptor.java +++ b/idea/src/org/jetbrains/jet/lang/types/FunctionDescriptor.java @@ -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(); } diff --git a/idea/src/org/jetbrains/jet/lang/types/FunctionDescriptorImpl.java b/idea/src/org/jetbrains/jet/lang/types/FunctionDescriptorImpl.java index 8d26f373332..0e70599936c 100644 --- a/idea/src/org/jetbrains/jet/lang/types/FunctionDescriptorImpl.java +++ b/idea/src/org/jetbrains/jet/lang/types/FunctionDescriptorImpl.java @@ -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 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; diff --git a/idea/src/org/jetbrains/jet/lang/types/JetStandardLibrary.java b/idea/src/org/jetbrains/jet/lang/types/JetStandardLibrary.java index c777c734a55..0c2d4bc928d 100644 --- a/idea/src/org/jetbrains/jet/lang/types/JetStandardLibrary.java +++ b/idea/src/org/jetbrains/jet/lang/types/JetStandardLibrary.java @@ -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 types = Collections.singletonList(new TypeProjection(variance, argument)); + return new TypeImpl( + Collections.emptyList(), + getArray().getTypeConstructor(), + false, + types, + getArray().getMemberScope(types) + ); + } } diff --git a/idea/src/org/jetbrains/jet/lang/types/LazySubstitutedPropertyDescriptorImpl.java b/idea/src/org/jetbrains/jet/lang/types/LazySubstitutedPropertyDescriptorImpl.java index 233c3567015..2bbc5ff30c2 100644 --- a/idea/src/org/jetbrains/jet/lang/types/LazySubstitutedPropertyDescriptorImpl.java +++ b/idea/src/org/jetbrains/jet/lang/types/LazySubstitutedPropertyDescriptorImpl.java @@ -36,4 +36,9 @@ public class LazySubstitutedPropertyDescriptorImpl implements PropertyDescriptor public String getName() { return propertyDescriptor.getName(); } + + @Override + public DeclarationDescriptor getOriginal() { + return propertyDescriptor.getOriginal(); + } } diff --git a/idea/src/org/jetbrains/jet/lang/types/LazySubstitutingFunctionDescriptor.java b/idea/src/org/jetbrains/jet/lang/types/LazySubstitutingFunctionDescriptor.java index 4bdc39791ba..e7fa600b63f 100644 --- a/idea/src/org/jetbrains/jet/lang/types/LazySubstitutingFunctionDescriptor.java +++ b/idea/src/org/jetbrains/jet/lang/types/LazySubstitutingFunctionDescriptor.java @@ -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(); } + + } diff --git a/idea/testData/resolve/ResolveToJava.jet b/idea/testData/resolve/ResolveToJava.jet index d8b5bd82049..5fd30ba8b86 100644 --- a/idea/testData/resolve/ResolveToJava.jet +++ b/idea/testData/resolve/ResolveToJava.jet @@ -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 { diff --git a/idea/tests/org/jetbrains/jet/resolve/ExpectedResolveData.java b/idea/tests/org/jetbrains/jet/resolve/ExpectedResolveData.java index 47d6f78abae..b1465511ba3 100644 --- a/idea/tests/org/jetbrains/jet/resolve/ExpectedResolveData.java +++ b/idea/tests/org/jetbrains/jet/resolve/ExpectedResolveData.java @@ -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; } diff --git a/idea/tests/org/jetbrains/jet/resolve/JetResolveTest.java b/idea/tests/org/jetbrains/jet/resolve/JetResolveTest.java index 3e49ce8134d..a3b1ddcd10d 100644 --- a/idea/tests/org/jetbrains/jet/resolve/JetResolveTest.java +++ b/idea/tests/org/jetbrains/jet/resolve/JetResolveTest.java @@ -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 nameToDescriptor = new HashMap(); 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 nameToDeclaration = new HashMap(); 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.emptyList()).getFunctionGroup(name); - Collection functions = functionGroup.getPossiblyApplicableFunctions(Collections.emptyList(), Collections.singletonList(parameterType)); + @NotNull + private FunctionDescriptor standardFunction(ClassDescriptor classDescriptor, String name, Type parameterType) { + List typeArguments = Collections.emptyList(); + return standardFunction(classDescriptor, typeArguments, name, parameterType); + } + + @NotNull + private FunctionDescriptor standardFunction(ClassDescriptor classDescriptor, List typeArguments, String name, Type... parameterType) { + FunctionGroup functionGroup = classDescriptor.getMemberScope(typeArguments).getFunctionGroup(name); + List parameterTypeList = Arrays.asList(parameterType); + Collection functions = functionGroup.getPossiblyApplicableFunctions(Collections.emptyList(), parameterTypeList); for (FunctionDescriptor function : functions) { - if (function.getUnsubstitutedValueParameters().get(0).getType().equals(parameterType)) { - return function; + List 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); }