JET-14 Support anonymous initializers
This commit is contained in:
@@ -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>()
|
||||||
Reference in New Issue
Block a user