From 7a8ea7fd88303e3d6707411882314a640b2f3158 Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Thu, 2 Jun 2011 13:35:45 +0400 Subject: [PATCH] JET-65 Identifier in initializer block resolves to constructor parameter instead of property + Scopes for secondary constructors fixed --- .../jet/lang/resolve/TopDownAnalyzer.java | 35 +++++++++++-------- .../ScopeForSecondaryConstructors.jet | 18 ++++++++++ idea/testData/resolve/PrimaryConstructors.jet | 19 +++++++++- 3 files changed, 56 insertions(+), 16 deletions(-) create mode 100644 idea/testData/checker/regression/ScopeForSecondaryConstructors.jet diff --git a/idea/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java b/idea/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java index 26f61448593..dd650a38589 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java @@ -37,7 +37,6 @@ public class TopDownAnalyzer { private final JetSemanticServices semanticServices; private final ClassDescriptorResolver classDescriptorResolver; private final BindingTraceContext trace; - private boolean readyToProcessExpressions = false; private final BindingTraceAdapter traceForConstructors; private final BindingTraceAdapter traceForMembers; @@ -93,7 +92,6 @@ public class TopDownAnalyzer { resolveFunctionAndPropertyHeaders(declarations); // Constructor headers are resolved as well - readyToProcessExpressions = true; resolveBehaviorDeclarationBodies(); } @@ -397,7 +395,7 @@ public class TopDownAnalyzer { final ConstructorDescriptor primaryConstructor = descriptor.getUnsubstitutedPrimaryConstructor(); final JetScope scopeForConstructor = primaryConstructor == null ? null - : getInnerScopeForConstructor(primaryConstructor, descriptor.getScopeForMemberResolution()); + : getInnerScopeForConstructor(primaryConstructor, descriptor.getScopeForMemberResolution(), true); final JetTypeInferrer typeInferrer = semanticServices.getTypeInferrer(traceForConstructors, JetFlowInformationProvider.NONE); // TODO : flow for (JetDelegationSpecifier delegationSpecifier : jetClass.getDelegationSpecifiers()) { @@ -472,7 +470,7 @@ public class TopDownAnalyzer { if (jetClass.hasPrimaryConstructor()) { ConstructorDescriptor primaryConstructor = classDescriptor.getUnsubstitutedPrimaryConstructor(); assert primaryConstructor != null; - final JetScope scopeForConstructor = getInnerScopeForConstructor(primaryConstructor, classDescriptor.getScopeForMemberResolution()); + final JetScope scopeForConstructor = getInnerScopeForConstructor(primaryConstructor, classDescriptor.getScopeForMemberResolution(), true); JetTypeInferrer typeInferrer = semanticServices.getTypeInferrer(traceForConstructors, JetFlowInformationProvider.NONE); // TODO : flow for (JetClassInitializer anonymousInitializer : anonymousInitializers) { typeInferrer.getType(scopeForConstructor, anonymousInitializer.getBody(), true); @@ -491,17 +489,14 @@ public class TopDownAnalyzer { JetDeclaration declaration = entry.getKey(); ConstructorDescriptor descriptor = entry.getValue(); - JetScope declaringScope = declaringScopes.get(declaration); - assert declaringScope != null; - - resolveSecondaryConstructorBody((JetConstructor) declaration, descriptor, declaringScope); + resolveSecondaryConstructorBody((JetConstructor) declaration, descriptor, ((MutableClassDescriptor) descriptor.getContainingDeclaration()).getScopeForMemberResolution()); assert descriptor.getUnsubstitutedReturnType() != null; } } private void resolveSecondaryConstructorBody(JetConstructor declaration, final ConstructorDescriptor descriptor, final JetScope declaringScope) { - final JetScope functionInnerScope = getInnerScopeForConstructor(descriptor, declaringScope); + final JetScope functionInnerScope = getInnerScopeForConstructor(descriptor, declaringScope, false); final JetTypeInferrer typeInferrerForInitializers = semanticServices.getTypeInferrer(traceForConstructors, JetFlowInformationProvider.NONE); @@ -529,7 +524,7 @@ public class TopDownAnalyzer { public void visitDelegationToThisCall(JetDelegatorToThisCall call) { // TODO : check that there's no recursion in this() calls // TODO : check: if a this() call is present, no other initializers are allowed - ClassDescriptor classDescriptor = (ClassDescriptor) descriptor.getContainingDeclaration(); + ClassDescriptor classDescriptor = descriptor.getContainingDeclaration(); typeInferrerForInitializers.checkClassConstructorCall( functionInnerScope, call.getThisReference(), @@ -570,12 +565,24 @@ public class TopDownAnalyzer { } @NotNull - private JetScope getInnerScopeForConstructor(@NotNull ConstructorDescriptor descriptor, @NotNull JetScope declaringScope) { + private JetScope getInnerScopeForConstructor(@NotNull ConstructorDescriptor descriptor, @NotNull JetScope declaringScope, boolean primary) { WritableScope constructorScope = new WritableScopeImpl(declaringScope, declaringScope.getContainingDeclaration(), trace.getErrorHandler()); for (PropertyDescriptor propertyDescriptor : ((MutableClassDescriptor) descriptor.getContainingDeclaration()).getProperties()) { constructorScope.addPropertyDescriptorByFieldName("$" + propertyDescriptor.getName(), propertyDescriptor); } - return FunctionDescriptorUtil.getFunctionInnerScope(constructorScope, descriptor, trace); + + constructorScope.setThisType(descriptor.getContainingDeclaration().getDefaultType()); + + for (ValueParameterDescriptor valueParameterDescriptor : descriptor.getUnsubstitutedValueParameters()) { + JetParameter parameter = (JetParameter) trace.getDeclarationPsiElement(valueParameterDescriptor); + if (parameter.getValOrVarNode() == null || !primary) { + constructorScope.addVariableDescriptor(valueParameterDescriptor); + } + } + + constructorScope.addLabeledDeclaration(descriptor); // TODO : Labels for constructors?! + + return constructorScope; } private void resolvePropertyDeclarationBodies() { @@ -599,7 +606,7 @@ public class TopDownAnalyzer { trace.getErrorHandler().genericError(initializer.getNode(), "Property initializers are not allowed when no primary constructor is present"); } else { - JetScope scope = getInnerScopeForConstructor(primaryConstructor, classDescriptor.getScopeForMemberResolution()); + JetScope scope = getInnerScopeForConstructor(primaryConstructor, classDescriptor.getScopeForMemberResolution(), true); resolvePropertyInitializer(property, propertyDescriptor, initializer, scope); } } @@ -727,8 +734,6 @@ public class TopDownAnalyzer { JetFlowInformationProvider flowInformationProvider = classDescriptorResolver.computeFlowData(function.asElement(), bodyExpression); JetTypeInferrer typeInferrer = semanticServices.getTypeInferrer(trace, flowInformationProvider); - assert readyToProcessExpressions : "Must be ready collecting types"; - typeInferrer.checkFunctionReturnType(declaringScope, function, functionDescriptor); List unreachableElements = new ArrayList(); diff --git a/idea/testData/checker/regression/ScopeForSecondaryConstructors.jet b/idea/testData/checker/regression/ScopeForSecondaryConstructors.jet new file mode 100644 index 00000000000..2cac1044074 --- /dev/null +++ b/idea/testData/checker/regression/ScopeForSecondaryConstructors.jet @@ -0,0 +1,18 @@ + class Foo(var bar : Int, barr : Int, val barrr : Int) { + { + bar = 1 + barr = 1 + barrr = 1 + 1 : Int + this : Foo + } + + this(val bar : Int) : this(1, 1, 1) { + bar = 1 + this.bar + 1 : Int + val a : Int =1 + this : Foo + } + } + diff --git a/idea/testData/resolve/PrimaryConstructors.jet b/idea/testData/resolve/PrimaryConstructors.jet index b0dcaa23d81..d02894b39ba 100644 --- a/idea/testData/resolve/PrimaryConstructors.jet +++ b/idea/testData/resolve/PrimaryConstructors.jet @@ -1,6 +1,6 @@ class A(~a~val a : Int) { this() {`$a`a} - ~b~val b = `a`a + ~b~val b = `$a`a ~f~fun f() = `$a`a } @@ -10,3 +10,20 @@ fun test() { a.`b`b`:std::Int` a.`f`f()`:std::Int` } + +namespace Jet65 { + + class Foo(~bar~var bar : Int, ~barr~barr : Int, ~barrr~val barrr : Int) { + { + `$bar`bar = 1 + `barr`barr = 1 + `$barrr`barrr = 1 + } + + this(~s.bar~val bar : Int) : this(1, 1, 1) { + `s.bar`bar = 1 + this.`$bar`bar + } + } + +}