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
|
||||
: 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>()
|
||||
Reference in New Issue
Block a user