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:
@@ -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));
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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> {
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user