提交 64a8da32 编写于 作者: A Andrey Breslav

JET-14 Support anonymous initializers

上级 d23a76b6
......@@ -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();
}
}
\ No newline at end of file
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
}
}
\ No newline at end of file
class Foo : java.util.ArrayList<*>
\ No newline at end of file
class Foo() : java.util.ArrayList<Int>()
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册