提交 cd339fbb 编写于 作者: A Andrey Breslav

Property resolution

上级 3ba947da
......@@ -24,6 +24,10 @@ public class JetProperty extends JetNamedDeclaration {
visitor.visitProperty(this);
}
public boolean isVar() {
return getNode().findChildByType(JetTokens.VAR_KEYWORD) != null;
}
@Nullable
public JetTypeReference getReceiverTypeRef() {
ASTNode node = getNode().getFirstChildNode();
......
......@@ -193,9 +193,10 @@ public class ClassDescriptorResolver {
JetParameter valueParameter = valueParameters.get(i);
JetTypeReference typeReference = valueParameter.getTypeReference();
String name = valueParameter.getName();
JetType type;
if (typeReference == null) {
semanticServices.getErrorHandler().genericError(valueParameter.getNode(), "A type annotation is required on a value parameter " + valueParameter.getName());
semanticServices.getErrorHandler().genericError(valueParameter.getNode(), "A type annotation is required on a value parameter");
type = ErrorType.createErrorType("Type annotation was missing");
} else {
type = typeResolver.resolveType(parameterScope, typeReference);
......@@ -204,7 +205,7 @@ public class ClassDescriptorResolver {
functionDescriptor,
i,
AttributeResolver.INSTANCE.resolveAttributes(valueParameter.getModifierList()),
valueParameter.getName(),
name == null ? "<no name provided>" : name,
type,
valueParameter.getDefaultValue() != null,
false // TODO : varargs
......@@ -280,6 +281,7 @@ public class ClassDescriptorResolver {
containingDeclaration,
AttributeResolver.INSTANCE.resolveAttributes(parameter.getModifierList()),
parameter.getName(),
type, // TODO
type);
}
......@@ -305,6 +307,7 @@ public class ClassDescriptorResolver {
containingDeclaration,
AttributeResolver.INSTANCE.resolveAttributes(property.getModifierList()),
property.getName(),
property.isVar() ? type : null,
type);
}
......
......@@ -61,7 +61,7 @@ public class OverloadResolver {
// possibly an array/list/etc passed as a whole vararg
for (int i = 0, positionedValueArgumentTypesSize = positionedValueArgumentTypes.size(); i < positionedValueArgumentTypesSize; i++) {
JetType argumentType = positionedValueArgumentTypes.get(i);
JetType parameterType = parameters.get(i).getType();
JetType parameterType = parameters.get(i).getOutType();
// TODO : handle vararg cases here
if (!typeChecker.isConvertibleTo(argumentType, parameterType)) {
continue descLoop;
......@@ -72,12 +72,12 @@ public class OverloadResolver {
int nonVarargs = parameters.size() - 1;
for (int i = 0; i < nonVarargs; i++) {
JetType argumentType = positionedValueArgumentTypes.get(i);
JetType parameterType = parameters.get(i).getType();
JetType parameterType = parameters.get(i).getOutType();
if (!typeChecker.isConvertibleTo(argumentType, parameterType)) {
continue descLoop;
}
}
JetType varArgType = parameters.get(nonVarargs).getType();
JetType varArgType = parameters.get(nonVarargs).getOutType();
for (int i = nonVarargs, args = positionedValueArgumentTypes.size(); i < args; i++) {
JetType argumentType = positionedValueArgumentTypes.get(i);
if (!typeChecker.isConvertibleTo(argumentType, varArgType)) {
......@@ -137,8 +137,8 @@ public class OverloadResolver {
int fSize = fParams.size();
if (fSize != gParams.size()) return false;
for (int i = 0; i < fSize; i++) {
JetType fParamType = fParams.get(i).getType();
JetType gParamType = gParams.get(i).getType();
JetType fParamType = fParams.get(i).getOutType();
JetType gParamType = gParams.get(i).getOutType();
// TODO : maybe isSubtypeOf is sufficient?
if (!typeChecker.isConvertibleTo(fParamType, gParamType)) {
......
package org.jetbrains.jet.lang.resolve;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.types.*;
import java.util.Map;
......@@ -24,7 +25,26 @@ public class SubstitutingScope implements JetScope {
if (property == null || substitutionContext.isEmpty()) {
return property;
}
return new LazySubstitutedPropertyDescriptorImpl(property, substitutionContext);
JetType inType = substitute(property.getInType(), Variance.IN_VARIANCE);
JetType outType = substitute(property.getOutType(), Variance.OUT_VARIANCE);
if (inType == null && outType == null) {
return null; // TODO : tell the user that the property was projected out
}
return new PropertyDescriptorImpl(
property.getContainingDeclaration(),
property.getAttributes(), // TODO
property.getName(),
inType,
outType
);
}
@Nullable
private JetType substitute(@Nullable JetType originalType, @NotNull Variance variance) {
if (originalType == null) return null;
return TypeSubstitutor.INSTANCE.substitute(substitutionContext, originalType, variance);
}
@Override
......
......@@ -49,11 +49,13 @@ public class JavaClassMembersScope implements JetScope {
return null;
}
JetType type = semanticServices.getTypeTransformer().transform(field.getType());
PropertyDescriptorImpl propertyDescriptor = new PropertyDescriptorImpl(
containingDeclaration,
Collections.<Attribute>emptyList(),
field.getName(),
semanticServices.getTypeTransformer().transform(field.getType()));
field.hasModifierProperty(PsiModifier.FINAL) ? null : type,
type);
semanticServices.getTrace().recordDeclarationResolution(field, propertyDescriptor);
return propertyDescriptor;
}
......
......@@ -157,11 +157,12 @@ public class JavaDescriptorResolver {
List<ValueParameterDescriptor> result = new ArrayList<ValueParameterDescriptor>();
for (int i = 0, parametersLength = parameters.length; i < parametersLength; i++) {
PsiParameter parameter = parameters[i];
String name = parameter.getName();
result.add(new ValueParameterDescriptorImpl(
containingDeclaration,
i,
Collections.<Attribute>emptyList(), // TODO
parameter.getName(),
name == null ? "p" + i : name,
semanticServices.getTypeTransformer().transform(parameter.getType()),
false,
parameter.isVarArgs()
......
......@@ -20,6 +20,7 @@ public abstract class DeclarationDescriptorImpl extends AnnotatedImpl implements
this.containingDeclaration = containingDeclaration;
}
@NotNull
@Override
public String getName() {
return name;
......
......@@ -86,7 +86,9 @@ public class ErrorType {
return ERROR_SCOPE;
}
private static final PropertyDescriptor ERROR_PROPERTY = new PropertyDescriptorImpl(ERROR_CLASS, Collections.<Attribute>emptyList(), "<ERROR PROPERTY>", createErrorType("<ERROR PROPERTY TYPE>"));
private static final JetType ERROR_PROPERTY_TYPE = createErrorType("<ERROR PROPERTY TYPE>");
private static final PropertyDescriptor ERROR_PROPERTY = new PropertyDescriptorImpl(
ERROR_CLASS, Collections.<Attribute>emptyList(), "<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.<Attribute>emptyList(), "<ERROR FUNCTION>");
......
......@@ -61,7 +61,7 @@ public class FunctionDescriptorUtil {
for (int i = 0, unsubstitutedValueParametersSize = unsubstitutedValueParameters.size(); i < unsubstitutedValueParametersSize; i++) {
ValueParameterDescriptor unsubstitutedValueParameter = unsubstitutedValueParameters.get(i);
// TODO : Lazy?
JetType substitutedType = TypeSubstitutor.INSTANCE.substitute(substitutionContext, unsubstitutedValueParameter.getType(), Variance.IN_VARIANCE);
JetType substitutedType = TypeSubstitutor.INSTANCE.substitute(substitutionContext, unsubstitutedValueParameter.getOutType(), Variance.IN_VARIANCE);
if (substitutedType == null) return null;
result.add(new ValueParameterDescriptorImpl(
substitutedDescriptor,
......
......@@ -289,7 +289,7 @@ public class JetStandardClasses {
private static List<JetType> toTypes(List<ValueParameterDescriptor> labeledEntries) {
List<JetType> result = new ArrayList<JetType>();
for (ValueParameterDescriptor entry : labeledEntries) {
result.add(entry.getType());
result.add(entry.getOutType());
}
return result;
}
......
......@@ -334,7 +334,7 @@ public class JetTypeInferrer {
PropertyDescriptor property = scope.getProperty(referencedName);
if (property != null) {
trace.recordReferenceResolution(expression, property);
result = property.getType();
result = property.getOutType();
return;
} else {
NamespaceDescriptor namespace = scope.getNamespace(referencedName);
......@@ -377,7 +377,7 @@ public class JetTypeInferrer {
}
PropertyDescriptor propertyDescriptor = classDescriptorResolver.resolvePropertyDescriptor(functionDescriptor, scope, parameter);
parameterDescriptors.put(parameter.getName(), propertyDescriptor);
parameterTypes.add(propertyDescriptor.getType());
parameterTypes.add(propertyDescriptor.getOutType());
}
JetType returnType;
if (returnTypeRef != null) {
......@@ -642,7 +642,7 @@ public class JetTypeInferrer {
PropertyDescriptor propertyDescriptor;
if (typeReference != null) {
propertyDescriptor = semanticServices.getClassDescriptorResolver(trace).resolvePropertyDescriptor(scope.getContainingDeclaration(), scope, loopParameter);
JetType actualParameterType = propertyDescriptor.getType();
JetType actualParameterType = propertyDescriptor.getOutType();
if (expectedParameterType != null &&
!semanticServices.getTypeChecker().isSubtypeOf(expectedParameterType, actualParameterType)) {
semanticServices.getErrorHandler().genericError(typeReference.getNode(), "The loop iterates over values of type " + expectedParameterType + " but the parameter is declared to be " + actualParameterType);
......
package org.jetbrains.jet.lang.types;
import org.jetbrains.annotations.NotNull;
import java.util.List;
import java.util.Map;
/**
* @author abreslav
*/
public class LazySubstitutedPropertyDescriptorImpl implements PropertyDescriptor {
private final PropertyDescriptor propertyDescriptor;
private final Map<TypeConstructor, TypeProjection> substitutionContext;
private JetType propertyType = null;
public LazySubstitutedPropertyDescriptorImpl(@NotNull PropertyDescriptor propertyDescriptor, @NotNull Map<TypeConstructor, TypeProjection> substitutionContext) {
this.propertyDescriptor = propertyDescriptor;
this.substitutionContext = substitutionContext;
}
@Override
public JetType getType() {
if (propertyType == null) {
propertyType = TypeSubstitutor.INSTANCE.safeSubstitute(substitutionContext, propertyDescriptor.getType(), Variance.OUT_VARIANCE);
}
return propertyType;
}
@Override
public List<Attribute> getAttributes() {
// TODO : Substitute, lazily
return propertyDescriptor.getAttributes();
}
@Override
public String getName() {
return propertyDescriptor.getName();
}
@NotNull
@Override
public DeclarationDescriptor getOriginal() {
return propertyDescriptor.getOriginal();
}
@NotNull
@Override
public DeclarationDescriptor getContainingDeclaration() {
return propertyDescriptor.getContainingDeclaration();
}
@Override
public <R, D> R accept(DeclarationDescriptorVisitor<R, D> visitor, D data) {
return visitor.visitPropertyDescriptor(this, data);
}
@Override
public void acceptVoid(DeclarationDescriptorVisitor<Void, Void> visitor) {
accept(visitor, null);
}
}
package org.jetbrains.jet.lang.types;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* @author abreslav
*/
public interface PropertyDescriptor extends DeclarationDescriptor {
JetType getType();
@Nullable
JetType getOutType();
@Nullable
JetType getInType();
@Override
@NotNull
......
package org.jetbrains.jet.lang.types;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
......@@ -8,16 +9,30 @@ import java.util.List;
* @author abreslav
*/
public class PropertyDescriptorImpl extends DeclarationDescriptorImpl implements PropertyDescriptor {
private JetType type;
private final JetType inType;
private final JetType outType;
public PropertyDescriptorImpl(@NotNull DeclarationDescriptor containingDeclaration, List<Attribute> attributes, String name, JetType type) {
public PropertyDescriptorImpl(
@NotNull DeclarationDescriptor containingDeclaration,
@NotNull List<Attribute> attributes,
@NotNull String name,
@Nullable JetType inType,
@Nullable JetType outType) {
super(containingDeclaration, attributes, name);
this.type = type;
assert (inType != null) || (outType != null);
this.inType = inType;
this.outType = outType;
}
@Override
public JetType getOutType() {
return outType;
}
@Override
public JetType getType() {
return type;
public JetType getInType() {
return inType;
}
@Override
......
......@@ -12,8 +12,15 @@ public class ValueParameterDescriptorImpl extends PropertyDescriptorImpl impleme
private final boolean isVararg;
private final int index;
public ValueParameterDescriptorImpl(@NotNull DeclarationDescriptor containingDeclaration, int index, List<Attribute> attributes, String name, JetType type, boolean hasDefaultValue, boolean isVararg) {
super(containingDeclaration, attributes, name, type);
public ValueParameterDescriptorImpl(
@NotNull DeclarationDescriptor containingDeclaration,
int index,
@NotNull List<Attribute> attributes,
@NotNull String name,
@NotNull JetType type,
boolean hasDefaultValue,
boolean isVararg) {
super(containingDeclaration, attributes, name, type, type); // TODO : writable?
this.index = index;
this.hasDefaultValue = hasDefaultValue;
this.isVararg = isVararg;
......
......@@ -15,7 +15,7 @@ public class DescriptorUtil {
new DeclarationDescriptorVisitor<Void, StringBuilder>() {
@Override
public Void visitPropertyDescriptor(PropertyDescriptor descriptor, StringBuilder builder) {
JetType type = descriptor.getType();
JetType type = descriptor.getOutType();
builder.append(renderName(descriptor)).append(" : ").append(type);
return super.visitPropertyDescriptor(descriptor, builder);
}
......
......@@ -36,7 +36,7 @@ import util.*
}
~Foo~class Foo {
~set1~fun set(i : Int, val : String) {}
~set1~fun set(i : Int, val1 : String) {}
~get1~fun get(i : Int) : Int {}
~get2~fun get(i : Int, j : Int) : String {}
~get3~fun get(i : Object) : Any {return i }
......
......@@ -99,7 +99,7 @@ public class JetResolveTest extends ExtensibleResolveTestCase {
List<ValueParameterDescriptor> unsubstitutedValueParameters = function.getUnsubstitutedValueParameters();
for (int i = 0, unsubstitutedValueParametersSize = unsubstitutedValueParameters.size(); i < unsubstitutedValueParametersSize; i++) {
ValueParameterDescriptor unsubstitutedValueParameter = unsubstitutedValueParameters.get(i);
if (unsubstitutedValueParameter.getType().equals(parameterType[i])) {
if (unsubstitutedValueParameter.getOutType().equals(parameterType[i])) {
return function;
}
}
......
......@@ -333,7 +333,7 @@ public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase {
assertType("new Props<out Int>().p", "Int");
assertType("new Props<Properties>().p.p", "Int");
assertErrorType("new Props<in Int>().p");
assertErrorType("(return : Props<in Int>).p");
}
public void testOverloads() throws Exception {
......@@ -449,7 +449,7 @@ public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase {
private void assertErrorType(String expression) {
Project project = getProject();
JetExpression jetExpression = JetChangeUtil.createExpression(project, expression);
JetType type = semanticServices.getTypeInferrer(BindingTrace.DUMMY).getType(classDefinitions.BASIC_SCOPE, jetExpression, false);
JetType type = semanticServices.getTypeInferrer(BindingTrace.DUMMY).safeGetType(classDefinitions.BASIC_SCOPE, jetExpression, false);
assertTrue("Error type expected but " + type + " returned", ErrorType.isErrorType(type));
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册