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
: modifiers "class" SimpleName
typeParameters?
("wraps" | modifiers)?
valueParameters?
("wraps" valueParameters? | modifiers valueParameters?)?
(":" attributes delegationSpecifier{","})?
(classBody? | enumClassBody)
;
@@ -253,8 +253,8 @@ public class JetParsing extends AbstractJetParsing {
/*
* (modifier | attribute)*
*/
public void parseModifierList(JetNodeType nodeType) {
parseModifierList(nodeType, null);
public boolean parseModifierList(JetNodeType nodeType) {
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
*/
public void parseModifierList(JetNodeType nodeType, Consumer<IElementType> tokenConsumer) {
public boolean parseModifierList(JetNodeType nodeType, Consumer<IElementType> tokenConsumer) {
PsiBuilder.Marker list = mark();
boolean empty = true;
while (!eof()) {
@@ -282,6 +282,7 @@ public class JetParsing extends AbstractJetParsing {
} else {
list.done(nodeType);
}
return !empty;
}
/*
@@ -376,8 +377,9 @@ public class JetParsing extends AbstractJetParsing {
* class
* : modifiers "class" SimpleName
* typeParameters?
* ("wraps" | modifiers)?
* ("(" primaryConstructorParameter{","} ")")?
* (
* ("wraps" "(" primaryConstructorParameter{","} ")") |
* (modifiers "(" primaryConstructorParameter{","} ")"))?
* (":" attributes delegationSpecifier{","})?
* (classBody? | enumClassBody)
* ;
@@ -391,13 +393,17 @@ public class JetParsing extends AbstractJetParsing {
if (at(WRAPS_KEYWORD)) {
advance(); // WRAPS_KEYWORD
parseValueParameterList(false, TokenSet.create(COLON, LBRACE));
}
else {
parseModifierList(PRIMARY_CONSTRUCTOR_MODIFIER_LIST);
}
if (at(LPAR)) {
parseValueParameterList(false, TokenSet.EMPTY);
if (parseModifierList(PRIMARY_CONSTRUCTOR_MODIFIER_LIST)) {
parseValueParameterList(false, TokenSet.create(COLON, LBRACE));
}
else {
if (at(LPAR)) {
parseValueParameterList(false, TokenSet.create(COLON, LBRACE));
}
}
}
if (at(COLON)) {
@@ -66,4 +66,16 @@ public class JetClass extends JetTypeParameterListOwner implements JetClassOrObj
public JetModifierList getPrimaryConstructorModifierList() {
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.psi.util.PsiTreeUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.JetNodeTypes;
import java.util.List;
@@ -26,4 +27,9 @@ public class JetClassBody extends JetElement {
public void accept(@NotNull JetVisitor visitor) {
visitor.visitClassBody(this);
}
@NotNull
public List<JetClassInitializer> getAnonymousInitializers() {
return findChildrenByType(JetNodeTypes.ANONYMOUS_INITIALIZER);
}
}
@@ -473,15 +473,14 @@ public class ClassDescriptorResolver {
@Nullable
public ConstructorDescriptor resolvePrimaryConstructorDescriptor(@NotNull JetScope scope, @NotNull ClassDescriptor classDescriptor, @NotNull JetClass classElement) {
JetParameterList primaryConstructorParameterList = classElement.getPrimaryConstructorParameterList();
if (primaryConstructorParameterList == null) return null;
if (!classElement.hasPrimaryConstructor()) return null;
return createConstructorDescriptor(
scope,
classDescriptor,
true,
classElement.getPrimaryConstructorModifierList(),
classElement,
primaryConstructorParameterList.getParameters());
classElement.getPrimaryConstructorParameters());
}
@NotNull
@@ -54,6 +54,11 @@ public class LazySubstitutingClassDescriptor implements ClassDescriptor {
return original.getUnsubstitutedPrimaryConstructor();
}
@Override
public boolean hasConstructors() {
return original.hasConstructors();
}
@Override
public List<Attribute> getAttributes() {
throw new UnsupportedOperationException(); // TODO
@@ -112,4 +112,9 @@ public class MutableClassDescriptor extends MutableDeclarationDescriptor impleme
public ConstructorDescriptor getUnsubstitutedPrimaryConstructor() {
return primaryConstructor;
}
@Override
public boolean hasConstructors() {
return !constructors.isEmpty();
}
}
@@ -220,9 +220,14 @@ public class TopDownAnalyzer {
}
}
@Override
public void visitAnonymousInitializer(JetClassInitializer initializer) {
// Nothing
}
@Override
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) {
if (klass.getPrimaryConstructorParameterList() == null) return; // No constructors
if (!klass.hasPrimaryConstructor()) return;
// TODO : not all the parameters are real properties
WritableScope memberScope = classDescriptor.getWritableUnsubstitutedMemberScope(); // TODO : this is REALLY questionable
@@ -282,6 +287,9 @@ public class TopDownAnalyzer {
private void resolveBehaviorDeclarationBodies() {
resolveDelegationSpecifierLists();
resolveAnonymousInitializers();
resolveSecondaryConstructorBodies();
//TODO : anonymous initializers
@@ -316,7 +324,7 @@ public class TopDownAnalyzer {
JetTypeReference typeReference = call.getTypeReference();
if (typeReference != null) {
typeInferrer.checkConstructorCall(descriptor.getWritableUnsubstitutedMemberScope(), typeReference, call);
if (jetClass.getPrimaryConstructorParameterList() == null) {
if (!jetClass.hasPrimaryConstructor()) {
JetArgumentList valueArgumentList = call.getValueArgumentList();
assert valueArgumentList != null;
semanticServices.getErrorHandler().genericError(valueArgumentList.getNode(),
@@ -332,7 +340,7 @@ public class TopDownAnalyzer {
DeclarationDescriptor declarationDescriptor = supertype.getConstructor().getDeclarationDescriptor();
if (declarationDescriptor instanceof ClassDescriptor) {
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");
}
}
@@ -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() {
for (Map.Entry<JetDeclaration, ConstructorDescriptor> entry : constructors.entrySet()) {
JetDeclaration declaration = entry.getKey();
@@ -372,17 +403,13 @@ public class TopDownAnalyzer {
}
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 JetScope functionInnerScope = getInnerScopeForConstructor(descriptor, declaringScope);
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) {
if (!containingClass.hasPrimaryConstructor()) {
semanticServices.getErrorHandler().genericError(declaration.getNameNode(), "A secondary constructor may appear only in a class that has a primary constructor");
}
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() {
for (Map.Entry<JetProperty, PropertyDescriptor> entry : properties.entrySet()) {
JetProperty declaration = entry.getKey();
@@ -122,9 +122,11 @@ public class TypeResolver {
parameterTypes.add(resolveType(scope, parameter.getTypeReference()));
}
JetType returnType = resolveType(scope, type.getReturnTypeRef());
result[0] = JetStandardClasses.getFunctionType(attributes, receiverType, parameterTypes, returnType);
JetTypeReference returnTypeRef = type.getReturnTypeRef();
if (returnTypeRef != null) {
JetType returnType = resolveType(scope, returnTypeRef);
result[0] = JetStandardClasses.getFunctionType(attributes, receiverType, parameterTypes, returnType);
}
}
@Override
@@ -20,6 +20,8 @@ public interface ClassDescriptor extends ClassifierDescriptor {
@Nullable
ConstructorDescriptor getUnsubstitutedPrimaryConstructor();
boolean hasConstructors();
@Override
@NotNull
DeclarationDescriptor getContainingDeclaration();
@@ -89,4 +89,9 @@ public class ClassDescriptorImpl extends DeclarationDescriptorImpl implements Cl
public ConstructorDescriptor getUnsubstitutedPrimaryConstructor() {
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>()