提交 8c8f1eb4 编写于 作者: A Andrey Breslav

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

JET-6 Perform checks for primary and secondary constructors (In progress): class having a stateful property must have a constructor
上级 441bef99
......@@ -63,6 +63,11 @@ public class JetSemanticServices {
@NotNull
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);
}
}
package org.jetbrains.jet.lang.resolve;
import com.google.common.collect.Sets;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.JetSemanticServices;
......@@ -7,14 +8,16 @@ import org.jetbrains.jet.lang.types.*;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* @author abreslav
*/
public class MutableClassDescriptor extends MutableDeclarationDescriptor implements ClassDescriptor {
private final WritableFunctionGroup constructors = new WritableFunctionGroup("<init>");
private final WritableScope classHeaderScope;
private final WritableScope writableMemberScope;
private final WritableFunctionGroup constructors = new WritableFunctionGroup("<init>");
private final Set<PropertyDescriptor> properties = Sets.newHashSet();
private ConstructorDescriptor primaryConstructor;
private TypeConstructor typeConstructor;
......@@ -23,7 +26,13 @@ public class MutableClassDescriptor extends MutableDeclarationDescriptor impleme
public MutableClassDescriptor(@NotNull JetSemanticServices semanticServices, @NotNull DeclarationDescriptor containingDeclaration, @NotNull JetScope outerScope) {
super(containingDeclaration);
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;
}
......@@ -48,6 +57,10 @@ public class MutableClassDescriptor extends MutableDeclarationDescriptor impleme
this.typeConstructor = typeConstructor;
}
public Set<PropertyDescriptor> getProperties() {
return properties;
}
@NotNull
@Override
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.Multimap;
import com.google.common.collect.Sets;
import com.intellij.psi.PsiElement;
import com.intellij.psi.util.PsiTreeUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.JetSemanticServices;
......@@ -312,6 +313,23 @@ public class TopDownAnalyzer {
resolveSecondaryConstructorBodies();
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() {
......
......@@ -34,10 +34,14 @@ public class WritableScopeImpl extends WritableScopeWithImports {
@Nullable
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);
this.ownerDeclarationDescriptor = owner;
this.errorHandler = errorHandler;
this.modificationListener = modificationListener;
}
@NotNull
......@@ -46,6 +50,12 @@ public class WritableScopeImpl extends WritableScopeWithImports {
return ownerDeclarationDescriptor;
}
private void notifyListeners(DeclarationDescriptor descriptor) {
if (modificationListener != null) {
descriptor.accept(modificationListener, this);
}
}
@NotNull
private Map<String, List<DeclarationDescriptor>> getLabelsToDescriptors() {
if (labelsToDescriptors == null) {
......@@ -80,6 +90,7 @@ public class WritableScopeImpl extends WritableScopeWithImports {
labelsToDescriptors.put(name, declarationDescriptors);
}
declarationDescriptors.add(descriptor);
notifyListeners(descriptor);
}
@NotNull
......@@ -99,6 +110,7 @@ public class WritableScopeImpl extends WritableScopeWithImports {
}
// TODO : Should this always happen?
propertyDescriptors.put(variableDescriptor.getName(), variableDescriptor);
notifyListeners(variableDescriptor);
}
@Override
......@@ -143,6 +155,7 @@ public class WritableScopeImpl extends WritableScopeWithImports {
functionGroups.put(name, functionGroup);
}
functionGroup.addFunction(functionDescriptor);
notifyListeners(functionDescriptor);
}
@Override
......@@ -174,6 +187,7 @@ public class WritableScopeImpl extends WritableScopeWithImports {
errorHandler.redeclaration(originalDescriptor, typeParameterDescriptor);
}
classifierDescriptors.put(name, typeParameterDescriptor);
notifyListeners(typeParameterDescriptor);
}
@NotNull
......@@ -197,6 +211,7 @@ public class WritableScopeImpl extends WritableScopeWithImports {
errorHandler.redeclaration(originalDescriptor, classifierDescriptor);
}
classifierDescriptors.put(name, classifierDescriptor);
notifyListeners(classifierDescriptor);
}
@Override
......@@ -239,6 +254,7 @@ public class WritableScopeImpl extends WritableScopeWithImports {
if (oldValue != null) {
errorHandler.redeclaration(oldValue, namespaceDescriptor);
}
notifyListeners(namespaceDescriptor);
}
@Override
......@@ -285,6 +301,7 @@ public class WritableScopeImpl extends WritableScopeWithImports {
@Override
public void addPropertyDescriptorByFieldName(@NotNull String fieldName, @NotNull PropertyDescriptor propertyDescriptor) {
getPropertyDescriptorsByFieldNames().put(fieldName, propertyDescriptor);
notifyListeners(propertyDescriptor);
}
@Override
......
......@@ -168,7 +168,7 @@ public class JetStandardClasses {
/*package*/ static final JetScope STANDARD_CLASSES;
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;
writableScope.addClassifierAlias("Unit", getTuple(0));
......
......@@ -43,7 +43,7 @@ class WithCPI(x : Int) {
val xy : Int = x
}
class NoCPI {
class <error>NoCPI</error> {
val a = <error>1</error>
var ab = <error>1</error>
get() = 1
......
......@@ -35,7 +35,7 @@ class NotRange5() {
class AmbiguousHasNextIterator {
fun hasNext() : Boolean
val hasNext : Boolean
val hasNext : Boolean get() = false
fun next() : Int
}
......@@ -44,7 +44,7 @@ class NotRange6() {
}
class ImproperIterator4 {
val hasNext : Int
val hasNext : Int get() = 1
fun next() : Int
}
......
......@@ -31,7 +31,7 @@ class Iteratee<in I, out O> {
abstract fun done() : O
}
class Sum : Iteratee<Int, Int> {
class Sum() : Iteratee<Int, Int> {
override fun process(item : Int) : Iteratee<Int, Int> {
return foobar.done<Int>(item);
}
......
class <error>X</error> {
val x : Int
}
class Y() {
val x : Int
}
class Y1 {
val x : Int get() = 1
}
class Z : Y<error>()</error> {
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册