提交 3e0141ad 编写于 作者: A Andrey Breslav

Correct descriptors for properties with receivers

上级 805123f4
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
......
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("> ");
}
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册