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