diff --git a/idea/src/org/jetbrains/jet/lang/modules/MemberDomain.java b/idea/src/org/jetbrains/jet/lang/modules/MemberDomain.java deleted file mode 100644 index 14182a867a3..00000000000 --- a/idea/src/org/jetbrains/jet/lang/modules/MemberDomain.java +++ /dev/null @@ -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 getMethods(String name); - - @Nullable - ClassDescriptor getClass(String name); - - @Nullable - PropertyDescriptor getProperty(String name); - - @Nullable - ExtensionDescriptor getExtension(String name); -} diff --git a/idea/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java b/idea/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java index 4c53ae66617..d4451ef9de1 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java @@ -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 typeParameters, final JetScope outerScope, final TypeParameterExtensibleScope typeParameterScope, final Collection supertypes) { - // TODO : Cache!!! - return new TypeMemberDomain() { - @Override - public PropertyDescriptor getProperty(Type contextType, @NotNull String name) { - // TODO : primary constructor parameters - List 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 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 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 resolveTypeParameters(TypeParameterExtensibleScope extensibleScope, List typeParameters) { diff --git a/idea/src/org/jetbrains/jet/lang/resolve/JetScope.java b/idea/src/org/jetbrains/jet/lang/resolve/JetScope.java index 817e6a65e53..8acc3da532e 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/JetScope.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/JetScope.java @@ -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 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); diff --git a/idea/src/org/jetbrains/jet/lang/resolve/ScopeWithReceiver.java b/idea/src/org/jetbrains/jet/lang/resolve/ScopeWithReceiver.java index 5f014ffb3a7..9372d623c92 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/ScopeWithReceiver.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/ScopeWithReceiver.java @@ -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 diff --git a/idea/src/org/jetbrains/jet/lang/resolve/SubstitutingScope.java b/idea/src/org/jetbrains/jet/lang/resolve/SubstitutingScope.java new file mode 100644 index 00000000000..3614a312af9 --- /dev/null +++ b/idea/src/org/jetbrains/jet/lang/resolve/SubstitutingScope.java @@ -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 substitutionContext; + + public SubstitutingScope(JetScope workerScope, Map 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 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 + } +} diff --git a/idea/src/org/jetbrains/jet/lang/resolve/TypeResolver.java b/idea/src/org/jetbrains/jet/lang/resolve/TypeResolver.java index 13a5a7fbb68..a3a90993788 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/TypeResolver.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/TypeResolver.java @@ -36,12 +36,13 @@ public class TypeResolver { ClassDescriptor classDescriptor = resolveClass(scope, type); if (classDescriptor != null) { TypeConstructor typeConstructor = classDescriptor.getTypeConstructor(); + List 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()) { diff --git a/idea/src/org/jetbrains/jet/lang/resolve/TypeScope.java b/idea/src/org/jetbrains/jet/lang/resolve/TypeScope.java deleted file mode 100644 index e1830370c48..00000000000 --- a/idea/src/org/jetbrains/jet/lang/resolve/TypeScope.java +++ /dev/null @@ -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 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; - } -} diff --git a/idea/src/org/jetbrains/jet/lang/resolve/WritableScope.java b/idea/src/org/jetbrains/jet/lang/resolve/WritableScope.java new file mode 100644 index 00000000000..6416995ddc7 --- /dev/null +++ b/idea/src/org/jetbrains/jet/lang/resolve/WritableScope.java @@ -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 propertyDescriptors; + + public void addPropertyDescriptor(PropertyDescriptor propertyDescriptor) { + if (propertyDescriptors == null) { + propertyDescriptors = new HashMap(); + } + 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 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 + } +} diff --git a/idea/src/org/jetbrains/jet/lang/types/ClassDescriptor.java b/idea/src/org/jetbrains/jet/lang/types/ClassDescriptor.java index 075db373af7..da0a9bc1fed 100644 --- a/idea/src/org/jetbrains/jet/lang/types/ClassDescriptor.java +++ b/idea/src/org/jetbrains/jet/lang/types/ClassDescriptor.java @@ -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 attributes, boolean sealed, String name, List typeParameters, - Collection superclasses, TypeMemberDomain memberDomain) { + Collection 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.emptyList(), true, name, Collections.emptyList(), - Collections.singleton(JetStandardClasses.getAnyType()), memberDomain); + Collections.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 typeArguments) { + Map substitutionContext = TypeSubstitutor.INSTANCE.buildSubstitutionContext(typeConstructor.getParameters(), typeArguments); + return new SubstitutingScope(memberDeclarations, substitutionContext); } - - public ClassDescriptor getClass(String referencedName) { - throw new UnsupportedOperationException(); // TODO - } - } \ No newline at end of file diff --git a/idea/src/org/jetbrains/jet/lang/types/ErrorType.java b/idea/src/org/jetbrains/jet/lang/types/ErrorType.java index 4777883b2c5..f9e894051b8 100644 --- a/idea/src/org/jetbrains/jet/lang/types/ErrorType.java +++ b/idea/src/org/jetbrains/jet/lang/types/ErrorType.java @@ -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 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 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.emptyList(), false, "[ERROR : " + debugMessage + "]", Collections.emptyList(), Collections.emptyList()), memberDomain); + private static Type createErrorType(String debugMessage, JetScope memberScope) { + return new ErrorTypeImpl(new TypeConstructor(Collections.emptyList(), false, "[ERROR : " + debugMessage + "]", Collections.emptyList(), Collections.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 diff --git a/idea/src/org/jetbrains/jet/lang/types/JetStandardClasses.java b/idea/src/org/jetbrains/jet/lang/types/JetStandardClasses.java index f562fbdb8a7..21456a606c7 100644 --- a/idea/src/org/jetbrains/jet/lang/types/JetStandardClasses.java +++ b/idea/src/org/jetbrains/jet/lang/types/JetStandardClasses.java @@ -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.emptyList(), Collections.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 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.emptyList(), - TypeMemberDomain.EMPTY); + JetScope.EMPTY); private static final Map CLASS_MAP = new HashMap(); static { diff --git a/idea/src/org/jetbrains/jet/lang/types/JetTypeChecker.java b/idea/src/org/jetbrains/jet/lang/types/JetTypeChecker.java index 967017d547f..e71d70feaf4 100644 --- a/idea/src/org/jetbrains/jet/lang/types/JetTypeChecker.java +++ b/idea/src/org/jetbrains/jet/lang/types/JetTypeChecker.java @@ -233,9 +233,10 @@ public class JetTypeChecker { JetUserType typeElement = (JetUserType) superTypeQualifier.getTypeElement(); ClassDescriptor superclass = TypeResolver.INSTANCE.resolveClass(scope, typeElement); Collection supertypes = thisType.getConstructor().getSupertypes(); + Map 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 substitutionContext = getSubstitutionContext(current); + Map 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 getSubstitutionContext(Type context) { - Map parameterValues = new HashMap(); - - List parameters = context.getConstructor().getParameters(); - List 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 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 parameterValues, TypeProjection subject) { - @NotNull Type subjectType = subject.getType(); - TypeProjection value = parameterValues.get(subjectType.getConstructor()); - if (value != null) { - return value; - } - List newArguments = substituteInArguments(parameterValues, subjectType); - return new TypeProjection(subject.getProjectionKind(), specializeType(subjectType, newArguments)); - } - - private List substituteInArguments(Map parameterValues, Type subjectType) { - List newArguments = new ArrayList(); - 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 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); - } - } \ No newline at end of file diff --git a/idea/src/org/jetbrains/jet/lang/types/LazySubstitutedPropertyDescriptorImpl.java b/idea/src/org/jetbrains/jet/lang/types/LazySubstitutedPropertyDescriptorImpl.java index 9a6aceea415..233c3567015 100644 --- a/idea/src/org/jetbrains/jet/lang/types/LazySubstitutedPropertyDescriptorImpl.java +++ b/idea/src/org/jetbrains/jet/lang/types/LazySubstitutedPropertyDescriptorImpl.java @@ -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 substitutionContext; private Type propertyType = null; - public LazySubstitutedPropertyDescriptorImpl(PropertyDescriptor propertyDescriptor, Type contextType) { + public LazySubstitutedPropertyDescriptorImpl(@NotNull PropertyDescriptor propertyDescriptor, @NotNull Map 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; } diff --git a/idea/src/org/jetbrains/jet/lang/types/NamespaceDescriptor.java b/idea/src/org/jetbrains/jet/lang/types/NamespaceDescriptor.java index d95c984cf1b..999531558d6 100644 --- a/idea/src/org/jetbrains/jet/lang/types/NamespaceDescriptor.java +++ b/idea/src/org/jetbrains/jet/lang/types/NamespaceDescriptor.java @@ -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 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 } diff --git a/idea/src/org/jetbrains/jet/lang/types/Type.java b/idea/src/org/jetbrains/jet/lang/types/Type.java index a8af560c0f2..c3139bac462 100644 --- a/idea/src/org/jetbrains/jet/lang/types/Type.java +++ b/idea/src/org/jetbrains/jet/lang/types/Type.java @@ -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 getArguments(); boolean isNullable(); - @NotNull TypeMemberDomain getMemberDomain(); + @NotNull + JetScope getMemberScope(); } diff --git a/idea/src/org/jetbrains/jet/lang/types/TypeImpl.java b/idea/src/org/jetbrains/jet/lang/types/TypeImpl.java index d44ad6a1f78..ff6eb8ef297 100644 --- a/idea/src/org/jetbrains/jet/lang/types/TypeImpl.java +++ b/idea/src/org/jetbrains/jet/lang/types/TypeImpl.java @@ -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 arguments; private final boolean nullable; - private final TypeMemberDomain memberDomain; + private JetScope memberScope; - public TypeImpl(List attributes, TypeConstructor constructor, boolean nullable, List arguments, TypeMemberDomain memberDomain) { + public TypeImpl(List attributes, TypeConstructor constructor, boolean nullable, List 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.emptyList(), constructor, false, Collections.emptyList(), memberDomain); + public TypeImpl(TypeConstructor constructor, JetScope memberScope) { + this(Collections.emptyList(), constructor, false, Collections.emptyList(), memberScope); } public TypeImpl(ClassDescriptor classDescriptor) { @@ -33,7 +34,7 @@ public final class TypeImpl extends AnnotatedImpl implements Type { classDescriptor.getTypeConstructor(), false, Collections.emptyList(), - classDescriptor.getMemberDomain()); + classDescriptor.getMemberScope(Collections.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; } diff --git a/idea/src/org/jetbrains/jet/lang/types/TypeMemberDomain.java b/idea/src/org/jetbrains/jet/lang/types/TypeMemberDomain.java deleted file mode 100644 index 27150105664..00000000000 --- a/idea/src/org/jetbrains/jet/lang/types/TypeMemberDomain.java +++ /dev/null @@ -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 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 getMethods(Type contextType, String name); - - @Nullable - PropertyDescriptor getProperty(Type contextType, String name); - - @Nullable - ExtensionDescriptor getExtension(Type contextType, String name); -} diff --git a/idea/src/org/jetbrains/jet/lang/types/TypeSubstitutor.java b/idea/src/org/jetbrains/jet/lang/types/TypeSubstitutor.java new file mode 100644 index 00000000000..d6bacbd1e2d --- /dev/null +++ b/idea/src/org/jetbrains/jet/lang/types/TypeSubstitutor.java @@ -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 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 getSubstitutionContext(Type context) { + List parameters = context.getConstructor().getParameters(); + List contextArguments = context.getArguments(); + + return buildSubstitutionContext(parameters, contextArguments); + } + + public Map buildSubstitutionContext(List parameters, List contextArguments) { + Map parameterValues = new HashMap(); + 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 parameterValues, TypeProjection subject) { + @NotNull Type subjectType = subject.getType(); + TypeProjection value = parameterValues.get(subjectType.getConstructor()); + if (value != null) { + return value; + } + List newArguments = substituteInArguments(parameterValues, subjectType); + return new TypeProjection(subject.getProjectionKind(), specializeType(subjectType, newArguments)); + } + + private List substituteInArguments(Map parameterValues, Type subjectType) { + List newArguments = new ArrayList(); + for (TypeProjection argument : subjectType.getArguments()) { + newArguments.add(substituteInProjection(parameterValues, argument)); + } + return newArguments; + } + + private Type specializeType(Type type, List newArguments) { + return new TypeImpl(type.getAttributes(), type.getConstructor(), type.isNullable(), newArguments, type.getMemberScope()); + } +} diff --git a/idea/src/org/jetbrains/jet/lang/types/TypeUtils.java b/idea/src/org/jetbrains/jet/lang/types/TypeUtils.java index 1ebddf4cde6..b8c5fd13e36 100644 --- a/idea/src/org/jetbrains/jet/lang/types/TypeUtils.java +++ b/idea/src/org/jetbrains/jet/lang/types/TypeUtils.java @@ -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 diff --git a/idea/tests/org/jetbrains/jet/types/JetTypeCheckerTest.java b/idea/tests/org/jetbrains/jet/types/JetTypeCheckerTest.java index 38d7b56fddf..8f9a6e5f1ad 100644 --- a/idea/tests/org/jetbrains/jet/types/JetTypeCheckerTest.java +++ b/idea/tests/org/jetbrains/jet/types/JetTypeCheckerTest.java @@ -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) {