Property resolution
This commit is contained in:
@@ -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)) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
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);
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,17 @@
|
||||
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
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
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 getType() {
|
||||
return type;
|
||||
public JetType getOutType() {
|
||||
return outType;
|
||||
}
|
||||
|
||||
@Override
|
||||
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));
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user