JET-14 Support anonymous initializers

This commit is contained in:
Andrey Breslav
2011-04-26 18:13:16 +04:00
parent d23a76b64d
commit 64a8da3296
13 changed files with 140 additions and 29 deletions
+1 -2
View File
@@ -13,8 +13,7 @@ internal class Example<X, T : Comparable<X>>(protected val x : Foo<X, T>, y : So
class class
: modifiers "class" SimpleName : modifiers "class" SimpleName
typeParameters? typeParameters?
("wraps" | modifiers)? ("wraps" valueParameters? | modifiers valueParameters?)?
valueParameters?
(":" attributes delegationSpecifier{","})? (":" attributes delegationSpecifier{","})?
(classBody? | enumClassBody) (classBody? | enumClassBody)
; ;
@@ -253,8 +253,8 @@ public class JetParsing extends AbstractJetParsing {
/* /*
* (modifier | attribute)* * (modifier | attribute)*
*/ */
public void parseModifierList(JetNodeType nodeType) { public boolean parseModifierList(JetNodeType nodeType) {
parseModifierList(nodeType, null); return 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 * Feeds modifiers (not attributes) into the passed consumer, if it is not null
*/ */
public void parseModifierList(JetNodeType nodeType, Consumer<IElementType> tokenConsumer) { public boolean parseModifierList(JetNodeType nodeType, Consumer<IElementType> tokenConsumer) {
PsiBuilder.Marker list = mark(); PsiBuilder.Marker list = mark();
boolean empty = true; boolean empty = true;
while (!eof()) { while (!eof()) {
@@ -282,6 +282,7 @@ public class JetParsing extends AbstractJetParsing {
} else { } else {
list.done(nodeType); list.done(nodeType);
} }
return !empty;
} }
/* /*
@@ -376,8 +377,9 @@ public class JetParsing extends AbstractJetParsing {
* class * class
* : modifiers "class" SimpleName * : modifiers "class" SimpleName
* typeParameters? * typeParameters?
* ("wraps" | modifiers)? * (
* ("(" primaryConstructorParameter{","} ")")? * ("wraps" "(" primaryConstructorParameter{","} ")") |
* (modifiers "(" primaryConstructorParameter{","} ")"))?
* (":" attributes delegationSpecifier{","})? * (":" attributes delegationSpecifier{","})?
* (classBody? | enumClassBody) * (classBody? | enumClassBody)
* ; * ;
@@ -391,13 +393,17 @@ public class JetParsing extends AbstractJetParsing {
if (at(WRAPS_KEYWORD)) { if (at(WRAPS_KEYWORD)) {
advance(); // WRAPS_KEYWORD advance(); // WRAPS_KEYWORD
parseValueParameterList(false, TokenSet.create(COLON, LBRACE));
} }
else { else {
parseModifierList(PRIMARY_CONSTRUCTOR_MODIFIER_LIST); if (parseModifierList(PRIMARY_CONSTRUCTOR_MODIFIER_LIST)) {
} parseValueParameterList(false, TokenSet.create(COLON, LBRACE));
}
if (at(LPAR)) { else {
parseValueParameterList(false, TokenSet.EMPTY); if (at(LPAR)) {
parseValueParameterList(false, TokenSet.create(COLON, LBRACE));
}
}
} }
if (at(COLON)) { if (at(COLON)) {
@@ -66,4 +66,16 @@ public class JetClass extends JetTypeParameterListOwner implements JetClassOrObj
public JetModifierList getPrimaryConstructorModifierList() { public JetModifierList getPrimaryConstructorModifierList() {
return (JetModifierList) findChildByType(JetNodeTypes.PRIMARY_CONSTRUCTOR_MODIFIER_LIST); return (JetModifierList) findChildByType(JetNodeTypes.PRIMARY_CONSTRUCTOR_MODIFIER_LIST);
} }
@NotNull
public List<JetClassInitializer> getAnonymousInitializers() {
JetClassBody body = (JetClassBody) findChildByType(JetNodeTypes.CLASS_BODY);
if (body == null) return Collections.emptyList();
return body.getAnonymousInitializers();
}
public boolean hasPrimaryConstructor() {
return getPrimaryConstructorParameterList() != null;
}
} }
@@ -3,6 +3,7 @@ package org.jetbrains.jet.lang.psi;
import com.intellij.lang.ASTNode; import com.intellij.lang.ASTNode;
import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiTreeUtil;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.JetNodeTypes;
import java.util.List; import java.util.List;
@@ -26,4 +27,9 @@ public class JetClassBody extends JetElement {
public void accept(@NotNull JetVisitor visitor) { public void accept(@NotNull JetVisitor visitor) {
visitor.visitClassBody(this); visitor.visitClassBody(this);
} }
@NotNull
public List<JetClassInitializer> getAnonymousInitializers() {
return findChildrenByType(JetNodeTypes.ANONYMOUS_INITIALIZER);
}
} }
@@ -473,15 +473,14 @@ public class ClassDescriptorResolver {
@Nullable @Nullable
public ConstructorDescriptor resolvePrimaryConstructorDescriptor(@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 (!classElement.hasPrimaryConstructor()) return null;
if (primaryConstructorParameterList == null) return null;
return createConstructorDescriptor( return createConstructorDescriptor(
scope, scope,
classDescriptor, classDescriptor,
true, true,
classElement.getPrimaryConstructorModifierList(), classElement.getPrimaryConstructorModifierList(),
classElement, classElement,
primaryConstructorParameterList.getParameters()); classElement.getPrimaryConstructorParameters());
} }
@NotNull @NotNull
@@ -54,6 +54,11 @@ public class LazySubstitutingClassDescriptor implements ClassDescriptor {
return original.getUnsubstitutedPrimaryConstructor(); return original.getUnsubstitutedPrimaryConstructor();
} }
@Override
public boolean hasConstructors() {
return original.hasConstructors();
}
@Override @Override
public List<Attribute> getAttributes() { public List<Attribute> getAttributes() {
throw new UnsupportedOperationException(); // TODO throw new UnsupportedOperationException(); // TODO
@@ -112,4 +112,9 @@ public class MutableClassDescriptor extends MutableDeclarationDescriptor impleme
public ConstructorDescriptor getUnsubstitutedPrimaryConstructor() { public ConstructorDescriptor getUnsubstitutedPrimaryConstructor() {
return primaryConstructor; return primaryConstructor;
} }
@Override
public boolean hasConstructors() {
return !constructors.isEmpty();
}
} }
@@ -220,9 +220,14 @@ public class TopDownAnalyzer {
} }
} }
@Override
public void visitAnonymousInitializer(JetClassInitializer initializer) {
// Nothing
}
@Override @Override
public void visitDeclaration(JetDeclaration dcl) { public void visitDeclaration(JetDeclaration dcl) {
semanticServices.getErrorHandler().genericError(dcl.getNode(), "Unsupported declaration: " + dcl); // TODO semanticServices.getErrorHandler().genericError(dcl.getNode(), "[TopDownAnalyzer] Unsupported declaration: " + dcl); // TODO
} }
}); });
} }
@@ -230,7 +235,7 @@ public class TopDownAnalyzer {
} }
private void processPrimaryConstructor(MutableClassDescriptor classDescriptor, JetClass klass) { private void processPrimaryConstructor(MutableClassDescriptor classDescriptor, JetClass klass) {
if (klass.getPrimaryConstructorParameterList() == null) return; // No constructors if (!klass.hasPrimaryConstructor()) return;
// TODO : not all the parameters are real properties // TODO : not all the parameters are real properties
WritableScope memberScope = classDescriptor.getWritableUnsubstitutedMemberScope(); // TODO : this is REALLY questionable WritableScope memberScope = classDescriptor.getWritableUnsubstitutedMemberScope(); // TODO : this is REALLY questionable
@@ -282,6 +287,9 @@ public class TopDownAnalyzer {
private void resolveBehaviorDeclarationBodies() { private void resolveBehaviorDeclarationBodies() {
resolveDelegationSpecifierLists(); resolveDelegationSpecifierLists();
resolveAnonymousInitializers();
resolveSecondaryConstructorBodies(); resolveSecondaryConstructorBodies();
//TODO : anonymous initializers //TODO : anonymous initializers
@@ -316,7 +324,7 @@ public class TopDownAnalyzer {
JetTypeReference typeReference = call.getTypeReference(); JetTypeReference typeReference = call.getTypeReference();
if (typeReference != null) { if (typeReference != null) {
typeInferrer.checkConstructorCall(descriptor.getWritableUnsubstitutedMemberScope(), typeReference, call); typeInferrer.checkConstructorCall(descriptor.getWritableUnsubstitutedMemberScope(), typeReference, call);
if (jetClass.getPrimaryConstructorParameterList() == null) { if (!jetClass.hasPrimaryConstructor()) {
JetArgumentList valueArgumentList = call.getValueArgumentList(); JetArgumentList valueArgumentList = call.getValueArgumentList();
assert valueArgumentList != null; assert valueArgumentList != null;
semanticServices.getErrorHandler().genericError(valueArgumentList.getNode(), semanticServices.getErrorHandler().genericError(valueArgumentList.getNode(),
@@ -332,7 +340,7 @@ public class TopDownAnalyzer {
DeclarationDescriptor declarationDescriptor = supertype.getConstructor().getDeclarationDescriptor(); DeclarationDescriptor declarationDescriptor = supertype.getConstructor().getDeclarationDescriptor();
if (declarationDescriptor instanceof ClassDescriptor) { if (declarationDescriptor instanceof ClassDescriptor) {
ClassDescriptor classDescriptor = (ClassDescriptor) declarationDescriptor; ClassDescriptor classDescriptor = (ClassDescriptor) declarationDescriptor;
if (classDescriptor.getUnsubstitutedPrimaryConstructor() != null) { if (classDescriptor.hasConstructors()) {
semanticServices.getErrorHandler().genericError(specifier.getNode(), "This type has a constructor, and thus must be initialized here"); semanticServices.getErrorHandler().genericError(specifier.getNode(), "This type has a constructor, and thus must be initialized here");
} }
} }
@@ -357,6 +365,29 @@ public class TopDownAnalyzer {
} }
} }
private void resolveAnonymousInitializers() {
for (Map.Entry<JetClass, MutableClassDescriptor> entry : classes.entrySet()) {
JetClass jetClass = entry.getKey();
MutableClassDescriptor classDescriptor = entry.getValue();
List<JetClassInitializer> anonymousInitializers = jetClass.getAnonymousInitializers();
if (jetClass.hasPrimaryConstructor()) {
ConstructorDescriptor primaryConstructor = classDescriptor.getUnsubstitutedPrimaryConstructor();
assert primaryConstructor != null;
final JetScope scopeForConstructor = getInnerScopeForConstructor(primaryConstructor, classDescriptor.getWritableUnsubstitutedMemberScope());
JetTypeInferrer typeInferrer = semanticServices.getTypeInferrer(traceForConstructors, JetFlowInformationProvider.NONE); // TODO : flow
for (JetClassInitializer anonymousInitializer : anonymousInitializers) {
typeInferrer.getType(scopeForConstructor, anonymousInitializer.getBody(), true);
}
}
else {
for (JetClassInitializer anonymousInitializer : anonymousInitializers) {
semanticServices.getErrorHandler().genericError(anonymousInitializer.getNode(), "Anonymous initializers are only allowed in the presence of a primary constructor");
}
}
}
}
private void resolveSecondaryConstructorBodies() { private void resolveSecondaryConstructorBodies() {
for (Map.Entry<JetDeclaration, ConstructorDescriptor> entry : constructors.entrySet()) { for (Map.Entry<JetDeclaration, ConstructorDescriptor> entry : constructors.entrySet()) {
JetDeclaration declaration = entry.getKey(); JetDeclaration declaration = entry.getKey();
@@ -372,17 +403,13 @@ public class TopDownAnalyzer {
} }
private void resolveSecondaryConstructorBody(JetConstructor declaration, final ConstructorDescriptor descriptor, final WritableScope declaringScope) { private void resolveSecondaryConstructorBody(JetConstructor declaration, final ConstructorDescriptor descriptor, final WritableScope declaringScope) {
WritableScope constructorScope = semanticServices.createWritableScope(declaringScope, declaringScope.getContainingDeclaration()); final JetScope functionInnerScope = getInnerScopeForConstructor(descriptor, declaringScope);
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); final JetTypeInferrer typeInferrerForInitializers = semanticServices.getTypeInferrer(traceForConstructors, JetFlowInformationProvider.NONE);
JetClass containingClass = PsiTreeUtil.getParentOfType(declaration, JetClass.class); JetClass containingClass = PsiTreeUtil.getParentOfType(declaration, JetClass.class);
assert containingClass != null : "This must be guaranteed by the parser"; assert containingClass != null : "This must be guaranteed by the parser";
if (containingClass.getPrimaryConstructorParameterList() == null) { if (!containingClass.hasPrimaryConstructor()) {
semanticServices.getErrorHandler().genericError(declaration.getNameNode(), "A secondary constructor may appear only in a class that has a primary constructor"); semanticServices.getErrorHandler().genericError(declaration.getNameNode(), "A secondary constructor may appear only in a class that has a primary constructor");
} }
else { else {
@@ -444,6 +471,15 @@ public class TopDownAnalyzer {
} }
} }
@NotNull
private JetScope getInnerScopeForConstructor(@NotNull ConstructorDescriptor descriptor, @NotNull JetScope declaringScope) {
WritableScope constructorScope = semanticServices.createWritableScope(declaringScope, declaringScope.getContainingDeclaration());
for (PropertyDescriptor propertyDescriptor : declaringScopesToProperties.get(descriptor.getContainingDeclaration())) {
constructorScope.addPropertyDescriptorByFieldName("$" + propertyDescriptor.getName(), propertyDescriptor);
}
return FunctionDescriptorUtil.getFunctionInnerScope(constructorScope, descriptor, semanticServices);
}
private void resolvePropertyDeclarationBodies() { private void resolvePropertyDeclarationBodies() {
for (Map.Entry<JetProperty, PropertyDescriptor> entry : properties.entrySet()) { for (Map.Entry<JetProperty, PropertyDescriptor> entry : properties.entrySet()) {
JetProperty declaration = entry.getKey(); JetProperty declaration = entry.getKey();
@@ -122,9 +122,11 @@ public class TypeResolver {
parameterTypes.add(resolveType(scope, parameter.getTypeReference())); parameterTypes.add(resolveType(scope, parameter.getTypeReference()));
} }
JetType returnType = resolveType(scope, type.getReturnTypeRef()); JetTypeReference returnTypeRef = type.getReturnTypeRef();
if (returnTypeRef != null) {
result[0] = JetStandardClasses.getFunctionType(attributes, receiverType, parameterTypes, returnType); JetType returnType = resolveType(scope, returnTypeRef);
result[0] = JetStandardClasses.getFunctionType(attributes, receiverType, parameterTypes, returnType);
}
} }
@Override @Override
@@ -20,6 +20,8 @@ public interface ClassDescriptor extends ClassifierDescriptor {
@Nullable @Nullable
ConstructorDescriptor getUnsubstitutedPrimaryConstructor(); ConstructorDescriptor getUnsubstitutedPrimaryConstructor();
boolean hasConstructors();
@Override @Override
@NotNull @NotNull
DeclarationDescriptor getContainingDeclaration(); DeclarationDescriptor getContainingDeclaration();
@@ -89,4 +89,9 @@ public class ClassDescriptorImpl extends DeclarationDescriptorImpl implements Cl
public ConstructorDescriptor getUnsubstitutedPrimaryConstructor() { public ConstructorDescriptor getUnsubstitutedPrimaryConstructor() {
return primaryConstructor; return primaryConstructor;
} }
@Override
public boolean hasConstructors() {
return !constructors.isEmpty();
}
} }
@@ -0,0 +1,34 @@
class NoC {
<error>{
}</error>
val a : Int get() = 1
<error>{
}</error>
}
class WithC() {
val x : Int
{
$x = 1
<error>$y</error> = 2
val b = x
}
val a : Int get() = 1
{
val z = <error>b</error>
val zz = x
val zzz = <error>$a</error>
}
this(a : Int) : this() {
val b = x
}
}
@@ -1 +1 @@
class Foo : java.util.ArrayList<*> class Foo() : java.util.ArrayList<Int>()