diff --git a/idea/src/org/jetbrains/jet/lang/resolve/TypeResolver.java b/idea/src/org/jetbrains/jet/lang/resolve/TypeResolver.java index 1b537d0bef7..231c8a88411 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/TypeResolver.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/TypeResolver.java @@ -7,6 +7,7 @@ import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.types.*; import java.util.ArrayList; +import java.util.Collections; import java.util.List; /** @@ -23,29 +24,48 @@ public class TypeResolver { public Type resolveType(@NotNull final JetScope scope, @NotNull final JetTypeReference typeReference) { final List attributes = AttributeResolver.INSTANCE.resolveAttributes(typeReference.getAttributes()); + JetTypeElement typeElement = typeReference.getTypeElement(); + return resolveTypeElement(scope, attributes, typeElement, false); + } + + private Type resolveTypeElement(final JetScope scope, final List attributes, JetTypeElement typeElement, final boolean nullable) { final Type[] result = new Type[1]; - typeReference.getTypeElement().accept(new JetVisitor() { + typeElement.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()) + result[0] = new TypeImpl( + attributes, + classDescriptor.getTypeConstructor(), + nullable, + resolveTypeProjections(scope, type.getTypeArguments()), + JetStandardClasses.STUB ); - } else if (type.getTypeArguments().isEmpty()) { + } + else if (type.getTypeArguments().isEmpty()) { TypeParameterDescriptor typeParameterDescriptor = scope.getTypeParameterDescriptor(type.getReferencedName()); if (typeParameterDescriptor != null) { - result[0] = new TypeVariable(attributes, typeParameterDescriptor); + result[0] = new TypeImpl( + attributes, + typeParameterDescriptor.getTypeConstructor(), + nullable || hasNullableBound(typeParameterDescriptor), + Collections.emptyList(), + JetStandardClasses.STUB + ); } } } + @Override + public void visitNullableType(JetNullableType nullableType) { + result[0] = resolveTypeElement(scope, attributes, nullableType.getInnerType(), true); + } + @Override public void visitTupleType(JetTupleType type) { // TODO labels - result[0] = TupleType.getTupleType(resolveTypes(scope, type.getComponentTypeRefs())); + result[0] = JetStandardClasses.getTupleType(resolveTypes(scope, type.getComponentTypeRefs())); } @Override @@ -54,11 +74,20 @@ public class TypeResolver { } }); if (result[0] == null) { - return new ErrorType(typeReference); + return ErrorType.createErrorType(typeElement.getText()); } return result[0]; } + private boolean hasNullableBound(TypeParameterDescriptor typeParameterDescriptor) { + for (Type bound : typeParameterDescriptor.getUpperBounds()) { + if (bound.isNullable()) { + return true; + } + } + return false; + } + private List resolveTypes(JetScope scope, List argumentElements) { final List arguments = new ArrayList(); for (JetTypeReference argumentElement : argumentElements) { diff --git a/idea/src/org/jetbrains/jet/lang/types/ClassType.java b/idea/src/org/jetbrains/jet/lang/types/ClassType.java deleted file mode 100644 index b084a38ecb4..00000000000 --- a/idea/src/org/jetbrains/jet/lang/types/ClassType.java +++ /dev/null @@ -1,42 +0,0 @@ -package org.jetbrains.jet.lang.types; - -import org.jetbrains.annotations.NotNull; - -import java.util.Collection; -import java.util.Collections; -import java.util.List; - -/** - * @author abreslav - */ -public class ClassType extends TypeImpl { - @NotNull - private final ClassDescriptor classDescriptor; - - 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()); - assert classDescriptor.getTypeConstructor().getParameters().size() == 0; - } - - @NotNull - public ClassDescriptor getClassDescriptor() { - return classDescriptor; - } - - @Override - public Collection getMembers() { - throw new UnsupportedOperationException(); // TODO - } - - @Override - public R accept(TypeVisitor visitor, D data) { - return visitor.visitClassType(this, data); - } -} diff --git a/idea/src/org/jetbrains/jet/lang/types/ErrorType.java b/idea/src/org/jetbrains/jet/lang/types/ErrorType.java index 7af0c20e08c..96b660ec231 100644 --- a/idea/src/org/jetbrains/jet/lang/types/ErrorType.java +++ b/idea/src/org/jetbrains/jet/lang/types/ErrorType.java @@ -1,45 +1,26 @@ package org.jetbrains.jet.lang.types; -import org.jetbrains.jet.lang.psi.JetTypeReference; +import org.jetbrains.annotations.NotNull; -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 class ErrorType { + private static final TypeMemberDomain ERROR_DOMAIN = new TypeMemberDomain() { + @Override + public ClassDescriptor getClassDescriptor(@NotNull Type type) { + throw new UnsupportedOperationException(); // TODO + } + }; + private static final TypeConstructor ERROR = new TypeConstructor(Collections.emptyList(), "ERROR", Collections.emptyList(), Collections.emptyList()); - public ErrorType(JetTypeReference typeReference) { - super(Collections.emptyList()); - this.debugLabel = typeReference.getText(); - assert debugLabel != null; + public static Type createErrorType(String debugMessage) { + return new TypeImpl(ERROR, ERROR_DOMAIN); } - @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) { - return visitor.visitErrorType(this, data); - } - - @Override - public String toString() { - return "!!!" + debugLabel + "!!!"; + public static boolean isError(Type type) { + return type.getConstructor() == ERROR; } } diff --git a/idea/src/org/jetbrains/jet/lang/types/JetStandardClasses.java b/idea/src/org/jetbrains/jet/lang/types/JetStandardClasses.java index 29c05290f1f..0dbddf910a7 100644 --- a/idea/src/org/jetbrains/jet/lang/types/JetStandardClasses.java +++ b/idea/src/org/jetbrains/jet/lang/types/JetStandardClasses.java @@ -2,14 +2,34 @@ package org.jetbrains.jet.lang.types; import org.jetbrains.annotations.NotNull; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; +import java.util.*; /** * @author abreslav */ public class JetStandardClasses { + private static final TypeConstructor NOTHING = new TypeConstructor( + Collections.emptyList(), + "Nothing", + Collections.emptyList(), + new AbstractCollection() { + + @Override + public boolean contains(Object o) { + return o instanceof Type; + } + + @Override + public Iterator iterator() { + throw new UnsupportedOperationException(); + } + + @Override + public int size() { + throw new UnsupportedOperationException(); + } + }); + private static final ClassDescriptor ANY = new ClassDescriptor( Collections.emptyList(), "Any", @@ -17,7 +37,7 @@ public class JetStandardClasses { Collections.emptySet() ); - private static final ClassType ANY_TYPE = new ClassType(ANY); + private static final Type ANY_TYPE = new TypeImpl(ANY.getTypeConstructor(), TypeMemberDomain.EMPTY); private static final ClassDescriptor BYTE = new ClassDescriptor("Byte"); private static final ClassDescriptor CHAR = new ClassDescriptor("Char"); @@ -48,13 +68,33 @@ public class JetStandardClasses { } } + public static final TypeMemberDomain STUB = new TypeMemberDomain() { + @Override + public ClassDescriptor getClassDescriptor(@NotNull Type type) { + throw new UnsupportedOperationException(); // TODO + } + }; + + private static final Type BYTE_TYPE = new TypeImpl(getByte().getTypeConstructor(), STUB); + private static final Type CHAR_TYPE = new TypeImpl(getChar().getTypeConstructor(), STUB); + private static final Type SHORT_TYPE = new TypeImpl(getShort().getTypeConstructor(), STUB); + private static final Type INT_TYPE = new TypeImpl(getInt().getTypeConstructor(), STUB); + private static final Type LONG_TYPE = new TypeImpl(getLong().getTypeConstructor(), STUB); + private static final Type FLOAT_TYPE = new TypeImpl(getFloat().getTypeConstructor(), STUB); + private static final Type DOUBLE_TYPE = new TypeImpl(getDouble().getTypeConstructor(), STUB); + private static final Type BOOLEAN_TYPE = new TypeImpl(getBoolean().getTypeConstructor(), STUB); + private static final Type STRING_TYPE = new TypeImpl(getString().getTypeConstructor(), STUB); + private static final Type UNIT_TYPE = new TypeImpl(getTuple(0).getTypeConstructor(), STUB); + private static final Type NOTHING_TYPE = new TypeImpl(NOTHING, STUB); + private static final Type NULLABLE_NOTHING_TYPE = new TypeImpl(Collections.emptyList(), NOTHING, true, Collections.emptyList(), TypeMemberDomain.EMPTY); + @NotNull public static ClassDescriptor getAny() { return ANY; } @NotNull - public static ClassType getAnyType() { + public static Type getAnyType() { return ANY_TYPE; } @@ -108,9 +148,92 @@ public class JetStandardClasses { return TUPLE[size]; } - @NotNull - public static ClassDescriptor getLabeledTuple(int size) { + public static Type getIntType() { + return INT_TYPE; + } + + public static Type getLongType() { + return LONG_TYPE; + } + + public static Type getDoubleType() { + return DOUBLE_TYPE; + } + + public static Type getFloatType() { + return FLOAT_TYPE; + } + + public static Type getCharType() { + return CHAR_TYPE; + } + + public static Type getBooleanType() { + return BOOLEAN_TYPE; + } + + public static Type getStringType() { + return STRING_TYPE; + } + + public static Type getByteType() { + return BYTE_TYPE; + } + + public static Type getShortType() { + return SHORT_TYPE; + } + + public static Type getUnitType() { + return UNIT_TYPE; + } + + public static Type getNothingType() { + return NOTHING_TYPE; + } + + public static Type getNullableNothingType() { + return NULLABLE_NOTHING_TYPE; + } + + public static Type getTupleType(List attributes, List arguments) { + if (attributes.isEmpty() && arguments.isEmpty()) { + return getUnitType(); + } + return new TypeImpl(attributes, getTuple(arguments.size()).getTypeConstructor(), false, toProjections(arguments), STUB); + } + + public static Type getTupleType(List arguments) { + return getTupleType(Collections.emptyList(), arguments); + } + + public static Type getTupleType(Type... arguments) { + return getTupleType(Collections.emptyList(), Arrays.asList(arguments)); + } + + public static Type getLabeledTupleType(List attributes, List arguments) { // TODO - return getTuple(size); + return getTupleType(attributes, toTypes(arguments)); + } + + public static Type getLabeledTupleType(List arguments) { + // TODO + return getLabeledTupleType(Collections.emptyList(), arguments); + } + + private static List toProjections(List arguments) { + List result = new ArrayList(); + for (Type argument : arguments) { + result.add(new TypeProjection(ProjectionKind.OUT_ONLY, argument)); + } + return result; + } + + private static List toTypes(List labeledEntries) { + List result = new ArrayList(); + for (ParameterDescriptor entry : labeledEntries) { + result.add(entry.getType()); + } + return result; } } diff --git a/idea/src/org/jetbrains/jet/lang/types/JetStandardTypes.java b/idea/src/org/jetbrains/jet/lang/types/JetStandardTypes.java deleted file mode 100644 index 4510a379bd1..00000000000 --- a/idea/src/org/jetbrains/jet/lang/types/JetStandardTypes.java +++ /dev/null @@ -1,64 +0,0 @@ -package org.jetbrains.jet.lang.types; - -import java.util.Collections; - -/** - * @author abreslav - */ -public class JetStandardTypes { - private static final ClassType ANY_TYPE = new ClassType(JetStandardClasses.getAny()); - private static final ClassType BYTE = new ClassType(JetStandardClasses.getByte()); - private static final ClassType CHAR = new ClassType(JetStandardClasses.getChar()); - private static final ClassType SHORT = new ClassType(JetStandardClasses.getShort()); - private static final ClassType INT = new ClassType(JetStandardClasses.getInt()); - private static final ClassType LONG = new ClassType(JetStandardClasses.getLong()); - private static final ClassType FLOAT = new ClassType(JetStandardClasses.getFloat()); - private static final ClassType DOUBLE = new ClassType(JetStandardClasses.getDouble()); - private static final ClassType BOOLEAN = new ClassType(JetStandardClasses.getBoolean()); - private static final ClassType STRING = new ClassType(JetStandardClasses.getString()); - private static final TupleType UNIT = TupleType.UNIT; - - public static ClassType getInt() { - return INT; - } - - public static ClassType getLong() { - return LONG; - } - - public static ClassType getDouble() { - return DOUBLE; - } - - public static ClassType getFloat() { - return FLOAT; - } - - public static ClassType getChar() { - return CHAR; - } - - public static ClassType getBoolean() { - return BOOLEAN; - } - - public static ClassType getString() { - return STRING; - } - - public static ClassType getByte() { - return BYTE; - } - - public static ClassType getShort() { - return SHORT; - } - - public static TupleType getUnit() { - return UNIT; - } - - public static Type getAny() { - return ANY_TYPE; - } -} diff --git a/idea/src/org/jetbrains/jet/lang/types/JetTypeChecker.java b/idea/src/org/jetbrains/jet/lang/types/JetTypeChecker.java index 03c715fe47d..9da93fe2cb2 100644 --- a/idea/src/org/jetbrains/jet/lang/types/JetTypeChecker.java +++ b/idea/src/org/jetbrains/jet/lang/types/JetTypeChecker.java @@ -15,6 +15,8 @@ import java.util.Map; * @author abreslav */ public class JetTypeChecker { + public static final JetTypeChecker INSTANCE = new JetTypeChecker(); + public Type getType(JetExpression expression) { final Type[] result = new Type[1]; expression.accept(new JetVisitor() { @@ -22,24 +24,26 @@ public class JetTypeChecker { public void visitConstantExpression(JetConstantExpression expression) { IElementType elementType = expression.getNode().getElementType(); if (elementType == JetNodeTypes.INTEGER_CONSTANT) { - result[0] = JetStandardTypes.getInt(); + result[0] = JetStandardClasses.getIntType(); } else if (elementType == JetNodeTypes.LONG_CONSTANT) { - result[0] = JetStandardTypes.getLong(); + result[0] = JetStandardClasses.getLongType(); } else if (elementType == JetNodeTypes.FLOAT_CONSTANT) { String text = expression.getText(); assert text.length() > 0; char lastChar = text.charAt(text.length() - 1); if (lastChar == 'f' || lastChar == 'F') { - result[0] = JetStandardTypes.getFloat(); + result[0] = JetStandardClasses.getFloatType(); } else { - result[0] = JetStandardTypes.getDouble(); + result[0] = JetStandardClasses.getDoubleType(); } } else if (elementType == JetNodeTypes.BOOLEAN_CONSTANT) { - result[0] = JetStandardTypes.getBoolean(); + result[0] = JetStandardClasses.getBooleanType(); } else if (elementType == JetNodeTypes.CHARACTER_CONSTANT) { - result[0] = JetStandardTypes.getChar(); + result[0] = JetStandardClasses.getCharType(); } else if (elementType == JetNodeTypes.STRING_CONSTANT) { - result[0] = JetStandardTypes.getString(); + result[0] = JetStandardClasses.getStringType(); + } else if (elementType == JetNodeTypes.NULL) { + result[0] = JetStandardClasses.getNullableNothingType(); } else { throw new IllegalArgumentException("Unsupported constant: " + expression); } @@ -52,7 +56,7 @@ public class JetTypeChecker { for (JetExpression entry : entries) { types.add(getType(entry)); } - result[0] = TupleType.getTupleType(types); + result[0] = JetStandardClasses.getTupleType(types); } @Override @@ -68,8 +72,10 @@ public class JetTypeChecker { } public boolean isSubtypeOf(Type subtype, Type supertype) { - @Nullable - Type closestSupertype = findCorrespondingSupertype(subtype, supertype); + if (!supertype.isNullable() && subtype.isNullable()) { + return false; + } + @Nullable Type closestSupertype = findCorrespondingSupertype(subtype, supertype); if (closestSupertype == null) { return false; } @@ -95,30 +101,24 @@ public class JetTypeChecker { } private Type substituteForParameters(Type context, Type subject) { - Map parameterValues = new HashMap(); + 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, value); + parameterValues.put(parameter.getTypeConstructor(), value); } return substitute(parameterValues, subject); } @NotNull - private Type substitute(Map parameterValues, Type subject) { - if (subject instanceof TypeVariable) { - TypeVariable typeVariable = (TypeVariable) subject; - TypeProjection value = parameterValues.get(typeVariable.getTypeParameterDescriptor()); - if (value == null) { - return typeVariable; - } - Type type = value.getType(); - assert type != null; - return type; + private Type substitute(Map parameterValues, Type subject) { + TypeProjection value = parameterValues.get(subject.getConstructor()); + if (value != null) { + return value.getType(); } List newArguments = new ArrayList(); for (TypeProjection argument : subject.getArguments()) { @@ -128,13 +128,7 @@ public class JetTypeChecker { } private Type specializeType(Type type, List newArguments) { - return type.accept(new TypeVisitor>() { - @Override - public Type visitClassType(ClassType classType, List newArguments) { - return new ClassType(classType.getAttributes(), classType.getClassDescriptor(), newArguments); - } - - }, newArguments); + return new TypeImpl(type.getAttributes(), type.getConstructor(), type.isNullable(), newArguments, type.getMemberDomain()); } private boolean checkSubtypeForTheSameConstructor(Type subtype, Type supertype) { @@ -212,7 +206,7 @@ public class JetTypeChecker { return true; } - private boolean equalTypes(Type type1, Type type2) { + public boolean equalTypes(Type type1, Type type2) { if (!type1.getConstructor().equals(type2.getConstructor())) { return false; } diff --git a/idea/src/org/jetbrains/jet/lang/types/NothingType.java b/idea/src/org/jetbrains/jet/lang/types/NothingType.java deleted file mode 100644 index 2e5a8d705d2..00000000000 --- a/idea/src/org/jetbrains/jet/lang/types/NothingType.java +++ /dev/null @@ -1,46 +0,0 @@ -package org.jetbrains.jet.lang.types; - -import java.util.*; - -/** - * @author abreslav - */ -public class NothingType extends TypeImpl { - - public static final TypeConstructor NOTHING = new TypeConstructor( - Collections.emptyList(), - "Nothing", - Collections.emptyList(), - new AbstractCollection() { - - @Override - public boolean contains(Object o) { - return o instanceof Type; - } - - @Override - public Iterator iterator() { - throw new UnsupportedOperationException(); - } - - @Override - public int size() { - throw new UnsupportedOperationException(); - } - }); - - // TODO: attributes seem wrong here - public NothingType(List attributes) { - super(attributes, NOTHING, Collections.emptyList()); - } - - @Override - public Collection getMembers() { - return Collections.emptySet(); - } - - @Override - public R accept(TypeVisitor visitor, D data) { - return visitor.visitNothingType(this, data); - } -} diff --git a/idea/src/org/jetbrains/jet/lang/types/NullableType.java b/idea/src/org/jetbrains/jet/lang/types/NullableType.java deleted file mode 100644 index 7a4bb27c8ac..00000000000 --- a/idea/src/org/jetbrains/jet/lang/types/NullableType.java +++ /dev/null @@ -1,33 +0,0 @@ -package org.jetbrains.jet.lang.types; - -import java.util.Collection; -import java.util.List; - -/** - * @author abreslav - */ -public class NullableType extends VisitableTypeImpl { - public NullableType(List attributes) { - super(attributes); - } - - @Override - public TypeConstructor getConstructor() { - throw new UnsupportedOperationException(); // TODO - } - - @Override - public List getArguments() { - throw new UnsupportedOperationException(); // TODO - } - - @Override - public Collection getMembers() { - throw new UnsupportedOperationException(); // TODO - } - - @Override - public R accept(TypeVisitor visitor, D data) { - return visitor.visitNullableType(this, data); - } -} diff --git a/idea/src/org/jetbrains/jet/lang/types/ThisType.java b/idea/src/org/jetbrains/jet/lang/types/ThisType.java deleted file mode 100644 index 433a497fd16..00000000000 --- a/idea/src/org/jetbrains/jet/lang/types/ThisType.java +++ /dev/null @@ -1,33 +0,0 @@ -package org.jetbrains.jet.lang.types; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; - -/** - * @author abreslav - */ -public class ThisType extends TypeImpl { - 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))); - } - return result; - } - - @Override - public Collection getMembers() { - throw new UnsupportedOperationException(); // TODO - } - - @Override - public R accept(TypeVisitor visitor, D data) { - return visitor.visitThisType(this, data); - } -} diff --git a/idea/src/org/jetbrains/jet/lang/types/TupleType.java b/idea/src/org/jetbrains/jet/lang/types/TupleType.java deleted file mode 100644 index c995f71d79a..00000000000 --- a/idea/src/org/jetbrains/jet/lang/types/TupleType.java +++ /dev/null @@ -1,66 +0,0 @@ -package org.jetbrains.jet.lang.types; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; - -/** - * @author abreslav - */ -public class TupleType extends TypeImpl { - - public static final TupleType UNIT = new TupleType(Collections.emptyList(), Collections.emptyList()); - - public static TupleType getTupleType(List attributes, List arguments) { - if (attributes.isEmpty() && arguments.isEmpty()) { - return UNIT; - } - return new TupleType(attributes, arguments); - } - - - public static TupleType getTupleType(List arguments) { - return getTupleType(Collections.emptyList(), 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); - } - - - private TupleType(List attributes, List arguments) { - super(attributes, JetStandardClasses.getTuple(arguments.size()).getTypeConstructor(), toProjections(arguments)); - } - - @Override - public Collection getMembers() { - throw new UnsupportedOperationException("Not implemented"); // TODO - } - - @Override - public R accept(TypeVisitor visitor, D data) { - return visitor.visitTupleType(this, data); - } - - private static List toProjections(List arguments) { - List result = new ArrayList(); - for (Type argument : arguments) { - result.add(new TypeProjection(ProjectionKind.OUT_ONLY, argument)); - } - return result; - } - - private static List toTypes(List labeledEntries) { - List result = new ArrayList(); - for (ParameterDescriptor entry : labeledEntries) { - result.add(entry.getType()); - } - return result; - } -} diff --git a/idea/src/org/jetbrains/jet/lang/types/Type.java b/idea/src/org/jetbrains/jet/lang/types/Type.java index 25f5bc4d98d..0bc961dc3f9 100644 --- a/idea/src/org/jetbrains/jet/lang/types/Type.java +++ b/idea/src/org/jetbrains/jet/lang/types/Type.java @@ -1,18 +1,18 @@ package org.jetbrains.jet.lang.types; -import java.util.Collection; +import org.jetbrains.annotations.NotNull; + import java.util.List; /** * @author abreslav */ public interface Type extends Annotated { - TypeConstructor getConstructor(); - List getArguments(); + @NotNull TypeConstructor getConstructor(); + @NotNull List getArguments(); + boolean isNullable(); - Collection getMembers(); + @NotNull TypeMemberDomain getMemberDomain(); - R accept(TypeVisitor visitor, D data); - R acceptNoData(TypeVisitor visitor); - void acceptVoid(TypeVisitor visitor); + @NotNull Type getNullableVersion(); } diff --git a/idea/src/org/jetbrains/jet/lang/types/TypeImpl.java b/idea/src/org/jetbrains/jet/lang/types/TypeImpl.java index 98c23604542..5969d954bd1 100644 --- a/idea/src/org/jetbrains/jet/lang/types/TypeImpl.java +++ b/idea/src/org/jetbrains/jet/lang/types/TypeImpl.java @@ -1,20 +1,38 @@ package org.jetbrains.jet.lang.types; +import java.util.Collections; import java.util.Iterator; import java.util.List; /** * @author abreslav */ -public abstract class TypeImpl extends VisitableTypeImpl { +public final class TypeImpl extends AnnotatedImpl implements Type { private final TypeConstructor constructor; private final List arguments; + private final boolean nullable; + private final TypeMemberDomain memberDomain; - public TypeImpl(List attributes, TypeConstructor constructor, List arguments) { + public TypeImpl(List attributes, TypeConstructor constructor, boolean nullable, List arguments, TypeMemberDomain memberDomain) { super(attributes); this.constructor = constructor; + this.nullable = nullable; this.arguments = arguments; + this.memberDomain = memberDomain; + } + + public TypeImpl(TypeConstructor constructor, TypeMemberDomain memberDomain) { + this(Collections.emptyList(), constructor, false, Collections.emptyList(), memberDomain); + } + + @Override + public Type getNullableVersion() { + if (isNullable()) { + return this; + } + // TODO: cache these? + return new TypeImpl(getAttributes(), constructor, true, arguments, memberDomain); } @Override @@ -27,9 +45,19 @@ public abstract class TypeImpl extends VisitableTypeImpl { return arguments; } + @Override + public boolean isNullable() { + return nullable; + } + + @Override + public TypeMemberDomain getMemberDomain() { + return memberDomain; + } + @Override public String toString() { - return constructor + (arguments.isEmpty() ? "" : "<" + argumentsToString() + ">"); + return constructor + (arguments.isEmpty() ? "" : "<" + argumentsToString() + ">") + (isNullable() ? "?" : ""); } private StringBuilder argumentsToString() { diff --git a/idea/src/org/jetbrains/jet/lang/types/TypeMemberDomain.java b/idea/src/org/jetbrains/jet/lang/types/TypeMemberDomain.java new file mode 100644 index 00000000000..a1db793c0f1 --- /dev/null +++ b/idea/src/org/jetbrains/jet/lang/types/TypeMemberDomain.java @@ -0,0 +1,19 @@ +package org.jetbrains.jet.lang.types; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * @author abreslav + */ +public interface TypeMemberDomain { + TypeMemberDomain EMPTY = new TypeMemberDomain() { + @Override + public ClassDescriptor getClassDescriptor(@NotNull Type type) { + return null; + } + }; + + @Nullable ClassDescriptor getClassDescriptor(@NotNull Type type); + // ... +} diff --git a/idea/src/org/jetbrains/jet/lang/types/TypeParameterDescriptor.java b/idea/src/org/jetbrains/jet/lang/types/TypeParameterDescriptor.java index d53f349b4b7..9c722456bde 100644 --- a/idea/src/org/jetbrains/jet/lang/types/TypeParameterDescriptor.java +++ b/idea/src/org/jetbrains/jet/lang/types/TypeParameterDescriptor.java @@ -19,7 +19,7 @@ public class TypeParameterDescriptor extends NamedAnnotatedImpl { // TODO: Should we actually pass the attributes on to the type constructor? this.typeConstructor = new TypeConstructor( attributes, - name, + "&" + name, Collections.emptyList(), upperBounds); } @@ -35,4 +35,9 @@ public class TypeParameterDescriptor extends NamedAnnotatedImpl { public TypeConstructor getTypeConstructor() { return typeConstructor; } + + @Override + public String toString() { + return typeConstructor.toString(); + } } diff --git a/idea/src/org/jetbrains/jet/lang/types/TypeVariable.java b/idea/src/org/jetbrains/jet/lang/types/TypeVariable.java deleted file mode 100644 index 528a9e45fae..00000000000 --- a/idea/src/org/jetbrains/jet/lang/types/TypeVariable.java +++ /dev/null @@ -1,40 +0,0 @@ -package org.jetbrains.jet.lang.types; - - -import org.jetbrains.annotations.NotNull; - -import java.util.Collection; -import java.util.Collections; -import java.util.List; - -/** - * @author abreslav - */ -public class TypeVariable extends TypeImpl { - - private final TypeParameterDescriptor typeParameterDescriptor; - - public TypeVariable(@NotNull List attributes, @NotNull TypeParameterDescriptor typeParameter) { - super(attributes, typeParameter.getTypeConstructor(), Collections.emptyList()); - this.typeParameterDescriptor = typeParameter; - } - - public TypeParameterDescriptor getTypeParameterDescriptor() { - return typeParameterDescriptor; - } - - @Override - public Collection getMembers() { - 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 deleted file mode 100644 index bf6f59ab705..00000000000 --- a/idea/src/org/jetbrains/jet/lang/types/TypeVisitor.java +++ /dev/null @@ -1,38 +0,0 @@ -package org.jetbrains.jet.lang.types; - -/** - * @author abreslav - */ -public class TypeVisitor { - public R visitNothingType(NothingType nothingType, D data) { - return visitType(nothingType, data); - } - - public R visitTupleType(TupleType tupleType, D data) { - return visitType(tupleType, data); - } - - public R visitTypeVariable(TypeVariable typeVariable, D data) { - return visitType(typeVariable, data); - } - - public R visitClassType(ClassType classType, D data) { - return visitType(classType, data); - } - - public R visitThisType(ThisType thisType, D data) { - return visitType(thisType, data); - } - - public R visitErrorType(ErrorType errorType, D data) { - return visitType(errorType, data); - } - - public R visitNullableType(NullableType nullableType, D data) { - return visitType(nullableType, 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 deleted file mode 100644 index d527ae6c317..00000000000 --- a/idea/src/org/jetbrains/jet/lang/types/VisitableTypeImpl.java +++ /dev/null @@ -1,22 +0,0 @@ -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 7b949248561..cf290880b99 100644 --- a/idea/tests/org/jetbrains/jet/types/JetTypeCheckerTest.java +++ b/idea/tests/org/jetbrains/jet/types/JetTypeCheckerTest.java @@ -29,33 +29,41 @@ public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase { } public void testConstants() throws Exception { - assertType("1", JetStandardTypes.getInt()); - assertType("0x1", JetStandardTypes.getInt()); - assertType("0X1", JetStandardTypes.getInt()); - assertType("0b1", JetStandardTypes.getInt()); - assertType("0B1", JetStandardTypes.getInt()); + assertType("1", JetStandardClasses.getIntType()); + assertType("0x1", JetStandardClasses.getIntType()); + assertType("0X1", JetStandardClasses.getIntType()); + assertType("0b1", JetStandardClasses.getIntType()); + assertType("0B1", JetStandardClasses.getIntType()); - assertType("1l", JetStandardTypes.getLong()); - assertType("1L", JetStandardTypes.getLong()); + assertType("1l", JetStandardClasses.getLongType()); + assertType("1L", JetStandardClasses.getLongType()); - assertType("1.0", JetStandardTypes.getDouble()); - assertType("1.0d", JetStandardTypes.getDouble()); - assertType("1.0D", JetStandardTypes.getDouble()); - assertType("0x1.fffffffffffffp1023", JetStandardTypes.getDouble()); + assertType("1.0", JetStandardClasses.getDoubleType()); + assertType("1.0d", JetStandardClasses.getDoubleType()); + assertType("1.0D", JetStandardClasses.getDoubleType()); + assertType("0x1.fffffffffffffp1023", JetStandardClasses.getDoubleType()); - assertType("1.0f", JetStandardTypes.getFloat()); - assertType("1.0F", JetStandardTypes.getFloat()); - assertType("0x1.fffffffffffffp1023f", JetStandardTypes.getFloat()); + assertType("1.0f", JetStandardClasses.getFloatType()); + assertType("1.0F", JetStandardClasses.getFloatType()); + assertType("0x1.fffffffffffffp1023f", JetStandardClasses.getFloatType()); - assertType("true", JetStandardTypes.getBoolean()); - assertType("false", JetStandardTypes.getBoolean()); + assertType("true", JetStandardClasses.getBooleanType()); + assertType("false", JetStandardClasses.getBooleanType()); - assertType("'d'", JetStandardTypes.getChar()); + assertType("'d'", JetStandardClasses.getCharType()); - assertType("\"d\"", JetStandardTypes.getString()); - assertType("\"\"\"d\"\"\"", JetStandardTypes.getString()); + assertType("\"d\"", JetStandardClasses.getStringType()); + assertType("\"\"\"d\"\"\"", JetStandardClasses.getStringType()); - assertType("()", JetStandardTypes.getUnit()); + assertType("()", JetStandardClasses.getUnitType()); + + assertType("null", JetStandardClasses.getNullableNothingType()); + } + + public void testTupleConstants() throws Exception { + assertType("()", JetStandardClasses.getUnitType()); + + assertType("(1, 'a')", JetStandardClasses.getTupleType(JetStandardClasses.getIntType(), JetStandardClasses.getCharType())); } public void testBasicSubtyping() throws Exception { @@ -170,7 +178,7 @@ public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase { } public void testImplicitConversions() throws Exception { - assertConvertibleTo("1", JetStandardTypes.getByte()); + assertConvertibleTo("1", JetStandardClasses.getByteType()); } private static void assertSubtype(String type1, String type2) { @@ -184,7 +192,7 @@ public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase { private static void assertSubtypingRelation(String type1, String type2, boolean expected) { 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( + boolean result = JetTypeChecker.INSTANCE.isSubtypeOf( typeNode1, typeNode2); String modifier = expected ? "not " : ""; @@ -195,21 +203,21 @@ public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase { JetExpression jetExpression = JetChangeUtil.createExpression(getProject(), expression); assertTrue( expression + " must be convertible to " + type, - new JetTypeChecker().isConvertibleTo(jetExpression, type)); + JetTypeChecker.INSTANCE.isConvertibleTo(jetExpression, type)); } private static void assertNotConvertibleTo(String expression, Type type) { JetExpression jetExpression = JetChangeUtil.createExpression(getProject(), expression); assertFalse( expression + " must not be convertible to " + type, - new JetTypeChecker().isConvertibleTo(jetExpression, type)); + JetTypeChecker.INSTANCE.isConvertibleTo(jetExpression, type)); } private static void assertType(String expression, Type expectedType) { Project project = getProject(); JetExpression jetExpression = JetChangeUtil.createExpression(project, expression); - Type type = new JetTypeChecker().getType(jetExpression); - assertEquals(type, expectedType); + Type type = JetTypeChecker.INSTANCE.getType(jetExpression); + assertTrue(type + "!=" + expectedType, JetTypeChecker.INSTANCE.equalTypes(type, expectedType)); } private static class ClassDefinitions {