Resolve framework refactored

This commit is contained in:
Andrey Breslav
2011-02-11 17:20:39 +03:00
parent 019fee5cb7
commit 864428f345
20 changed files with 330 additions and 333 deletions
@@ -1,27 +0,0 @@
package org.jetbrains.jet.lang.modules;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.types.ClassDescriptor;
import org.jetbrains.jet.lang.types.ExtensionDescriptor;
import org.jetbrains.jet.lang.types.MethodDescriptor;
import org.jetbrains.jet.lang.types.PropertyDescriptor;
import java.util.Collection;
/**
* @author abreslav
*/
public interface MemberDomain {
@NotNull
Collection<MethodDescriptor> getMethods(String name);
@Nullable
ClassDescriptor getClass(String name);
@Nullable
PropertyDescriptor getProperty(String name);
@Nullable
ExtensionDescriptor getExtension(String name);
}
@@ -30,75 +30,44 @@ public class ClassDescriptorResolver {
? Collections.singleton(JetStandardClasses.getAnyType())
: resolveTypes(typeParameterScope, delegationSpecifiers);
boolean open = classElement.hasModifier(JetTokens.OPEN_KEYWORD);
WritableScope members = resolveMembers(classElement, typeParameters, scope, typeParameterScope, superclasses);
return new ClassDescriptor(
AttributeResolver.INSTANCE.resolveAttributes(classElement.getModifierList()),
!open,
classElement.getName(),
typeParameters,
superclasses,
resolveMemberDomain(classElement, scope, typeParameterScope, superclasses)
members
);
}
private TypeMemberDomain resolveMemberDomain(
private WritableScope resolveMembers(
final JetClass classElement,
List<TypeParameterDescriptor> typeParameters,
final JetScope outerScope,
final TypeParameterExtensibleScope typeParameterScope,
final Collection<? extends Type> supertypes) {
// TODO : Cache!!!
return new TypeMemberDomain() {
@Override
public PropertyDescriptor getProperty(Type contextType, @NotNull String name) {
// TODO : primary constructor parameters
List<JetDeclaration> declarations = classElement.getDeclarations();
for (JetDeclaration declaration : declarations) {
if (!name.equals(declaration.getName())) {
continue;
}
if (declaration instanceof JetProperty) {
JetProperty property = (JetProperty) declaration;
if (property.getPropertyTypeRef() != null) {
return substituteInPropertyDescriptor(contextType, resolvePropertyDescriptor(typeParameterScope, property));
} else {
// TODO : Caution: a cyclic dependency possible
throw new UnsupportedOperationException();
}
}
WritableScope memberDeclarations = new WritableScope();
List<JetDeclaration> declarations = classElement.getDeclarations();
for (JetDeclaration declaration : declarations) {
if (declaration instanceof JetProperty) {
JetProperty property = (JetProperty) declaration;
if (property.getPropertyTypeRef() != null) {
memberDeclarations.addPropertyDescriptor(resolvePropertyDescriptor(typeParameterScope, property));
} else {
// TODO : Caution: a cyclic dependency possible
throw new UnsupportedOperationException();
}
for (Type supertype : supertypes) {
PropertyDescriptor property = supertype.getMemberDomain().getProperty(JetTypeChecker.INSTANCE.substitute(contextType, supertype, Variance.INVARIANT), name);
if (property != null) {
return property;
}
}
return null;
}
@Override
public ClassDescriptor getClassDescriptor(@NotNull Type contextType, String name) {
} else {
throw new UnsupportedOperationException(); // TODO
}
@NotNull
@Override
public Collection<MethodDescriptor> getMethods(Type contextType, String name) {
throw new UnsupportedOperationException(); // TODO
}
@Override
public ExtensionDescriptor getExtension(Type contextType, String name) {
throw new UnsupportedOperationException(); // TODO
}
};
}
private PropertyDescriptor substituteInPropertyDescriptor(Type contextType, PropertyDescriptor propertyDescriptor) {
if (contextType.getConstructor().getParameters().isEmpty()) {
return propertyDescriptor;
}
return new LazySubstitutedPropertyDescriptorImpl(propertyDescriptor, contextType);
return memberDeclarations;
}
private static List<TypeParameterDescriptor> resolveTypeParameters(TypeParameterExtensibleScope extensibleScope, List<JetTypeParameter> typeParameters) {
@@ -2,16 +2,31 @@ package org.jetbrains.jet.lang.resolve;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.modules.MemberDomain;
import org.jetbrains.jet.lang.modules.NamespaceDomain;
import org.jetbrains.jet.lang.types.*;
import java.util.Collection;
/**
* @author abreslav
*/
public interface JetScope extends NamespaceDomain, MemberDomain {
public interface JetScope {
JetScope EMPTY = new JetScopeImpl() {};
@NotNull
Collection<MethodDescriptor> getMethods(String name);
@Nullable
ClassDescriptor getClass(String name);
@Nullable
PropertyDescriptor getProperty(String name);
@Nullable
ExtensionDescriptor getExtension(String name);
@Nullable
NamespaceDescriptor getNamespace(String name);
@Nullable
TypeParameterDescriptor getTypeParameterDescriptor(String name);
@@ -15,7 +15,7 @@ public class ScopeWithReceiver extends JetScopeImpl {
public ScopeWithReceiver(JetScope outerScope, Type receiverType) {
this.outerScope = outerScope;
this.receiverTypeScope = new TypeScope(receiverType);
this.receiverTypeScope = receiverType.getMemberScope();
}
@Override
@@ -0,0 +1,62 @@
package org.jetbrains.jet.lang.resolve;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.types.*;
import java.util.Collection;
import java.util.Map;
/**
* @author abreslav
*/
public class SubstitutingScope implements JetScope {
private final JetScope workerScope;
private final Map<TypeConstructor, TypeProjection> substitutionContext;
public SubstitutingScope(JetScope workerScope, Map<TypeConstructor, TypeProjection> substitutionContext) {
this.workerScope = workerScope;
this.substitutionContext = substitutionContext;
}
@Override
public PropertyDescriptor getProperty(String name) {
PropertyDescriptor property = workerScope.getProperty(name);
if (property == null) {
return null;
}
return new LazySubstitutedPropertyDescriptorImpl(property, substitutionContext);
}
@NotNull
@Override
public Collection<MethodDescriptor> getMethods(String name) {
throw new UnsupportedOperationException(); // TODO
}
@Override
public ClassDescriptor getClass(String name) {
throw new UnsupportedOperationException(); // TODO
}
@Override
public ExtensionDescriptor getExtension(String name) {
throw new UnsupportedOperationException(); // TODO
}
@Override
public NamespaceDescriptor getNamespace(String name) {
throw new UnsupportedOperationException(); // TODO
}
@Override
public TypeParameterDescriptor getTypeParameterDescriptor(String name) {
throw new UnsupportedOperationException(); // TODO
}
@NotNull
@Override
public Type getThisType() {
throw new UnsupportedOperationException(); // TODO
}
}
@@ -36,12 +36,13 @@ public class TypeResolver {
ClassDescriptor classDescriptor = resolveClass(scope, type);
if (classDescriptor != null) {
TypeConstructor typeConstructor = classDescriptor.getTypeConstructor();
List<TypeProjection> arguments = resolveTypeProjections(scope, typeConstructor, type.getTypeArguments());
result[0] = new TypeImpl(
attributes,
typeConstructor,
nullable,
resolveTypeProjections(scope, typeConstructor, type.getTypeArguments()),
classDescriptor.getMemberDomain()
arguments,
classDescriptor.getMemberScope(arguments)
);
}
else if (type.getTypeArguments().isEmpty()) {
@@ -1,53 +0,0 @@
package org.jetbrains.jet.lang.resolve;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.types.*;
import java.util.Collection;
/**
* @author abreslav
*/
public class TypeScope implements JetScope {
private final Type receiverType;
public TypeScope(Type receiverType) {
this.receiverType = receiverType;
}
@Override
public TypeParameterDescriptor getTypeParameterDescriptor(String name) {
return null;
}
@NotNull
@Override
public Type getThisType() {
return receiverType;
}
@Override
public Collection<MethodDescriptor> getMethods(String name) {
return receiverType.getMemberDomain().getMethods(receiverType, name);
}
@Override
public ClassDescriptor getClass(String name) {
return receiverType.getMemberDomain().getClassDescriptor(receiverType, name);
}
@Override
public PropertyDescriptor getProperty(String name) {
return receiverType.getMemberDomain().getProperty(receiverType, name);
}
@Override
public ExtensionDescriptor getExtension(String name) {
return receiverType.getMemberDomain().getExtension(receiverType, name);
}
@Override
public NamespaceDescriptor getNamespace(String name) {
return null;
}
}
@@ -0,0 +1,60 @@
package org.jetbrains.jet.lang.resolve;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.types.*;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
/**
* @author abreslav
*/
public class WritableScope implements JetScope {
private Map<String, PropertyDescriptor> propertyDescriptors;
public void addPropertyDescriptor(PropertyDescriptor propertyDescriptor) {
if (propertyDescriptors == null) {
propertyDescriptors = new HashMap<String, PropertyDescriptor>();
}
assert !propertyDescriptors.containsKey(propertyDescriptor.getName()) : "Property redeclared";
propertyDescriptors.put(propertyDescriptor.getName(), propertyDescriptor);
}
@Override
public PropertyDescriptor getProperty(String name) {
return propertyDescriptors.get(name);
}
@NotNull
@Override
public Collection<MethodDescriptor> getMethods(String name) {
throw new UnsupportedOperationException(); // TODO
}
@Override
public ClassDescriptor getClass(String name) {
throw new UnsupportedOperationException(); // TODO
}
@Override
public ExtensionDescriptor getExtension(String name) {
throw new UnsupportedOperationException(); // TODO
}
@Override
public NamespaceDescriptor getNamespace(String name) {
throw new UnsupportedOperationException(); // TODO
}
@Override
public TypeParameterDescriptor getTypeParameterDescriptor(String name) {
throw new UnsupportedOperationException(); // TODO
}
@NotNull
@Override
public Type getThisType() {
throw new UnsupportedOperationException(); // TODO
}
}
@@ -1,31 +1,34 @@
package org.jetbrains.jet.lang.types;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.resolve.JetScope;
import org.jetbrains.jet.lang.resolve.SubstitutingScope;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
/**
* @author abreslav
*/
public class ClassDescriptor extends MemberDescriptorImpl {
private final TypeConstructor typeConstructor;
private final TypeMemberDomain memberDomain;
private final JetScope memberDeclarations;
public ClassDescriptor(
List<Attribute> attributes, boolean sealed,
String name, List<TypeParameterDescriptor> typeParameters,
Collection<? extends Type> superclasses, TypeMemberDomain memberDomain) {
Collection<? extends Type> superclasses, JetScope memberDeclarations) {
super(attributes, name);
this.typeConstructor = new TypeConstructor(attributes, sealed, name, typeParameters, superclasses);
this.memberDomain = memberDomain;
this.memberDeclarations = memberDeclarations;
}
public ClassDescriptor(String name, TypeMemberDomain memberDomain) {
public ClassDescriptor(String name, JetScope memberDeclarations) {
this(Collections.<Attribute>emptyList(), true,
name, Collections.<TypeParameterDescriptor>emptyList(),
Collections.<Type>singleton(JetStandardClasses.getAnyType()), memberDomain);
Collections.<Type>singleton(JetStandardClasses.getAnyType()), memberDeclarations);
}
@NotNull
@@ -33,12 +36,8 @@ public class ClassDescriptor extends MemberDescriptorImpl {
return typeConstructor;
}
public TypeMemberDomain getMemberDomain() {
return memberDomain;
public JetScope getMemberScope(List<TypeProjection> typeArguments) {
Map<TypeConstructor,TypeProjection> substitutionContext = TypeSubstitutor.INSTANCE.buildSubstitutionContext(typeConstructor.getParameters(), typeArguments);
return new SubstitutingScope(memberDeclarations, substitutionContext);
}
public ClassDescriptor getClass(String referencedName) {
throw new UnsupportedOperationException(); // TODO
}
}
@@ -1,6 +1,7 @@
package org.jetbrains.jet.lang.types;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.resolve.JetScope;
import java.util.Collection;
import java.util.Collections;
@@ -10,25 +11,41 @@ import java.util.List;
* @author abreslav
*/
public class ErrorType {
private static final TypeMemberDomain ERROR_DOMAIN = new TypeMemberDomain() {
private static final JetScope ERROR_SCOPE = new JetScope() {
@NotNull
@Override
public ClassDescriptor getClassDescriptor(@NotNull Type contextType, String name) {
public Collection<MethodDescriptor> getMethods(String name) {
throw new UnsupportedOperationException(); // TODO
}
@Override
public ClassDescriptor getClass(String name) {
throw new UnsupportedOperationException(); // TODO
}
@Override
public PropertyDescriptor getProperty(String name) {
throw new UnsupportedOperationException(); // TODO
}
@Override
public ExtensionDescriptor getExtension(String name) {
throw new UnsupportedOperationException(); // TODO
}
@Override
public NamespaceDescriptor getNamespace(String name) {
throw new UnsupportedOperationException(); // TODO
}
@Override
public TypeParameterDescriptor getTypeParameterDescriptor(String name) {
throw new UnsupportedOperationException(); // TODO
}
@NotNull
@Override
public Collection<MethodDescriptor> getMethods(Type contextType, String name) {
throw new UnsupportedOperationException(); // TODO
}
@Override
public PropertyDescriptor getProperty(Type contextType, String name) {
throw new UnsupportedOperationException(); // TODO
}
@Override
public ExtensionDescriptor getExtension(Type contextType, String name) {
public Type getThisType() {
throw new UnsupportedOperationException(); // TODO
}
};
@@ -36,15 +53,15 @@ public class ErrorType {
private ErrorType() {}
public static Type createErrorType(String debugMessage) {
return createErrorType(debugMessage, ERROR_DOMAIN);
return createErrorType(debugMessage, ERROR_SCOPE);
}
private static Type createErrorType(String debugMessage, TypeMemberDomain memberDomain) {
return new ErrorTypeImpl(new TypeConstructor(Collections.<Attribute>emptyList(), false, "[ERROR : " + debugMessage + "]", Collections.<TypeParameterDescriptor>emptyList(), Collections.<Type>emptyList()), memberDomain);
private static Type createErrorType(String debugMessage, JetScope memberScope) {
return new ErrorTypeImpl(new TypeConstructor(Collections.<Attribute>emptyList(), false, "[ERROR : " + debugMessage + "]", Collections.<TypeParameterDescriptor>emptyList(), Collections.<Type>emptyList()), memberScope);
}
public static Type createWrongVarianceErrorType(TypeProjection value) {
return createErrorType(value + " is not allowed here]", value.getType().getMemberDomain());
return createErrorType(value + " is not allowed here]", value.getType().getMemberScope());
}
public static boolean isErrorType(Type type) {
@@ -54,11 +71,11 @@ public class ErrorType {
private static class ErrorTypeImpl implements Type {
private final TypeConstructor constructor;
private final TypeMemberDomain memberDomain;
private final JetScope memberScope;
private ErrorTypeImpl(TypeConstructor constructor, TypeMemberDomain memberDomain) {
private ErrorTypeImpl(TypeConstructor constructor, JetScope memberScope) {
this.constructor = constructor;
this.memberDomain = memberDomain;
this.memberScope = memberScope;
}
@NotNull
@@ -80,8 +97,8 @@ public class ErrorType {
@NotNull
@Override
public TypeMemberDomain getMemberDomain() {
return memberDomain;
public JetScope getMemberScope() {
return memberScope;
}
@Override
@@ -4,6 +4,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.resolve.JetScope;
import org.jetbrains.jet.lang.resolve.JetScopeImpl;
import org.jetbrains.jet.lang.resolve.WritableScope;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
@@ -34,7 +35,7 @@ public class JetStandardClasses {
public int size() {
throw new UnsupportedOperationException();
}
}, TypeMemberDomain.EMPTY
}, JetScope.EMPTY
);
private static final ClassDescriptor ANY = new ClassDescriptor(
@@ -43,33 +44,12 @@ public class JetStandardClasses {
"Any",
Collections.<TypeParameterDescriptor>emptyList(),
Collections.<Type>emptySet(),
TypeMemberDomain.EMPTY
JetScope.EMPTY
);
public static final TypeMemberDomain STUB = new TypeMemberDomain() {
@Override
public ClassDescriptor getClassDescriptor(@NotNull Type contextType, String name) {
throw new UnsupportedOperationException(); // TODO
}
public static final JetScope STUB = JetScope.EMPTY;
@NotNull
@Override
public Collection<MethodDescriptor> getMethods(Type contextType, String name) {
throw new UnsupportedOperationException(); // TODO
}
@Override
public PropertyDescriptor getProperty(Type contextType, String name) {
throw new UnsupportedOperationException(); // TODO
}
@Override
public ExtensionDescriptor getExtension(Type contextType, String name) {
throw new UnsupportedOperationException(); // TODO
}
};
private static final Type ANY_TYPE = new TypeImpl(ANY.getTypeConstructor(), TypeMemberDomain.EMPTY);
private static final Type ANY_TYPE = new TypeImpl(ANY.getTypeConstructor(), JetScope.EMPTY);
private static final Type NULLABLE_ANY_TYPE = TypeUtils.makeNullable(ANY_TYPE);
private static final ClassDescriptor BYTE = new ClassDescriptor("Byte", STUB);
@@ -157,7 +137,7 @@ public class JetStandardClasses {
getNothing().getTypeConstructor(),
true,
Collections.<TypeProjection>emptyList(),
TypeMemberDomain.EMPTY);
JetScope.EMPTY);
private static final Map<String, ClassDescriptor> CLASS_MAP = new HashMap<String, ClassDescriptor>();
static {
@@ -233,9 +233,10 @@ public class JetTypeChecker {
JetUserType typeElement = (JetUserType) superTypeQualifier.getTypeElement();
ClassDescriptor superclass = TypeResolver.INSTANCE.resolveClass(scope, typeElement);
Collection<? extends Type> supertypes = thisType.getConstructor().getSupertypes();
Map<TypeConstructor, TypeProjection> substitutionContext = TypeSubstitutor.INSTANCE.getSubstitutionContext(thisType);
for (Type declaredSupertype : supertypes) {
if (declaredSupertype.getConstructor().equals(superclass.getTypeConstructor())) {
result[0] = substituteInType(getSubstitutionContext(thisType), declaredSupertype, Variance.INVARIANT);
result[0] = TypeSubstitutor.INSTANCE.substitute(substitutionContext, declaredSupertype, Variance.INVARIANT);
break;
}
}
@@ -515,13 +516,13 @@ public class JetTypeChecker {
return;
}
handler.beforeChildren(current);
Map<TypeConstructor, TypeProjection> substitutionContext = getSubstitutionContext(current);
Map<TypeConstructor, TypeProjection> substitutionContext = TypeSubstitutor.INSTANCE.getSubstitutionContext(current);
for (Type supertype : current.getConstructor().getSupertypes()) {
TypeConstructor supertypeConstructor = supertype.getConstructor();
if (visited.contains(supertypeConstructor)) {
continue;
}
Type substitutedSupertype = substituteInType(substitutionContext, supertype, Variance.INVARIANT);
Type substitutedSupertype = TypeSubstitutor.INSTANCE.substitute(substitutionContext, supertype, Variance.INVARIANT);
dfs(substitutedSupertype, visited, handler);
}
handler.afterChildren(current);
@@ -557,67 +558,12 @@ public class JetTypeChecker {
for (Type immediateSupertype : constructor.getSupertypes()) {
Type correspondingSupertype = findCorrespondingSupertype(immediateSupertype, supertype);
if (correspondingSupertype != null) {
return substituteInType(getSubstitutionContext(subtype), correspondingSupertype, Variance.INVARIANT);
return TypeSubstitutor.INSTANCE.substitute(subtype, correspondingSupertype, Variance.INVARIANT);
}
}
return null;
}
private Map<TypeConstructor, TypeProjection> getSubstitutionContext(Type context) {
Map<TypeConstructor, TypeProjection> parameterValues = new HashMap<TypeConstructor, TypeProjection>();
List<TypeParameterDescriptor> parameters = context.getConstructor().getParameters();
List<TypeProjection> contextArguments = context.getArguments();
for (int i = 0, parametersSize = parameters.size(); i < parametersSize; i++) {
TypeParameterDescriptor parameter = parameters.get(i);
TypeProjection value = contextArguments.get(i);
parameterValues.put(parameter.getTypeConstructor(), value);
}
return parameterValues;
}
private Type substituteInType(Map<TypeConstructor, TypeProjection> substitutionContext, Type type, Variance howThisTypeIsUsed) {
TypeProjection value = substitutionContext.get(type.getConstructor());
if (value != null) {
Variance projectionKind = value.getProjectionKind();
if (howThisTypeIsUsed.allowsInPosition() && !projectionKind.allowsInPosition()
|| howThisTypeIsUsed.allowsOutPosition() && !projectionKind.allowsOutPosition()) {
return ErrorType.createWrongVarianceErrorType(value);
}
return value.getType();
}
return specializeType(type, substituteInArguments(substitutionContext, type));
}
@NotNull
private TypeProjection substitute(Map<TypeConstructor, TypeProjection> parameterValues, TypeProjection subject) {
@NotNull Type subjectType = subject.getType();
TypeProjection value = parameterValues.get(subjectType.getConstructor());
if (value != null) {
return value;
}
List<TypeProjection> newArguments = substituteInArguments(parameterValues, subjectType);
return new TypeProjection(subject.getProjectionKind(), specializeType(subjectType, newArguments));
}
private List<TypeProjection> substituteInArguments(Map<TypeConstructor, TypeProjection> parameterValues, Type subjectType) {
List<TypeProjection> newArguments = new ArrayList<TypeProjection>();
for (TypeProjection argument : subjectType.getArguments()) {
newArguments.add(substitute(parameterValues, argument));
}
return newArguments;
}
@NotNull
public Type substitute(@NotNull Type context, @NotNull Type subject, @NotNull Variance howThisTypeIsUsed) {
return substituteInType(getSubstitutionContext(context), subject, howThisTypeIsUsed);
}
private Type specializeType(Type type, List<TypeProjection> newArguments) {
return new TypeImpl(type.getAttributes(), type.getConstructor(), type.isNullable(), newArguments, type.getMemberDomain());
}
private boolean checkSubtypeForTheSameConstructor(Type subtype, Type supertype) {
TypeConstructor constructor = subtype.getConstructor();
assert constructor.equals(supertype.getConstructor());
@@ -636,7 +582,7 @@ public class JetTypeChecker {
case INVARIANT:
switch (superArgument.getProjectionKind()) {
case INVARIANT:
if (!equalTypes(subArgumentType, superArgumentType)) {
if (!TypeImpl.equalTypes(subArgumentType, superArgumentType)) {
return false;
}
break;
@@ -688,9 +634,4 @@ public class JetTypeChecker {
}
return true;
}
public boolean equalTypes(@NotNull Type type1, @NotNull Type type2) {
return TypeImpl.equalTypes(type1, type2);
}
}
@@ -1,24 +1,27 @@
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 Type contextType;
private final Map<TypeConstructor, TypeProjection> substitutionContext;
private Type propertyType = null;
public LazySubstitutedPropertyDescriptorImpl(PropertyDescriptor propertyDescriptor, Type contextType) {
public LazySubstitutedPropertyDescriptorImpl(@NotNull PropertyDescriptor propertyDescriptor, @NotNull Map<TypeConstructor, TypeProjection> substitutionContext) {
this.propertyDescriptor = propertyDescriptor;
this.contextType = contextType;
this.substitutionContext = substitutionContext;
}
@Override
public Type getType() {
if (propertyType == null) {
propertyType = JetTypeChecker.INSTANCE.substitute(contextType, propertyDescriptor.getType(), Variance.OUT_VARIANCE);
propertyType = TypeSubstitutor.INSTANCE.substitute(substitutionContext, propertyDescriptor.getType(), Variance.OUT_VARIANCE);
}
return propertyType;
}
@@ -1,6 +1,5 @@
package org.jetbrains.jet.lang.types;
import org.jetbrains.jet.lang.modules.MemberDomain;
import org.jetbrains.jet.lang.modules.NamespaceDomain;
import java.util.Collection;
@@ -8,23 +7,19 @@ import java.util.Collection;
/**
* @author abreslav
*/
public class NamespaceDescriptor implements NamespaceDomain, MemberDomain {
@Override
public class NamespaceDescriptor implements NamespaceDomain {
public ClassDescriptor getClass(String name) {
throw new UnsupportedOperationException(); // TODO
}
@Override
public Collection<MethodDescriptor> getMethods(String name) {
throw new UnsupportedOperationException(); // TODO
}
@Override
public PropertyDescriptor getProperty(String name) {
throw new UnsupportedOperationException(); // TODO
}
@Override
public ExtensionDescriptor getExtension(String name) {
throw new UnsupportedOperationException(); // TODO
}
@@ -1,6 +1,7 @@
package org.jetbrains.jet.lang.types;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.resolve.JetScope;
import java.util.List;
@@ -12,5 +13,6 @@ public interface Type extends Annotated {
@NotNull List<TypeProjection> getArguments();
boolean isNullable();
@NotNull TypeMemberDomain getMemberDomain();
@NotNull
JetScope getMemberScope();
}
@@ -1,6 +1,7 @@
package org.jetbrains.jet.lang.types;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.resolve.JetScope;
import java.util.Collections;
import java.util.Iterator;
@@ -14,18 +15,18 @@ public final class TypeImpl extends AnnotatedImpl implements Type {
private final TypeConstructor constructor;
private final List<TypeProjection> arguments;
private final boolean nullable;
private final TypeMemberDomain memberDomain;
private JetScope memberScope;
public TypeImpl(List<Attribute> attributes, TypeConstructor constructor, boolean nullable, List<TypeProjection> arguments, TypeMemberDomain memberDomain) {
public TypeImpl(List<Attribute> attributes, TypeConstructor constructor, boolean nullable, List<TypeProjection> arguments, JetScope memberScope) {
super(attributes);
this.constructor = constructor;
this.nullable = nullable;
this.arguments = arguments;
this.memberDomain = memberDomain;
this.memberScope = memberScope;
}
public TypeImpl(TypeConstructor constructor, TypeMemberDomain memberDomain) {
this(Collections.<Attribute>emptyList(), constructor, false, Collections.<TypeProjection>emptyList(), memberDomain);
public TypeImpl(TypeConstructor constructor, JetScope memberScope) {
this(Collections.<Attribute>emptyList(), constructor, false, Collections.<TypeProjection>emptyList(), memberScope);
}
public TypeImpl(ClassDescriptor classDescriptor) {
@@ -33,7 +34,7 @@ public final class TypeImpl extends AnnotatedImpl implements Type {
classDescriptor.getTypeConstructor(),
false,
Collections.<TypeProjection>emptyList(),
classDescriptor.getMemberDomain());
classDescriptor.getMemberScope(Collections.<TypeProjection>emptyList()));
}
@Override
@@ -52,8 +53,11 @@ public final class TypeImpl extends AnnotatedImpl implements Type {
}
@Override
public TypeMemberDomain getMemberDomain() {
return memberDomain;
public JetScope getMemberScope() {
if (memberScope == null) {
// TODO
}
return memberScope;
}
@Override
@@ -85,7 +89,7 @@ public final class TypeImpl extends AnnotatedImpl implements Type {
// if (nullable != type.nullable) return false;
// if (arguments != null ? !arguments.equals(type.arguments) : type.arguments != null) return false;
// if (constructor != null ? !constructor.equals(type.constructor) : type.constructor != null) return false;
// if (memberDomain != null ? !memberDomain.equals(type.memberDomain) : type.memberDomain != null) return false;
// if (memberScope != null ? !memberScope.equals(type.memberScope) : type.memberScope != null) return false;
// return true;
}
@@ -1,47 +0,0 @@
package org.jetbrains.jet.lang.types;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import java.util.Collections;
/**
* @author abreslav
*/
public interface TypeMemberDomain {
TypeMemberDomain EMPTY = new TypeMemberDomain() {
@Override
public ClassDescriptor getClassDescriptor(@NotNull Type contextType, String name) {
return null;
}
@NotNull
@Override
public Collection<MethodDescriptor> getMethods(Type contextType, String name) {
return Collections.emptyList();
}
@Override
public PropertyDescriptor getProperty(Type contextType, String name) {
return null;
}
@Override
public ExtensionDescriptor getExtension(Type contextType, String name) {
return null;
}
};
@Nullable
ClassDescriptor getClassDescriptor(@NotNull Type contextType, String name);
@NotNull
Collection<MethodDescriptor> getMethods(Type contextType, String name);
@Nullable
PropertyDescriptor getProperty(Type contextType, String name);
@Nullable
ExtensionDescriptor getExtension(Type contextType, String name);
}
@@ -0,0 +1,76 @@
package org.jetbrains.jet.lang.types;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author abreslav
*/
public class TypeSubstitutor {
public static final TypeSubstitutor INSTANCE = new TypeSubstitutor();
private TypeSubstitutor() {}
public Type substitute(@NotNull Type context, @NotNull Type subject, @NotNull Variance howThisTypeIsUsed) {
return substitute(getSubstitutionContext(context), subject, howThisTypeIsUsed);
}
@NotNull
public Type substitute(@NotNull Map<TypeConstructor, TypeProjection> substitutionContext, @NotNull Type type, @NotNull Variance howThisTypeIsUsed) {
TypeProjection value = substitutionContext.get(type.getConstructor());
if (value != null) {
Variance projectionKind = value.getProjectionKind();
if (howThisTypeIsUsed.allowsInPosition() && !projectionKind.allowsInPosition()
|| howThisTypeIsUsed.allowsOutPosition() && !projectionKind.allowsOutPosition()) {
return ErrorType.createWrongVarianceErrorType(value);
}
return value.getType();
}
return specializeType(type, substituteInArguments(substitutionContext, type));
}
public Map<TypeConstructor, TypeProjection> getSubstitutionContext(Type context) {
List<TypeParameterDescriptor> parameters = context.getConstructor().getParameters();
List<TypeProjection> contextArguments = context.getArguments();
return buildSubstitutionContext(parameters, contextArguments);
}
public Map<TypeConstructor, TypeProjection> buildSubstitutionContext(List<TypeParameterDescriptor> parameters, List<TypeProjection> contextArguments) {
Map<TypeConstructor, TypeProjection> parameterValues = new HashMap<TypeConstructor, TypeProjection>();
for (int i = 0, parametersSize = parameters.size(); i < parametersSize; i++) {
TypeParameterDescriptor parameter = parameters.get(i);
TypeProjection value = contextArguments.get(i);
parameterValues.put(parameter.getTypeConstructor(), value);
}
return parameterValues;
}
@NotNull
private TypeProjection substituteInProjection(Map<TypeConstructor, TypeProjection> parameterValues, TypeProjection subject) {
@NotNull Type subjectType = subject.getType();
TypeProjection value = parameterValues.get(subjectType.getConstructor());
if (value != null) {
return value;
}
List<TypeProjection> newArguments = substituteInArguments(parameterValues, subjectType);
return new TypeProjection(subject.getProjectionKind(), specializeType(subjectType, newArguments));
}
private List<TypeProjection> substituteInArguments(Map<TypeConstructor, TypeProjection> parameterValues, Type subjectType) {
List<TypeProjection> newArguments = new ArrayList<TypeProjection>();
for (TypeProjection argument : subjectType.getArguments()) {
newArguments.add(substituteInProjection(parameterValues, argument));
}
return newArguments;
}
private Type specializeType(Type type, List<TypeProjection> newArguments) {
return new TypeImpl(type.getAttributes(), type.getConstructor(), type.isNullable(), newArguments, type.getMemberScope());
}
}
@@ -15,7 +15,7 @@ public class TypeUtils {
if (type.isNullable()) {
return type;
}
return new TypeImpl(type.getAttributes(), type.getConstructor(), true, type.getArguments(), type.getMemberDomain());
return new TypeImpl(type.getAttributes(), type.getConstructor(), true, type.getArguments(), type.getMemberScope());
}
@Nullable
@@ -335,7 +335,7 @@ public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase {
subtypes.add(makeType(type));
}
Type result = JetTypeChecker.INSTANCE.commonSupertype(subtypes);
assertTrue(result + " != " + expected, JetTypeChecker.INSTANCE.equalTypes(result, makeType(expected)));
assertTrue(result + " != " + expected, TypeImpl.equalTypes(result, makeType(expected)));
}
private static void assertSubtypingRelation(String type1, String type2, boolean expected) {
@@ -366,7 +366,7 @@ public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase {
Project project = getProject();
JetExpression jetExpression = JetChangeUtil.createExpression(project, expression);
Type type = JetTypeChecker.INSTANCE.getType(ClassDefinitions.BASIC_SCOPE, jetExpression, false);
assertTrue(type + " != " + expectedType, JetTypeChecker.INSTANCE.equalTypes(type, expectedType));
assertTrue(type + " != " + expectedType, TypeImpl.equalTypes(type, expectedType));
}
private void assertErrorType(String expression) {
@@ -397,7 +397,7 @@ public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase {
JetExpression jetExpression = JetChangeUtil.createExpression(project, expression);
Type type = JetTypeChecker.INSTANCE.getType(scope, jetExpression, false);
Type expectedType = makeType(expectedTypeStr);
assertTrue(type + " != " + expectedType, JetTypeChecker.INSTANCE.equalTypes(type, expectedType));
assertTrue(type + " != " + expectedType, TypeImpl.equalTypes(type, expectedType));
}
private static Type makeType(String typeStr) {