diff --git a/idea/src/org/jetbrains/jet/lang/resolve/BindingContext.java b/idea/src/org/jetbrains/jet/lang/resolve/BindingContext.java index ce6d09efaa9..935299c75e8 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/BindingContext.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/BindingContext.java @@ -9,6 +9,9 @@ import org.jetbrains.jet.lang.types.*; * @author abreslav */ public interface BindingContext { + @Deprecated // "Tests only" + DeclarationDescriptor getDeclarationDescriptor(PsiElement declaration); + NamespaceDescriptor getNamespaceDescriptor(JetNamespace declaration); ClassDescriptor getClassDescriptor(JetClass declaration); TypeParameterDescriptor getTypeParameterDescriptor(JetTypeParameter declaration); diff --git a/idea/src/org/jetbrains/jet/lang/resolve/BindingTraceContext.java b/idea/src/org/jetbrains/jet/lang/resolve/BindingTraceContext.java index 77779926139..d351025cd2f 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/BindingTraceContext.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/BindingTraceContext.java @@ -121,6 +121,15 @@ public class BindingTraceContext implements BindingContext, BindingTrace { //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + @Override + public DeclarationDescriptor getDeclarationDescriptor(PsiElement declaration) { + if (declaration instanceof JetNamespace) { + JetNamespace namespace = (JetNamespace) declaration; + return getNamespaceDescriptor(namespace); + } + return declarationsToDescriptors.get(declaration); + } + public NamespaceDescriptor getNamespaceDescriptor(JetNamespace declaration) { return namespaceDeclarationsToDescriptors.get(declaration); } @@ -152,8 +161,13 @@ public class BindingTraceContext implements BindingContext, BindingTrace { @Override public PropertyDescriptor getPropertyDescriptor(JetParameter primaryConstructorParameter) { - PropertyDescriptor descriptor = primaryConstructorParameterDeclarationsToPropertyDescriptors.get(primaryConstructorParameter); - return descriptor; + return primaryConstructorParameterDeclarationsToPropertyDescriptors.get(primaryConstructorParameter); + } + + @Nullable + @Override + public ConstructorDescriptor getConstructorDescriptor(@NotNull JetElement declaration) { + return constructorDeclarationsToDescriptors.get(declaration); } @Override @@ -166,12 +180,6 @@ public class BindingTraceContext implements BindingContext, BindingTrace { return expressionTypes.get(expression); } - @Nullable - @Override - public ConstructorDescriptor getConstructorDescriptor(@NotNull JetElement declaration) { - return constructorDeclarationsToDescriptors.get(declaration); - } - @Override public DeclarationDescriptor resolveReferenceExpression(JetReferenceExpression referenceExpression) { return resolutionResults.get(referenceExpression); diff --git a/idea/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java b/idea/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java index dbfbf1483b7..73b2f29bb05 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java @@ -316,10 +316,12 @@ public class TopDownAnalyzer { private void resolveDelegationSpecifierLists() { // TODO : Make sure the same thing is not initialized twice - final JetTypeInferrer typeInferrer = semanticServices.getTypeInferrer(trace, JetFlowInformationProvider.NONE); for (Map.Entry entry : classes.entrySet()) { final JetClass jetClass = entry.getKey(); final MutableClassDescriptor descriptor = entry.getValue(); + final ConstructorDescriptor primaryConstructor = descriptor.getUnsubstitutedPrimaryConstructor(); + final JetScope scopeForConstructor = primaryConstructor == null ? null : getInnerScopeForConstructor(primaryConstructor, descriptor.getWritableUnsubstitutedMemberScope()); + final JetTypeInferrer typeInferrer = semanticServices.getTypeInferrer(traceForConstructors, JetFlowInformationProvider.NONE); // TODO : flow for (JetDelegationSpecifier delegationSpecifier : jetClass.getDelegationSpecifiers()) { delegationSpecifier.accept(new JetVisitor() { @@ -327,7 +329,8 @@ public class TopDownAnalyzer { public void visitDelegationByExpressionSpecifier(JetDelegatorByExpressionSpecifier specifier) { JetExpression delegateExpression = specifier.getDelegateExpression(); if (delegateExpression != null) { - JetType type = typeInferrer.getType(descriptor.getWritableUnsubstitutedMemberScope(), delegateExpression, false); + JetScope scope = scopeForConstructor == null ? descriptor.getWritableUnsubstitutedMemberScope() : scopeForConstructor; + JetType type = typeInferrer.getType(scope, delegateExpression, false); JetType supertype = trace.resolveTypeReference(specifier.getTypeReference()); if (type != null && !semanticServices.getTypeChecker().isSubtypeOf(type, supertype)) { // TODO : Convertible? semanticServices.getErrorHandler().typeMismatch(delegateExpression, supertype, type); @@ -339,13 +342,15 @@ public class TopDownAnalyzer { public void visitDelegationToSuperCallSpecifier(JetDelegatorToSuperCall call) { JetTypeReference typeReference = call.getTypeReference(); if (typeReference != null) { - typeInferrer.checkConstructorCall(descriptor.getWritableUnsubstitutedMemberScope(), typeReference, call); if (!jetClass.hasPrimaryConstructor()) { JetArgumentList valueArgumentList = call.getValueArgumentList(); assert valueArgumentList != null; semanticServices.getErrorHandler().genericError(valueArgumentList.getNode(), "Class " + JetPsiUtil.safeName(jetClass.getName()) + " must have a constructor in order to be able to initialize supertypes"); } + else { + typeInferrer.checkConstructorCall(scopeForConstructor, typeReference, call); + } } } diff --git a/idea/testData/resolve/PrimaryConstructorParameters..jet b/idea/testData/resolve/PrimaryConstructorParameters..jet new file mode 100644 index 00000000000..68c40d9c8ff --- /dev/null +++ b/idea/testData/resolve/PrimaryConstructorParameters..jet @@ -0,0 +1,19 @@ + +class C(~x~x : Int, ~y~val y : Int) : Base(`x`x /*parameter*/), Base1 by new Base1(`x`x) { + var z = `x`x // parameter + get() = `$x`x // property + + { + val z = `x`x // parameter + } + + this() : this(1, 2) { + val z = x // inaccessible + val zz = `$y`y // property + } + + fun f() : Int { + return `$x`x // property + } +} + diff --git a/idea/testData/resolve/PrimaryConstructors.jet b/idea/testData/resolve/PrimaryConstructors.jet index 978919dc874..b0dcaa23d81 100644 --- a/idea/testData/resolve/PrimaryConstructors.jet +++ b/idea/testData/resolve/PrimaryConstructors.jet @@ -1,12 +1,12 @@ class A(~a~val a : Int) { - this() {`a`a} + this() {`$a`a} ~b~val b = `a`a - ~f~fun f() = `a`a + ~f~fun f() = `$a`a } fun test() { ~va~val a = new A() - `va`a.`a`a`:std::Int` + `va`a.`$a`a`:std::Int` a.`b`b`:std::Int` a.`f`f()`:std::Int` } diff --git a/idea/tests/org/jetbrains/jet/resolve/ExpectedResolveData.java b/idea/tests/org/jetbrains/jet/resolve/ExpectedResolveData.java index f34087399c0..09865c6779e 100644 --- a/idea/tests/org/jetbrains/jet/resolve/ExpectedResolveData.java +++ b/idea/tests/org/jetbrains/jet/resolve/ExpectedResolveData.java @@ -119,6 +119,9 @@ public class ExpectedResolveData { } PsiElement expected = nameToDeclaration.get(name); + if (expected == null && name.startsWith("$")) { + expected = nameToDeclaration.get(name.substring(1)); + } if (expected == null) { expected = nameToPsiElement.get(name); } @@ -143,6 +146,7 @@ public class ExpectedResolveData { assert expected != null : "No declaration for " + name; PsiElement actual = bindingContext.resolveToDeclarationPsiElement(reference); + String actualName = null; if (actual != null) { actualName = declarationToName.get(actual); @@ -151,9 +155,31 @@ public class ExpectedResolveData { } } assertNotNull(reference); - assertEquals( - "Reference `" + name + "`" + renderReferenceInContext(reference) + " is resolved into " + actualName + ".", - expected, actual); + + if (expected instanceof JetParameter || actual instanceof JetParameter) { + DeclarationDescriptor expectedDescriptor; + if (name.startsWith("$")) { + expectedDescriptor = bindingContext.getPropertyDescriptor((JetParameter) expected); + } + else { + expectedDescriptor = bindingContext.getDeclarationDescriptor(expected); + if (expectedDescriptor == null) { + expectedDescriptor = bindingContext.getConstructorDescriptor((JetElement) expected); + } + } + + + DeclarationDescriptor actualDescriptor = bindingContext.resolveReferenceExpression(reference); + + assertEquals( + "Reference `" + name + "`" + renderReferenceInContext(reference) + " is resolved into " + actualName + ".", + expectedDescriptor, actualDescriptor); + } + else { + assertEquals( + "Reference `" + name + "`" + renderReferenceInContext(reference) + " is resolved into " + actualName + ".", + expected, actual); + } } for (Map.Entry entry : positionToType.entrySet()) { diff --git a/idea/tests/org/jetbrains/jet/resolve/JetResolveTest.java b/idea/tests/org/jetbrains/jet/resolve/JetResolveTest.java index 1c90bb5ff5c..c0dc55fa2e2 100644 --- a/idea/tests/org/jetbrains/jet/resolve/JetResolveTest.java +++ b/idea/tests/org/jetbrains/jet/resolve/JetResolveTest.java @@ -8,6 +8,7 @@ import com.intellij.psi.PsiClass; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiMethod; import com.intellij.psi.search.GlobalSearchScope; +import junit.framework.Test; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.JetTestCaseBase; import org.jetbrains.jet.lang.resolve.OverloadResolutionResult; @@ -22,6 +23,14 @@ import java.util.*; */ public class JetResolveTest extends ExtensibleResolveTestCase { + private final String path; + private final String name; + + public JetResolveTest(String path, String name) { + this.path = path; + this.name = name; + } + @Override protected ExpectedResolveData getExpectedResolveData() { Project project = getProject(); @@ -116,43 +125,62 @@ public class JetResolveTest extends ExtensibleResolveTestCase { } private static String getHomeDirectory() { - return new File(PathManager.getResourceRoot(JetParsingTest.class, "/org/jetbrains/jet/parsing/JetParsingTest.class")).getParentFile().getParentFile().getParent(); + return new File(PathManager.getResourceRoot(JetParsingTest.class, "/org/jetbrains/jet/parsing/JetParsingTest.class")).getParentFile().getParentFile().getParent(); } - public void testBasic() throws Exception { - doTest("/resolve/Basic.jet", true, true); + @Override + public String getName() { + return "test" + name; } - public void testResolveToJava() throws Exception { - doTest("/resolve/ResolveToJava.jet", true, true); + @Override + protected void runTest() throws Throwable { + doTest(path, true, false); } - public void testResolveOfInfixExpressions() throws Exception { - doTest("/resolve/ResolveOfInfixExpressions.jet", true, true); - } +// public void testBasic() throws Exception { +// doTest("/resolve/Basic.jet", true, true); +// } +// +// public void testResolveToJava() throws Exception { +// doTest("/resolve/ResolveToJava.jet", true, true); +// } +// +// public void testResolveOfInfixExpressions() throws Exception { +// doTest("/resolve/ResolveOfInfixExpressions.jet", true, true); +// } +// +// public void testProjections() throws Exception { +// doTest("/resolve/Projections.jet", true, true); +// } +// +// public void testPrimaryConstructors() throws Exception { +// doTest("/resolve/PrimaryConstructors.jet", true, true); +// } +// +// public void testClassifiers() throws Exception { +// doTest("/resolve/Classifiers.jet", true, true); +// } +// +// public void testConstructorsAndInitializers() throws Exception { +// doTest("/resolve/ConstructorsAndInitializers.jet", true, true); +// } +// +// public void testNamespaces() throws Exception { +// doTest("/resolve/Namespaces.jet", true, true); +// } +// +// public void testTryCatch() throws Exception { +// doTest("/resolve/TryCatch.jet", true, true); +// } - public void testProjections() throws Exception { - doTest("/resolve/Projections.jet", true, true); + public static Test suite() { + return JetTestCaseBase.suiteForDirectory(getHomeDirectory() + "/idea/testData/", "/resolve/", true, new JetTestCaseBase.NamedTestFactory() { + @NotNull + @Override + public Test createTest(@NotNull String dataPath, @NotNull String name) { + return new JetResolveTest(dataPath + "/" + name + ".jet", name); + } + }); } - - public void testPrimaryConstructors() throws Exception { - doTest("/resolve/PrimaryConstructors.jet", true, true); - } - - public void testClassifiers() throws Exception { - doTest("/resolve/Classifiers.jet", true, true); - } - - public void testConstructorsAndInitializers() throws Exception { - doTest("/resolve/ConstructorsAndInitializers.jet", true, true); - } - - public void testNamespaces() throws Exception { - doTest("/resolve/Namespaces.jet", true, true); - } - - public void testTryCatch() throws Exception { - doTest("/resolve/TryCatch.jet", true, true); - } - } \ No newline at end of file