From 798510b719d93a6ee20540b6e08717f803801447 Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Wed, 26 Jan 2011 22:05:59 +0300 Subject: [PATCH] Contexts added for type parameter resolution. Annotations renamed into attributes for consistency --- .../jet/lang/modules/NamespaceDomain.java | 2 +- .../jetbrains/jet/lang/psi/JetUserType.java | 8 + .../jet/lang/resolve/AttributeResolver.java | 35 +++ .../lang/resolve/ClassDescriptorResolver.java | 97 ++++++++ .../jetbrains/jet/lang/resolve/JetScope.java | 29 +-- .../jet/lang/resolve/JetScopeAdapter.java | 45 ++++ .../jet/lang/resolve/JetScopeImpl.java | 38 +++ .../jet/lang/resolve/TypeResolver.java | 78 +++++- .../jetbrains/jet/lang/types/Annotated.java | 2 +- .../jet/lang/types/AnnotatedImpl.java | 10 +- .../types/{Annotation.java => Attribute.java} | 2 +- .../jet/lang/types/ClassDescriptor.java | 8 +- .../jetbrains/jet/lang/types/ClassType.java | 10 +- .../jetbrains/jet/lang/types/ErrorType.java | 45 ++++ .../jet/lang/types/JetStandardClasses.java | 6 +- .../jet/lang/types/MemberDescriptorImpl.java | 4 +- .../jet/lang/types/NamedAnnotatedImpl.java | 4 +- .../jetbrains/jet/lang/types/NothingType.java | 8 +- .../jet/lang/types/ParameterDescriptor.java | 4 +- .../jetbrains/jet/lang/types/ThisType.java | 6 +- .../jetbrains/jet/lang/types/TupleType.java | 20 +- .../jet/lang/types/TypeConstructor.java | 4 +- .../jetbrains/jet/lang/types/TypeImpl.java | 15 +- .../lang/types/TypeParameterDescriptor.java | 8 +- .../jet/lang/types/TypeVariable.java | 14 +- .../jetbrains/jet/lang/types/TypeVisitor.java | 6 +- .../jet/lang/types/VisitableTypeImpl.java | 22 ++ .../jet/types/JetTypeCheckerTest.java | 225 +++++------------- 28 files changed, 497 insertions(+), 258 deletions(-) create mode 100644 idea/src/org/jetbrains/jet/lang/resolve/AttributeResolver.java create mode 100644 idea/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java create mode 100644 idea/src/org/jetbrains/jet/lang/resolve/JetScopeAdapter.java create mode 100644 idea/src/org/jetbrains/jet/lang/resolve/JetScopeImpl.java rename idea/src/org/jetbrains/jet/lang/types/{Annotation.java => Attribute.java} (69%) create mode 100644 idea/src/org/jetbrains/jet/lang/types/ErrorType.java create mode 100644 idea/src/org/jetbrains/jet/lang/types/VisitableTypeImpl.java diff --git a/idea/src/org/jetbrains/jet/lang/modules/NamespaceDomain.java b/idea/src/org/jetbrains/jet/lang/modules/NamespaceDomain.java index 6a5934d620c..2f85f7b8e3f 100644 --- a/idea/src/org/jetbrains/jet/lang/modules/NamespaceDomain.java +++ b/idea/src/org/jetbrains/jet/lang/modules/NamespaceDomain.java @@ -8,5 +8,5 @@ import org.jetbrains.jet.lang.types.NamespaceDescriptor; */ public interface NamespaceDomain { @Nullable - NamespaceDescriptor getNamespace(String namespaceName); + NamespaceDescriptor getNamespace(String name); } diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetUserType.java b/idea/src/org/jetbrains/jet/lang/psi/JetUserType.java index f0c2da815eb..2e1e884e67a 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetUserType.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetUserType.java @@ -2,6 +2,7 @@ package org.jetbrains.jet.lang.psi; import com.intellij.lang.ASTNode; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.JetNodeTypes; import java.util.Collections; @@ -30,7 +31,14 @@ public class JetUserType extends JetTypeElement { return typeArgumentList == null ? Collections.emptyList() : typeArgumentList.getArguments(); } + @Nullable public JetReferenceExpression getReferenceExpression() { return (JetReferenceExpression) findChildByType(JetNodeTypes.REFERENCE_EXPRESSION); } + + @Nullable + public String getReferencedName() { + JetReferenceExpression referenceExpression = getReferenceExpression(); + return referenceExpression == null ? null : referenceExpression.getReferencedName(); + } } diff --git a/idea/src/org/jetbrains/jet/lang/resolve/AttributeResolver.java b/idea/src/org/jetbrains/jet/lang/resolve/AttributeResolver.java new file mode 100644 index 00000000000..2a2fac3d9c5 --- /dev/null +++ b/idea/src/org/jetbrains/jet/lang/resolve/AttributeResolver.java @@ -0,0 +1,35 @@ +package org.jetbrains.jet.lang.resolve; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.psi.JetAttribute; +import org.jetbrains.jet.lang.psi.JetModifierList; +import org.jetbrains.jet.lang.types.Attribute; + +import java.util.Collections; +import java.util.List; + +/** + * @author abreslav + */ +public class AttributeResolver { + public static final AttributeResolver INSTANCE = new AttributeResolver(); + + private AttributeResolver() {} + + @NotNull + public List resolveAttributes(@NotNull List attributeElements) { + if (attributeElements.isEmpty()) { + return Collections.emptyList(); + } + throw new UnsupportedOperationException(); // TODO + } + + @NotNull + public List resolveAttributes(@Nullable JetModifierList modifierList) { + if (modifierList == null) { + return Collections.emptyList(); + } + return resolveAttributes(modifierList.getAttributes()); + } +} diff --git a/idea/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java b/idea/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java new file mode 100644 index 00000000000..5378819456e --- /dev/null +++ b/idea/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java @@ -0,0 +1,97 @@ +package org.jetbrains.jet.lang.resolve; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.psi.JetClass; +import org.jetbrains.jet.lang.psi.JetDelegationSpecifier; +import org.jetbrains.jet.lang.psi.JetTypeParameter; +import org.jetbrains.jet.lang.psi.JetTypeReference; +import org.jetbrains.jet.lang.types.ClassDescriptor; +import org.jetbrains.jet.lang.types.JetStandardClasses; +import org.jetbrains.jet.lang.types.Type; +import org.jetbrains.jet.lang.types.TypeParameterDescriptor; + +import java.util.*; + +/** + * @author abreslav + */ +public class ClassDescriptorResolver { + public static final ClassDescriptorResolver INSTANCE = new ClassDescriptorResolver(); + + private ClassDescriptorResolver() {} + + @Nullable + public ClassDescriptor resolveClassDescriptor(@NotNull JetScope scope, @NotNull JetClass classElement) { + TypeParameterExtensibleScope extensibleScope = new TypeParameterExtensibleScope(scope); + return new ClassDescriptor( + AttributeResolver.INSTANCE.resolveAttributes(classElement.getModifierList()), + classElement.getName(), + resolveTypeParameters(extensibleScope, classElement.getTypeParameters()), + resolveTypes(extensibleScope, classElement.getDelegationSpecifiers()) + ); + } + + private static List resolveTypeParameters(TypeParameterExtensibleScope extensibleScope, List typeParameters) { + List result = new ArrayList(); + for (JetTypeParameter typeParameter : typeParameters) { + result.add(resolveTypeParameter(extensibleScope, typeParameter)); + } + return result; + } + + private static TypeParameterDescriptor resolveTypeParameter(TypeParameterExtensibleScope extensibleScope, JetTypeParameter typeParameter) { + JetTypeReference extendsBound = typeParameter.getExtendsBound(); + TypeParameterDescriptor typeParameterDescriptor = new TypeParameterDescriptor( + AttributeResolver.INSTANCE.resolveAttributes(typeParameter.getModifierList()), + typeParameter.getVariance(), + typeParameter.getName(), + extendsBound == null + ? Collections.singleton(JetStandardClasses.getAnyType()) + : Collections.singleton(TypeResolver.INSTANCE.resolveType(extensibleScope, extendsBound)) + ); + extensibleScope.addTypeParameterDescriptor(typeParameterDescriptor); + return typeParameterDescriptor; + } + + private static Collection resolveTypes(TypeParameterExtensibleScope extensibleScope, List delegationSpecifiers) { + if (delegationSpecifiers.isEmpty()) { + return Collections.emptyList(); + } + Collection result = new ArrayList(); + for (JetDelegationSpecifier delegationSpecifier : delegationSpecifiers) { + result.add(resolveType(extensibleScope, delegationSpecifier)); + } + return result; + } + + private static Type resolveType(JetScope scope, JetDelegationSpecifier delegationSpecifier) { + JetTypeReference typeReference = delegationSpecifier.getTypeReference(); // TODO : make it not null + return TypeResolver.INSTANCE.resolveType(scope, typeReference); + } + + private static final class TypeParameterExtensibleScope extends JetScopeAdapter { + private final Map typeParameterDescriptors = new HashMap(); + + private TypeParameterExtensibleScope(JetScope scope) { + super(scope); + } + + public void addTypeParameterDescriptor(TypeParameterDescriptor typeParameterDescriptor) { + String name = typeParameterDescriptor.getName(); + if (typeParameterDescriptors.containsKey(name)) { + throw new UnsupportedOperationException(); // TODO + } + typeParameterDescriptors.put(name, typeParameterDescriptor); + } + + @Override + public TypeParameterDescriptor getTypeParameterDescriptor(String name) { + TypeParameterDescriptor typeParameterDescriptor = typeParameterDescriptors.get(name); + if (typeParameterDescriptor != null) { + return typeParameterDescriptor; + } + return super.getTypeParameterDescriptor(name); + } + } +} diff --git a/idea/src/org/jetbrains/jet/lang/resolve/JetScope.java b/idea/src/org/jetbrains/jet/lang/resolve/JetScope.java index a6ecc924ca8..e2fe5cfd910 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/JetScope.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/JetScope.java @@ -1,5 +1,6 @@ package org.jetbrains.jet.lang.resolve; +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.*; @@ -10,31 +11,7 @@ import org.jetbrains.jet.lang.types.*; public interface JetScope extends NamespaceDomain, MemberDomain { JetScope EMPTY = new JetScopeImpl() {}; - abstract class JetScopeImpl implements JetScope { - @Override - public MethodDescriptor getMethods(String name) { - return null; - } - - @Override - public ClassDescriptor getClass(String name) { - return null; - } - - @Override - public PropertyDescriptor getProperty(String name) { - return null; - } - - @Override - public ExtensionDescriptor getExtension(String name) { - return null; - } - - @Override - public NamespaceDescriptor getNamespace(String namespaceName) { - return null; - } - }; + @Nullable + TypeParameterDescriptor getTypeParameterDescriptor(String name); } diff --git a/idea/src/org/jetbrains/jet/lang/resolve/JetScopeAdapter.java b/idea/src/org/jetbrains/jet/lang/resolve/JetScopeAdapter.java new file mode 100644 index 00000000000..72ed35a3f69 --- /dev/null +++ b/idea/src/org/jetbrains/jet/lang/resolve/JetScopeAdapter.java @@ -0,0 +1,45 @@ +package org.jetbrains.jet.lang.resolve; + +import org.jetbrains.jet.lang.types.*; + +/** + * @author abreslav + */ +public class JetScopeAdapter implements JetScope { + + private final JetScope scope; + + public JetScopeAdapter(JetScope scope) { + this.scope = scope; + } + + @Override + public TypeParameterDescriptor getTypeParameterDescriptor(String name) { + return scope.getTypeParameterDescriptor(name); + } + + @Override + public NamespaceDescriptor getNamespace(String name) { + return scope.getNamespace(name); + } + + @Override + public MethodDescriptor getMethods(String name) { + return scope.getMethods(name); + } + + @Override + public ClassDescriptor getClass(String name) { + return scope.getClass(name); + } + + @Override + public PropertyDescriptor getProperty(String name) { + return scope.getProperty(name); + } + + @Override + public ExtensionDescriptor getExtension(String name) { + return scope.getExtension(name); + } +} diff --git a/idea/src/org/jetbrains/jet/lang/resolve/JetScopeImpl.java b/idea/src/org/jetbrains/jet/lang/resolve/JetScopeImpl.java new file mode 100644 index 00000000000..81c5f2e5211 --- /dev/null +++ b/idea/src/org/jetbrains/jet/lang/resolve/JetScopeImpl.java @@ -0,0 +1,38 @@ +package org.jetbrains.jet.lang.resolve; + +import org.jetbrains.jet.lang.types.*; + +/** +* @author abreslav +*/ +public abstract class JetScopeImpl implements JetScope { + @Override + public MethodDescriptor getMethods(String name) { + return null; + } + + @Override + public ClassDescriptor getClass(String name) { + return null; + } + + @Override + public PropertyDescriptor getProperty(String name) { + return null; + } + + @Override + public ExtensionDescriptor getExtension(String name) { + return null; + } + + @Override + public NamespaceDescriptor getNamespace(String name) { + return null; + } + + @Override + public TypeParameterDescriptor getTypeParameterDescriptor(String name) { + return null; + } +} diff --git a/idea/src/org/jetbrains/jet/lang/resolve/TypeResolver.java b/idea/src/org/jetbrains/jet/lang/resolve/TypeResolver.java index 2d7222860be..1b537d0bef7 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/TypeResolver.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/TypeResolver.java @@ -1,21 +1,89 @@ 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.psi.JetReferenceExpression; -import org.jetbrains.jet.lang.psi.JetUserType; -import org.jetbrains.jet.lang.types.ClassDescriptor; -import org.jetbrains.jet.lang.types.NamespaceDescriptor; +import org.jetbrains.jet.lang.psi.*; +import org.jetbrains.jet.lang.types.*; + +import java.util.ArrayList; +import java.util.List; /** * @author abreslav */ public class TypeResolver { + @NotNull public static final TypeResolver INSTANCE = new TypeResolver(); private TypeResolver() {} + @NotNull + public Type resolveType(@NotNull final JetScope scope, @NotNull final JetTypeReference typeReference) { + final List attributes = AttributeResolver.INSTANCE.resolveAttributes(typeReference.getAttributes()); + + final Type[] result = new Type[1]; + typeReference.getTypeElement().accept(new JetVisitor() { + @Override + public void visitUserType(JetUserType type) { + ClassDescriptor classDescriptor = resolveClass(scope, type); + if (classDescriptor != null) { + result[0] = new ClassType( + attributes, + classDescriptor, + resolveTypeProjections(scope, type.getTypeArguments()) + ); + } else if (type.getTypeArguments().isEmpty()) { + TypeParameterDescriptor typeParameterDescriptor = scope.getTypeParameterDescriptor(type.getReferencedName()); + if (typeParameterDescriptor != null) { + result[0] = new TypeVariable(attributes, typeParameterDescriptor); + } + } + } + + @Override + public void visitTupleType(JetTupleType type) { + // TODO labels + result[0] = TupleType.getTupleType(resolveTypes(scope, type.getComponentTypeRefs())); + } + + @Override + public void visitJetElement(JetElement elem) { + throw new IllegalArgumentException("Unsupported type: " + elem); + } + }); + if (result[0] == null) { + return new ErrorType(typeReference); + } + return result[0]; + } + + private List resolveTypes(JetScope scope, List argumentElements) { + final List arguments = new ArrayList(); + for (JetTypeReference argumentElement : argumentElements) { + arguments.add(resolveType(scope, argumentElement)); + } + return arguments; + } + + @NotNull + private List resolveTypeProjections(JetScope scope, List argumentElements) { + final List arguments = new ArrayList(); + for (JetTypeProjection argumentElement : argumentElements) { + ProjectionKind projectionKind = argumentElement.getProjectionKind(); + Type type; + if (projectionKind == ProjectionKind.NEITHER_OUT_NOR_IN) { + type = null; + } else { + type = resolveType(scope, argumentElement.getTypeReference()); + } + TypeProjection typeProjection = new TypeProjection(projectionKind, type); + arguments.add(typeProjection); + } + return arguments; + } + @Nullable public ClassDescriptor resolveClass(JetScope scope, JetUserType userType) { return resolveClass(scope, userType.getReferenceExpression()); @@ -29,7 +97,7 @@ public class TypeResolver { JetReferenceExpression qualifier = expression.getQualifier(); if (qualifier != null) { - // TODO: this is slow. The faster way would be to start with the first item in the quilified name + // TODO: this is slow. The faster way would be to start with the first item in the qualified name // TODO: priorities: class of namespace first? MemberDomain domain = resolveClass(scope, qualifier); if (domain == null) { diff --git a/idea/src/org/jetbrains/jet/lang/types/Annotated.java b/idea/src/org/jetbrains/jet/lang/types/Annotated.java index 5d7aef15d40..2b04abb1c9d 100644 --- a/idea/src/org/jetbrains/jet/lang/types/Annotated.java +++ b/idea/src/org/jetbrains/jet/lang/types/Annotated.java @@ -6,5 +6,5 @@ import java.util.List; * @author abreslav */ public interface Annotated { - List getAnnotations(); + List getAttributes(); } diff --git a/idea/src/org/jetbrains/jet/lang/types/AnnotatedImpl.java b/idea/src/org/jetbrains/jet/lang/types/AnnotatedImpl.java index 1527a1a9c23..e5c8ccf8559 100644 --- a/idea/src/org/jetbrains/jet/lang/types/AnnotatedImpl.java +++ b/idea/src/org/jetbrains/jet/lang/types/AnnotatedImpl.java @@ -6,14 +6,14 @@ import java.util.List; * @author abreslav */ public abstract class AnnotatedImpl implements Annotated { - private final List annotations; + private final List attributes; - public AnnotatedImpl(List annotations) { - this.annotations = annotations; + public AnnotatedImpl(List attributes) { + this.attributes = attributes; } @Override - public List getAnnotations() { - return annotations; + public List getAttributes() { + return attributes; } } diff --git a/idea/src/org/jetbrains/jet/lang/types/Annotation.java b/idea/src/org/jetbrains/jet/lang/types/Attribute.java similarity index 69% rename from idea/src/org/jetbrains/jet/lang/types/Annotation.java rename to idea/src/org/jetbrains/jet/lang/types/Attribute.java index e233fa1a1ec..2bc38245de0 100644 --- a/idea/src/org/jetbrains/jet/lang/types/Annotation.java +++ b/idea/src/org/jetbrains/jet/lang/types/Attribute.java @@ -3,5 +3,5 @@ package org.jetbrains.jet.lang.types; /** * @author abreslav */ -public interface Annotation { +public interface Attribute { } diff --git a/idea/src/org/jetbrains/jet/lang/types/ClassDescriptor.java b/idea/src/org/jetbrains/jet/lang/types/ClassDescriptor.java index 18ca9a27ef9..179030f4096 100644 --- a/idea/src/org/jetbrains/jet/lang/types/ClassDescriptor.java +++ b/idea/src/org/jetbrains/jet/lang/types/ClassDescriptor.java @@ -13,14 +13,14 @@ public class ClassDescriptor extends MemberDescriptorImpl implements MemberDomai private final TypeConstructor typeConstructor; public ClassDescriptor( - List annotations, + List attributes, String name, List typeParameters, Collection superclasses) { - super(annotations, name); - this.typeConstructor = new TypeConstructor(annotations, name, typeParameters, superclasses); + super(attributes, name); + this.typeConstructor = new TypeConstructor(attributes, name, typeParameters, superclasses); } public ClassDescriptor(String name) { - this(Collections.emptyList(), + this(Collections.emptyList(), name, Collections.emptyList(), Collections.singleton(JetStandardClasses.getAnyType())); } diff --git a/idea/src/org/jetbrains/jet/lang/types/ClassType.java b/idea/src/org/jetbrains/jet/lang/types/ClassType.java index 0974dd88c93..b084a38ecb4 100644 --- a/idea/src/org/jetbrains/jet/lang/types/ClassType.java +++ b/idea/src/org/jetbrains/jet/lang/types/ClassType.java @@ -1,5 +1,7 @@ package org.jetbrains.jet.lang.types; +import org.jetbrains.annotations.NotNull; + import java.util.Collection; import java.util.Collections; import java.util.List; @@ -8,20 +10,22 @@ import java.util.List; * @author abreslav */ public class ClassType extends TypeImpl { + @NotNull private final ClassDescriptor classDescriptor; - public ClassType(List annotations, ClassDescriptor classDescriptor, List arguments) { - super(annotations, classDescriptor.getTypeConstructor(), arguments); + public ClassType(@NotNull List attributes, @NotNull ClassDescriptor classDescriptor, @NotNull List arguments) { + super(attributes, classDescriptor.getTypeConstructor(), arguments); assert classDescriptor.getTypeConstructor().getParameters().size() == arguments.size() : classDescriptor.getTypeConstructor().getParameters().size() + " != " + arguments.size(); this.classDescriptor = classDescriptor; } public ClassType(ClassDescriptor classDescriptor) { - this(Collections.emptyList(), classDescriptor, Collections.emptyList()); + this(Collections.emptyList(), classDescriptor, Collections.emptyList()); assert classDescriptor.getTypeConstructor().getParameters().size() == 0; } + @NotNull public ClassDescriptor getClassDescriptor() { return classDescriptor; } diff --git a/idea/src/org/jetbrains/jet/lang/types/ErrorType.java b/idea/src/org/jetbrains/jet/lang/types/ErrorType.java new file mode 100644 index 00000000000..83ae2f762d6 --- /dev/null +++ b/idea/src/org/jetbrains/jet/lang/types/ErrorType.java @@ -0,0 +1,45 @@ +package org.jetbrains.jet.lang.types; + +import org.jetbrains.jet.lang.psi.JetTypeReference; + +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +/** + * @author abreslav + */ +public class ErrorType extends VisitableTypeImpl implements Type { + private final String debugLabel; + + public ErrorType(JetTypeReference typeReference) { + super(Collections.emptyList()); + this.debugLabel = typeReference.getText(); + assert debugLabel != null; + } + + @Override + public TypeConstructor getConstructor() { + throw new UnsupportedOperationException("Not found: " + debugLabel); // TODO + } + + @Override + public List getArguments() { + throw new UnsupportedOperationException("Not found: " + debugLabel); // TODO + } + + @Override + public Collection getMembers() { + throw new UnsupportedOperationException("Not found: " + debugLabel); // TODO + } + + @Override + public R accept(TypeVisitor visitor, D data) { + throw new UnsupportedOperationException("Not found: " + debugLabel); // TODO + } + + @Override + public String toString() { + return "!!!" + debugLabel + "!!!"; + } +} diff --git a/idea/src/org/jetbrains/jet/lang/types/JetStandardClasses.java b/idea/src/org/jetbrains/jet/lang/types/JetStandardClasses.java index fbbe1782661..29c05290f1f 100644 --- a/idea/src/org/jetbrains/jet/lang/types/JetStandardClasses.java +++ b/idea/src/org/jetbrains/jet/lang/types/JetStandardClasses.java @@ -11,7 +11,7 @@ import java.util.List; */ public class JetStandardClasses { private static final ClassDescriptor ANY = new ClassDescriptor( - Collections.emptyList(), + Collections.emptyList(), "Any", Collections.emptyList(), Collections.emptySet() @@ -36,12 +36,12 @@ public class JetStandardClasses { List parameters = new ArrayList(); for (int j = 0; j < i; j++) { parameters.add(new TypeParameterDescriptor( - Collections.emptyList(), + Collections.emptyList(), Variance.OUT_VARIANCE, "T" + j, Collections.emptySet())); } TUPLE[i] = new ClassDescriptor( - Collections.emptyList(), + Collections.emptyList(), "Tuple" + i, parameters, Collections.singleton(JetStandardClasses.getAnyType())); diff --git a/idea/src/org/jetbrains/jet/lang/types/MemberDescriptorImpl.java b/idea/src/org/jetbrains/jet/lang/types/MemberDescriptorImpl.java index cc530f77185..92f5d32858d 100644 --- a/idea/src/org/jetbrains/jet/lang/types/MemberDescriptorImpl.java +++ b/idea/src/org/jetbrains/jet/lang/types/MemberDescriptorImpl.java @@ -6,7 +6,7 @@ import java.util.List; * @author abreslav */ public abstract class MemberDescriptorImpl extends NamedAnnotatedImpl { - public MemberDescriptorImpl(List annotations, String name) { - super(annotations, name); + public MemberDescriptorImpl(List attributes, String name) { + super(attributes, name); } } diff --git a/idea/src/org/jetbrains/jet/lang/types/NamedAnnotatedImpl.java b/idea/src/org/jetbrains/jet/lang/types/NamedAnnotatedImpl.java index 2892cb0335e..ca54d2db47d 100644 --- a/idea/src/org/jetbrains/jet/lang/types/NamedAnnotatedImpl.java +++ b/idea/src/org/jetbrains/jet/lang/types/NamedAnnotatedImpl.java @@ -9,8 +9,8 @@ public abstract class NamedAnnotatedImpl extends AnnotatedImpl { private final String name; - public NamedAnnotatedImpl(List annotations, String name) { - super(annotations); + public NamedAnnotatedImpl(List attributes, String name) { + super(attributes); this.name = name; } diff --git a/idea/src/org/jetbrains/jet/lang/types/NothingType.java b/idea/src/org/jetbrains/jet/lang/types/NothingType.java index 7038502bf0b..2e5a8d705d2 100644 --- a/idea/src/org/jetbrains/jet/lang/types/NothingType.java +++ b/idea/src/org/jetbrains/jet/lang/types/NothingType.java @@ -8,7 +8,7 @@ import java.util.*; public class NothingType extends TypeImpl { public static final TypeConstructor NOTHING = new TypeConstructor( - Collections.emptyList(), + Collections.emptyList(), "Nothing", Collections.emptyList(), new AbstractCollection() { @@ -29,9 +29,9 @@ public class NothingType extends TypeImpl { } }); - // TODO: annotations seem wrong here - public NothingType(List annotations) { - super(annotations, NOTHING, Collections.emptyList()); + // TODO: attributes seem wrong here + public NothingType(List attributes) { + super(attributes, NOTHING, Collections.emptyList()); } @Override diff --git a/idea/src/org/jetbrains/jet/lang/types/ParameterDescriptor.java b/idea/src/org/jetbrains/jet/lang/types/ParameterDescriptor.java index 6519555318e..a748636e0fb 100644 --- a/idea/src/org/jetbrains/jet/lang/types/ParameterDescriptor.java +++ b/idea/src/org/jetbrains/jet/lang/types/ParameterDescriptor.java @@ -9,8 +9,8 @@ public class ParameterDescriptor extends AnnotatedImpl { private final Type type; private final String name; - public ParameterDescriptor(List annotations, Type type, String name) { - super(annotations); + public ParameterDescriptor(List attributes, Type type, String name) { + super(attributes); this.type = type; this.name = name; } diff --git a/idea/src/org/jetbrains/jet/lang/types/ThisType.java b/idea/src/org/jetbrains/jet/lang/types/ThisType.java index bbf04dfc7f7..433a497fd16 100644 --- a/idea/src/org/jetbrains/jet/lang/types/ThisType.java +++ b/idea/src/org/jetbrains/jet/lang/types/ThisType.java @@ -9,14 +9,14 @@ import java.util.List; * @author abreslav */ public class ThisType extends TypeImpl { - public ThisType(List annotations, ClassDescriptor thisClass) { - super(annotations, thisClass.getTypeConstructor(), toArguments(thisClass.getTypeConstructor().getParameters())); + public ThisType(List attributes, ClassDescriptor thisClass) { + super(attributes, thisClass.getTypeConstructor(), toArguments(thisClass.getTypeConstructor().getParameters())); } private static List toArguments(List parameters) { List result = new ArrayList(); for (TypeParameterDescriptor parameter : parameters) { - result.add(new TypeProjection(new TypeVariable(Collections.emptyList(), parameter))); + result.add(new TypeProjection(new TypeVariable(Collections.emptyList(), parameter))); } return result; } diff --git a/idea/src/org/jetbrains/jet/lang/types/TupleType.java b/idea/src/org/jetbrains/jet/lang/types/TupleType.java index eb00810e090..c995f71d79a 100644 --- a/idea/src/org/jetbrains/jet/lang/types/TupleType.java +++ b/idea/src/org/jetbrains/jet/lang/types/TupleType.java @@ -10,32 +10,32 @@ import java.util.List; */ public class TupleType extends TypeImpl { - public static final TupleType UNIT = new TupleType(Collections.emptyList(), Collections.emptyList()); + public static final TupleType UNIT = new TupleType(Collections.emptyList(), Collections.emptyList()); - public static TupleType getTupleType(List annotations, List arguments) { - if (annotations.isEmpty() && arguments.isEmpty()) { + public static TupleType getTupleType(List attributes, List arguments) { + if (attributes.isEmpty() && arguments.isEmpty()) { return UNIT; } - return new TupleType(annotations, arguments); + return new TupleType(attributes, arguments); } public static TupleType getTupleType(List arguments) { - return getTupleType(Collections.emptyList(), arguments); + return getTupleType(Collections.emptyList(), arguments); } - public static TupleType getLabeledTupleType(List annotations, List arguments) { - return getTupleType(annotations, toTypes(arguments)); + public static TupleType getLabeledTupleType(List attributes, List arguments) { + return getTupleType(attributes, toTypes(arguments)); } public static TupleType getLabeledTupleType(List arguments) { - return getLabeledTupleType(Collections.emptyList(), arguments); + return getLabeledTupleType(Collections.emptyList(), arguments); } - private TupleType(List annotations, List arguments) { - super(annotations, JetStandardClasses.getTuple(arguments.size()).getTypeConstructor(), toProjections(arguments)); + private TupleType(List attributes, List arguments) { + super(attributes, JetStandardClasses.getTuple(arguments.size()).getTypeConstructor(), toProjections(arguments)); } @Override diff --git a/idea/src/org/jetbrains/jet/lang/types/TypeConstructor.java b/idea/src/org/jetbrains/jet/lang/types/TypeConstructor.java index 37fe781e77d..f96d3f11d8d 100644 --- a/idea/src/org/jetbrains/jet/lang/types/TypeConstructor.java +++ b/idea/src/org/jetbrains/jet/lang/types/TypeConstructor.java @@ -11,8 +11,8 @@ public class TypeConstructor extends AnnotatedImpl { private final Collection supertypes; private final String debugName; - public TypeConstructor(List annotations, String debugName, List parameters, Collection supertypes) { - super(annotations); + public TypeConstructor(List attributes, String debugName, List parameters, Collection supertypes) { + super(attributes); this.debugName = debugName; this.parameters = parameters; this.supertypes = supertypes; diff --git a/idea/src/org/jetbrains/jet/lang/types/TypeImpl.java b/idea/src/org/jetbrains/jet/lang/types/TypeImpl.java index 4cf4e32eb86..98c23604542 100644 --- a/idea/src/org/jetbrains/jet/lang/types/TypeImpl.java +++ b/idea/src/org/jetbrains/jet/lang/types/TypeImpl.java @@ -6,13 +6,13 @@ import java.util.List; /** * @author abreslav */ -public abstract class TypeImpl extends AnnotatedImpl implements Type { +public abstract class TypeImpl extends VisitableTypeImpl { private final TypeConstructor constructor; private final List arguments; - public TypeImpl(List annotations, TypeConstructor constructor, List arguments) { - super(annotations); + public TypeImpl(List attributes, TypeConstructor constructor, List arguments) { + super(attributes); this.constructor = constructor; this.arguments = arguments; } @@ -44,13 +44,4 @@ public abstract class TypeImpl extends AnnotatedImpl implements Type { return stringBuilder; } - @Override - public R acceptNoData(TypeVisitor visitor) { - return accept(visitor, null); - } - - @Override - public void acceptVoid(TypeVisitor visitor) { - accept(visitor, null); - } } diff --git a/idea/src/org/jetbrains/jet/lang/types/TypeParameterDescriptor.java b/idea/src/org/jetbrains/jet/lang/types/TypeParameterDescriptor.java index 0cf4ee22e4e..d53f349b4b7 100644 --- a/idea/src/org/jetbrains/jet/lang/types/TypeParameterDescriptor.java +++ b/idea/src/org/jetbrains/jet/lang/types/TypeParameterDescriptor.java @@ -12,13 +12,13 @@ public class TypeParameterDescriptor extends NamedAnnotatedImpl { private final Collection upperBounds; private final TypeConstructor typeConstructor; - public TypeParameterDescriptor(List annotations, Variance variance, String name, Collection upperBounds) { - super(annotations, name); + public TypeParameterDescriptor(List attributes, Variance variance, String name, Collection upperBounds) { + super(attributes, name); this.variance = variance; this.upperBounds = upperBounds; - // TODO: Should we actually pass the annotations on to the type constructor? + // TODO: Should we actually pass the attributes on to the type constructor? this.typeConstructor = new TypeConstructor( - annotations, + attributes, name, Collections.emptyList(), upperBounds); diff --git a/idea/src/org/jetbrains/jet/lang/types/TypeVariable.java b/idea/src/org/jetbrains/jet/lang/types/TypeVariable.java index 8061ba2f7cd..57af307a210 100644 --- a/idea/src/org/jetbrains/jet/lang/types/TypeVariable.java +++ b/idea/src/org/jetbrains/jet/lang/types/TypeVariable.java @@ -1,6 +1,8 @@ package org.jetbrains.jet.lang.types; +import org.jetbrains.annotations.NotNull; + import java.util.Collection; import java.util.Collections; import java.util.List; @@ -10,18 +12,22 @@ import java.util.List; */ public class TypeVariable extends TypeImpl { - - public TypeVariable(List annotations, TypeParameterDescriptor typeParameter) { - super(annotations, typeParameter.getTypeConstructor(), Collections.emptyList()); + public TypeVariable(@NotNull List attributes, @NotNull TypeParameterDescriptor typeParameter) { + super(attributes, typeParameter.getTypeConstructor(), Collections.emptyList()); } @Override public Collection getMembers() { - throw new javax.help.UnsupportedOperationException(); // TODO + throw new UnsupportedOperationException(); // TODO } @Override public R accept(TypeVisitor visitor, D data) { return visitor.visitTypeVariable(this, data); } + + @Override + public String toString() { + return "&" + super.toString(); + } } diff --git a/idea/src/org/jetbrains/jet/lang/types/TypeVisitor.java b/idea/src/org/jetbrains/jet/lang/types/TypeVisitor.java index 27f48335334..4fb07e17766 100644 --- a/idea/src/org/jetbrains/jet/lang/types/TypeVisitor.java +++ b/idea/src/org/jetbrains/jet/lang/types/TypeVisitor.java @@ -23,7 +23,11 @@ public class TypeVisitor { public R visitThisType(ThisType thisType, D data) { return visitType(thisType, data); } - + + public R visitErrorType(ErrorType errorType, D data) { + return visitType(errorType, data); + } + public R visitType(Type type, D data) { throw new UnsupportedOperationException(); // TODO } diff --git a/idea/src/org/jetbrains/jet/lang/types/VisitableTypeImpl.java b/idea/src/org/jetbrains/jet/lang/types/VisitableTypeImpl.java new file mode 100644 index 00000000000..d527ae6c317 --- /dev/null +++ b/idea/src/org/jetbrains/jet/lang/types/VisitableTypeImpl.java @@ -0,0 +1,22 @@ +package org.jetbrains.jet.lang.types; + +import java.util.List; + +/** + * @author abreslav + */ +public abstract class VisitableTypeImpl extends AnnotatedImpl implements Type { + public VisitableTypeImpl(List attributes) { + super(attributes); + } + + @Override + public R acceptNoData(TypeVisitor visitor) { + return accept(visitor, null); + } + + @Override + public void acceptVoid(TypeVisitor visitor) { + accept(visitor, null); + } +} diff --git a/idea/tests/org/jetbrains/jet/types/JetTypeCheckerTest.java b/idea/tests/org/jetbrains/jet/types/JetTypeCheckerTest.java index 25762ddcfc8..70d7adce87d 100644 --- a/idea/tests/org/jetbrains/jet/types/JetTypeCheckerTest.java +++ b/idea/tests/org/jetbrains/jet/types/JetTypeCheckerTest.java @@ -4,7 +4,9 @@ import com.intellij.codeInsight.daemon.LightDaemonAnalyzerTestCase; import com.intellij.openapi.application.PathManager; import com.intellij.openapi.project.Project; import org.jetbrains.jet.lang.psi.*; +import org.jetbrains.jet.lang.resolve.ClassDescriptorResolver; import org.jetbrains.jet.lang.resolve.JetScope; +import org.jetbrains.jet.lang.resolve.JetScopeImpl; import org.jetbrains.jet.lang.resolve.TypeResolver; import org.jetbrains.jet.lang.types.*; import org.jetbrains.jet.parsing.JetParsingTest; @@ -17,66 +19,6 @@ import java.util.*; */ public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase { - public static final ClassDescriptor BASE_T = new ClassDescriptor( - Collections.emptyList(), - "Base_T", - Arrays.asList( - new TypeParameterDescriptor( - Collections.emptyList(), - Variance.INVARIANT, "T", - Collections.emptyList()) - ), - Collections.singleton(JetStandardClasses.getAnyType()) - ); - - private static Map CLASSES = new HashMap(); - private static String[] CLASS_DECLARATIONS = { - "class Base_T", - "class Base_inT", - "class Base_outT", - }; - - private static final JetScope BASIC_SCOPE = new JetScope.JetScopeImpl() { - @Override - public ClassDescriptor getClass(String name) { - if ("Int".equals(name)) { - return JetStandardClasses.getInt(); - } else if ("Boolean".equals(name)) { - return JetStandardClasses.getBoolean(); - } else if ("Byte".equals(name)) { - return JetStandardClasses.getByte(); - } else if ("Char".equals(name)) { - return JetStandardClasses.getChar(); - } else if ("Short".equals(name)) { - return JetStandardClasses.getShort(); - } else if ("Long".equals(name)) { - return JetStandardClasses.getLong(); - } else if ("Float".equals(name)) { - return JetStandardClasses.getFloat(); - } else if ("Double".equals(name)) { - return JetStandardClasses.getDouble(); - } else if ("Unit".equals(name)) { - return JetStandardClasses.getTuple(0); - } else if ("Any".equals(name)) { - return JetStandardClasses.getAny(); - } - if (CLASSES.isEmpty()) { - for (String classDeclaration : CLASS_DECLARATIONS) { - JetClass classElement = JetChangeUtil.createClass(getProject(), classDeclaration); - ClassDescriptor classDescriptor = toClassDescriptor(classElement); - CLASSES.put(classDescriptor.getName(), classDescriptor); - } - } - ClassDescriptor classDescriptor = CLASSES.get(name); - if (classDescriptor != null) { - return classDescriptor; - } - fail("Type not found: " + name); - throw new IllegalStateException(); - } - }; - - @Override protected String getTestDataPath() { return getHomeDirectory() + "/idea/testData"; @@ -215,46 +157,19 @@ public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase { assertNotSubtype("Base_T", "Base_T"); assertNotSubtype("Base_T", "Base_T"); assertNotSubtype("Base_T<*>", "Base_T"); + + assertNotSubtype("Derived_T", "Base_T"); + assertSubtype("Derived_outT", "Base_outT"); + assertNotSubtype("Derived_T", "Base_T"); + assertSubtype("Derived_outT", "Base_outT"); + assertSubtype("Derived_T", "Base_T"); + assertSubtype("Derived_T", "Base_T"); } public void testImplicitConversions() throws Exception { assertConvertibleTo("1", JetStandardTypes.getByte()); } - private static ClassDescriptor toClassDescriptor(JetClass classElement) { - return new ClassDescriptor( - toAttributes(classElement.getModifierList()), - classElement.getName(), - toTypeParameters(classElement.getTypeParameters()), - toTypes(classElement.getDelegationSpecifiers()) - ); - } - - private static List toTypeParameters(List typeParameters) { - List result = new ArrayList(); - for (JetTypeParameter typeParameter : typeParameters) { - result.add(toTypeParameter(typeParameter)); - } - return result; - } - - private static TypeParameterDescriptor toTypeParameter(JetTypeParameter typeParameter) { - JetTypeReference extendsBound = typeParameter.getExtendsBound(); - return new TypeParameterDescriptor( - toAttributes(typeParameter.getModifierList()), - typeParameter.getVariance(), - typeParameter.getName(), - extendsBound == null ? Collections.singleton(JetStandardClasses.getAnyType()) : Collections.singleton(toType(extendsBound)) - ); - } - - private static Collection toTypes(List delegationSpecifiers) { - if (delegationSpecifiers.isEmpty()) { - return Collections.emptyList(); - } - throw new UnsupportedOperationException(); // TODO - } - private static void assertSubtype(String type1, String type2) { assertSubtypingRelation(type1, type2, true); } @@ -264,8 +179,8 @@ public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase { } private static void assertSubtypingRelation(String type1, String type2, boolean expected) { - Type typeNode1 = toType(JetChangeUtil.createType(getProject(), type1)); - Type typeNode2 = toType(JetChangeUtil.createType(getProject(), type2)); + Type typeNode1 = TypeResolver.INSTANCE.resolveType(ClassDefinitions.BASIC_SCOPE, JetChangeUtil.createType(getProject(), type1)); + Type typeNode2 = TypeResolver.INSTANCE.resolveType(ClassDefinitions.BASIC_SCOPE, JetChangeUtil.createType(getProject(), type2)); boolean result = new JetTypeChecker().isSubtypeOf( typeNode1, typeNode2); @@ -273,73 +188,6 @@ public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase { assertTrue(typeNode1 + " is " + modifier + "a subtype of " + typeNode2, result == expected); } - private static Type toType(JetTypeReference typeNode) { - List attributeElements = typeNode.getAttributes(); - final List attributes = toAttributes(attributeElements); - JetTypeElement typeElement = typeNode.getTypeElement(); - - // TODO annotations - final Type[] result = new Type[1]; - typeElement.accept(new JetVisitor() { - @Override - public void visitUserType(JetUserType type) { - List argumentElements = type.getTypeArguments(); - - final List arguments = toTypeProjections(argumentElements); - result[0] = new ClassType(attributes, TypeResolver.INSTANCE.resolveClass(BASIC_SCOPE, type), arguments); - } - - @Override - public void visitTupleType(JetTupleType type) { - // TODO labels - result[0] = TupleType.getTupleType(toTypes(type.getComponentTypeRefs())); - } - - @Override - public void visitJetElement(JetElement elem) { - throw new IllegalArgumentException("Unsupported type: " + elem); - } - }); - - return result[0]; - } - - private static List toAttributes(List attributeElements) { - return Collections.emptyList(); - } - - private static List toAttributes(JetModifierList modifierList) { - if (modifierList == null) { - return Collections.emptyList(); - } - // TODO: - return Collections.emptyList(); - } - - private static List toTypes(List argumentElements) { - final List arguments = new ArrayList(); - for (JetTypeReference argumentElement : argumentElements) { - arguments.add(toType(argumentElement)); - } - return arguments; - } - - private static List toTypeProjections(List argumentElements) { - final List arguments = new ArrayList(); - for (JetTypeProjection argumentElement : argumentElements) { - ProjectionKind projectionKind = argumentElement.getProjectionKind(); - Type type; - if (projectionKind == ProjectionKind.NEITHER_OUT_NOR_IN) { - type = null; - } else { - type = toType(argumentElement.getTypeReference()); - } - TypeProjection typeProjection = new TypeProjection(projectionKind, type); - arguments.add(typeProjection); - } - return arguments; - } - private static void assertConvertibleTo(String expression, Type type) { JetExpression jetExpression = JetChangeUtil.createExpression(getProject(), expression); assertTrue( @@ -360,4 +208,55 @@ public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase { Type type = new JetTypeChecker().getType(jetExpression); assertEquals(type, expectedType); } + + private static class ClassDefinitions { + private static Map CLASSES = new HashMap(); + private static String[] CLASS_DECLARATIONS = { + "class Base_T", + "class Derived_T : Base_T", + "class Base_inT", + "class Derived_inT : Base_inT", + "class Base_outT", + "class Derived_outT : Base_outT", + }; + + public static JetScope BASIC_SCOPE = new JetScopeImpl() { + @Override + public ClassDescriptor getClass(String name) { + if ("Int".equals(name)) { + return JetStandardClasses.getInt(); + } else if ("Boolean".equals(name)) { + return JetStandardClasses.getBoolean(); + } else if ("Byte".equals(name)) { + return JetStandardClasses.getByte(); + } else if ("Char".equals(name)) { + return JetStandardClasses.getChar(); + } else if ("Short".equals(name)) { + return JetStandardClasses.getShort(); + } else if ("Long".equals(name)) { + return JetStandardClasses.getLong(); + } else if ("Float".equals(name)) { + return JetStandardClasses.getFloat(); + } else if ("Double".equals(name)) { + return JetStandardClasses.getDouble(); + } else if ("Unit".equals(name)) { + return JetStandardClasses.getTuple(0); + } else if ("Any".equals(name)) { + return JetStandardClasses.getAny(); + } + if (CLASSES.isEmpty()) { + for (String classDeclaration : CLASS_DECLARATIONS) { + JetClass classElement = JetChangeUtil.createClass(getProject(), classDeclaration); + ClassDescriptor classDescriptor = ClassDescriptorResolver.INSTANCE.resolveClassDescriptor(this, classElement); + CLASSES.put(classDescriptor.getName(), classDescriptor); + } + } + ClassDescriptor classDescriptor = CLASSES.get(name); + if (classDescriptor != null) { + return classDescriptor; + } + return null; + } + }; + } }