Correct descriptors for properties with receivers
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
package org.jetbrains.jet.lang.descriptors;
|
package org.jetbrains.jet.lang.descriptors;
|
||||||
|
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
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.types.JetType;
|
import org.jetbrains.jet.lang.types.JetType;
|
||||||
@@ -15,6 +16,8 @@ public class PropertyDescriptor extends VariableDescriptorImpl implements Member
|
|||||||
|
|
||||||
private final MemberModifiers memberModifiers;
|
private final MemberModifiers memberModifiers;
|
||||||
private final boolean isVar;
|
private final boolean isVar;
|
||||||
|
private final JetType receiverType;
|
||||||
|
private final List<TypeParameterDescriptor> typeParemeters = Lists.newArrayListWithCapacity(0);
|
||||||
private PropertyGetterDescriptor getter;
|
private PropertyGetterDescriptor getter;
|
||||||
private PropertySetterDescriptor setter;
|
private PropertySetterDescriptor setter;
|
||||||
|
|
||||||
@@ -23,35 +26,51 @@ public class PropertyDescriptor extends VariableDescriptorImpl implements Member
|
|||||||
@NotNull List<Annotation> annotations,
|
@NotNull List<Annotation> annotations,
|
||||||
@NotNull MemberModifiers memberModifiers,
|
@NotNull MemberModifiers memberModifiers,
|
||||||
boolean isVar,
|
boolean isVar,
|
||||||
|
@Nullable JetType receiverType,
|
||||||
@NotNull String name,
|
@NotNull String name,
|
||||||
@Nullable JetType inType,
|
@Nullable JetType inType,
|
||||||
@Nullable JetType outType) {
|
@NotNull JetType outType) {
|
||||||
super(containingDeclaration, annotations, name, inType, outType);
|
super(containingDeclaration, annotations, name, inType, outType);
|
||||||
assert !isVar || inType != null;
|
assert !isVar || inType != null;
|
||||||
assert outType != null;
|
// assert outType != null;
|
||||||
this.isVar = isVar;
|
this.isVar = isVar;
|
||||||
this.memberModifiers = memberModifiers;
|
this.memberModifiers = memberModifiers;
|
||||||
|
this.receiverType = receiverType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public PropertyDescriptor(
|
private PropertyDescriptor(
|
||||||
@NotNull PropertyDescriptor original,
|
@NotNull PropertyDescriptor original,
|
||||||
|
@Nullable JetType receiverType,
|
||||||
@Nullable JetType inType,
|
@Nullable JetType inType,
|
||||||
@Nullable JetType outType) {
|
@NotNull JetType outType) {
|
||||||
this(
|
this(
|
||||||
original.getContainingDeclaration(),
|
original.getContainingDeclaration(),
|
||||||
original.getAnnotations(), // TODO : substitute?
|
original.getAnnotations(), // TODO : substitute?
|
||||||
original.getModifiers(),
|
original.getModifiers(),
|
||||||
original.isVar,
|
original.isVar,
|
||||||
|
receiverType,
|
||||||
original.getName(),
|
original.getName(),
|
||||||
inType,
|
inType,
|
||||||
outType);
|
outType);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void initialize(@Nullable PropertyGetterDescriptor getter, @Nullable PropertySetterDescriptor setter) {
|
public void initialize(@NotNull List<TypeParameterDescriptor> typeParameters, @Nullable PropertyGetterDescriptor getter, @Nullable PropertySetterDescriptor setter) {
|
||||||
|
this.typeParemeters.addAll(typeParameters);
|
||||||
this.getter = getter;
|
this.getter = getter;
|
||||||
this.setter = setter;
|
this.setter = setter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public List<TypeParameterDescriptor> getTypeParemeters() {
|
||||||
|
return typeParemeters;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public JetType getReceiverType() {
|
||||||
|
return receiverType;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public boolean isVar() {
|
public boolean isVar() {
|
||||||
return isVar;
|
return isVar;
|
||||||
}
|
}
|
||||||
@@ -78,12 +97,14 @@ public class PropertyDescriptor extends VariableDescriptorImpl implements Member
|
|||||||
JetType originalInType = getInType();
|
JetType originalInType = getInType();
|
||||||
JetType inType = originalInType == null ? null : substitutor.substitute(originalInType, Variance.IN_VARIANCE);
|
JetType inType = originalInType == null ? null : substitutor.substitute(originalInType, Variance.IN_VARIANCE);
|
||||||
JetType originalOutType = getOutType();
|
JetType originalOutType = getOutType();
|
||||||
JetType outType = originalOutType == null ? null : substitutor.substitute(originalOutType, Variance.OUT_VARIANCE);
|
JetType outType = substitutor.substitute(originalOutType, Variance.OUT_VARIANCE);
|
||||||
if (inType == null && outType == null) {
|
if (inType == null && outType == null) {
|
||||||
return null; // TODO : tell the user that the property was projected out
|
return null; // TODO : tell the user that the property was projected out
|
||||||
}
|
}
|
||||||
|
JetType receiverType = getReceiverType();
|
||||||
return new PropertyDescriptor(
|
return new PropertyDescriptor(
|
||||||
this,
|
this,
|
||||||
|
receiverType == null ? null : substitutor.substitute(receiverType, Variance.IN_VARIANCE),
|
||||||
inType,
|
inType,
|
||||||
outType
|
outType
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import java.util.List;
|
|||||||
/**
|
/**
|
||||||
* @author max
|
* @author max
|
||||||
*/
|
*/
|
||||||
public class JetProperty extends JetNamedDeclaration {
|
public class JetProperty extends JetTypeParameterListOwner {
|
||||||
public JetProperty(@NotNull ASTNode node) {
|
public JetProperty(@NotNull ASTNode node) {
|
||||||
super(node);
|
super(node);
|
||||||
}
|
}
|
||||||
@@ -44,7 +44,6 @@ public class JetProperty extends JetNamedDeclaration {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public JetTypeReference getPropertyTypeRef() {
|
public JetTypeReference getPropertyTypeRef() {
|
||||||
ASTNode node = getNode().getFirstChildNode();
|
ASTNode node = getNode().getFirstChildNode();
|
||||||
|
|||||||
@@ -358,22 +358,45 @@ public class ClassDescriptorResolver {
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public PropertyDescriptor resolvePropertyDescriptor(@NotNull DeclarationDescriptor containingDeclaration, @NotNull JetScope scope, JetProperty property) {
|
public PropertyDescriptor resolvePropertyDescriptor(@NotNull DeclarationDescriptor containingDeclaration, @NotNull JetScope scope, JetProperty property) {
|
||||||
JetType type = getType(scope, property, true);
|
|
||||||
|
|
||||||
boolean isVar = property.isVar();
|
JetScope scopeWithTypeParameters;
|
||||||
|
List<TypeParameterDescriptor> typeParameterDescriptors;
|
||||||
|
List<JetTypeParameter> typeParameters = property.getTypeParameters();
|
||||||
|
if (typeParameters.isEmpty()) {
|
||||||
|
scopeWithTypeParameters = scope;
|
||||||
|
typeParameterDescriptors = Collections.emptyList();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
WritableScope writableScope = new WritableScopeImpl(scope, containingDeclaration, trace.getErrorHandler());
|
||||||
|
typeParameterDescriptors = resolveTypeParameters(containingDeclaration, writableScope, typeParameters);
|
||||||
|
scopeWithTypeParameters = writableScope;
|
||||||
|
}
|
||||||
|
|
||||||
|
JetType receiverType = null;
|
||||||
|
JetTypeReference receiverTypeRef = property.getReceiverTypeRef();
|
||||||
|
if (receiverTypeRef != null) {
|
||||||
|
receiverType = typeResolver.resolveType(scopeWithTypeParameters, receiverTypeRef);
|
||||||
|
}
|
||||||
|
|
||||||
JetModifierList modifierList = property.getModifierList();
|
JetModifierList modifierList = property.getModifierList();
|
||||||
|
boolean isVar = property.isVar();
|
||||||
|
|
||||||
|
JetType type = getType(scopeWithTypeParameters, property, true);
|
||||||
|
|
||||||
PropertyDescriptor propertyDescriptor = new PropertyDescriptor(
|
PropertyDescriptor propertyDescriptor = new PropertyDescriptor(
|
||||||
containingDeclaration,
|
containingDeclaration,
|
||||||
AnnotationResolver.INSTANCE.resolveAnnotations(modifierList),
|
AnnotationResolver.INSTANCE.resolveAnnotations(modifierList),
|
||||||
resolveModifiers(modifierList, DEFAULT_MODIFIERS), // TODO : default modifiers differ in different contexts
|
resolveModifiers(modifierList, DEFAULT_MODIFIERS), // TODO : default modifiers differ in different contexts
|
||||||
isVar,
|
isVar,
|
||||||
|
receiverType,
|
||||||
JetPsiUtil.safeName(property.getName()),
|
JetPsiUtil.safeName(property.getName()),
|
||||||
isVar ? type : null,
|
isVar ? type : null,
|
||||||
type);
|
type);
|
||||||
|
|
||||||
propertyDescriptor.initialize(
|
propertyDescriptor.initialize(
|
||||||
resolvePropertyGetterDescriptor(scope, property, propertyDescriptor),
|
typeParameterDescriptors,
|
||||||
resolvePropertySetterDescriptor(scope, property, propertyDescriptor));
|
resolvePropertyGetterDescriptor(scopeWithTypeParameters, property, propertyDescriptor),
|
||||||
|
resolvePropertySetterDescriptor(scopeWithTypeParameters, property, propertyDescriptor));
|
||||||
|
|
||||||
trace.recordDeclarationResolution(property, propertyDescriptor);
|
trace.recordDeclarationResolution(property, propertyDescriptor);
|
||||||
return propertyDescriptor;
|
return propertyDescriptor;
|
||||||
@@ -384,14 +407,12 @@ public class ClassDescriptorResolver {
|
|||||||
// TODO : receiver?
|
// TODO : receiver?
|
||||||
JetTypeReference propertyTypeRef = property.getPropertyTypeRef();
|
JetTypeReference propertyTypeRef = property.getPropertyTypeRef();
|
||||||
|
|
||||||
JetType type;
|
|
||||||
if (propertyTypeRef == null) {
|
if (propertyTypeRef == null) {
|
||||||
final JetExpression initializer = property.getInitializer();
|
final JetExpression initializer = property.getInitializer();
|
||||||
if (initializer == null) {
|
if (initializer == null) {
|
||||||
trace.getErrorHandler().genericError(property.getNode(), "This property must either have a type annotation or be initialized");
|
trace.getErrorHandler().genericError(property.getNode(), "This property must either have a type annotation or be initialized");
|
||||||
type = ErrorUtils.createErrorType("No type, no body");
|
return ErrorUtils.createErrorType("No type, no body");
|
||||||
} else {
|
} else {
|
||||||
// TODO : ??? Fix-point here: what if we have something like "val a = foo {a.bar()}"
|
|
||||||
// TODO : a risk of a memory leak
|
// TODO : a risk of a memory leak
|
||||||
LazyValue<JetType> lazyValue = new LazyValue<JetType>() {
|
LazyValue<JetType> lazyValue = new LazyValue<JetType>() {
|
||||||
@Override
|
@Override
|
||||||
@@ -400,16 +421,15 @@ public class ClassDescriptorResolver {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
if (allowDeferred) {
|
if (allowDeferred) {
|
||||||
type = new DeferredType(lazyValue);
|
return new DeferredType(lazyValue);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
type = lazyValue.get();
|
return lazyValue.get();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
type = typeResolver.resolveType(scope, propertyTypeRef);
|
return typeResolver.resolveType(scope, propertyTypeRef);
|
||||||
}
|
}
|
||||||
return type;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@@ -551,10 +571,11 @@ public class ClassDescriptorResolver {
|
|||||||
AnnotationResolver.INSTANCE.resolveAnnotations(modifierList),
|
AnnotationResolver.INSTANCE.resolveAnnotations(modifierList),
|
||||||
resolveModifiers(modifierList, DEFAULT_MODIFIERS),
|
resolveModifiers(modifierList, DEFAULT_MODIFIERS),
|
||||||
isMutable,
|
isMutable,
|
||||||
|
null,
|
||||||
name == null ? "<no name>" : name,
|
name == null ? "<no name>" : name,
|
||||||
isMutable ? type : null,
|
isMutable ? type : null,
|
||||||
type);
|
type);
|
||||||
propertyDescriptor.initialize(null, null);
|
propertyDescriptor.initialize(Collections.<TypeParameterDescriptor>emptyList(), null, null);
|
||||||
trace.recordValueParameterAsPropertyResolution(parameter, propertyDescriptor);
|
trace.recordValueParameterAsPropertyResolution(parameter, propertyDescriptor);
|
||||||
return propertyDescriptor;
|
return propertyDescriptor;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -92,6 +92,7 @@ public class JavaClassMembersScope implements JetScope {
|
|||||||
Collections.<Annotation>emptyList(),
|
Collections.<Annotation>emptyList(),
|
||||||
new MemberModifiers(false, false, false),
|
new MemberModifiers(false, false, false),
|
||||||
!isFinal,
|
!isFinal,
|
||||||
|
null,
|
||||||
field.getName(),
|
field.getName(),
|
||||||
isFinal ? null : type,
|
isFinal ? null : type,
|
||||||
type);
|
type);
|
||||||
|
|||||||
@@ -100,7 +100,13 @@ public class ErrorUtils {
|
|||||||
|
|
||||||
private static final JetType ERROR_PROPERTY_TYPE = createErrorType("<ERROR PROPERTY TYPE>");
|
private static final JetType ERROR_PROPERTY_TYPE = createErrorType("<ERROR PROPERTY TYPE>");
|
||||||
private static final VariableDescriptor ERROR_PROPERTY = new PropertyDescriptor(
|
private static final VariableDescriptor ERROR_PROPERTY = new PropertyDescriptor(
|
||||||
ERROR_CLASS, Collections.<Annotation>emptyList(), new MemberModifiers(false, false, false), true, "<ERROR PROPERTY>", ERROR_PROPERTY_TYPE, ERROR_PROPERTY_TYPE);
|
ERROR_CLASS,
|
||||||
|
Collections.<Annotation>emptyList(),
|
||||||
|
new MemberModifiers(false, false, false),
|
||||||
|
true,
|
||||||
|
null,
|
||||||
|
"<ERROR PROPERTY>",
|
||||||
|
ERROR_PROPERTY_TYPE, ERROR_PROPERTY_TYPE);
|
||||||
|
|
||||||
private static FunctionDescriptor createErrorFunction(List<TypeParameterDescriptor> typeParameters, List<JetType> positionedValueArgumentTypes) {
|
private static FunctionDescriptor createErrorFunction(List<TypeParameterDescriptor> typeParameters, List<JetType> positionedValueArgumentTypes) {
|
||||||
FunctionDescriptorImpl functionDescriptor = new FunctionDescriptorImpl(ERROR_CLASS, Collections.<Annotation>emptyList(), "<ERROR FUNCTION>");
|
FunctionDescriptorImpl functionDescriptor = new FunctionDescriptorImpl(ERROR_CLASS, Collections.<Annotation>emptyList(), "<ERROR FUNCTION>");
|
||||||
|
|||||||
@@ -883,8 +883,6 @@ public class JetTypeInferrer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitTupleExpression(JetTupleExpression expression) {
|
public void visitTupleExpression(JetTupleExpression expression) {
|
||||||
List<JetExpression> entries = expression.getEntries();
|
List<JetExpression> entries = expression.getEntries();
|
||||||
@@ -1019,7 +1017,10 @@ public class JetTypeInferrer {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitWhenConditionIsPattern(JetWhenConditionIsPattern condition) {
|
public void visitWhenConditionIsPattern(JetWhenConditionIsPattern condition) {
|
||||||
checkPatternType(condition.getPattern(), finalSubjectType);
|
JetPattern pattern = condition.getPattern();
|
||||||
|
if (pattern != null) {
|
||||||
|
checkPatternType(pattern, finalSubjectType);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -1,9 +1,12 @@
|
|||||||
package org.jetbrains.jet.resolve;
|
package org.jetbrains.jet.resolve;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.jet.lang.descriptors.*;
|
import org.jetbrains.jet.lang.descriptors.*;
|
||||||
import org.jetbrains.jet.lang.types.*;
|
import org.jetbrains.jet.lang.types.*;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -89,8 +92,18 @@ public class DescriptorRenderer {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Void visitVariableDescriptor(VariableDescriptor descriptor, StringBuilder builder) {
|
public Void visitVariableDescriptor(VariableDescriptor descriptor, StringBuilder builder) {
|
||||||
JetType outType = descriptor.getOutType();
|
String typeString = renderPropertyPrefixAndComputeTypeString(builder, Collections.<TypeParameterDescriptor>emptyList(), null, descriptor.getOutType(), descriptor.getInType());
|
||||||
JetType inType = descriptor.getInType();
|
renderName(descriptor, builder);
|
||||||
|
builder.append(" : ").append(escape(typeString));
|
||||||
|
return super.visitVariableDescriptor(descriptor, builder);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String renderPropertyPrefixAndComputeTypeString(
|
||||||
|
@NotNull StringBuilder builder,
|
||||||
|
@NotNull List<TypeParameterDescriptor> typeParameters,
|
||||||
|
@Nullable JetType receiverType,
|
||||||
|
@Nullable JetType outType,
|
||||||
|
@Nullable JetType inType) {
|
||||||
String typeString = lt() + "no type>";
|
String typeString = lt() + "no type>";
|
||||||
if (inType != null && outType != null) {
|
if (inType != null && outType != null) {
|
||||||
builder.append(renderKeyword("var")).append(" ");
|
builder.append(renderKeyword("var")).append(" ");
|
||||||
@@ -109,9 +122,26 @@ public class DescriptorRenderer {
|
|||||||
builder.append(lt()).append("write-only> ");
|
builder.append(lt()).append("write-only> ");
|
||||||
typeString = inType.toString();
|
typeString = inType.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
renderTypeParameters(typeParameters, builder);
|
||||||
|
|
||||||
|
if (receiverType != null) {
|
||||||
|
builder.append(escape(receiverType.toString())).append(".");
|
||||||
|
}
|
||||||
|
|
||||||
|
return typeString;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Void visitPropertyDescriptor(PropertyDescriptor descriptor, StringBuilder builder) {
|
||||||
|
String typeString = renderPropertyPrefixAndComputeTypeString(
|
||||||
|
builder, descriptor.getTypeParemeters(),
|
||||||
|
descriptor.getReceiverType(),
|
||||||
|
descriptor.getOutType(),
|
||||||
|
descriptor.getInType());
|
||||||
renderName(descriptor, builder);
|
renderName(descriptor, builder);
|
||||||
builder.append(" : ").append(escape(typeString));
|
builder.append(" : ").append(escape(typeString));
|
||||||
return super.visitVariableDescriptor(descriptor, builder);
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -119,9 +149,6 @@ public class DescriptorRenderer {
|
|||||||
builder.append(renderKeyword("fun")).append(" ");
|
builder.append(renderKeyword("fun")).append(" ");
|
||||||
List<TypeParameterDescriptor> typeParameters = descriptor.getTypeParameters();
|
List<TypeParameterDescriptor> typeParameters = descriptor.getTypeParameters();
|
||||||
renderTypeParameters(typeParameters, builder);
|
renderTypeParameters(typeParameters, builder);
|
||||||
if (!typeParameters.isEmpty()) {
|
|
||||||
builder.append(" ");
|
|
||||||
}
|
|
||||||
|
|
||||||
JetType receiverType = descriptor.getReceiverType();
|
JetType receiverType = descriptor.getReceiverType();
|
||||||
if (receiverType != null) {
|
if (receiverType != null) {
|
||||||
@@ -151,7 +178,7 @@ public class DescriptorRenderer {
|
|||||||
builder.append(", ");
|
builder.append(", ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
builder.append(">");
|
builder.append("> ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user