From d23a76b64dcb89d0ec4d491c5350fa469f366cb4 Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Tue, 26 Apr 2011 17:00:07 +0400 Subject: [PATCH] JET-6 Perform checks for primary and secondary constructors (In progress) --- idea/src/org/jetbrains/jet/JetNodeTypes.java | 1 + .../org/jetbrains/jet/lang/ErrorHandler.java | 5 +- .../jet/lang/annotations/JetPsiChecker.java | 2 +- .../lang/parsing/JetExpressionParsing.java | 6 +- .../jet/lang/parsing/JetParsing.java | 30 +-- .../org/jetbrains/jet/lang/psi/JetClass.java | 5 + .../jet/lang/psi/JetConstructor.java | 4 + .../lang/resolve/ClassDescriptorResolver.java | 72 +++--- .../LazySubstitutingClassDescriptor.java | 5 + .../lang/resolve/MutableClassDescriptor.java | 14 ++ .../jet/lang/resolve/TopDownAnalyzer.java | 216 +++++++++++------- .../jet/lang/types/ClassDescriptor.java | 4 + .../jet/lang/types/ClassDescriptorImpl.java | 12 +- .../jetbrains/jet/lang/types/ErrorUtils.java | 8 +- .../jet/lang/types/JetStandardClasses.java | 13 +- .../checker/BinaryCallsOnNullableValues.jet | 6 +- idea/testData/checker/Constructors.jet | 33 ++- idea/testData/checker/ForRangeConventions.jet | 18 +- idea/testData/checker/IncDec.jet | 6 +- idea/testData/checker/Properties.jet | 4 +- idea/testData/psi/Constructors.jet | 5 + idea/testData/psi/Constructors.txt | 104 ++++++++- .../resolve/ConstructorsAndInitializers.jet | 2 +- 23 files changed, 406 insertions(+), 169 deletions(-) diff --git a/idea/src/org/jetbrains/jet/JetNodeTypes.java b/idea/src/org/jetbrains/jet/JetNodeTypes.java index d3fe59bb0d8..8fab0c1cb73 100644 --- a/idea/src/org/jetbrains/jet/JetNodeTypes.java +++ b/idea/src/org/jetbrains/jet/JetNodeTypes.java @@ -35,6 +35,7 @@ public interface JetNodeTypes { JetNodeType IMPORT_DIRECTIVE = new JetNodeType("IMPORT_DIRECTIVE", JetImportDirective.class); JetNodeType NAMESPACE_BODY = new JetNodeType("NAMESPACE_BODY", JetNamespaceBody.class); JetNodeType MODIFIER_LIST = new JetNodeType("MODIFIER_LIST", JetModifierList.class); + JetNodeType PRIMARY_CONSTRUCTOR_MODIFIER_LIST = new JetNodeType("PRIMARY_CONSTRUCTOR_MODIFIER_LIST", JetModifierList.class); JetNodeType ATTRIBUTE_ANNOTATION = new JetNodeType("ATTRIBUTE_ANNOTATION", JetAttributeAnnotation.class); JetNodeType ATTRIBUTE = new JetNodeType("ATTRIBUTE", JetAttribute.class); JetNodeType TYPE_ARGUMENT_LIST = new JetNodeType("TYPE_ARGUMENT_LIST", JetTypeArgumentList.class); diff --git a/idea/src/org/jetbrains/jet/lang/ErrorHandler.java b/idea/src/org/jetbrains/jet/lang/ErrorHandler.java index 327fd11e89d..5d76edf11ea 100644 --- a/idea/src/org/jetbrains/jet/lang/ErrorHandler.java +++ b/idea/src/org/jetbrains/jet/lang/ErrorHandler.java @@ -1,6 +1,7 @@ package org.jetbrains.jet.lang; import com.intellij.lang.ASTNode; +import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.psi.JetExpression; import org.jetbrains.jet.lang.psi.JetReferenceExpression; import org.jetbrains.jet.lang.types.DeclarationDescriptor; @@ -18,7 +19,7 @@ public class ErrorHandler { } @Override - public void genericError(ASTNode node, String errorMessage) { + public void genericError(@NotNull ASTNode node, String errorMessage) { throw new IllegalStateException(errorMessage); } @@ -42,7 +43,7 @@ public class ErrorHandler { public void redeclaration(DeclarationDescriptor existingDescriptor, DeclarationDescriptor redeclaredDescriptor) { } - public void genericError(ASTNode node, String errorMessage) { + public void genericError(@NotNull ASTNode node, String errorMessage) { } public void genericWarning(ASTNode node, String message) { diff --git a/idea/src/org/jetbrains/jet/lang/annotations/JetPsiChecker.java b/idea/src/org/jetbrains/jet/lang/annotations/JetPsiChecker.java index 7dd3be4efe5..2e0a78b412d 100644 --- a/idea/src/org/jetbrains/jet/lang/annotations/JetPsiChecker.java +++ b/idea/src/org/jetbrains/jet/lang/annotations/JetPsiChecker.java @@ -63,7 +63,7 @@ public class JetPsiChecker implements Annotator { } @Override - public void genericError(ASTNode node, String errorMessage) { + public void genericError(@NotNull ASTNode node, String errorMessage) { holder.createErrorAnnotation(node, errorMessage); } diff --git a/idea/src/org/jetbrains/jet/lang/parsing/JetExpressionParsing.java b/idea/src/org/jetbrains/jet/lang/parsing/JetExpressionParsing.java index 2484e5db4d6..2e7af9bfed8 100644 --- a/idea/src/org/jetbrains/jet/lang/parsing/JetExpressionParsing.java +++ b/idea/src/org/jetbrains/jet/lang/parsing/JetExpressionParsing.java @@ -929,7 +929,7 @@ public class JetExpressionParsing extends AbstractJetParsing { private boolean parseLocalDeclaration() { PsiBuilder.Marker decls = mark(); JetParsing.TokenDetector enumDetector = new JetParsing.TokenDetector(ENUM_KEYWORD); - myJetParsing.parseModifierList(enumDetector); + myJetParsing.parseModifierList(MODIFIER_LIST, enumDetector); JetNodeType declType = parseLocalDeclarationRest(enumDetector.isDetected()); @@ -1002,7 +1002,7 @@ public class JetExpressionParsing extends AbstractJetParsing { PsiBuilder.Marker parameter = mark(); int parameterNamePos = matchTokenStreamPredicate(new LastBefore(new At(IDENTIFIER), new AtOffset(doubleArrowPos))); - createTruncatedBuilder(parameterNamePos).parseModifierList(); + createTruncatedBuilder(parameterNamePos).parseModifierList(MODIFIER_LIST); expect(IDENTIFIER, "Expecting parameter name", TokenSet.create(DOUBLE_ARROW)); @@ -1046,7 +1046,7 @@ public class JetExpressionParsing extends AbstractJetParsing { PsiBuilder.Marker parameter = mark(); int parameterNamePos = matchTokenStreamPredicate(new LastBefore(new At(IDENTIFIER), new AtSet(COMMA, RPAR, COLON, DOUBLE_ARROW))); - createTruncatedBuilder(parameterNamePos).parseModifierList(); + createTruncatedBuilder(parameterNamePos).parseModifierList(MODIFIER_LIST); expect(IDENTIFIER, "Expecting parameter declaration"); diff --git a/idea/src/org/jetbrains/jet/lang/parsing/JetParsing.java b/idea/src/org/jetbrains/jet/lang/parsing/JetParsing.java index f5ae2ea66bc..935b3c07dfa 100644 --- a/idea/src/org/jetbrains/jet/lang/parsing/JetParsing.java +++ b/idea/src/org/jetbrains/jet/lang/parsing/JetParsing.java @@ -115,7 +115,7 @@ public class JetParsing extends AbstractJetParsing { * ; */ PsiBuilder.Marker firstEntry = mark(); - parseModifierList(); + parseModifierList(MODIFIER_LIST); if (at(NAMESPACE_KEYWORD)) { advance(); // NAMESPACE_KEYWORD @@ -218,7 +218,7 @@ public class JetParsing extends AbstractJetParsing { PsiBuilder.Marker decl = mark(); TokenDetector detector = new TokenDetector(ENUM_KEYWORD); - parseModifierList(detector); + parseModifierList(MODIFIER_LIST, detector); IElementType keywordToken = tt(); JetNodeType declType = null; @@ -253,8 +253,8 @@ public class JetParsing extends AbstractJetParsing { /* * (modifier | attribute)* */ - public void parseModifierList() { - parseModifierList(null); + public void parseModifierList(JetNodeType nodeType) { + parseModifierList(nodeType, null); } /** @@ -262,7 +262,7 @@ public class JetParsing extends AbstractJetParsing { * * Feeds modifiers (not attributes) into the passed consumer, if it is not null */ - public void parseModifierList(Consumer tokenConsumer) { + public void parseModifierList(JetNodeType nodeType, Consumer tokenConsumer) { PsiBuilder.Marker list = mark(); boolean empty = true; while (!eof()) { @@ -280,7 +280,7 @@ public class JetParsing extends AbstractJetParsing { if (empty) { list.drop(); } else { - list.done(MODIFIER_LIST); + list.done(nodeType); } } @@ -393,7 +393,7 @@ public class JetParsing extends AbstractJetParsing { advance(); // WRAPS_KEYWORD } else { - parseModifierList(); + parseModifierList(PRIMARY_CONSTRUCTOR_MODIFIER_LIST); } if (at(LPAR)) { @@ -436,7 +436,7 @@ public class JetParsing extends AbstractJetParsing { TokenSet constructorNameFollow = TokenSet.create(SEMICOLON, COLON, LPAR, LT, LBRACE); int lastId = findLastBefore(ENUM_MEMBER_FIRST, constructorNameFollow, false); TokenDetector enumDetector = new TokenDetector(ENUM_KEYWORD); - createTruncatedBuilder(lastId).parseModifierList(enumDetector); + createTruncatedBuilder(lastId).parseModifierList(MODIFIER_LIST, enumDetector); IElementType type; if (at(IDENTIFIER)) { @@ -535,7 +535,7 @@ public class JetParsing extends AbstractJetParsing { PsiBuilder.Marker decl = mark(); TokenDetector enumDetector = new TokenDetector(ENUM_KEYWORD); - parseModifierList(enumDetector); + parseModifierList(MODIFIER_LIST, enumDetector); JetNodeType declType = parseMemberDeclarationRest(enumDetector.isDetected()); @@ -786,7 +786,7 @@ public class JetParsing extends AbstractJetParsing { private boolean parsePropertyGetterOrSetter() { PsiBuilder.Marker getterOrSetter = mark(); - parseModifierList(); + parseModifierList(MODIFIER_LIST); if (!at(GET_KEYWORD) && !at(SET_KEYWORD)) { getterOrSetter.rollbackTo(); @@ -807,7 +807,7 @@ public class JetParsing extends AbstractJetParsing { PsiBuilder.Marker parameterList = mark(); PsiBuilder.Marker setterParameter = mark(); int lastId = findLastBefore(TokenSet.create(IDENTIFIER), TokenSet.create(RPAR, COMMA, COLON), false); - createTruncatedBuilder(lastId).parseModifierList(); + createTruncatedBuilder(lastId).parseModifierList(MODIFIER_LIST); expect(IDENTIFIER, "Expecting parameter name", TokenSet.create(RPAR, COLON, LBRACE, EQ)); if (at(COLON)) { @@ -1111,7 +1111,7 @@ public class JetParsing extends AbstractJetParsing { PsiBuilder.Marker mark = mark(); int lastId = findLastBefore(TokenSet.create(IDENTIFIER), TokenSet.create(COMMA, GT, COLON), false); - createTruncatedBuilder(lastId).parseModifierList(); + createTruncatedBuilder(lastId).parseModifierList(MODIFIER_LIST); expect(IDENTIFIER, "Type parameter name expected", TokenSet.EMPTY); @@ -1235,7 +1235,7 @@ public class JetParsing extends AbstractJetParsing { PsiBuilder.Marker projection = mark(); int lastId = findLastBefore(TokenSet.create(IDENTIFIER), TokenSet.create(COMMA, COLON, GT), false); - createTruncatedBuilder(lastId).parseModifierList(); + createTruncatedBuilder(lastId).parseModifierList(MODIFIER_LIST); if (at(MUL)) { advance(); // MUL @@ -1372,7 +1372,7 @@ public class JetParsing extends AbstractJetParsing { if (isFunctionTypeContents) { if (!tryParseValueParameter()) { PsiBuilder.Marker valueParameter = mark(); - parseModifierList(); // lazy, out, ref + parseModifierList(MODIFIER_LIST); // lazy, out, ref parseTypeRef(); valueParameter.done(VALUE_PARAMETER); } @@ -1406,7 +1406,7 @@ public class JetParsing extends AbstractJetParsing { PsiBuilder.Marker parameter = mark(); int lastId = findLastBefore(TokenSet.create(IDENTIFIER), TokenSet.create(COMMA, RPAR, COLON), false); - createTruncatedBuilder(lastId).parseModifierList(); + createTruncatedBuilder(lastId).parseModifierList(MODIFIER_LIST); if (at(VAR_KEYWORD) || at(VAL_KEYWORD)) { advance(); // VAR_KEYWORD | VAL_KEYWORD diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetClass.java b/idea/src/org/jetbrains/jet/lang/psi/JetClass.java index 6eaa974df5f..2dc9127aec5 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetClass.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetClass.java @@ -61,4 +61,9 @@ public class JetClass extends JetTypeParameterListOwner implements JetClassOrObj JetDelegationSpecifierList list = getDelegationSpecifierList(); return list != null ? list.getDelegationSpecifiers() : Collections.emptyList(); } + + @Nullable + public JetModifierList getPrimaryConstructorModifierList() { + return (JetModifierList) findChildByType(JetNodeTypes.PRIMARY_CONSTRUCTOR_MODIFIER_LIST); + } } diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetConstructor.java b/idea/src/org/jetbrains/jet/lang/psi/JetConstructor.java index 59944c3989a..89158226496 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetConstructor.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetConstructor.java @@ -59,4 +59,8 @@ public class JetConstructor extends JetDeclaration implements JetDeclarationWith public JetElement asElement() { return this; } + + public ASTNode getNameNode() { + return getNode().findChildByType(JetTokens.THIS_KEYWORD); + } } diff --git a/idea/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java b/idea/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java index ad26483549d..f6de56ae9e1 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java @@ -56,9 +56,9 @@ public class ClassDescriptorResolver { WritableFunctionGroup constructors = new WritableFunctionGroup(""); for (JetConstructor constructor : classElement.getSecondaryConstructors()) { - constructors.addFunction(resolveConstructorDescriptor(members, classDescriptor, constructor, false)); + constructors.addFunction(resolveSecondaryConstructorDescriptor(members, classDescriptor, constructor)); } - ConstructorDescriptor primaryConstructorDescriptor = resolvePrimaryConstructor(scope, classDescriptor, classElement); + ConstructorDescriptor primaryConstructorDescriptor = resolvePrimaryConstructorDescriptor(scope, classDescriptor, classElement); if (primaryConstructorDescriptor != null) { constructors.addFunction(primaryConstructorDescriptor); } @@ -67,7 +67,8 @@ public class ClassDescriptorResolver { typeParameters, supertypes, members, - constructors + constructors, + primaryConstructorDescriptor ); } @@ -159,7 +160,7 @@ public class ClassDescriptorResolver { } @NotNull - public FunctionDescriptor resolveFunctionDescriptor(DeclarationDescriptor containingDescriptor, JetScope scope, JetFunction function) { + public FunctionDescriptorImpl resolveFunctionDescriptor(DeclarationDescriptor containingDescriptor, JetScope scope, JetFunction function) { FunctionDescriptorImpl functionDescriptor = new FunctionDescriptorImpl( containingDescriptor, AttributeResolver.INSTANCE.resolveAttributes(function.getModifierList()), @@ -307,19 +308,21 @@ public class ClassDescriptorResolver { return variableDescriptor; } + @NotNull public VariableDescriptor resolveLocalVariableDescriptor(DeclarationDescriptor containingDeclaration, WritableScope scope, JetProperty property) { JetType type = getType(scope, property); - VariableDescriptorImpl propertyDescriptor = new LocalVariableDescriptor( + VariableDescriptorImpl variableDescriptor = new LocalVariableDescriptor( containingDeclaration, AttributeResolver.INSTANCE.resolveAttributes(property.getModifierList()), JetPsiUtil.safeName(property.getName()), type, property.isVar()); - trace.recordDeclarationResolution(property, propertyDescriptor); - return propertyDescriptor; + trace.recordDeclarationResolution(property, variableDescriptor); + return variableDescriptor; } + @NotNull public PropertyDescriptor resolvePropertyDescriptor(@NotNull DeclarationDescriptor containingDeclaration, @NotNull JetScope scope, JetProperty property) { JetType type = getType(scope, property); @@ -443,12 +446,18 @@ public class ClassDescriptorResolver { } @NotNull - public ConstructorDescriptor resolveConstructorDescriptor(@NotNull JetScope scope, ClassDescriptor classDescriptor, JetConstructor constructor, boolean isPrimary) { - return createConstructorDescriptor(scope, classDescriptor, isPrimary, constructor.getModifierList(), constructor, constructor.getParameters()); + public ConstructorDescriptor resolveSecondaryConstructorDescriptor(@NotNull JetScope scope, @NotNull ClassDescriptor classDescriptor, @NotNull JetConstructor constructor) { + return createConstructorDescriptor(scope, classDescriptor, false, constructor.getModifierList(), constructor, constructor.getParameters()); } @NotNull - private ConstructorDescriptor createConstructorDescriptor(JetScope scope, ClassDescriptor classDescriptor, boolean isPrimary, JetModifierList modifierList, JetDeclaration declarationToTrace, List valueParameters) { + private ConstructorDescriptor createConstructorDescriptor( + @NotNull JetScope scope, + @NotNull ClassDescriptor classDescriptor, + boolean isPrimary, + @Nullable JetModifierList modifierList, + @NotNull JetDeclaration declarationToTrace, + @NotNull List valueParameters) { ConstructorDescriptorImpl constructorDescriptor = new ConstructorDescriptorImpl( classDescriptor, AttributeResolver.INSTANCE.resolveAttributes(modifierList), @@ -463,33 +472,20 @@ public class ClassDescriptorResolver { } @Nullable - public ConstructorDescriptor resolvePrimaryConstructor(@NotNull JetScope scope, @NotNull ClassDescriptor classDescriptor, @NotNull JetClass classElement) { + public ConstructorDescriptor resolvePrimaryConstructorDescriptor(@NotNull JetScope scope, @NotNull ClassDescriptor classDescriptor, @NotNull JetClass classElement) { JetParameterList primaryConstructorParameterList = classElement.getPrimaryConstructorParameterList(); - if (primaryConstructorParameterList != null) { - return createConstructorDescriptor( - scope, - classDescriptor, - true, - classElement.getModifierList(), // TODO - classElement, - primaryConstructorParameterList.getParameters()); - } - else { - List secondaryConstructors = classElement.getSecondaryConstructors(); - if (secondaryConstructors.isEmpty()) { - return createConstructorDescriptor( - scope, - classDescriptor, - true, - classElement.getModifierList(), // TODO - classElement, - Collections.emptyList()); - } - else return null; - } + if (primaryConstructorParameterList == null) return null; + return createConstructorDescriptor( + scope, + classDescriptor, + true, + classElement.getPrimaryConstructorModifierList(), + classElement, + primaryConstructorParameterList.getParameters()); } - public VariableDescriptor resolvePrimaryConstructorParameterToAProperty( + @NotNull + public PropertyDescriptor resolvePrimaryConstructorParameterToAProperty( @NotNull ClassDescriptor classDescriptor, @NotNull JetScope scope, @NotNull JetParameter parameter) { @@ -497,6 +493,14 @@ public class ClassDescriptorResolver { String name = parameter.getName(); boolean isMutable = parameter.isMutable(); JetModifierList modifierList = parameter.getModifierList(); + + if (modifierList != null) { + ASTNode abstractNode = modifierList.getModifierNode(JetTokens.ABSTRACT_KEYWORD); + if (abstractNode != null) { + semanticServices.getErrorHandler().genericError(abstractNode, "This property cannot be declared abstract"); + } + } + PropertyDescriptor propertyDescriptor = new PropertyDescriptor( classDescriptor, AttributeResolver.INSTANCE.resolveAttributes(modifierList), diff --git a/idea/src/org/jetbrains/jet/lang/resolve/LazySubstitutingClassDescriptor.java b/idea/src/org/jetbrains/jet/lang/resolve/LazySubstitutingClassDescriptor.java index b0f95a7d105..cf2a954e4c7 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/LazySubstitutingClassDescriptor.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/LazySubstitutingClassDescriptor.java @@ -49,6 +49,11 @@ public class LazySubstitutingClassDescriptor implements ClassDescriptor { throw new UnsupportedOperationException(); // TODO } + @Override + public ConstructorDescriptor getUnsubstitutedPrimaryConstructor() { + return original.getUnsubstitutedPrimaryConstructor(); + } + @Override public List getAttributes() { throw new UnsupportedOperationException(); // TODO diff --git a/idea/src/org/jetbrains/jet/lang/resolve/MutableClassDescriptor.java b/idea/src/org/jetbrains/jet/lang/resolve/MutableClassDescriptor.java index e1a29b65a66..9fa30fd8146 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/MutableClassDescriptor.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/MutableClassDescriptor.java @@ -1,6 +1,7 @@ package org.jetbrains.jet.lang.resolve; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.JetSemanticServices; import org.jetbrains.jet.lang.types.*; @@ -14,6 +15,7 @@ public class MutableClassDescriptor extends MutableDeclarationDescriptor impleme private final WritableScope classHeaderScope; private final WritableScope writableMemberScope; private final WritableFunctionGroup constructors = new WritableFunctionGroup(""); + private ConstructorDescriptor primaryConstructor; private TypeConstructor typeConstructor; private JetScope unsubstitutedMemberScope; @@ -98,4 +100,16 @@ public class MutableClassDescriptor extends MutableDeclarationDescriptor impleme public R accept(DeclarationDescriptorVisitor visitor, D data) { return visitor.visitClassDescriptor(this, data); } + + public void setPrimaryConstructor(@NotNull ConstructorDescriptor constructorDescriptor) { + assert this.primaryConstructor == null : "Primary constructor assigned twice " + this; + this.primaryConstructor = constructorDescriptor; + addConstructor(constructorDescriptor); + } + + @Override + @Nullable + public ConstructorDescriptor getUnsubstitutedPrimaryConstructor() { + return primaryConstructor; + } } diff --git a/idea/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java b/idea/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java index e84be350184..d7df0678d21 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java @@ -1,7 +1,9 @@ package org.jetbrains.jet.lang.resolve; import com.google.common.collect.ArrayListMultimap; +import com.google.common.collect.Maps; import com.google.common.collect.Multimap; +import com.intellij.psi.util.PsiTreeUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.JetSemanticServices; import org.jetbrains.jet.lang.cfg.JetControlFlowProcessor; @@ -20,7 +22,8 @@ public class TopDownAnalyzer { private final Map classes = new LinkedHashMap(); private final Map namespaceScopes = new LinkedHashMap(); - private final Map functions = new LinkedHashMap(); + private final Map functions = Maps.newLinkedHashMap(); + private final Map constructors = Maps.newLinkedHashMap(); private final Map properties = new LinkedHashMap(); private final Map declaringScopes = new HashMap(); private final Multimap declaringScopesToProperties = ArrayListMultimap.create(); @@ -37,6 +40,8 @@ public class TopDownAnalyzer { this.classDescriptorResolver = new ClassDescriptorResolver(semanticServices, bindingTrace); this.trace = bindingTrace; this.flowDataTraceFactory = flowDataTraceFactory; + + // This allows access to backing fields this.traceForConstructors = new BindingTraceAdapter(trace) { @Override public void recordReferenceResolution(@NotNull JetReferenceExpression expression, @NotNull DeclarationDescriptor descriptor) { @@ -208,7 +213,7 @@ public class TopDownAnalyzer { public void visitConstructor(JetConstructor constructor) { DeclarationDescriptor containingDeclaration = declaringScope.getContainingDeclaration(); if (containingDeclaration instanceof ClassDescriptor) { - processConstructor((MutableClassDescriptor) containingDeclaration, constructor); + processSecondaryConstructor((MutableClassDescriptor) containingDeclaration, constructor); } else { semanticServices.getErrorHandler().genericError(constructor.getNode(), "Constructors are only allowed inside classes"); @@ -225,9 +230,11 @@ public class TopDownAnalyzer { } private void processPrimaryConstructor(MutableClassDescriptor classDescriptor, JetClass klass) { + if (klass.getPrimaryConstructorParameterList() == null) return; // No constructors + // TODO : not all the parameters are real properties WritableScope memberScope = classDescriptor.getWritableUnsubstitutedMemberScope(); // TODO : this is REALLY questionable - ConstructorDescriptor constructorDescriptor = classDescriptorResolver.resolvePrimaryConstructor(memberScope, classDescriptor, klass); + ConstructorDescriptor constructorDescriptor = classDescriptorResolver.resolvePrimaryConstructorDescriptor(memberScope, classDescriptor, klass); for (JetParameter parameter : klass.getPrimaryConstructorParameters()) { VariableDescriptor propertyDescriptor = classDescriptorResolver.resolvePrimaryConstructorParameterToAProperty( classDescriptor, @@ -238,20 +245,23 @@ public class TopDownAnalyzer { propertyDescriptor); } if (constructorDescriptor != null) { - classDescriptor.addConstructor(constructorDescriptor); + classDescriptor.setPrimaryConstructor(constructorDescriptor); } } - private void processConstructor(MutableClassDescriptor classDescriptor, JetConstructor constructor) { - ConstructorDescriptor constructorDescriptor = classDescriptorResolver.resolveConstructorDescriptor(classDescriptor.getWritableUnsubstitutedMemberScope(), classDescriptor, constructor, false); + private void processSecondaryConstructor(MutableClassDescriptor classDescriptor, JetConstructor constructor) { + ConstructorDescriptor constructorDescriptor = classDescriptorResolver.resolveSecondaryConstructorDescriptor( + classDescriptor.getWritableUnsubstitutedMemberScope(), + classDescriptor, + constructor); classDescriptor.addConstructor(constructorDescriptor); - functions.put(constructor, constructorDescriptor); + constructors.put(constructor, constructorDescriptor); declaringScopes.put(constructor, classDescriptor.getWritableUnsubstitutedMemberScope()); } private void processFunction(@NotNull WritableScope declaringScope, JetFunction function) { declaringScopes.put(function, declaringScope); - FunctionDescriptor descriptor = classDescriptorResolver.resolveFunctionDescriptor(declaringScope.getContainingDeclaration(), declaringScope, function); + FunctionDescriptorImpl descriptor = classDescriptorResolver.resolveFunctionDescriptor(declaringScope.getContainingDeclaration(), declaringScope, function); declaringScope.addFunctionDescriptor(descriptor); functions.put(function, descriptor); } @@ -272,21 +282,22 @@ public class TopDownAnalyzer { private void resolveBehaviorDeclarationBodies() { resolveDelegationSpecifierLists(); - + resolveSecondaryConstructorBodies(); //TODO : anonymous initializers resolvePropertyDeclarationBodies(); - resolveFunctionDeclarationBodies(); + resolveFunctionBodies(); } 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 declaration = entry.getKey(); + final JetClass jetClass = entry.getKey(); final MutableClassDescriptor descriptor = entry.getValue(); - for (JetDelegationSpecifier delegationSpecifier : declaration.getDelegationSpecifiers()) { + for (JetDelegationSpecifier delegationSpecifier : jetClass.getDelegationSpecifiers()) { delegationSpecifier.accept(new JetVisitor() { @Override public void visitDelegationByExpressionSpecifier(JetDelegatorByExpressionSpecifier specifier) { @@ -305,19 +316,36 @@ public class TopDownAnalyzer { JetTypeReference typeReference = call.getTypeReference(); if (typeReference != null) { typeInferrer.checkConstructorCall(descriptor.getWritableUnsubstitutedMemberScope(), typeReference, call); + if (jetClass.getPrimaryConstructorParameterList() == null) { + 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"); + } } } @Override public void visitDelegationToSuperClassSpecifier(JetDelegatorToSuperClass specifier) { - if (declaration.getPrimaryConstructorParameterList() != null) { - semanticServices.getErrorHandler().genericError(specifier.getNode(), "Constructor parameters required in initializer"); + JetType supertype = trace.resolveTypeReference(specifier.getTypeReference()); + if (supertype != null) { + DeclarationDescriptor declarationDescriptor = supertype.getConstructor().getDeclarationDescriptor(); + if (declarationDescriptor instanceof ClassDescriptor) { + ClassDescriptor classDescriptor = (ClassDescriptor) declarationDescriptor; + if (classDescriptor.getUnsubstitutedPrimaryConstructor() != null) { + semanticServices.getErrorHandler().genericError(specifier.getNode(), "This type has a constructor, and thus must be initialized here"); + } + } + else { + semanticServices.getErrorHandler().genericError(specifier.getNode(), "Only classes may serve as supertypes"); + } + } } @Override public void visitDelegationToThisCall(JetDelegatorToThisCall thisCall) { - throw new IllegalStateException("This-calls should be prohibitied by the parser"); + throw new IllegalStateException("This-calls should be prohibited by the parser"); } @Override @@ -329,6 +357,93 @@ public class TopDownAnalyzer { } } + private void resolveSecondaryConstructorBodies() { + for (Map.Entry entry : constructors.entrySet()) { + JetDeclaration declaration = entry.getKey(); + ConstructorDescriptor descriptor = entry.getValue(); + + WritableScope declaringScope = declaringScopes.get(declaration); + assert declaringScope != null; + + resolveSecondaryConstructorBody((JetConstructor) declaration, descriptor, declaringScope); + + assert descriptor.getUnsubstitutedReturnType() != null; + } + } + + private void resolveSecondaryConstructorBody(JetConstructor declaration, final ConstructorDescriptor 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); + + JetClass containingClass = PsiTreeUtil.getParentOfType(declaration, JetClass.class); + assert containingClass != null : "This must be guaranteed by the parser"; + if (containingClass.getPrimaryConstructorParameterList() == null) { + semanticServices.getErrorHandler().genericError(declaration.getNameNode(), "A secondary constructor may appear only in a class that has a primary constructor"); + } + else { + List initializers = declaration.getInitializers(); + if (initializers.isEmpty()) { + semanticServices.getErrorHandler().genericError(declaration.getNameNode(), "Secondary constructors must have an initializer list"); + } + else { + initializers.get(0).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(); + } + }); + for (int i = 1, initializersSize = initializers.size(); i < initializersSize; i++) { + JetDelegationSpecifier initializer = initializers.get(i); + semanticServices.getErrorHandler().genericError(initializer.getNode(), "Only one call to 'this(...)' is allowed"); + } + } + } + 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 resolvePropertyDeclarationBodies() { for (Map.Entry entry : properties.entrySet()) { JetProperty declaration = entry.getKey(); @@ -395,85 +510,20 @@ public class TopDownAnalyzer { } } - private void resolveFunctionDeclarationBodies() { - for (Map.Entry entry : functions.entrySet()) { + private void resolveFunctionBodies() { + 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 - } + resolveFunctionBody(trace, (JetFunction) declaration, (FunctionDescriptorImpl) descriptor, declaringScope); 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/ClassDescriptor.java b/idea/src/org/jetbrains/jet/lang/types/ClassDescriptor.java index f5f5917091f..0ad8ac14a87 100644 --- a/idea/src/org/jetbrains/jet/lang/types/ClassDescriptor.java +++ b/idea/src/org/jetbrains/jet/lang/types/ClassDescriptor.java @@ -1,6 +1,7 @@ package org.jetbrains.jet.lang.types; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.resolve.JetScope; import java.util.List; @@ -16,6 +17,9 @@ public interface ClassDescriptor extends ClassifierDescriptor { @NotNull FunctionGroup getConstructors(List typeArguments); + @Nullable + ConstructorDescriptor getUnsubstitutedPrimaryConstructor(); + @Override @NotNull DeclarationDescriptor getContainingDeclaration(); diff --git a/idea/src/org/jetbrains/jet/lang/types/ClassDescriptorImpl.java b/idea/src/org/jetbrains/jet/lang/types/ClassDescriptorImpl.java index 47e28377b3a..2e47f3c7c3f 100644 --- a/idea/src/org/jetbrains/jet/lang/types/ClassDescriptorImpl.java +++ b/idea/src/org/jetbrains/jet/lang/types/ClassDescriptorImpl.java @@ -1,6 +1,7 @@ package org.jetbrains.jet.lang.types; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.resolve.JetScope; import org.jetbrains.jet.lang.resolve.SubstitutingScope; @@ -16,6 +17,7 @@ public class ClassDescriptorImpl extends DeclarationDescriptorImpl implements Cl private JetScope memberDeclarations; private FunctionGroup constructors; + private ConstructorDescriptor primaryConstructor; public ClassDescriptorImpl( @NotNull DeclarationDescriptor containingDeclaration, @@ -28,10 +30,13 @@ public class ClassDescriptorImpl extends DeclarationDescriptorImpl implements Cl @NotNull List typeParameters, @NotNull Collection superclasses, @NotNull JetScope memberDeclarations, - @NotNull FunctionGroup constructors) { + @NotNull FunctionGroup constructors, + @Nullable ConstructorDescriptor primaryConstructor) { this.typeConstructor = new TypeConstructorImpl(this, getAttributes(), sealed, getName(), typeParameters, superclasses); this.memberDeclarations = memberDeclarations; this.constructors = constructors; + this.primaryConstructor = primaryConstructor; + assert !constructors.isEmpty() || primaryConstructor == null; return this; } @@ -79,4 +84,9 @@ public class ClassDescriptorImpl extends DeclarationDescriptorImpl implements Cl public R accept(DeclarationDescriptorVisitor visitor, D data) { return visitor.visitClassDescriptor(this, data); } + + @Override + public ConstructorDescriptor getUnsubstitutedPrimaryConstructor() { + return primaryConstructor; + } } \ No newline at end of file diff --git a/idea/src/org/jetbrains/jet/lang/types/ErrorUtils.java b/idea/src/org/jetbrains/jet/lang/types/ErrorUtils.java index adf146176eb..5c70aa2b06a 100644 --- a/idea/src/org/jetbrains/jet/lang/types/ErrorUtils.java +++ b/idea/src/org/jetbrains/jet/lang/types/ErrorUtils.java @@ -80,8 +80,12 @@ public class ErrorUtils { } }; - private static final ClassDescriptor ERROR_CLASS = new ClassDescriptorImpl(ERROR_MODULE, Collections.emptyList(), "").initialize( - true, Collections.emptyList(), Collections.emptyList(), getErrorScope(), ERROR_FUNCTION_GROUP); + private static final ClassDescriptorImpl ERROR_CLASS = new ClassDescriptorImpl(ERROR_MODULE, Collections.emptyList(), ""); + private static final ConstructorDescriptor ERROR_CONSTRUCTOR = new ConstructorDescriptorImpl(ERROR_CLASS, Collections.emptyList(), true); + static { + ERROR_CLASS.initialize( + true, Collections.emptyList(), Collections.emptyList(), getErrorScope(), ERROR_FUNCTION_GROUP, ERROR_CONSTRUCTOR); + } private static JetScope getErrorScope() { return ERROR_SCOPE; diff --git a/idea/src/org/jetbrains/jet/lang/types/JetStandardClasses.java b/idea/src/org/jetbrains/jet/lang/types/JetStandardClasses.java index 7e3f8a6e45b..86f4c9a919d 100644 --- a/idea/src/org/jetbrains/jet/lang/types/JetStandardClasses.java +++ b/idea/src/org/jetbrains/jet/lang/types/JetStandardClasses.java @@ -47,7 +47,8 @@ public class JetStandardClasses { } }, JetScope.EMPTY, - FunctionGroup.EMPTY + FunctionGroup.EMPTY, + null ); private static final JetType NOTHING_TYPE = new JetTypeImpl(getNothing()); @@ -68,7 +69,8 @@ public class JetStandardClasses { Collections.emptyList(), Collections.emptySet(), JetScope.EMPTY, - FunctionGroup.EMPTY + FunctionGroup.EMPTY, + null ); private static final JetType ANY_TYPE = new JetTypeImpl(ANY.getTypeConstructor(), JetScope.EMPTY); @@ -102,7 +104,8 @@ public class JetStandardClasses { parameters, Collections.singleton(getAnyType()), STUB, - STUB_FG); + STUB_FG, + null); // TODO : constructor } } @@ -122,7 +125,7 @@ public class JetStandardClasses { FUNCTION[i] = function.initialize( false, createTypeParameters(i, function), - Collections.singleton(getAnyType()), STUB, STUB_FG); + Collections.singleton(getAnyType()), STUB, FunctionGroup.EMPTY, null); ClassDescriptorImpl receiverFunction = new ClassDescriptorImpl( STANDARD_CLASSES_NAMESPACE, @@ -136,7 +139,7 @@ public class JetStandardClasses { RECEIVER_FUNCTION[i] = receiverFunction.initialize( false, parameters, - Collections.singleton(getAnyType()), STUB, STUB_FG); + Collections.singleton(getAnyType()), STUB, FunctionGroup.EMPTY, null); } } diff --git a/idea/testData/checker/BinaryCallsOnNullableValues.jet b/idea/testData/checker/BinaryCallsOnNullableValues.jet index fa3f397e598..0881cbb9548 100644 --- a/idea/testData/checker/BinaryCallsOnNullableValues.jet +++ b/idea/testData/checker/BinaryCallsOnNullableValues.jet @@ -1,12 +1,12 @@ -class A { +class A() { fun equals(a : Any?) : Boolean } -class B { +class B() { fun equals(a : Any?) : Boolean? } -class C { +class C() { fun equals(a : Any?) : Int } diff --git a/idea/testData/checker/Constructors.jet b/idea/testData/checker/Constructors.jet index c024d163d7d..f66ee628103 100644 --- a/idea/testData/checker/Constructors.jet +++ b/idea/testData/checker/Constructors.jet @@ -1,9 +1,34 @@ -class Z { - this() : this(1, true) {} - this(x : Int, y : Boolean) : this(1) {} +class NoC +class NoC1 : NoC + +class WithC0() : NoC() +class WithC1() : NoC +class NoC2 : WithC1 +class NoC3 : WithC1() +class WithC2() : WithC1 + +class NoPC { + this() {} } -class Foo() : Z, this() { +class WithPC0() { + this(a : Int) : this() {} +} + +class WithPC1(a : Int) { + this() {} + + this(b : Long) : this("") {} + + this(s : String) : this(1) {} + + this(b : Char) : this("", 2) {} + + this(b : Byte) : this(""), this(1) {} +} + + +class Foo() : WithPC0, this() { } \ No newline at end of file diff --git a/idea/testData/checker/ForRangeConventions.jet b/idea/testData/checker/ForRangeConventions.jet index df1b5ff89b4..a1b4022a7b4 100644 --- a/idea/testData/checker/ForRangeConventions.jet +++ b/idea/testData/checker/ForRangeConventions.jet @@ -1,10 +1,10 @@ import java.util.*; -class NotRange1 { +class NotRange1() { } -class NotRange2 { +class NotRange2() { fun iterator() : Unit } @@ -12,7 +12,7 @@ class ImproperIterator1 { fun hasNext() : Boolean } -class NotRange3 { +class NotRange3() { fun iterator() : ImproperIterator1 } @@ -20,7 +20,7 @@ class ImproperIterator2 { fun next() : Boolean } -class NotRange4 { +class NotRange4() { fun iterator() : ImproperIterator2 } @@ -29,7 +29,7 @@ class ImproperIterator3 { fun next() : Int } -class NotRange5 { +class NotRange5() { fun iterator() : ImproperIterator3 } @@ -39,7 +39,7 @@ class AmbiguousHasNextIterator { fun next() : Int } -class NotRange6 { +class NotRange6() { fun iterator() : AmbiguousHasNextIterator } @@ -48,7 +48,7 @@ class ImproperIterator4 { fun next() : Int } -class NotRange7 { +class NotRange7() { fun iterator() : ImproperIterator3 } @@ -57,11 +57,11 @@ class GoodIterator { fun next() : Int } -class Range0 { +class Range0() { fun iterator() : GoodIterator } -class Range1 { +class Range1() { fun iterator() : Iterator } diff --git a/idea/testData/checker/IncDec.jet b/idea/testData/checker/IncDec.jet index 1c763ee6774..ab4c9d7ce19 100644 --- a/idea/testData/checker/IncDec.jet +++ b/idea/testData/checker/IncDec.jet @@ -1,4 +1,4 @@ -class IncDec { +class IncDec() { fun inc() : IncDec = this fun dec() : IncDec = this } @@ -15,7 +15,7 @@ fun testIncDec() { x = --x } -class WrongIncDec { +class WrongIncDec() { fun inc() : Int = 1 fun dec() : Int = 1 } @@ -28,7 +28,7 @@ fun testWrongIncDec() { --x } -class UnitIncDec { +class UnitIncDec() { fun inc() : Unit {} fun dec() : Unit {} } diff --git a/idea/testData/checker/Properties.jet b/idea/testData/checker/Properties.jet index 8199b9a165e..61330844bc4 100644 --- a/idea/testData/checker/Properties.jet +++ b/idea/testData/checker/Properties.jet @@ -12,11 +12,11 @@ val p : Int = 1 get() = 1 -class Test { +class Test() { var a : Int var b : Int get() = $a; set(x) {a = x; $a = x} - this() { + this(i : Int) : this() { $b = $a $a = $b a = $b diff --git a/idea/testData/psi/Constructors.jet b/idea/testData/psi/Constructors.jet index b51cc945bf2..5251a19e464 100644 --- a/idea/testData/psi/Constructors.jet +++ b/idea/testData/psi/Constructors.jet @@ -7,3 +7,8 @@ class foo { } } + +public class foo() : Bar +protected class foo private () : Bar +private class foo() : Bar +internal class foo private () : Bar \ No newline at end of file diff --git a/idea/testData/psi/Constructors.txt b/idea/testData/psi/Constructors.txt index 89be5930eff..8f6190bcb22 100644 --- a/idea/testData/psi/Constructors.txt +++ b/idea/testData/psi/Constructors.txt @@ -124,4 +124,106 @@ JetFile: Constructors.jet PsiWhiteSpace('\n\n ') PsiElement(RBRACE)('}') PsiWhiteSpace('\n\n') - PsiElement(RBRACE)('}') \ No newline at end of file + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n\n') + CLASS + MODIFIER_LIST + PsiElement(public)('public') + PsiWhiteSpace(' ') + PsiElement(class)('class') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('foo') + TYPE_PARAMETER_LIST + + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + DELEGATION_SPECIFIER_LIST + DELEGATOR_SUPER_CLASS + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Bar') + PsiWhiteSpace('\n') + CLASS + MODIFIER_LIST + PsiElement(protected)('protected') + PsiWhiteSpace(' ') + PsiElement(class)('class') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('foo') + PsiWhiteSpace(' ') + TYPE_PARAMETER_LIST + + PRIMARY_CONSTRUCTOR_MODIFIER_LIST + PsiElement(private)('private') + PsiWhiteSpace(' ') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + DELEGATION_SPECIFIER_LIST + DELEGATOR_SUPER_CLASS + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Bar') + PsiWhiteSpace('\n') + CLASS + MODIFIER_LIST + PsiElement(private)('private') + PsiWhiteSpace(' ') + PsiElement(class)('class') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('foo') + TYPE_PARAMETER_LIST + PsiElement(LT)('<') + TYPE_PARAMETER + PsiElement(IDENTIFIER)('T') + PsiElement(GT)('>') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + DELEGATION_SPECIFIER_LIST + DELEGATOR_SUPER_CLASS + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Bar') + PsiWhiteSpace('\n') + CLASS + MODIFIER_LIST + PsiElement(internal)('internal') + PsiWhiteSpace(' ') + PsiElement(class)('class') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('foo') + TYPE_PARAMETER_LIST + PsiElement(LT)('<') + TYPE_PARAMETER + PsiElement(IDENTIFIER)('T') + PsiElement(GT)('>') + PsiWhiteSpace(' ') + PRIMARY_CONSTRUCTOR_MODIFIER_LIST + PsiElement(private)('private') + PsiWhiteSpace(' ') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + DELEGATION_SPECIFIER_LIST + DELEGATOR_SUPER_CLASS + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Bar') \ No newline at end of file diff --git a/idea/testData/resolve/ConstructorsAndInitializers.jet b/idea/testData/resolve/ConstructorsAndInitializers.jet index d27160b258d..c20f608505b 100644 --- a/idea/testData/resolve/ConstructorsAndInitializers.jet +++ b/idea/testData/resolve/ConstructorsAndInitializers.jet @@ -1,4 +1,4 @@ -class Z { +class Z(a : Int) { ~c1~this() : `c2`this(1, true) {} ~c2~this(x : Int, y : Boolean) : `c1`this() {}