JET-6 Perform checks for primary and secondary constructors (In progress): class having a stateful property must have a constructor

This commit is contained in:
Andrey Breslav
2011-05-04 15:13:25 +04:00
parent 441bef9935
commit 8c8f1eb4dd
9 changed files with 76 additions and 9 deletions
@@ -63,6 +63,11 @@ public class JetSemanticServices {
@NotNull @NotNull
public WritableScope createWritableScope(@NotNull JetScope scope, @NotNull DeclarationDescriptor owner) { public WritableScope createWritableScope(@NotNull JetScope scope, @NotNull DeclarationDescriptor owner) {
return new WritableScopeImpl(scope, owner, errorHandler); return new WritableScopeImpl(scope, owner, errorHandler, null);
}
@NotNull
public WritableScope createWritableScope(@NotNull JetScope scope, @NotNull DeclarationDescriptor owner, @NotNull DeclarationDescriptorVisitor<?, ? super WritableScope> modificationListener) {
return new WritableScopeImpl(scope, owner, errorHandler, modificationListener);
} }
} }
@@ -1,5 +1,6 @@
package org.jetbrains.jet.lang.resolve; package org.jetbrains.jet.lang.resolve;
import com.google.common.collect.Sets;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.JetSemanticServices; import org.jetbrains.jet.lang.JetSemanticServices;
@@ -7,14 +8,16 @@ import org.jetbrains.jet.lang.types.*;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
/** /**
* @author abreslav * @author abreslav
*/ */
public class MutableClassDescriptor extends MutableDeclarationDescriptor implements ClassDescriptor { public class MutableClassDescriptor extends MutableDeclarationDescriptor implements ClassDescriptor {
private final WritableFunctionGroup constructors = new WritableFunctionGroup("<init>");
private final WritableScope classHeaderScope; private final WritableScope classHeaderScope;
private final WritableScope writableMemberScope; private final WritableScope writableMemberScope;
private final WritableFunctionGroup constructors = new WritableFunctionGroup("<init>"); private final Set<PropertyDescriptor> properties = Sets.newHashSet();
private ConstructorDescriptor primaryConstructor; private ConstructorDescriptor primaryConstructor;
private TypeConstructor typeConstructor; private TypeConstructor typeConstructor;
@@ -23,7 +26,13 @@ public class MutableClassDescriptor extends MutableDeclarationDescriptor impleme
public MutableClassDescriptor(@NotNull JetSemanticServices semanticServices, @NotNull DeclarationDescriptor containingDeclaration, @NotNull JetScope outerScope) { public MutableClassDescriptor(@NotNull JetSemanticServices semanticServices, @NotNull DeclarationDescriptor containingDeclaration, @NotNull JetScope outerScope) {
super(containingDeclaration); super(containingDeclaration);
this.classHeaderScope = semanticServices.createWritableScope(outerScope, this); this.classHeaderScope = semanticServices.createWritableScope(outerScope, this);
this.writableMemberScope = semanticServices.createWritableScope(classHeaderScope, this); this.writableMemberScope = semanticServices.createWritableScope(classHeaderScope, this, new DeclarationDescriptorVisitor<Void, WritableScope>() {
@Override
public Void visitPropertyDescriptor(PropertyDescriptor descriptor, WritableScope data) {
properties.add(descriptor);
return null;
}
});
this.unsubstitutedMemberScope = this.writableMemberScope; this.unsubstitutedMemberScope = this.writableMemberScope;
} }
@@ -48,6 +57,10 @@ public class MutableClassDescriptor extends MutableDeclarationDescriptor impleme
this.typeConstructor = typeConstructor; this.typeConstructor = typeConstructor;
} }
public Set<PropertyDescriptor> getProperties() {
return properties;
}
@NotNull @NotNull
@Override @Override
public JetScope getMemberScope(List<TypeProjection> typeArguments) { public JetScope getMemberScope(List<TypeProjection> typeArguments) {
@@ -4,6 +4,7 @@ import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import com.google.common.collect.Multimap; import com.google.common.collect.Multimap;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
import com.intellij.psi.PsiElement;
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.lang.JetSemanticServices; import org.jetbrains.jet.lang.JetSemanticServices;
@@ -312,6 +313,23 @@ public class TopDownAnalyzer {
resolveSecondaryConstructorBodies(); resolveSecondaryConstructorBodies();
resolveFunctionBodies(); resolveFunctionBodies();
for (Map.Entry<JetClass, MutableClassDescriptor> entry : classes.entrySet()) {
MutableClassDescriptor classDescriptor = entry.getValue();
JetClass jetClass = entry.getKey();
if (!jetClass.hasPrimaryConstructor()) {
for (PropertyDescriptor propertyDescriptor : classDescriptor.getProperties()) {
if (trace.hasBackingField(propertyDescriptor)) {
PsiElement nameIdentifier = jetClass.getNameIdentifier();
if (nameIdentifier != null) {
semanticServices.getErrorHandler().genericError(nameIdentifier.getNode(),
"This class must have a primary constructor, because property " + propertyDescriptor.getName() + " has a backing field");
}
break;
}
}
}
}
} }
private void resolveDelegationSpecifierLists() { private void resolveDelegationSpecifierLists() {
@@ -34,10 +34,14 @@ public class WritableScopeImpl extends WritableScopeWithImports {
@Nullable @Nullable
private JetType thisType; private JetType thisType;
public WritableScopeImpl(@NotNull JetScope scope, @NotNull DeclarationDescriptor owner, @NotNull ErrorHandler errorHandler) { @Nullable
private final DeclarationDescriptorVisitor<?, ? super WritableScopeImpl> modificationListener;
public WritableScopeImpl(@NotNull JetScope scope, @NotNull DeclarationDescriptor owner, @NotNull ErrorHandler errorHandler, @Nullable DeclarationDescriptorVisitor<?, ? super WritableScopeImpl> modificationListener) {
super(scope); super(scope);
this.ownerDeclarationDescriptor = owner; this.ownerDeclarationDescriptor = owner;
this.errorHandler = errorHandler; this.errorHandler = errorHandler;
this.modificationListener = modificationListener;
} }
@NotNull @NotNull
@@ -46,6 +50,12 @@ public class WritableScopeImpl extends WritableScopeWithImports {
return ownerDeclarationDescriptor; return ownerDeclarationDescriptor;
} }
private void notifyListeners(DeclarationDescriptor descriptor) {
if (modificationListener != null) {
descriptor.accept(modificationListener, this);
}
}
@NotNull @NotNull
private Map<String, List<DeclarationDescriptor>> getLabelsToDescriptors() { private Map<String, List<DeclarationDescriptor>> getLabelsToDescriptors() {
if (labelsToDescriptors == null) { if (labelsToDescriptors == null) {
@@ -80,6 +90,7 @@ public class WritableScopeImpl extends WritableScopeWithImports {
labelsToDescriptors.put(name, declarationDescriptors); labelsToDescriptors.put(name, declarationDescriptors);
} }
declarationDescriptors.add(descriptor); declarationDescriptors.add(descriptor);
notifyListeners(descriptor);
} }
@NotNull @NotNull
@@ -99,6 +110,7 @@ public class WritableScopeImpl extends WritableScopeWithImports {
} }
// TODO : Should this always happen? // TODO : Should this always happen?
propertyDescriptors.put(variableDescriptor.getName(), variableDescriptor); propertyDescriptors.put(variableDescriptor.getName(), variableDescriptor);
notifyListeners(variableDescriptor);
} }
@Override @Override
@@ -143,6 +155,7 @@ public class WritableScopeImpl extends WritableScopeWithImports {
functionGroups.put(name, functionGroup); functionGroups.put(name, functionGroup);
} }
functionGroup.addFunction(functionDescriptor); functionGroup.addFunction(functionDescriptor);
notifyListeners(functionDescriptor);
} }
@Override @Override
@@ -174,6 +187,7 @@ public class WritableScopeImpl extends WritableScopeWithImports {
errorHandler.redeclaration(originalDescriptor, typeParameterDescriptor); errorHandler.redeclaration(originalDescriptor, typeParameterDescriptor);
} }
classifierDescriptors.put(name, typeParameterDescriptor); classifierDescriptors.put(name, typeParameterDescriptor);
notifyListeners(typeParameterDescriptor);
} }
@NotNull @NotNull
@@ -197,6 +211,7 @@ public class WritableScopeImpl extends WritableScopeWithImports {
errorHandler.redeclaration(originalDescriptor, classifierDescriptor); errorHandler.redeclaration(originalDescriptor, classifierDescriptor);
} }
classifierDescriptors.put(name, classifierDescriptor); classifierDescriptors.put(name, classifierDescriptor);
notifyListeners(classifierDescriptor);
} }
@Override @Override
@@ -239,6 +254,7 @@ public class WritableScopeImpl extends WritableScopeWithImports {
if (oldValue != null) { if (oldValue != null) {
errorHandler.redeclaration(oldValue, namespaceDescriptor); errorHandler.redeclaration(oldValue, namespaceDescriptor);
} }
notifyListeners(namespaceDescriptor);
} }
@Override @Override
@@ -285,6 +301,7 @@ public class WritableScopeImpl extends WritableScopeWithImports {
@Override @Override
public void addPropertyDescriptorByFieldName(@NotNull String fieldName, @NotNull PropertyDescriptor propertyDescriptor) { public void addPropertyDescriptorByFieldName(@NotNull String fieldName, @NotNull PropertyDescriptor propertyDescriptor) {
getPropertyDescriptorsByFieldNames().put(fieldName, propertyDescriptor); getPropertyDescriptorsByFieldNames().put(fieldName, propertyDescriptor);
notifyListeners(propertyDescriptor);
} }
@Override @Override
@@ -168,7 +168,7 @@ public class JetStandardClasses {
/*package*/ static final JetScope STANDARD_CLASSES; /*package*/ static final JetScope STANDARD_CLASSES;
static { static {
WritableScope writableScope = new WritableScopeImpl(JetScope.EMPTY, STANDARD_CLASSES_NAMESPACE, ErrorHandler.DO_NOTHING); WritableScope writableScope = new WritableScopeImpl(JetScope.EMPTY, STANDARD_CLASSES_NAMESPACE, ErrorHandler.DO_NOTHING, null);
STANDARD_CLASSES = writableScope; STANDARD_CLASSES = writableScope;
writableScope.addClassifierAlias("Unit", getTuple(0)); writableScope.addClassifierAlias("Unit", getTuple(0));
+1 -1
View File
@@ -43,7 +43,7 @@ class WithCPI(x : Int) {
val xy : Int = x val xy : Int = x
} }
class NoCPI { class <error>NoCPI</error> {
val a = <error>1</error> val a = <error>1</error>
var ab = <error>1</error> var ab = <error>1</error>
get() = 1 get() = 1
@@ -35,7 +35,7 @@ class NotRange5() {
class AmbiguousHasNextIterator { class AmbiguousHasNextIterator {
fun hasNext() : Boolean fun hasNext() : Boolean
val hasNext : Boolean val hasNext : Boolean get() = false
fun next() : Int fun next() : Int
} }
@@ -44,7 +44,7 @@ class NotRange6() {
} }
class ImproperIterator4 { class ImproperIterator4 {
val hasNext : Int val hasNext : Int get() = 1
fun next() : Int fun next() : Int
} }
+1 -1
View File
@@ -31,7 +31,7 @@ class Iteratee<in I, out O> {
abstract fun done() : O abstract fun done() : O
} }
class Sum : Iteratee<Int, Int> { class Sum() : Iteratee<Int, Int> {
override fun process(item : Int) : Iteratee<Int, Int> { override fun process(item : Int) : Iteratee<Int, Int> {
return foobar.done<Int>(item); return foobar.done<Int>(item);
} }
@@ -0,0 +1,14 @@
class <error>X</error> {
val x : Int
}
class Y() {
val x : Int
}
class Y1 {
val x : Int get() = 1
}
class Z : Y<error>()</error> {
}