JET-6 Perform checks for primary and secondary constructors (In progress)

This commit is contained in:
Andrey Breslav
2011-04-26 17:00:07 +04:00
parent ca66b2fdbd
commit d23a76b64d
23 changed files with 406 additions and 169 deletions
@@ -35,6 +35,7 @@ public interface JetNodeTypes {
JetNodeType IMPORT_DIRECTIVE = new JetNodeType("IMPORT_DIRECTIVE", JetImportDirective.class);
JetNodeType NAMESPACE_BODY = new JetNodeType("NAMESPACE_BODY", JetNamespaceBody.class);
JetNodeType MODIFIER_LIST = new JetNodeType("MODIFIER_LIST", JetModifierList.class);
JetNodeType PRIMARY_CONSTRUCTOR_MODIFIER_LIST = new JetNodeType("PRIMARY_CONSTRUCTOR_MODIFIER_LIST", JetModifierList.class);
JetNodeType ATTRIBUTE_ANNOTATION = new JetNodeType("ATTRIBUTE_ANNOTATION", JetAttributeAnnotation.class);
JetNodeType ATTRIBUTE = new JetNodeType("ATTRIBUTE", JetAttribute.class);
JetNodeType TYPE_ARGUMENT_LIST = new JetNodeType("TYPE_ARGUMENT_LIST", JetTypeArgumentList.class);
@@ -1,6 +1,7 @@
package org.jetbrains.jet.lang;
import com.intellij.lang.ASTNode;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.psi.JetReferenceExpression;
import org.jetbrains.jet.lang.types.DeclarationDescriptor;
@@ -18,7 +19,7 @@ public class ErrorHandler {
}
@Override
public void genericError(ASTNode node, String errorMessage) {
public void genericError(@NotNull ASTNode node, String errorMessage) {
throw new IllegalStateException(errorMessage);
}
@@ -42,7 +43,7 @@ public class ErrorHandler {
public void redeclaration(DeclarationDescriptor existingDescriptor, DeclarationDescriptor redeclaredDescriptor) {
}
public void genericError(ASTNode node, String errorMessage) {
public void genericError(@NotNull ASTNode node, String errorMessage) {
}
public void genericWarning(ASTNode node, String message) {
@@ -63,7 +63,7 @@ public class JetPsiChecker implements Annotator {
}
@Override
public void genericError(ASTNode node, String errorMessage) {
public void genericError(@NotNull ASTNode node, String errorMessage) {
holder.createErrorAnnotation(node, errorMessage);
}
@@ -929,7 +929,7 @@ public class JetExpressionParsing extends AbstractJetParsing {
private boolean parseLocalDeclaration() {
PsiBuilder.Marker decls = mark();
JetParsing.TokenDetector enumDetector = new JetParsing.TokenDetector(ENUM_KEYWORD);
myJetParsing.parseModifierList(enumDetector);
myJetParsing.parseModifierList(MODIFIER_LIST, enumDetector);
JetNodeType declType = parseLocalDeclarationRest(enumDetector.isDetected());
@@ -1002,7 +1002,7 @@ public class JetExpressionParsing extends AbstractJetParsing {
PsiBuilder.Marker parameter = mark();
int parameterNamePos = matchTokenStreamPredicate(new LastBefore(new At(IDENTIFIER), new AtOffset(doubleArrowPos)));
createTruncatedBuilder(parameterNamePos).parseModifierList();
createTruncatedBuilder(parameterNamePos).parseModifierList(MODIFIER_LIST);
expect(IDENTIFIER, "Expecting parameter name", TokenSet.create(DOUBLE_ARROW));
@@ -1046,7 +1046,7 @@ public class JetExpressionParsing extends AbstractJetParsing {
PsiBuilder.Marker parameter = mark();
int parameterNamePos = matchTokenStreamPredicate(new LastBefore(new At(IDENTIFIER), new AtSet(COMMA, RPAR, COLON, DOUBLE_ARROW)));
createTruncatedBuilder(parameterNamePos).parseModifierList();
createTruncatedBuilder(parameterNamePos).parseModifierList(MODIFIER_LIST);
expect(IDENTIFIER, "Expecting parameter declaration");
@@ -115,7 +115,7 @@ public class JetParsing extends AbstractJetParsing {
* ;
*/
PsiBuilder.Marker firstEntry = mark();
parseModifierList();
parseModifierList(MODIFIER_LIST);
if (at(NAMESPACE_KEYWORD)) {
advance(); // NAMESPACE_KEYWORD
@@ -218,7 +218,7 @@ public class JetParsing extends AbstractJetParsing {
PsiBuilder.Marker decl = mark();
TokenDetector detector = new TokenDetector(ENUM_KEYWORD);
parseModifierList(detector);
parseModifierList(MODIFIER_LIST, detector);
IElementType keywordToken = tt();
JetNodeType declType = null;
@@ -253,8 +253,8 @@ public class JetParsing extends AbstractJetParsing {
/*
* (modifier | attribute)*
*/
public void parseModifierList() {
parseModifierList(null);
public void parseModifierList(JetNodeType nodeType) {
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(Consumer<IElementType> tokenConsumer) {
public void parseModifierList(JetNodeType nodeType, Consumer<IElementType> tokenConsumer) {
PsiBuilder.Marker list = mark();
boolean empty = true;
while (!eof()) {
@@ -280,7 +280,7 @@ public class JetParsing extends AbstractJetParsing {
if (empty) {
list.drop();
} else {
list.done(MODIFIER_LIST);
list.done(nodeType);
}
}
@@ -393,7 +393,7 @@ public class JetParsing extends AbstractJetParsing {
advance(); // WRAPS_KEYWORD
}
else {
parseModifierList();
parseModifierList(PRIMARY_CONSTRUCTOR_MODIFIER_LIST);
}
if (at(LPAR)) {
@@ -436,7 +436,7 @@ public class JetParsing extends AbstractJetParsing {
TokenSet constructorNameFollow = TokenSet.create(SEMICOLON, COLON, LPAR, LT, LBRACE);
int lastId = findLastBefore(ENUM_MEMBER_FIRST, constructorNameFollow, false);
TokenDetector enumDetector = new TokenDetector(ENUM_KEYWORD);
createTruncatedBuilder(lastId).parseModifierList(enumDetector);
createTruncatedBuilder(lastId).parseModifierList(MODIFIER_LIST, enumDetector);
IElementType type;
if (at(IDENTIFIER)) {
@@ -535,7 +535,7 @@ public class JetParsing extends AbstractJetParsing {
PsiBuilder.Marker decl = mark();
TokenDetector enumDetector = new TokenDetector(ENUM_KEYWORD);
parseModifierList(enumDetector);
parseModifierList(MODIFIER_LIST, enumDetector);
JetNodeType declType = parseMemberDeclarationRest(enumDetector.isDetected());
@@ -786,7 +786,7 @@ public class JetParsing extends AbstractJetParsing {
private boolean parsePropertyGetterOrSetter() {
PsiBuilder.Marker getterOrSetter = mark();
parseModifierList();
parseModifierList(MODIFIER_LIST);
if (!at(GET_KEYWORD) && !at(SET_KEYWORD)) {
getterOrSetter.rollbackTo();
@@ -807,7 +807,7 @@ public class JetParsing extends AbstractJetParsing {
PsiBuilder.Marker parameterList = mark();
PsiBuilder.Marker setterParameter = mark();
int lastId = findLastBefore(TokenSet.create(IDENTIFIER), TokenSet.create(RPAR, COMMA, COLON), false);
createTruncatedBuilder(lastId).parseModifierList();
createTruncatedBuilder(lastId).parseModifierList(MODIFIER_LIST);
expect(IDENTIFIER, "Expecting parameter name", TokenSet.create(RPAR, COLON, LBRACE, EQ));
if (at(COLON)) {
@@ -1111,7 +1111,7 @@ public class JetParsing extends AbstractJetParsing {
PsiBuilder.Marker mark = mark();
int lastId = findLastBefore(TokenSet.create(IDENTIFIER), TokenSet.create(COMMA, GT, COLON), false);
createTruncatedBuilder(lastId).parseModifierList();
createTruncatedBuilder(lastId).parseModifierList(MODIFIER_LIST);
expect(IDENTIFIER, "Type parameter name expected", TokenSet.EMPTY);
@@ -1235,7 +1235,7 @@ public class JetParsing extends AbstractJetParsing {
PsiBuilder.Marker projection = mark();
int lastId = findLastBefore(TokenSet.create(IDENTIFIER), TokenSet.create(COMMA, COLON, GT), false);
createTruncatedBuilder(lastId).parseModifierList();
createTruncatedBuilder(lastId).parseModifierList(MODIFIER_LIST);
if (at(MUL)) {
advance(); // MUL
@@ -1372,7 +1372,7 @@ public class JetParsing extends AbstractJetParsing {
if (isFunctionTypeContents) {
if (!tryParseValueParameter()) {
PsiBuilder.Marker valueParameter = mark();
parseModifierList(); // lazy, out, ref
parseModifierList(MODIFIER_LIST); // lazy, out, ref
parseTypeRef();
valueParameter.done(VALUE_PARAMETER);
}
@@ -1406,7 +1406,7 @@ public class JetParsing extends AbstractJetParsing {
PsiBuilder.Marker parameter = mark();
int lastId = findLastBefore(TokenSet.create(IDENTIFIER), TokenSet.create(COMMA, RPAR, COLON), false);
createTruncatedBuilder(lastId).parseModifierList();
createTruncatedBuilder(lastId).parseModifierList(MODIFIER_LIST);
if (at(VAR_KEYWORD) || at(VAL_KEYWORD)) {
advance(); // VAR_KEYWORD | VAL_KEYWORD
@@ -61,4 +61,9 @@ public class JetClass extends JetTypeParameterListOwner implements JetClassOrObj
JetDelegationSpecifierList list = getDelegationSpecifierList();
return list != null ? list.getDelegationSpecifiers() : Collections.<JetDelegationSpecifier>emptyList();
}
@Nullable
public JetModifierList getPrimaryConstructorModifierList() {
return (JetModifierList) findChildByType(JetNodeTypes.PRIMARY_CONSTRUCTOR_MODIFIER_LIST);
}
}
@@ -59,4 +59,8 @@ public class JetConstructor extends JetDeclaration implements JetDeclarationWith
public JetElement asElement() {
return this;
}
public ASTNode getNameNode() {
return getNode().findChildByType(JetTokens.THIS_KEYWORD);
}
}
@@ -56,9 +56,9 @@ public class ClassDescriptorResolver {
WritableFunctionGroup constructors = new WritableFunctionGroup("<init>");
for (JetConstructor constructor : classElement.getSecondaryConstructors()) {
constructors.addFunction(resolveConstructorDescriptor(members, classDescriptor, constructor, false));
constructors.addFunction(resolveSecondaryConstructorDescriptor(members, classDescriptor, constructor));
}
ConstructorDescriptor primaryConstructorDescriptor = resolvePrimaryConstructor(scope, classDescriptor, classElement);
ConstructorDescriptor primaryConstructorDescriptor = resolvePrimaryConstructorDescriptor(scope, classDescriptor, classElement);
if (primaryConstructorDescriptor != null) {
constructors.addFunction(primaryConstructorDescriptor);
}
@@ -67,7 +67,8 @@ public class ClassDescriptorResolver {
typeParameters,
supertypes,
members,
constructors
constructors,
primaryConstructorDescriptor
);
}
@@ -159,7 +160,7 @@ public class ClassDescriptorResolver {
}
@NotNull
public FunctionDescriptor resolveFunctionDescriptor(DeclarationDescriptor containingDescriptor, JetScope scope, JetFunction function) {
public FunctionDescriptorImpl resolveFunctionDescriptor(DeclarationDescriptor containingDescriptor, JetScope scope, JetFunction function) {
FunctionDescriptorImpl functionDescriptor = new FunctionDescriptorImpl(
containingDescriptor,
AttributeResolver.INSTANCE.resolveAttributes(function.getModifierList()),
@@ -307,19 +308,21 @@ public class ClassDescriptorResolver {
return variableDescriptor;
}
@NotNull
public VariableDescriptor resolveLocalVariableDescriptor(DeclarationDescriptor containingDeclaration, WritableScope scope, JetProperty property) {
JetType type = getType(scope, property);
VariableDescriptorImpl propertyDescriptor = new LocalVariableDescriptor(
VariableDescriptorImpl variableDescriptor = new LocalVariableDescriptor(
containingDeclaration,
AttributeResolver.INSTANCE.resolveAttributes(property.getModifierList()),
JetPsiUtil.safeName(property.getName()),
type,
property.isVar());
trace.recordDeclarationResolution(property, propertyDescriptor);
return propertyDescriptor;
trace.recordDeclarationResolution(property, variableDescriptor);
return variableDescriptor;
}
@NotNull
public PropertyDescriptor resolvePropertyDescriptor(@NotNull DeclarationDescriptor containingDeclaration, @NotNull JetScope scope, JetProperty property) {
JetType type = getType(scope, property);
@@ -443,12 +446,18 @@ public class ClassDescriptorResolver {
}
@NotNull
public ConstructorDescriptor resolveConstructorDescriptor(@NotNull JetScope scope, ClassDescriptor classDescriptor, JetConstructor constructor, boolean isPrimary) {
return createConstructorDescriptor(scope, classDescriptor, isPrimary, constructor.getModifierList(), constructor, constructor.getParameters());
public ConstructorDescriptor resolveSecondaryConstructorDescriptor(@NotNull JetScope scope, @NotNull ClassDescriptor classDescriptor, @NotNull JetConstructor constructor) {
return createConstructorDescriptor(scope, classDescriptor, false, constructor.getModifierList(), constructor, constructor.getParameters());
}
@NotNull
private ConstructorDescriptor createConstructorDescriptor(JetScope scope, ClassDescriptor classDescriptor, boolean isPrimary, JetModifierList modifierList, JetDeclaration declarationToTrace, List<JetParameter> valueParameters) {
private ConstructorDescriptor createConstructorDescriptor(
@NotNull JetScope scope,
@NotNull ClassDescriptor classDescriptor,
boolean isPrimary,
@Nullable JetModifierList modifierList,
@NotNull JetDeclaration declarationToTrace,
@NotNull List<JetParameter> valueParameters) {
ConstructorDescriptorImpl constructorDescriptor = new ConstructorDescriptorImpl(
classDescriptor,
AttributeResolver.INSTANCE.resolveAttributes(modifierList),
@@ -463,33 +472,20 @@ public class ClassDescriptorResolver {
}
@Nullable
public ConstructorDescriptor resolvePrimaryConstructor(@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 (primaryConstructorParameterList != null) {
return createConstructorDescriptor(
scope,
classDescriptor,
true,
classElement.getModifierList(), // TODO
classElement,
primaryConstructorParameterList.getParameters());
}
else {
List<JetConstructor> secondaryConstructors = classElement.getSecondaryConstructors();
if (secondaryConstructors.isEmpty()) {
return createConstructorDescriptor(
scope,
classDescriptor,
true,
classElement.getModifierList(), // TODO
classElement,
Collections.<JetParameter>emptyList());
}
else return null;
}
if (primaryConstructorParameterList == null) return null;
return createConstructorDescriptor(
scope,
classDescriptor,
true,
classElement.getPrimaryConstructorModifierList(),
classElement,
primaryConstructorParameterList.getParameters());
}
public VariableDescriptor resolvePrimaryConstructorParameterToAProperty(
@NotNull
public PropertyDescriptor resolvePrimaryConstructorParameterToAProperty(
@NotNull ClassDescriptor classDescriptor,
@NotNull JetScope scope,
@NotNull JetParameter parameter) {
@@ -497,6 +493,14 @@ public class ClassDescriptorResolver {
String name = parameter.getName();
boolean isMutable = parameter.isMutable();
JetModifierList modifierList = parameter.getModifierList();
if (modifierList != null) {
ASTNode abstractNode = modifierList.getModifierNode(JetTokens.ABSTRACT_KEYWORD);
if (abstractNode != null) {
semanticServices.getErrorHandler().genericError(abstractNode, "This property cannot be declared abstract");
}
}
PropertyDescriptor propertyDescriptor = new PropertyDescriptor(
classDescriptor,
AttributeResolver.INSTANCE.resolveAttributes(modifierList),
@@ -49,6 +49,11 @@ public class LazySubstitutingClassDescriptor implements ClassDescriptor {
throw new UnsupportedOperationException(); // TODO
}
@Override
public ConstructorDescriptor getUnsubstitutedPrimaryConstructor() {
return original.getUnsubstitutedPrimaryConstructor();
}
@Override
public List<Attribute> getAttributes() {
throw new UnsupportedOperationException(); // TODO
@@ -1,6 +1,7 @@
package org.jetbrains.jet.lang.resolve;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.JetSemanticServices;
import org.jetbrains.jet.lang.types.*;
@@ -14,6 +15,7 @@ public class MutableClassDescriptor extends MutableDeclarationDescriptor impleme
private final WritableScope classHeaderScope;
private final WritableScope writableMemberScope;
private final WritableFunctionGroup constructors = new WritableFunctionGroup("<init>");
private ConstructorDescriptor primaryConstructor;
private TypeConstructor typeConstructor;
private JetScope unsubstitutedMemberScope;
@@ -98,4 +100,16 @@ public class MutableClassDescriptor extends MutableDeclarationDescriptor impleme
public <R, D> R accept(DeclarationDescriptorVisitor<R, D> visitor, D data) {
return visitor.visitClassDescriptor(this, data);
}
public void setPrimaryConstructor(@NotNull ConstructorDescriptor constructorDescriptor) {
assert this.primaryConstructor == null : "Primary constructor assigned twice " + this;
this.primaryConstructor = constructorDescriptor;
addConstructor(constructorDescriptor);
}
@Override
@Nullable
public ConstructorDescriptor getUnsubstitutedPrimaryConstructor() {
return primaryConstructor;
}
}
@@ -1,7 +1,9 @@
package org.jetbrains.jet.lang.resolve;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import com.intellij.psi.util.PsiTreeUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.JetSemanticServices;
import org.jetbrains.jet.lang.cfg.JetControlFlowProcessor;
@@ -20,7 +22,8 @@ public class TopDownAnalyzer {
private final Map<JetClass, MutableClassDescriptor> classes = new LinkedHashMap<JetClass, MutableClassDescriptor>();
private final Map<JetNamespace, WritableScope> namespaceScopes = new LinkedHashMap<JetNamespace, WritableScope>();
private final Map<JetDeclaration, FunctionDescriptor> functions = new LinkedHashMap<JetDeclaration, FunctionDescriptor>();
private final Map<JetDeclaration, FunctionDescriptorImpl> functions = Maps.newLinkedHashMap();
private final Map<JetDeclaration, ConstructorDescriptor> constructors = Maps.newLinkedHashMap();
private final Map<JetProperty, PropertyDescriptor> properties = new LinkedHashMap<JetProperty, PropertyDescriptor>();
private final Map<JetDeclaration, WritableScope> declaringScopes = new HashMap<JetDeclaration, WritableScope>();
private final Multimap<DeclarationDescriptor, PropertyDescriptor> declaringScopesToProperties = ArrayListMultimap.create();
@@ -37,6 +40,8 @@ public class TopDownAnalyzer {
this.classDescriptorResolver = new ClassDescriptorResolver(semanticServices, bindingTrace);
this.trace = bindingTrace;
this.flowDataTraceFactory = flowDataTraceFactory;
// This allows access to backing fields
this.traceForConstructors = new BindingTraceAdapter(trace) {
@Override
public void recordReferenceResolution(@NotNull JetReferenceExpression expression, @NotNull DeclarationDescriptor descriptor) {
@@ -208,7 +213,7 @@ public class TopDownAnalyzer {
public void visitConstructor(JetConstructor constructor) {
DeclarationDescriptor containingDeclaration = declaringScope.getContainingDeclaration();
if (containingDeclaration instanceof ClassDescriptor) {
processConstructor((MutableClassDescriptor) containingDeclaration, constructor);
processSecondaryConstructor((MutableClassDescriptor) containingDeclaration, constructor);
}
else {
semanticServices.getErrorHandler().genericError(constructor.getNode(), "Constructors are only allowed inside classes");
@@ -225,9 +230,11 @@ public class TopDownAnalyzer {
}
private void processPrimaryConstructor(MutableClassDescriptor classDescriptor, JetClass klass) {
if (klass.getPrimaryConstructorParameterList() == null) return; // No constructors
// TODO : not all the parameters are real properties
WritableScope memberScope = classDescriptor.getWritableUnsubstitutedMemberScope(); // TODO : this is REALLY questionable
ConstructorDescriptor constructorDescriptor = classDescriptorResolver.resolvePrimaryConstructor(memberScope, classDescriptor, klass);
ConstructorDescriptor constructorDescriptor = classDescriptorResolver.resolvePrimaryConstructorDescriptor(memberScope, classDescriptor, klass);
for (JetParameter parameter : klass.getPrimaryConstructorParameters()) {
VariableDescriptor propertyDescriptor = classDescriptorResolver.resolvePrimaryConstructorParameterToAProperty(
classDescriptor,
@@ -238,20 +245,23 @@ public class TopDownAnalyzer {
propertyDescriptor);
}
if (constructorDescriptor != null) {
classDescriptor.addConstructor(constructorDescriptor);
classDescriptor.setPrimaryConstructor(constructorDescriptor);
}
}
private void processConstructor(MutableClassDescriptor classDescriptor, JetConstructor constructor) {
ConstructorDescriptor constructorDescriptor = classDescriptorResolver.resolveConstructorDescriptor(classDescriptor.getWritableUnsubstitutedMemberScope(), classDescriptor, constructor, false);
private void processSecondaryConstructor(MutableClassDescriptor classDescriptor, JetConstructor constructor) {
ConstructorDescriptor constructorDescriptor = classDescriptorResolver.resolveSecondaryConstructorDescriptor(
classDescriptor.getWritableUnsubstitutedMemberScope(),
classDescriptor,
constructor);
classDescriptor.addConstructor(constructorDescriptor);
functions.put(constructor, constructorDescriptor);
constructors.put(constructor, constructorDescriptor);
declaringScopes.put(constructor, classDescriptor.getWritableUnsubstitutedMemberScope());
}
private void processFunction(@NotNull WritableScope declaringScope, JetFunction function) {
declaringScopes.put(function, declaringScope);
FunctionDescriptor descriptor = classDescriptorResolver.resolveFunctionDescriptor(declaringScope.getContainingDeclaration(), declaringScope, function);
FunctionDescriptorImpl descriptor = classDescriptorResolver.resolveFunctionDescriptor(declaringScope.getContainingDeclaration(), declaringScope, function);
declaringScope.addFunctionDescriptor(descriptor);
functions.put(function, descriptor);
}
@@ -272,21 +282,22 @@ public class TopDownAnalyzer {
private void resolveBehaviorDeclarationBodies() {
resolveDelegationSpecifierLists();
resolveSecondaryConstructorBodies();
//TODO : anonymous initializers
resolvePropertyDeclarationBodies();
resolveFunctionDeclarationBodies();
resolveFunctionBodies();
}
private void resolveDelegationSpecifierLists() {
// TODO : Make sure the same thing is not initialized twice
final JetTypeInferrer typeInferrer = semanticServices.getTypeInferrer(trace, JetFlowInformationProvider.NONE);
for (Map.Entry<JetClass, MutableClassDescriptor> entry : classes.entrySet()) {
final JetClass declaration = entry.getKey();
final JetClass jetClass = entry.getKey();
final MutableClassDescriptor descriptor = entry.getValue();
for (JetDelegationSpecifier delegationSpecifier : declaration.getDelegationSpecifiers()) {
for (JetDelegationSpecifier delegationSpecifier : jetClass.getDelegationSpecifiers()) {
delegationSpecifier.accept(new JetVisitor() {
@Override
public void visitDelegationByExpressionSpecifier(JetDelegatorByExpressionSpecifier specifier) {
@@ -305,19 +316,36 @@ public class TopDownAnalyzer {
JetTypeReference typeReference = call.getTypeReference();
if (typeReference != null) {
typeInferrer.checkConstructorCall(descriptor.getWritableUnsubstitutedMemberScope(), typeReference, call);
if (jetClass.getPrimaryConstructorParameterList() == null) {
JetArgumentList valueArgumentList = call.getValueArgumentList();
assert valueArgumentList != null;
semanticServices.getErrorHandler().genericError(valueArgumentList.getNode(),
"Class " + JetPsiUtil.safeName(jetClass.getName()) + " must have a constructor in order to be able to initialize supertypes");
}
}
}
@Override
public void visitDelegationToSuperClassSpecifier(JetDelegatorToSuperClass specifier) {
if (declaration.getPrimaryConstructorParameterList() != null) {
semanticServices.getErrorHandler().genericError(specifier.getNode(), "Constructor parameters required in initializer");
JetType supertype = trace.resolveTypeReference(specifier.getTypeReference());
if (supertype != null) {
DeclarationDescriptor declarationDescriptor = supertype.getConstructor().getDeclarationDescriptor();
if (declarationDescriptor instanceof ClassDescriptor) {
ClassDescriptor classDescriptor = (ClassDescriptor) declarationDescriptor;
if (classDescriptor.getUnsubstitutedPrimaryConstructor() != null) {
semanticServices.getErrorHandler().genericError(specifier.getNode(), "This type has a constructor, and thus must be initialized here");
}
}
else {
semanticServices.getErrorHandler().genericError(specifier.getNode(), "Only classes may serve as supertypes");
}
}
}
@Override
public void visitDelegationToThisCall(JetDelegatorToThisCall thisCall) {
throw new IllegalStateException("This-calls should be prohibitied by the parser");
throw new IllegalStateException("This-calls should be prohibited by the parser");
}
@Override
@@ -329,6 +357,93 @@ public class TopDownAnalyzer {
}
}
private void resolveSecondaryConstructorBodies() {
for (Map.Entry<JetDeclaration, ConstructorDescriptor> entry : constructors.entrySet()) {
JetDeclaration declaration = entry.getKey();
ConstructorDescriptor descriptor = entry.getValue();
WritableScope declaringScope = declaringScopes.get(declaration);
assert declaringScope != null;
resolveSecondaryConstructorBody((JetConstructor) declaration, descriptor, declaringScope);
assert descriptor.getUnsubstitutedReturnType() != null;
}
}
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 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) {
semanticServices.getErrorHandler().genericError(declaration.getNameNode(), "A secondary constructor may appear only in a class that has a primary constructor");
}
else {
List<JetDelegationSpecifier> initializers = declaration.getInitializers();
if (initializers.isEmpty()) {
semanticServices.getErrorHandler().genericError(declaration.getNameNode(), "Secondary constructors must have an initializer list");
}
else {
initializers.get(0).accept(new JetVisitor() {
@Override
public void visitDelegationToSuperCallSpecifier(JetDelegatorToSuperCall call) {
JetTypeReference typeReference = call.getTypeReference();
if (typeReference != null) {
typeInferrerForInitializers.checkConstructorCall(functionInnerScope, typeReference, call);
}
}
@Override
public void visitDelegationToThisCall(JetDelegatorToThisCall call) {
// TODO : check that there's no recursion in this() calls
// TODO : check: if a this() call is present, no other initializers are allowed
ClassDescriptor classDescriptor = (ClassDescriptor) descriptor.getContainingDeclaration();
typeInferrerForInitializers.checkClassConstructorCall(
functionInnerScope,
call.getThisReference(),
classDescriptor,
classDescriptor.getDefaultType(),
call);
}
@Override
public void visitDelegationByExpressionSpecifier(JetDelegatorByExpressionSpecifier specifier) {
semanticServices.getErrorHandler().genericError(specifier.getNode(), "'by'-clause is only supported for primary constructors");
}
@Override
public void visitDelegationToSuperClassSpecifier(JetDelegatorToSuperClass specifier) {
semanticServices.getErrorHandler().genericError(specifier.getNode(), "Constructor parameters required");
}
@Override
public void visitDelegationSpecifier(JetDelegationSpecifier specifier) {
throw new IllegalStateException();
}
});
for (int i = 1, initializersSize = initializers.size(); i < initializersSize; i++) {
JetDelegationSpecifier initializer = initializers.get(i);
semanticServices.getErrorHandler().genericError(initializer.getNode(), "Only one call to 'this(...)' is allowed");
}
}
}
JetExpression bodyExpression = declaration.getBodyExpression();
if (bodyExpression != null) {
computeFlowData(declaration, bodyExpression);
JetFlowInformationProvider flowInformationProvider = computeFlowData(declaration, bodyExpression);
JetTypeInferrer typeInferrer = semanticServices.getTypeInferrer(traceForConstructors, flowInformationProvider);
typeInferrer.getType(functionInnerScope, bodyExpression, true);
}
}
private void resolvePropertyDeclarationBodies() {
for (Map.Entry<JetProperty, PropertyDescriptor> entry : properties.entrySet()) {
JetProperty declaration = entry.getKey();
@@ -395,85 +510,20 @@ public class TopDownAnalyzer {
}
}
private void resolveFunctionDeclarationBodies() {
for (Map.Entry<JetDeclaration, FunctionDescriptor> entry : functions.entrySet()) {
private void resolveFunctionBodies() {
for (Map.Entry<JetDeclaration, FunctionDescriptorImpl> entry : functions.entrySet()) {
JetDeclaration declaration = entry.getKey();
FunctionDescriptor descriptor = entry.getValue();
WritableScope declaringScope = declaringScopes.get(declaration);
assert declaringScope != null;
if (declaration instanceof JetFunction) {
resolveFunctionBody(trace, (JetFunction) declaration, (FunctionDescriptorImpl) descriptor, declaringScope);
}
else if (declaration instanceof JetConstructor) {
resolveConstructorBody((JetConstructor) declaration, descriptor, declaringScope);
}
else {
throw new UnsupportedOperationException(); // TODO
}
resolveFunctionBody(trace, (JetFunction) declaration, (FunctionDescriptorImpl) descriptor, declaringScope);
assert descriptor.getUnsubstitutedReturnType() != null;
}
}
private void resolveConstructorBody(JetConstructor declaration, final FunctionDescriptor 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 JetTypeInferrer typeInferrerForInitializers = semanticServices.getTypeInferrer(traceForConstructors, JetFlowInformationProvider.NONE);
for (JetDelegationSpecifier initializer : declaration.getInitializers()) {
// TODO : check that the type being referenced is actually a supertype
initializer.accept(new JetVisitor() {
@Override
public void visitDelegationToSuperCallSpecifier(JetDelegatorToSuperCall call) {
JetTypeReference typeReference = call.getTypeReference();
if (typeReference != null) {
typeInferrerForInitializers.checkConstructorCall(functionInnerScope, typeReference, call);
}
}
@Override
public void visitDelegationToThisCall(JetDelegatorToThisCall call) {
// TODO : check that there's no recursion in this() calls
// TODO : check: if a this() call is present, no other initializers are allowed
ClassDescriptor classDescriptor = (ClassDescriptor) descriptor.getContainingDeclaration();
typeInferrerForInitializers.checkClassConstructorCall(
functionInnerScope,
call.getThisReference(),
classDescriptor,
classDescriptor.getDefaultType(),
call);
}
@Override
public void visitDelegationByExpressionSpecifier(JetDelegatorByExpressionSpecifier specifier) {
semanticServices.getErrorHandler().genericError(specifier.getNode(), "'by'-clause is only supported for primary constructors");
}
@Override
public void visitDelegationToSuperClassSpecifier(JetDelegatorToSuperClass specifier) {
semanticServices.getErrorHandler().genericError(specifier.getNode(), "Constructor parameters required");
}
@Override
public void visitDelegationSpecifier(JetDelegationSpecifier specifier) {
throw new IllegalStateException();
}
});
}
JetExpression bodyExpression = declaration.getBodyExpression();
if (bodyExpression != null) {
computeFlowData(declaration, bodyExpression);
JetFlowInformationProvider flowInformationProvider = computeFlowData(declaration, bodyExpression);
JetTypeInferrer typeInferrer = semanticServices.getTypeInferrer(traceForConstructors, flowInformationProvider);
typeInferrer.getType(functionInnerScope, bodyExpression, true);
}
}
private void resolveFunctionBody(
@NotNull BindingTrace trace,
@NotNull JetDeclarationWithBody function,
@@ -1,6 +1,7 @@
package org.jetbrains.jet.lang.types;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.resolve.JetScope;
import java.util.List;
@@ -16,6 +17,9 @@ public interface ClassDescriptor extends ClassifierDescriptor {
@NotNull
FunctionGroup getConstructors(List<TypeProjection> typeArguments);
@Nullable
ConstructorDescriptor getUnsubstitutedPrimaryConstructor();
@Override
@NotNull
DeclarationDescriptor getContainingDeclaration();
@@ -1,6 +1,7 @@
package org.jetbrains.jet.lang.types;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.resolve.JetScope;
import org.jetbrains.jet.lang.resolve.SubstitutingScope;
@@ -16,6 +17,7 @@ public class ClassDescriptorImpl extends DeclarationDescriptorImpl implements Cl
private JetScope memberDeclarations;
private FunctionGroup constructors;
private ConstructorDescriptor primaryConstructor;
public ClassDescriptorImpl(
@NotNull DeclarationDescriptor containingDeclaration,
@@ -28,10 +30,13 @@ public class ClassDescriptorImpl extends DeclarationDescriptorImpl implements Cl
@NotNull List<TypeParameterDescriptor> typeParameters,
@NotNull Collection<? extends JetType> superclasses,
@NotNull JetScope memberDeclarations,
@NotNull FunctionGroup constructors) {
@NotNull FunctionGroup constructors,
@Nullable ConstructorDescriptor primaryConstructor) {
this.typeConstructor = new TypeConstructorImpl(this, getAttributes(), sealed, getName(), typeParameters, superclasses);
this.memberDeclarations = memberDeclarations;
this.constructors = constructors;
this.primaryConstructor = primaryConstructor;
assert !constructors.isEmpty() || primaryConstructor == null;
return this;
}
@@ -79,4 +84,9 @@ public class ClassDescriptorImpl extends DeclarationDescriptorImpl implements Cl
public <R, D> R accept(DeclarationDescriptorVisitor<R, D> visitor, D data) {
return visitor.visitClassDescriptor(this, data);
}
@Override
public ConstructorDescriptor getUnsubstitutedPrimaryConstructor() {
return primaryConstructor;
}
}
@@ -80,8 +80,12 @@ public class ErrorUtils {
}
};
private static final ClassDescriptor ERROR_CLASS = new ClassDescriptorImpl(ERROR_MODULE, Collections.<Attribute>emptyList(), "<ERROR CLASS>").initialize(
true, Collections.<TypeParameterDescriptor>emptyList(), Collections.<JetType>emptyList(), getErrorScope(), ERROR_FUNCTION_GROUP);
private static final ClassDescriptorImpl ERROR_CLASS = new ClassDescriptorImpl(ERROR_MODULE, Collections.<Attribute>emptyList(), "<ERROR CLASS>");
private static final ConstructorDescriptor ERROR_CONSTRUCTOR = new ConstructorDescriptorImpl(ERROR_CLASS, Collections.<Attribute>emptyList(), true);
static {
ERROR_CLASS.initialize(
true, Collections.<TypeParameterDescriptor>emptyList(), Collections.<JetType>emptyList(), getErrorScope(), ERROR_FUNCTION_GROUP, ERROR_CONSTRUCTOR);
}
private static JetScope getErrorScope() {
return ERROR_SCOPE;
@@ -47,7 +47,8 @@ public class JetStandardClasses {
}
},
JetScope.EMPTY,
FunctionGroup.EMPTY
FunctionGroup.EMPTY,
null
);
private static final JetType NOTHING_TYPE = new JetTypeImpl(getNothing());
@@ -68,7 +69,8 @@ public class JetStandardClasses {
Collections.<TypeParameterDescriptor>emptyList(),
Collections.<JetType>emptySet(),
JetScope.EMPTY,
FunctionGroup.EMPTY
FunctionGroup.EMPTY,
null
);
private static final JetType ANY_TYPE = new JetTypeImpl(ANY.getTypeConstructor(), JetScope.EMPTY);
@@ -102,7 +104,8 @@ public class JetStandardClasses {
parameters,
Collections.singleton(getAnyType()),
STUB,
STUB_FG);
STUB_FG,
null); // TODO : constructor
}
}
@@ -122,7 +125,7 @@ public class JetStandardClasses {
FUNCTION[i] = function.initialize(
false,
createTypeParameters(i, function),
Collections.singleton(getAnyType()), STUB, STUB_FG);
Collections.singleton(getAnyType()), STUB, FunctionGroup.EMPTY, null);
ClassDescriptorImpl receiverFunction = new ClassDescriptorImpl(
STANDARD_CLASSES_NAMESPACE,
@@ -136,7 +139,7 @@ public class JetStandardClasses {
RECEIVER_FUNCTION[i] = receiverFunction.initialize(
false,
parameters,
Collections.singleton(getAnyType()), STUB, STUB_FG);
Collections.singleton(getAnyType()), STUB, FunctionGroup.EMPTY, null);
}
}
@@ -1,12 +1,12 @@
class A {
class A() {
fun equals(a : Any?) : Boolean
}
class B {
class B() {
fun equals(a : Any?) : Boolean?
}
class C {
class C() {
fun equals(a : Any?) : Int
}
+29 -4
View File
@@ -1,9 +1,34 @@
class Z {
this() : this(1, true) {}
this(x : Int, y : Boolean) : this<error>(1)</error> {}
class NoC
class NoC1 : NoC
class WithC0() : NoC<error>()</error>
class WithC1() : NoC
class NoC2 : <error>WithC1</error>
class NoC3 : WithC1<error>()</error>
class WithC2() : <error>WithC1</error>
class NoPC {
<error>this</error>() {}
}
class Foo() : <error>Z</error>, <error>this</error>() {
class WithPC0() {
this(a : Int) : this() {}
}
class WithPC1(a : Int) {
<error>this</error>() {}
this(b : Long) : this("") {}
this(s : String) : this(1) {}
this(b : Char) : this<error>("", 2)</error> {}
this(b : Byte) : this(""), <error>this(1)</error> {}
}
class Foo() : <error>WithPC0</error>, <error>this</error>() {
}
@@ -1,10 +1,10 @@
import java.util.*;
class NotRange1 {
class NotRange1() {
}
class NotRange2 {
class NotRange2() {
fun iterator() : Unit
}
@@ -12,7 +12,7 @@ class ImproperIterator1 {
fun hasNext() : Boolean
}
class NotRange3 {
class NotRange3() {
fun iterator() : ImproperIterator1
}
@@ -20,7 +20,7 @@ class ImproperIterator2 {
fun next() : Boolean
}
class NotRange4 {
class NotRange4() {
fun iterator() : ImproperIterator2
}
@@ -29,7 +29,7 @@ class ImproperIterator3 {
fun next() : Int
}
class NotRange5 {
class NotRange5() {
fun iterator() : ImproperIterator3
}
@@ -39,7 +39,7 @@ class AmbiguousHasNextIterator {
fun next() : Int
}
class NotRange6 {
class NotRange6() {
fun iterator() : AmbiguousHasNextIterator
}
@@ -48,7 +48,7 @@ class ImproperIterator4 {
fun next() : Int
}
class NotRange7 {
class NotRange7() {
fun iterator() : ImproperIterator3
}
@@ -57,11 +57,11 @@ class GoodIterator {
fun next() : Int
}
class Range0 {
class Range0() {
fun iterator() : GoodIterator
}
class Range1 {
class Range1() {
fun iterator() : Iterator<Int>
}
+3 -3
View File
@@ -1,4 +1,4 @@
class IncDec {
class IncDec() {
fun inc() : IncDec = this
fun dec() : IncDec = this
}
@@ -15,7 +15,7 @@ fun testIncDec() {
x = --x
}
class WrongIncDec {
class WrongIncDec() {
fun inc() : Int = 1
fun dec() : Int = 1
}
@@ -28,7 +28,7 @@ fun testWrongIncDec() {
<error>--</error>x
}
class UnitIncDec {
class UnitIncDec() {
fun inc() : Unit {}
fun dec() : Unit {}
}
+2 -2
View File
@@ -12,11 +12,11 @@
val p : Int = <error>1</error>
get() = 1
class Test {
class Test() {
var a : Int
var b : Int get() = <error>$a</error>; set(x) {a = x; <error>$a</error> = x}
this() {
this(i : Int) : this() {
<error>$b</error> = $a
$a = <error>$b</error>
a = <error>$b</error>
+5
View File
@@ -7,3 +7,8 @@ class foo {
}
}
public class foo() : Bar
protected class foo private () : Bar
private class foo<T>() : Bar
internal class foo<T> private () : Bar
+103 -1
View File
@@ -124,4 +124,106 @@ JetFile: Constructors.jet
PsiWhiteSpace('\n\n ')
PsiElement(RBRACE)('}')
PsiWhiteSpace('\n\n')
PsiElement(RBRACE)('}')
PsiElement(RBRACE)('}')
PsiWhiteSpace('\n\n')
CLASS
MODIFIER_LIST
PsiElement(public)('public')
PsiWhiteSpace(' ')
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('foo')
TYPE_PARAMETER_LIST
<empty list>
VALUE_PARAMETER_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
PsiElement(COLON)(':')
PsiWhiteSpace(' ')
DELEGATION_SPECIFIER_LIST
DELEGATOR_SUPER_CLASS
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('Bar')
PsiWhiteSpace('\n')
CLASS
MODIFIER_LIST
PsiElement(protected)('protected')
PsiWhiteSpace(' ')
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('foo')
PsiWhiteSpace(' ')
TYPE_PARAMETER_LIST
<empty list>
PRIMARY_CONSTRUCTOR_MODIFIER_LIST
PsiElement(private)('private')
PsiWhiteSpace(' ')
VALUE_PARAMETER_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
PsiElement(COLON)(':')
PsiWhiteSpace(' ')
DELEGATION_SPECIFIER_LIST
DELEGATOR_SUPER_CLASS
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('Bar')
PsiWhiteSpace('\n')
CLASS
MODIFIER_LIST
PsiElement(private)('private')
PsiWhiteSpace(' ')
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('foo')
TYPE_PARAMETER_LIST
PsiElement(LT)('<')
TYPE_PARAMETER
PsiElement(IDENTIFIER)('T')
PsiElement(GT)('>')
VALUE_PARAMETER_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
PsiElement(COLON)(':')
PsiWhiteSpace(' ')
DELEGATION_SPECIFIER_LIST
DELEGATOR_SUPER_CLASS
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('Bar')
PsiWhiteSpace('\n')
CLASS
MODIFIER_LIST
PsiElement(internal)('internal')
PsiWhiteSpace(' ')
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('foo')
TYPE_PARAMETER_LIST
PsiElement(LT)('<')
TYPE_PARAMETER
PsiElement(IDENTIFIER)('T')
PsiElement(GT)('>')
PsiWhiteSpace(' ')
PRIMARY_CONSTRUCTOR_MODIFIER_LIST
PsiElement(private)('private')
PsiWhiteSpace(' ')
VALUE_PARAMETER_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
PsiElement(COLON)(':')
PsiWhiteSpace(' ')
DELEGATION_SPECIFIER_LIST
DELEGATOR_SUPER_CLASS
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('Bar')
@@ -1,4 +1,4 @@
class Z {
class Z(a : Int) {
~c1~this() : `c2`this(1, true) {}
~c2~this(x : Int, y : Boolean) : `c1`this() {}