Contexts added for type parameter resolution. Annotations renamed into attributes for consistency
This commit is contained in:
@@ -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;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user