Contexts added for type parameter resolution. Annotations renamed into attributes for consistency

This commit is contained in:
Andrey Breslav
2011-01-26 22:05:59 +03:00
parent d80d3a628d
commit 798510b719
28 changed files with 497 additions and 258 deletions
@@ -8,5 +8,5 @@ import org.jetbrains.jet.lang.types.NamespaceDescriptor;
*/
public interface NamespaceDomain {
@Nullable
NamespaceDescriptor getNamespace(String namespaceName);
NamespaceDescriptor getNamespace(String name);
}
@@ -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.<JetTypeProjection>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();
}
}
@@ -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<Attribute> resolveAttributes(@NotNull List<JetAttribute> attributeElements) {
if (attributeElements.isEmpty()) {
return Collections.emptyList();
}
throw new UnsupportedOperationException(); // TODO
}
@NotNull
public List<Attribute> resolveAttributes(@Nullable JetModifierList modifierList) {
if (modifierList == null) {
return Collections.emptyList();
}
return resolveAttributes(modifierList.getAttributes());
}
}
@@ -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<TypeParameterDescriptor> resolveTypeParameters(TypeParameterExtensibleScope extensibleScope, List<JetTypeParameter> typeParameters) {
List<TypeParameterDescriptor> result = new ArrayList<TypeParameterDescriptor>();
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.<Type>singleton(JetStandardClasses.getAnyType())
: Collections.singleton(TypeResolver.INSTANCE.resolveType(extensibleScope, extendsBound))
);
extensibleScope.addTypeParameterDescriptor(typeParameterDescriptor);
return typeParameterDescriptor;
}
private static Collection<? extends Type> resolveTypes(TypeParameterExtensibleScope extensibleScope, List<JetDelegationSpecifier> delegationSpecifiers) {
if (delegationSpecifiers.isEmpty()) {
return Collections.emptyList();
}
Collection<Type> result = new ArrayList<Type>();
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<String, TypeParameterDescriptor> typeParameterDescriptors = new HashMap<String, TypeParameterDescriptor>();
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);
}
}
}
@@ -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);
}
@@ -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);
}
}
@@ -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;
}
}
@@ -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<Attribute> 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<Type> resolveTypes(JetScope scope, List<JetTypeReference> argumentElements) {
final List<Type> arguments = new ArrayList<Type>();
for (JetTypeReference argumentElement : argumentElements) {
arguments.add(resolveType(scope, argumentElement));
}
return arguments;
}
@NotNull
private List<TypeProjection> resolveTypeProjections(JetScope scope, List<JetTypeProjection> argumentElements) {
final List<TypeProjection> arguments = new ArrayList<TypeProjection>();
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) {
@@ -6,5 +6,5 @@ import java.util.List;
* @author abreslav
*/
public interface Annotated {
List<Annotation> getAnnotations();
List<Attribute> getAttributes();
}
@@ -6,14 +6,14 @@ import java.util.List;
* @author abreslav
*/
public abstract class AnnotatedImpl implements Annotated {
private final List<Annotation> annotations;
private final List<Attribute> attributes;
public AnnotatedImpl(List<Annotation> annotations) {
this.annotations = annotations;
public AnnotatedImpl(List<Attribute> attributes) {
this.attributes = attributes;
}
@Override
public List<Annotation> getAnnotations() {
return annotations;
public List<Attribute> getAttributes() {
return attributes;
}
}
@@ -3,5 +3,5 @@ package org.jetbrains.jet.lang.types;
/**
* @author abreslav
*/
public interface Annotation {
public interface Attribute {
}
@@ -13,14 +13,14 @@ public class ClassDescriptor extends MemberDescriptorImpl implements MemberDomai
private final TypeConstructor typeConstructor;
public ClassDescriptor(
List<Annotation> annotations,
List<Attribute> attributes,
String name, List<TypeParameterDescriptor> typeParameters, Collection<? extends Type> 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.<Annotation>emptyList(),
this(Collections.<Attribute>emptyList(),
name, Collections.<TypeParameterDescriptor>emptyList(),
Collections.<Type>singleton(JetStandardClasses.getAnyType()));
}
@@ -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<Annotation> annotations, ClassDescriptor classDescriptor, List<TypeProjection> arguments) {
super(annotations, classDescriptor.getTypeConstructor(), arguments);
public ClassType(@NotNull List<Attribute> attributes, @NotNull ClassDescriptor classDescriptor, @NotNull List<TypeProjection> 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.<Annotation>emptyList(), classDescriptor, Collections.<TypeProjection>emptyList());
this(Collections.<Attribute>emptyList(), classDescriptor, Collections.<TypeProjection>emptyList());
assert classDescriptor.getTypeConstructor().getParameters().size() == 0;
}
@NotNull
public ClassDescriptor getClassDescriptor() {
return classDescriptor;
}
@@ -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.<Attribute>emptyList());
this.debugLabel = typeReference.getText();
assert debugLabel != null;
}
@Override
public TypeConstructor getConstructor() {
throw new UnsupportedOperationException("Not found: " + debugLabel); // TODO
}
@Override
public List<TypeProjection> getArguments() {
throw new UnsupportedOperationException("Not found: " + debugLabel); // TODO
}
@Override
public Collection<MemberDescriptor> getMembers() {
throw new UnsupportedOperationException("Not found: " + debugLabel); // TODO
}
@Override
public <R, D> R accept(TypeVisitor<R, D> visitor, D data) {
throw new UnsupportedOperationException("Not found: " + debugLabel); // TODO
}
@Override
public String toString() {
return "!!!" + debugLabel + "!!!";
}
}
@@ -11,7 +11,7 @@ import java.util.List;
*/
public class JetStandardClasses {
private static final ClassDescriptor ANY = new ClassDescriptor(
Collections.<Annotation>emptyList(),
Collections.<Attribute>emptyList(),
"Any",
Collections.<TypeParameterDescriptor>emptyList(),
Collections.<Type>emptySet()
@@ -36,12 +36,12 @@ public class JetStandardClasses {
List<TypeParameterDescriptor> parameters = new ArrayList<TypeParameterDescriptor>();
for (int j = 0; j < i; j++) {
parameters.add(new TypeParameterDescriptor(
Collections.<Annotation>emptyList(),
Collections.<Attribute>emptyList(),
Variance.OUT_VARIANCE, "T" + j,
Collections.<Type>emptySet()));
}
TUPLE[i] = new ClassDescriptor(
Collections.<Annotation>emptyList(),
Collections.<Attribute>emptyList(),
"Tuple" + i,
parameters,
Collections.singleton(JetStandardClasses.getAnyType()));
@@ -6,7 +6,7 @@ import java.util.List;
* @author abreslav
*/
public abstract class MemberDescriptorImpl extends NamedAnnotatedImpl {
public MemberDescriptorImpl(List<Annotation> annotations, String name) {
super(annotations, name);
public MemberDescriptorImpl(List<Attribute> attributes, String name) {
super(attributes, name);
}
}
@@ -9,8 +9,8 @@ public abstract class NamedAnnotatedImpl extends AnnotatedImpl {
private final String name;
public NamedAnnotatedImpl(List<Annotation> annotations, String name) {
super(annotations);
public NamedAnnotatedImpl(List<Attribute> attributes, String name) {
super(attributes);
this.name = name;
}
@@ -8,7 +8,7 @@ import java.util.*;
public class NothingType extends TypeImpl {
public static final TypeConstructor NOTHING = new TypeConstructor(
Collections.<Annotation>emptyList(),
Collections.<Attribute>emptyList(),
"Nothing",
Collections.<TypeParameterDescriptor>emptyList(),
new AbstractCollection<Type>() {
@@ -29,9 +29,9 @@ public class NothingType extends TypeImpl {
}
});
// TODO: annotations seem wrong here
public NothingType(List<Annotation> annotations) {
super(annotations, NOTHING, Collections.<TypeProjection>emptyList());
// TODO: attributes seem wrong here
public NothingType(List<Attribute> attributes) {
super(attributes, NOTHING, Collections.<TypeProjection>emptyList());
}
@Override
@@ -9,8 +9,8 @@ public class ParameterDescriptor extends AnnotatedImpl {
private final Type type;
private final String name;
public ParameterDescriptor(List<Annotation> annotations, Type type, String name) {
super(annotations);
public ParameterDescriptor(List<Attribute> attributes, Type type, String name) {
super(attributes);
this.type = type;
this.name = name;
}
@@ -9,14 +9,14 @@ import java.util.List;
* @author abreslav
*/
public class ThisType extends TypeImpl {
public ThisType(List<Annotation> annotations, ClassDescriptor thisClass) {
super(annotations, thisClass.getTypeConstructor(), toArguments(thisClass.getTypeConstructor().getParameters()));
public ThisType(List<Attribute> attributes, ClassDescriptor thisClass) {
super(attributes, thisClass.getTypeConstructor(), toArguments(thisClass.getTypeConstructor().getParameters()));
}
private static List<TypeProjection> toArguments(List<TypeParameterDescriptor> parameters) {
List<TypeProjection> result = new ArrayList<TypeProjection>();
for (TypeParameterDescriptor parameter : parameters) {
result.add(new TypeProjection(new TypeVariable(Collections.<Annotation>emptyList(), parameter)));
result.add(new TypeProjection(new TypeVariable(Collections.<Attribute>emptyList(), parameter)));
}
return result;
}
@@ -10,32 +10,32 @@ import java.util.List;
*/
public class TupleType extends TypeImpl {
public static final TupleType UNIT = new TupleType(Collections.<Annotation>emptyList(), Collections.<Type>emptyList());
public static final TupleType UNIT = new TupleType(Collections.<Attribute>emptyList(), Collections.<Type>emptyList());
public static TupleType getTupleType(List<Annotation> annotations, List<Type> arguments) {
if (annotations.isEmpty() && arguments.isEmpty()) {
public static TupleType getTupleType(List<Attribute> attributes, List<Type> arguments) {
if (attributes.isEmpty() && arguments.isEmpty()) {
return UNIT;
}
return new TupleType(annotations, arguments);
return new TupleType(attributes, arguments);
}
public static TupleType getTupleType(List<Type> arguments) {
return getTupleType(Collections.<Annotation>emptyList(), arguments);
return getTupleType(Collections.<Attribute>emptyList(), arguments);
}
public static TupleType getLabeledTupleType(List<Annotation> annotations, List<ParameterDescriptor> arguments) {
return getTupleType(annotations, toTypes(arguments));
public static TupleType getLabeledTupleType(List<Attribute> attributes, List<ParameterDescriptor> arguments) {
return getTupleType(attributes, toTypes(arguments));
}
public static TupleType getLabeledTupleType(List<ParameterDescriptor> arguments) {
return getLabeledTupleType(Collections.<Annotation>emptyList(), arguments);
return getLabeledTupleType(Collections.<Attribute>emptyList(), arguments);
}
private TupleType(List<Annotation> annotations, List<Type> arguments) {
super(annotations, JetStandardClasses.getTuple(arguments.size()).getTypeConstructor(), toProjections(arguments));
private TupleType(List<Attribute> attributes, List<Type> arguments) {
super(attributes, JetStandardClasses.getTuple(arguments.size()).getTypeConstructor(), toProjections(arguments));
}
@Override
@@ -11,8 +11,8 @@ public class TypeConstructor extends AnnotatedImpl {
private final Collection<? extends Type> supertypes;
private final String debugName;
public TypeConstructor(List<Annotation> annotations, String debugName, List<TypeParameterDescriptor> parameters, Collection<? extends Type> supertypes) {
super(annotations);
public TypeConstructor(List<Attribute> attributes, String debugName, List<TypeParameterDescriptor> parameters, Collection<? extends Type> supertypes) {
super(attributes);
this.debugName = debugName;
this.parameters = parameters;
this.supertypes = supertypes;
@@ -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<TypeProjection> arguments;
public TypeImpl(List<Annotation> annotations, TypeConstructor constructor, List<TypeProjection> arguments) {
super(annotations);
public TypeImpl(List<Attribute> attributes, TypeConstructor constructor, List<TypeProjection> 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> R acceptNoData(TypeVisitor<R, ?> visitor) {
return accept(visitor, null);
}
@Override
public void acceptVoid(TypeVisitor<?, ?> visitor) {
accept(visitor, null);
}
}
@@ -12,13 +12,13 @@ public class TypeParameterDescriptor extends NamedAnnotatedImpl {
private final Collection<Type> upperBounds;
private final TypeConstructor typeConstructor;
public TypeParameterDescriptor(List<Annotation> annotations, Variance variance, String name, Collection<Type> upperBounds) {
super(annotations, name);
public TypeParameterDescriptor(List<Attribute> attributes, Variance variance, String name, Collection<Type> 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.<TypeParameterDescriptor>emptyList(),
upperBounds);
@@ -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<Annotation> annotations, TypeParameterDescriptor typeParameter) {
super(annotations, typeParameter.getTypeConstructor(), Collections.<TypeProjection>emptyList());
public TypeVariable(@NotNull List<Attribute> attributes, @NotNull TypeParameterDescriptor typeParameter) {
super(attributes, typeParameter.getTypeConstructor(), Collections.<TypeProjection>emptyList());
}
@Override
public Collection<MemberDescriptor> getMembers() {
throw new javax.help.UnsupportedOperationException(); // TODO
throw new UnsupportedOperationException(); // TODO
}
@Override
public <R, D> R accept(TypeVisitor<R, D> visitor, D data) {
return visitor.visitTypeVariable(this, data);
}
@Override
public String toString() {
return "&" + super.toString();
}
}
@@ -23,7 +23,11 @@ public class TypeVisitor<R, D> {
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
}
@@ -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<Attribute> attributes) {
super(attributes);
}
@Override
public <R> R acceptNoData(TypeVisitor<R, ?> visitor) {
return accept(visitor, null);
}
@Override
public void acceptVoid(TypeVisitor<?, ?> visitor) {
accept(visitor, null);
}
}
@@ -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.<Annotation>emptyList(),
"Base_T",
Arrays.asList(
new TypeParameterDescriptor(
Collections.<Annotation>emptyList(),
Variance.INVARIANT, "T",
Collections.<Type>emptyList())
),
Collections.singleton(JetStandardClasses.getAnyType())
);
private static Map<String, ClassDescriptor> CLASSES = new HashMap<String, ClassDescriptor>();
private static String[] CLASS_DECLARATIONS = {
"class Base_T<T>",
"class Base_inT<in T>",
"class Base_outT<out T>",
};
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<out Any>", "Base_T<in Int>");
assertNotSubtype("Base_T<in Int>", "Base_T<out Int>");
assertNotSubtype("Base_T<*>", "Base_T<out Int>");
assertNotSubtype("Derived_T<Any>", "Base_T<Any>");
assertSubtype("Derived_outT<Any>", "Base_outT<Any>");
assertNotSubtype("Derived_T<Int>", "Base_T<Any>");
assertSubtype("Derived_outT<Int>", "Base_outT<Any>");
assertSubtype("Derived_T<Int>", "Base_T<out Any>");
assertSubtype("Derived_T<Any>", "Base_T<in Int>");
}
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<TypeParameterDescriptor> toTypeParameters(List<JetTypeParameter> typeParameters) {
List<TypeParameterDescriptor> result = new ArrayList<TypeParameterDescriptor>();
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.<Type>singleton(JetStandardClasses.getAnyType()) : Collections.singleton(toType(extendsBound))
);
}
private static Collection<? extends Type> toTypes(List<JetDelegationSpecifier> 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<JetAttribute> attributeElements = typeNode.getAttributes();
final List<Annotation> 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<JetTypeProjection> argumentElements = type.getTypeArguments();
final List<TypeProjection> 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<Annotation> toAttributes(List<JetAttribute> attributeElements) {
return Collections.emptyList();
}
private static List<Annotation> toAttributes(JetModifierList modifierList) {
if (modifierList == null) {
return Collections.emptyList();
}
// TODO:
return Collections.emptyList();
}
private static List<Type> toTypes(List<JetTypeReference> argumentElements) {
final List<Type> arguments = new ArrayList<Type>();
for (JetTypeReference argumentElement : argumentElements) {
arguments.add(toType(argumentElement));
}
return arguments;
}
private static List<TypeProjection> toTypeProjections(List<JetTypeProjection> argumentElements) {
final List<TypeProjection> arguments = new ArrayList<TypeProjection>();
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<String, ClassDescriptor> CLASSES = new HashMap<String, ClassDescriptor>();
private static String[] CLASS_DECLARATIONS = {
"class Base_T<T>",
"class Derived_T<T> : Base_T<T>",
"class Base_inT<in T>",
"class Derived_inT<in T> : Base_inT<T>",
"class Base_outT<out T>",
"class Derived_outT<out T> : Base_outT<T>",
};
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;
}
};
}
}