From 968e22f999fcbee7a8417ab2e1d9846758496b49 Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Fri, 22 Apr 2011 21:45:44 +0400 Subject: [PATCH] Working on constructors: references on 'this()' calls, etc. Many checks pending --- idea/src/org/jetbrains/jet/JetNodeTypes.java | 1 + .../jet/lang/parsing/JetParsing.java | 2 + .../jet/lang/psi/JetDelegatorToThisCall.java | 5 + .../lang/psi/JetThisReferenceExpression.java | 32 +++ .../jet/lang/resolve/TopDownAnalyzer.java | 187 ++++++++++++------ .../jet/lang/types/JetTypeInferrer.java | 104 +++++----- idea/testData/checker/Constructors.jet | 9 + idea/testData/psi/Constructors.txt | 6 +- idea/testData/psi/SimpleClassMembers.txt | 12 +- idea/testData/psi/SimpleClassMembers_ERR.txt | 6 +- idea/testData/psi/examples/BinaryTree.txt | 3 +- .../psi/examples/collections/HashMap.txt | 3 +- .../resolve/ConstructorsAndInitializers.jet | 12 ++ .../jetbrains/jet/resolve/JetResolveTest.java | 4 + 14 files changed, 266 insertions(+), 120 deletions(-) create mode 100644 idea/src/org/jetbrains/jet/lang/psi/JetThisReferenceExpression.java create mode 100644 idea/testData/checker/Constructors.jet create mode 100644 idea/testData/resolve/ConstructorsAndInitializers.jet diff --git a/idea/src/org/jetbrains/jet/JetNodeTypes.java b/idea/src/org/jetbrains/jet/JetNodeTypes.java index b94ef1c899a..d3fe59bb0d8 100644 --- a/idea/src/org/jetbrains/jet/JetNodeTypes.java +++ b/idea/src/org/jetbrains/jet/JetNodeTypes.java @@ -53,6 +53,7 @@ public interface JetNodeTypes { JetNodeType PROPERTY_ACCESSOR = new JetNodeType("PROPERTY_ACCESSOR", JetPropertyAccessor.class); JetNodeType INITIALIZER_LIST = new JetNodeType("INITIALIZER_LIST", JetInitializerList.class); JetNodeType THIS_CALL = new JetNodeType("THIS_CALL", JetDelegatorToThisCall.class); + JetNodeType THIS_CONSTRUCTOR_REFERENCE = new JetNodeType("THIS_CONSTRUCTOR_REFERENCE", JetThisReferenceExpression.class); JetNodeType TYPE_CONSTRAINT_LIST = new JetNodeType("TYPE_CONSTRAINT_LIST", JetTypeConstraintList.class); JetNodeType TYPE_CONSTRAINT = new JetNodeType("TYPE_CONSTRAINT", JetTypeConstraint.class); diff --git a/idea/src/org/jetbrains/jet/lang/parsing/JetParsing.java b/idea/src/org/jetbrains/jet/lang/parsing/JetParsing.java index fad8ce46984..f9981016787 100644 --- a/idea/src/org/jetbrains/jet/lang/parsing/JetParsing.java +++ b/idea/src/org/jetbrains/jet/lang/parsing/JetParsing.java @@ -623,7 +623,9 @@ public class JetParsing extends AbstractJetParsing { IElementType type; if (at(THIS_KEYWORD)) { + PsiBuilder.Marker mark = mark(); advance(); // THIS_KEYWORD + mark.done(THIS_CONSTRUCTOR_REFERENCE); type = THIS_CALL; } else if (atSet(TYPE_REF_FIRST)) { diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetDelegatorToThisCall.java b/idea/src/org/jetbrains/jet/lang/psi/JetDelegatorToThisCall.java index 658799c7611..dc6ecf53252 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetDelegatorToThisCall.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetDelegatorToThisCall.java @@ -12,6 +12,7 @@ import java.util.List; * @author max */ public class JetDelegatorToThisCall extends JetDelegationSpecifier implements JetCall { + public JetDelegatorToThisCall(@NotNull ASTNode node) { super(node); } @@ -37,4 +38,8 @@ public class JetDelegatorToThisCall extends JetDelegationSpecifier implements Je public List getFunctionLiteralArguments() { return Collections.emptyList(); } + + public JetReferenceExpression getThisReference() { + return findChildByClass(JetThisReferenceExpression.class); + } } diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetThisReferenceExpression.java b/idea/src/org/jetbrains/jet/lang/psi/JetThisReferenceExpression.java new file mode 100644 index 00000000000..97566a68106 --- /dev/null +++ b/idea/src/org/jetbrains/jet/lang/psi/JetThisReferenceExpression.java @@ -0,0 +1,32 @@ +package org.jetbrains.jet.lang.psi; + +import com.intellij.lang.ASTNode; +import com.intellij.openapi.util.TextRange; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiReference; +import org.jetbrains.annotations.NotNull; + +/** + * @author abreslav + */ +public class JetThisReferenceExpression extends JetReferenceExpression { + public JetThisReferenceExpression(@NotNull ASTNode node) { + super(node); + } + + @Override + public PsiReference getReference() { + return new JetPsiReference() { + + @Override + public PsiElement getElement() { + return JetThisReferenceExpression.this; + } + + @Override + public TextRange getRangeInElement() { + return new TextRange(0, getElement().getTextLength()); + } + }; + } +} diff --git a/idea/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java b/idea/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java index e27960523e8..27645f9f5b4 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java @@ -270,81 +270,61 @@ public class TopDownAnalyzer { //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// private void resolveBehaviorDeclarationBodies() { + resolveDelegationSpecifierLists(); + + + //TODO : anonymous initializers + resolvePropertyDeclarationBodies(); resolveFunctionDeclarationBodies(); } - private void resolveFunctionDeclarationBodies() { - for (Map.Entry entry : functions.entrySet()) { - JetDeclaration declaration = entry.getKey(); - FunctionDescriptor descriptor = entry.getValue(); + private void resolveDelegationSpecifierLists() { + final JetTypeInferrer typeInferrer = semanticServices.getTypeInferrer(trace, JetFlowInformationProvider.NONE); + for (Map.Entry entry : classes.entrySet()) { + final JetClass declaration = entry.getKey(); + final MutableClassDescriptor descriptor = entry.getValue(); - WritableScope declaringScope = declaringScopes.get(declaration); - assert declaringScope != null; - - if (declaration instanceof JetFunction) { - resolveFunctionBody(trace, (JetFunction) declaration, (FunctionDescriptorImpl) descriptor, declaringScope); - } - else if (declaration instanceof JetConstructor) { - resolveConstructorBody((JetConstructor) declaration, descriptor, declaringScope); - } - else { - throw new UnsupportedOperationException(); // TODO - } - - assert descriptor.getUnsubstitutedReturnType() != null; - } - } - - private void resolveConstructorBody(JetConstructor declaration, FunctionDescriptor descriptor, final WritableScope declaringScope) { - WritableScope constructorScope = semanticServices.createWritableScope(declaringScope, declaringScope.getContainingDeclaration()); - for (PropertyDescriptor propertyDescriptor : declaringScopesToProperties.get(descriptor.getContainingDeclaration())) { - constructorScope.addPropertyDescriptorByFieldName("$" + propertyDescriptor.getName(), propertyDescriptor); - } - final JetScope functionInnerScope = FunctionDescriptorUtil.getFunctionInnerScope(constructorScope, descriptor, semanticServices); - final JetTypeInferrer typeInferrerForInitializers = semanticServices.getTypeInferrer(traceForConstructors, JetFlowInformationProvider.NONE); - for (JetDelegationSpecifier initializer : declaration.getInitializers()) { - // TODO : check that the type being referenced is actually a supertype - initializer.accept(new JetVisitor() { - @Override - public void visitDelegationToSuperCallSpecifier(JetDelegatorToSuperCall call) { - JetTypeReference typeReference = call.getTypeReference(); - if (typeReference != null) { - typeInferrerForInitializers.getTypeForConstructorCall(functionInnerScope, typeReference, call); + for (JetDelegationSpecifier delegationSpecifier : declaration.getDelegationSpecifiers()) { + delegationSpecifier.accept(new JetVisitor() { + @Override + public void visitDelegationByExpressionSpecifier(JetDelegatorByExpressionSpecifier specifier) { + JetExpression delegateExpression = specifier.getDelegateExpression(); + if (delegateExpression != null) { + JetType type = typeInferrer.getType(descriptor.getWritableUnsubstitutedMemberScope(), delegateExpression, false); + JetType supertype = trace.resolveTypeReference(specifier.getTypeReference()); + if (type != null && !semanticServices.getTypeChecker().isSubtypeOf(type, supertype)) { // TODO : Convertible? + semanticServices.getErrorHandler().typeMismatch(delegateExpression, supertype, type); + } + } } - } - @Override - public void visitDelegationToThisCall(JetDelegatorToThisCall call) { - JetTypeReference typeReference = call.getTypeReference(); // TODO : use explicit type here - if (typeReference != null) { - typeInferrerForInitializers.getTypeForConstructorCall(functionInnerScope, typeReference, call); + @Override + public void visitDelegationToSuperCallSpecifier(JetDelegatorToSuperCall call) { + JetTypeReference typeReference = call.getTypeReference(); + if (typeReference != null) { + typeInferrer.checkConstructorCall(descriptor.getWritableUnsubstitutedMemberScope(), typeReference, call); + } } - } - @Override - public void visitDelegationByExpressionSpecifier(JetDelegatorByExpressionSpecifier specifier) { - semanticServices.getErrorHandler().genericError(specifier.getNode(), "'by'-clause is only supported for primary constructors"); - } + @Override + public void visitDelegationToSuperClassSpecifier(JetDelegatorToSuperClass specifier) { + if (declaration.getPrimaryConstructorParameterList() != null) { + semanticServices.getErrorHandler().genericError(specifier.getNode(), "Constructor parameters required in initializer"); + } + } - @Override - public void visitDelegationToSuperClassSpecifier(JetDelegatorToSuperClass specifier) { - semanticServices.getErrorHandler().genericError(specifier.getNode(), "Constructor parameters required"); - } + @Override + public void visitDelegationToThisCall(JetDelegatorToThisCall thisCall) { + throw new IllegalStateException("This-calls should be prohibitied by the parser"); + } - @Override - public void visitDelegationSpecifier(JetDelegationSpecifier specifier) { - throw new IllegalStateException(); - } - }); - } - JetExpression bodyExpression = declaration.getBodyExpression(); - if (bodyExpression != null) { - computeFlowData(declaration, bodyExpression); - JetFlowInformationProvider flowInformationProvider = computeFlowData(declaration, bodyExpression); - JetTypeInferrer typeInferrer = semanticServices.getTypeInferrer(traceForConstructors, flowInformationProvider); - - typeInferrer.getType(functionInnerScope, bodyExpression, true); + @Override + public void visitJetElement(JetElement elem) { + throw new UnsupportedOperationException(elem.getText() + " : " + elem); + } + }); + } } } @@ -414,6 +394,85 @@ public class TopDownAnalyzer { } } + private void resolveFunctionDeclarationBodies() { + for (Map.Entry entry : functions.entrySet()) { + JetDeclaration declaration = entry.getKey(); + FunctionDescriptor descriptor = entry.getValue(); + + WritableScope declaringScope = declaringScopes.get(declaration); + assert declaringScope != null; + + if (declaration instanceof JetFunction) { + resolveFunctionBody(trace, (JetFunction) declaration, (FunctionDescriptorImpl) descriptor, declaringScope); + } + else if (declaration instanceof JetConstructor) { + resolveConstructorBody((JetConstructor) declaration, descriptor, declaringScope); + } + else { + throw new UnsupportedOperationException(); // TODO + } + + assert descriptor.getUnsubstitutedReturnType() != null; + } + } + + private void resolveConstructorBody(JetConstructor declaration, final FunctionDescriptor descriptor, final WritableScope declaringScope) { + WritableScope constructorScope = semanticServices.createWritableScope(declaringScope, declaringScope.getContainingDeclaration()); + for (PropertyDescriptor propertyDescriptor : declaringScopesToProperties.get(descriptor.getContainingDeclaration())) { + constructorScope.addPropertyDescriptorByFieldName("$" + propertyDescriptor.getName(), propertyDescriptor); + } + final JetScope functionInnerScope = FunctionDescriptorUtil.getFunctionInnerScope(constructorScope, descriptor, semanticServices); + final JetTypeInferrer typeInferrerForInitializers = semanticServices.getTypeInferrer(traceForConstructors, JetFlowInformationProvider.NONE); + for (JetDelegationSpecifier initializer : declaration.getInitializers()) { + // TODO : check that the type being referenced is actually a supertype + initializer.accept(new JetVisitor() { + @Override + public void visitDelegationToSuperCallSpecifier(JetDelegatorToSuperCall call) { + JetTypeReference typeReference = call.getTypeReference(); + if (typeReference != null) { + typeInferrerForInitializers.checkConstructorCall(functionInnerScope, typeReference, call); + } + } + + @Override + 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(); + typeInferrerForInitializers.checkClassConstructorCall( + functionInnerScope, + call.getThisReference(), + classDescriptor, + classDescriptor.getDefaultType(), + call); + } + + @Override + public void visitDelegationByExpressionSpecifier(JetDelegatorByExpressionSpecifier specifier) { + semanticServices.getErrorHandler().genericError(specifier.getNode(), "'by'-clause is only supported for primary constructors"); + } + + @Override + public void visitDelegationToSuperClassSpecifier(JetDelegatorToSuperClass specifier) { + semanticServices.getErrorHandler().genericError(specifier.getNode(), "Constructor parameters required"); + } + + @Override + public void visitDelegationSpecifier(JetDelegationSpecifier specifier) { + throw new IllegalStateException(); + } + }); + } + JetExpression bodyExpression = declaration.getBodyExpression(); + if (bodyExpression != null) { + computeFlowData(declaration, bodyExpression); + JetFlowInformationProvider flowInformationProvider = computeFlowData(declaration, bodyExpression); + JetTypeInferrer typeInferrer = semanticServices.getTypeInferrer(traceForConstructors, flowInformationProvider); + + typeInferrer.getType(functionInnerScope, bodyExpression, true); + } + } + private void resolveFunctionBody( @NotNull BindingTrace trace, @NotNull JetDeclarationWithBody function, diff --git a/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java b/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java index f888c5c781b..6e905e08240 100644 --- a/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java +++ b/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java @@ -454,7 +454,7 @@ public class JetTypeInferrer { } @Nullable - public JetType getTypeForConstructorCall(JetScope scope, @NotNull JetTypeReference typeReference, @NotNull JetCall call) { + public JetType checkConstructorCall(JetScope scope, @NotNull JetTypeReference typeReference, @NotNull JetCall call) { JetTypeElement typeElement = typeReference.getTypeElement(); if (typeElement instanceof JetUserType) { JetUserType userType = (JetUserType) typeElement; @@ -483,50 +483,7 @@ public class JetTypeInferrer { JetSimpleNameExpression referenceExpression = userType.getReferenceExpression(); if (referenceExpression != null) { - // When one writes 'new Array(...)' this does not make much sense, and an instance - // of 'Array' must be created anyway. - // Thus, we should either prohibit projections in type arguments in such contexts, - // or treat them as an automatic upcast to the desired type, i.e. for the user not - // to be forced to write - // val a : Array = new Array(...) - // NOTE: Array may be a bad example here, some classes may have substantial functionality - // not involving their type parameters - // - // The code below upcasts the type automatically - - List typeArguments = receiverType.getArguments(); - - List projectionsStripped = new ArrayList(); - for (TypeProjection typeArgument : typeArguments) { - if (typeArgument.getProjectionKind() != Variance.INVARIANT) { - projectionsStripped.add(new TypeProjection(typeArgument.getType())); - } - else - projectionsStripped.add(typeArgument); - } - - FunctionGroup constructors = classDescriptor.getConstructors(projectionsStripped); - OverloadDomain constructorsOverloadDomain = semanticServices.getOverloadResolver().getOverloadDomain(constructors); - JetType constructorReturnedType = resolveOverloads( - scope, - wrapForTracing(constructorsOverloadDomain, referenceExpression, call.getValueArgumentList(), false), - Collections.emptyList(), - call.getValueArguments(), - call.getFunctionLiteralArguments()); - if (constructorReturnedType == null && !ErrorUtils.isErrorType(receiverType)) { - trace.recordReferenceResolution(referenceExpression, receiverType.getConstructor().getDeclarationDescriptor()); - // TODO : more helpful message - JetArgumentList argumentList = call.getValueArgumentList(); - if (argumentList != null) { - semanticServices.getErrorHandler().genericError(argumentList.getNode(), "Cannot find an overload for these arguments"); - } - constructorReturnedType = receiverType; - } - // If no upcast needed: - return constructorReturnedType; - - // Automatic upcast: -// result = receiverType; + return checkClassConstructorCall(scope, referenceExpression, classDescriptor, receiverType, call); } } else { @@ -541,6 +498,61 @@ public class JetTypeInferrer { return null; } + @Nullable + public JetType checkClassConstructorCall( + @NotNull JetScope scope, + @NotNull JetReferenceExpression referenceExpression, + @NotNull ClassDescriptor classDescriptor, + @NotNull JetType receiverType, + @NotNull JetCall call) { + // When one writes 'new Array(...)' this does not make much sense, and an instance + // of 'Array' must be created anyway. + // Thus, we should either prohibit projections in type arguments in such contexts, + // or treat them as an automatic upcast to the desired type, i.e. for the user not + // to be forced to write + // val a : Array = new Array(...) + // NOTE: Array may be a bad example here, some classes may have substantial functionality + // not involving their type parameters + // + // The code below upcasts the type automatically + + List typeArguments = receiverType.getArguments(); + + List projectionsStripped = new ArrayList(); + for (TypeProjection typeArgument : typeArguments) { + if (typeArgument.getProjectionKind() != Variance.INVARIANT) { + projectionsStripped.add(new TypeProjection(typeArgument.getType())); + } + else + projectionsStripped.add(typeArgument); + } + + FunctionGroup constructors = classDescriptor.getConstructors(projectionsStripped); + OverloadDomain constructorsOverloadDomain = semanticServices.getOverloadResolver().getOverloadDomain(constructors); + JetType constructorReturnedType = resolveOverloads( + scope, + wrapForTracing(constructorsOverloadDomain, referenceExpression, call.getValueArgumentList(), false), + Collections.emptyList(), + call.getValueArguments(), + call.getFunctionLiteralArguments()); + if (constructorReturnedType == null && !ErrorUtils.isErrorType(receiverType)) { + DeclarationDescriptor declarationDescriptor = receiverType.getConstructor().getDeclarationDescriptor(); + assert declarationDescriptor != null; + trace.recordReferenceResolution(referenceExpression, declarationDescriptor); + // TODO : more helpful message + JetArgumentList argumentList = call.getValueArgumentList(); + if (argumentList != null) { + semanticServices.getErrorHandler().genericError(argumentList.getNode(), "Cannot find an overload for these arguments"); + } + constructorReturnedType = receiverType; + } + // If no upcast needed: + return constructorReturnedType; + + // Automatic upcast: +// result = receiverType; + } + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -1133,7 +1145,7 @@ public class JetTypeInferrer { // TODO : type argument inference JetTypeReference typeReference = expression.getTypeReference(); if (typeReference != null) { - result = getTypeForConstructorCall(scope, typeReference, expression); + result = checkConstructorCall(scope, typeReference, expression); } } diff --git a/idea/testData/checker/Constructors.jet b/idea/testData/checker/Constructors.jet new file mode 100644 index 00000000000..c024d163d7d --- /dev/null +++ b/idea/testData/checker/Constructors.jet @@ -0,0 +1,9 @@ +class Z { + this() : this(1, true) {} + + this(x : Int, y : Boolean) : this(1) {} +} + +class Foo() : Z, this() { + +} \ No newline at end of file diff --git a/idea/testData/psi/Constructors.txt b/idea/testData/psi/Constructors.txt index dd76c74c650..89be5930eff 100644 --- a/idea/testData/psi/Constructors.txt +++ b/idea/testData/psi/Constructors.txt @@ -20,7 +20,8 @@ JetFile: Constructors.jet PsiWhiteSpace(' ') INITIALIZER_LIST THIS_CALL - PsiElement(this)('this') + THIS_CONSTRUCTOR_REFERENCE + PsiElement(this)('this') VALUE_ARGUMENT_LIST PsiElement(LPAR)('(') VALUE_ARGUMENT @@ -78,7 +79,8 @@ JetFile: Constructors.jet PsiWhiteSpace(' ') INITIALIZER_LIST THIS_CALL - PsiElement(this)('this') + THIS_CONSTRUCTOR_REFERENCE + PsiElement(this)('this') VALUE_ARGUMENT_LIST PsiElement(LPAR)('(') VALUE_ARGUMENT diff --git a/idea/testData/psi/SimpleClassMembers.txt b/idea/testData/psi/SimpleClassMembers.txt index ca537557ce9..06b9f7754fd 100644 --- a/idea/testData/psi/SimpleClassMembers.txt +++ b/idea/testData/psi/SimpleClassMembers.txt @@ -101,7 +101,8 @@ JetFile: SimpleClassMembers.jet PsiWhiteSpace(' ') INITIALIZER_LIST THIS_CALL - PsiElement(this)('this') + THIS_CONSTRUCTOR_REFERENCE + PsiElement(this)('this') VALUE_ARGUMENT_LIST PsiElement(LPAR)('(') VALUE_ARGUMENT @@ -343,7 +344,8 @@ JetFile: SimpleClassMembers.jet PsiWhiteSpace(' ') INITIALIZER_LIST THIS_CALL - PsiElement(this)('this') + THIS_CONSTRUCTOR_REFERENCE + PsiElement(this)('this') VALUE_ARGUMENT_LIST PsiElement(LPAR)('(') VALUE_ARGUMENT @@ -428,7 +430,8 @@ JetFile: SimpleClassMembers.jet PsiWhiteSpace(' ') INITIALIZER_LIST THIS_CALL - PsiElement(this)('this') + THIS_CONSTRUCTOR_REFERENCE + PsiElement(this)('this') VALUE_ARGUMENT_LIST PsiElement(LPAR)('(') VALUE_ARGUMENT @@ -477,7 +480,8 @@ JetFile: SimpleClassMembers.jet PsiWhiteSpace(' ') INITIALIZER_LIST THIS_CALL - PsiElement(this)('this') + THIS_CONSTRUCTOR_REFERENCE + PsiElement(this)('this') VALUE_ARGUMENT_LIST PsiElement(LPAR)('(') VALUE_ARGUMENT diff --git a/idea/testData/psi/SimpleClassMembers_ERR.txt b/idea/testData/psi/SimpleClassMembers_ERR.txt index a934a0fc8a1..273b233a20e 100644 --- a/idea/testData/psi/SimpleClassMembers_ERR.txt +++ b/idea/testData/psi/SimpleClassMembers_ERR.txt @@ -91,7 +91,8 @@ JetFile: SimpleClassMembers_ERR.jet PsiWhiteSpace(' ') INITIALIZER_LIST THIS_CALL - PsiElement(this)('this') + THIS_CONSTRUCTOR_REFERENCE + PsiElement(this)('this') VALUE_ARGUMENT_LIST PsiElement(LPAR)('(') VALUE_ARGUMENT @@ -141,7 +142,8 @@ JetFile: SimpleClassMembers_ERR.jet PsiWhiteSpace(' ') INITIALIZER_LIST THIS_CALL - PsiElement(this)('this') + THIS_CONSTRUCTOR_REFERENCE + PsiElement(this)('this') VALUE_ARGUMENT_LIST PsiElement(LPAR)('(') VALUE_ARGUMENT diff --git a/idea/testData/psi/examples/BinaryTree.txt b/idea/testData/psi/examples/BinaryTree.txt index ee096382c3f..f2685d1e07b 100644 --- a/idea/testData/psi/examples/BinaryTree.txt +++ b/idea/testData/psi/examples/BinaryTree.txt @@ -210,7 +210,8 @@ JetFile: BinaryTree.jet PsiWhiteSpace(' ') INITIALIZER_LIST THIS_CALL - PsiElement(this)('this') + THIS_CONSTRUCTOR_REFERENCE + PsiElement(this)('this') VALUE_ARGUMENT_LIST PsiElement(LPAR)('(') VALUE_ARGUMENT diff --git a/idea/testData/psi/examples/collections/HashMap.txt b/idea/testData/psi/examples/collections/HashMap.txt index 219274f0f3f..80067516cd3 100644 --- a/idea/testData/psi/examples/collections/HashMap.txt +++ b/idea/testData/psi/examples/collections/HashMap.txt @@ -975,7 +975,8 @@ JetFile: HashMap.jet PsiWhiteSpace(' ') INITIALIZER_LIST THIS_CALL - PsiElement(this)('this') + THIS_CONSTRUCTOR_REFERENCE + PsiElement(this)('this') VALUE_ARGUMENT_LIST PsiElement(LPAR)('(') VALUE_ARGUMENT diff --git a/idea/testData/resolve/ConstructorsAndInitializers.jet b/idea/testData/resolve/ConstructorsAndInitializers.jet new file mode 100644 index 00000000000..d27160b258d --- /dev/null +++ b/idea/testData/resolve/ConstructorsAndInitializers.jet @@ -0,0 +1,12 @@ +class Z { + ~c1~this() : `c2`this(1, true) {} + + ~c2~this(x : Int, y : Boolean) : `c1`this() {} +} + +~Z1.c()~class Z1() : Z { + + this(x : Int, y : Boolean) : `Z1.c()`this() {} +} + +class Foo \ No newline at end of file diff --git a/idea/tests/org/jetbrains/jet/resolve/JetResolveTest.java b/idea/tests/org/jetbrains/jet/resolve/JetResolveTest.java index 1da699289e8..b2d41cb04b2 100644 --- a/idea/tests/org/jetbrains/jet/resolve/JetResolveTest.java +++ b/idea/tests/org/jetbrains/jet/resolve/JetResolveTest.java @@ -143,4 +143,8 @@ public class JetResolveTest extends ExtensibleResolveTestCase { doTest("/resolve/Classifiers.jet", true, true); } + public void testConstructorsAndInitializers() throws Exception { + doTest("/resolve/ConstructorsAndInitializers.jet", true, true); + } + } \ No newline at end of file