提交 d9997f3c 编写于 作者: A Andrey Breslav

Generic Java classes supported

上级 55518cd6
......@@ -48,11 +48,11 @@ public class ClassDescriptorResolver {
List<JetDelegationSpecifier> delegationSpecifiers = classElement.getDelegationSpecifiers();
// TODO : assuming that the hierarchy is acyclic
Collection<? extends JetType> superclasses = delegationSpecifiers.isEmpty()
Collection<? extends JetType> supertypes = delegationSpecifiers.isEmpty()
? Collections.singleton(JetStandardClasses.getAnyType())
: resolveDelegationSpecifiers(parameterScope, delegationSpecifiers);
boolean open = classElement.hasModifier(JetTokens.OPEN_KEYWORD);
WritableScope members = resolveMembers(classDescriptor, classElement, typeParameters, scope, parameterScope, superclasses);
WritableScope members = resolveMembers(classDescriptor, classElement, typeParameters, scope, parameterScope, supertypes);
WritableFunctionGroup constructors = new WritableFunctionGroup("<init>");
for (JetConstructor constructor : classElement.getSecondaryConstructors()) {
......@@ -65,7 +65,7 @@ public class ClassDescriptorResolver {
return classDescriptor.initialize(
!open,
typeParameters,
superclasses,
supertypes,
members,
constructors
);
......
......@@ -12,15 +12,28 @@ import java.util.Map;
*/
public class MutableClassDescriptor extends MutableDeclarationDescriptor implements ClassDescriptor {
private final WritableScope classHeaderScope;
private final WritableScope unsubstitutedMemberScope;
private final WritableScope writableMemberScope;
private final WritableFunctionGroup constructors = new WritableFunctionGroup("<init>");
private TypeConstructor typeConstructor;
private JetScope unsubstitutedMemberScope;
public MutableClassDescriptor(@NotNull JetSemanticServices semanticServices, @NotNull DeclarationDescriptor containingDeclaration, @NotNull JetScope outerScope) {
super(containingDeclaration);
this.classHeaderScope = semanticServices.createWritableScope(outerScope, this);
this.unsubstitutedMemberScope = semanticServices.createWritableScope(classHeaderScope, this);
this.writableMemberScope = semanticServices.createWritableScope(classHeaderScope, this);
this.unsubstitutedMemberScope = this.writableMemberScope;
}
public MutableClassDescriptor(@NotNull DeclarationDescriptor containingDeclaration) {
super(containingDeclaration);
this.classHeaderScope = null;
this.writableMemberScope = null;
}
public void setUnsubstitutedMemberScope(@NotNull JetScope unsubstitutedMemberScope) {
assert writableMemberScope == null;
this.unsubstitutedMemberScope = unsubstitutedMemberScope;
}
@NotNull
......@@ -66,8 +79,8 @@ public class MutableClassDescriptor extends MutableDeclarationDescriptor impleme
}
@NotNull
public WritableScope getUnsubstitutedMemberScope() {
return unsubstitutedMemberScope;
public WritableScope getWritableUnsubstitutedMemberScope() {
return writableMemberScope;
}
@NotNull
......
......@@ -148,7 +148,7 @@ public class TopDownAnalyzer {
classes.put(klass, mutableClassDescriptor);
declaringScopes.put(klass, declaringScope);
return mutableClassDescriptor.getUnsubstitutedMemberScope();
return mutableClassDescriptor.getWritableUnsubstitutedMemberScope();
}
private void processExtension(JetExtension extension) {
......@@ -178,7 +178,7 @@ public class TopDownAnalyzer {
public void visitClass(JetClass klass) {
MutableClassDescriptor mutableClassDescriptor = classes.get(klass);
processPrimaryConstructor(mutableClassDescriptor, klass);
processBehaviorDeclarators(mutableClassDescriptor.getUnsubstitutedMemberScope(), klass.getDeclarations());
processBehaviorDeclarators(mutableClassDescriptor.getWritableUnsubstitutedMemberScope(), klass.getDeclarations());
}
@Override
......@@ -225,7 +225,7 @@ public class TopDownAnalyzer {
private void processPrimaryConstructor(MutableClassDescriptor classDescriptor, JetClass klass) {
// TODO : not all the parameters are real properties
WritableScope memberScope = classDescriptor.getUnsubstitutedMemberScope(); // TODO : this is REALLY questionable
WritableScope memberScope = classDescriptor.getWritableUnsubstitutedMemberScope(); // TODO : this is REALLY questionable
ConstructorDescriptor constructorDescriptor = classDescriptorResolver.resolvePrimaryConstructor(memberScope, classDescriptor, klass);
for (JetParameter parameter : klass.getPrimaryConstructorParameters()) {
VariableDescriptor propertyDescriptor = classDescriptorResolver.resolvePrimaryConstructorParameterToAProperty(
......@@ -242,10 +242,10 @@ public class TopDownAnalyzer {
}
private void processConstructor(MutableClassDescriptor classDescriptor, JetConstructor constructor) {
ConstructorDescriptor constructorDescriptor = classDescriptorResolver.resolveConstructorDescriptor(classDescriptor.getUnsubstitutedMemberScope(), classDescriptor, constructor, false);
ConstructorDescriptor constructorDescriptor = classDescriptorResolver.resolveConstructorDescriptor(classDescriptor.getWritableUnsubstitutedMemberScope(), classDescriptor, constructor, false);
classDescriptor.addConstructor(constructorDescriptor);
functions.put(constructor, constructorDescriptor);
declaringScopes.put(constructor, classDescriptor.getUnsubstitutedMemberScope());
declaringScopes.put(constructor, classDescriptor.getWritableUnsubstitutedMemberScope());
}
private void processFunction(@NotNull WritableScope declaringScope, JetFunction function) {
......@@ -359,7 +359,22 @@ public class TopDownAnalyzer {
JetFlowInformationProvider flowInformationProvider = computeFlowData(declaration, initializer);
JetTypeInferrer typeInferrer = semanticServices.getTypeInferrer(trace, flowInformationProvider);
JetType type = typeInferrer.getType(declaringScope, initializer, false);
// TODO : check type
JetType expectedType;
PropertySetterDescriptor setter = propertyDescriptor.getSetter();
if (setter != null) {
expectedType = setter.getUnsubstitutedReturnType();
}
else {
expectedType = propertyDescriptor.getInType();
if (expectedType == null) {
expectedType = propertyDescriptor.getOutType();
}
}
if (type != null && expectedType != null
&& !semanticServices.getTypeChecker().isConvertibleTo(type, expectedType)) {
semanticServices.getErrorHandler().typeMismatch(initializer, expectedType, type);
}
}
BindingTraceAdapter fieldAccessTrackingTrace = new BindingTraceAdapter(trace) {
......
......@@ -56,7 +56,7 @@ public class TypeResolver {
result[0] = new JetTypeImpl(
attributes,
typeParameterDescriptor.getTypeConstructor(),
nullable || hasNullableBound(typeParameterDescriptor),
nullable || TypeUtils.hasNullableBound(typeParameterDescriptor),
Collections.<TypeProjection>emptyList(),
// TODO : joint domain
JetStandardClasses.STUB
......@@ -70,22 +70,33 @@ public class TypeResolver {
List<TypeProjection> arguments = resolveTypeProjections(scope, typeConstructor, type.getTypeArguments());
int expectedArgumentCount = typeConstructor.getParameters().size();
int actualArgumentCount = arguments.size();
if (actualArgumentCount != expectedArgumentCount) {
String errorMessage = (expectedArgumentCount == 0 ? "No" : expectedArgumentCount) + " type arguments expected";
if (actualArgumentCount == 0) {
semanticServices.getErrorHandler().genericError(type.getNode(), errorMessage);
} else if (expectedArgumentCount == 0) {
semanticServices.getErrorHandler().genericError(type.getTypeArgumentList().getNode(), errorMessage);
}
} else {
if (ErrorUtils.isError(typeConstructor)) {
result[0] = new JetTypeImpl(
attributes,
typeConstructor,
nullable,
arguments,
classDescriptor.getMemberScope(arguments)
arguments, // TODO : review
classDescriptor.getMemberScope(Collections.<TypeProjection>emptyList())
);
}
else {
if (actualArgumentCount != expectedArgumentCount) {
String errorMessage = (expectedArgumentCount == 0 ? "No" : expectedArgumentCount) + " type arguments expected";
if (actualArgumentCount == 0) {
semanticServices.getErrorHandler().genericError(type.getNode(), errorMessage);
} else if (expectedArgumentCount == 0) {
semanticServices.getErrorHandler().genericError(type.getTypeArgumentList().getNode(), errorMessage);
}
} else {
result[0] = new JetTypeImpl(
attributes,
typeConstructor,
nullable,
arguments,
classDescriptor.getMemberScope(arguments)
);
}
}
}
}
}
......@@ -128,15 +139,6 @@ public class TypeResolver {
return result[0];
}
private boolean hasNullableBound(TypeParameterDescriptor typeParameterDescriptor) {
for (JetType bound : typeParameterDescriptor.getUpperBounds()) {
if (bound.isNullable()) {
return true;
}
}
return false;
}
private List<JetType> resolveTypes(JetScope scope, List<JetTypeReference> argumentElements) {
final List<JetType> arguments = new ArrayList<JetType>();
for (JetTypeReference argumentElement : argumentElements) {
......
......@@ -61,7 +61,7 @@ public class JavaClassMembersScope implements JetScope {
return null;
}
JetType type = semanticServices.getTypeTransformer().transform(field.getType());
JetType type = semanticServices.getTypeTransformer().transformToType(field.getType());
boolean isFinal = field.hasModifierProperty(PsiModifier.FINAL);
PropertyDescriptor propertyDescriptor = new PropertyDescriptor(
containingDeclaration,
......@@ -97,7 +97,7 @@ public class JavaClassMembersScope implements JetScope {
functionDescriptor.initialize(
Collections.<TypeParameterDescriptor>emptyList(), // TODO
semanticServices.getDescriptorResolver().resolveParameterDescriptors(functionDescriptor, parameters),
semanticServices.getTypeTransformer().transform(method.getReturnType())
semanticServices.getTypeTransformer().transformToType(method.getReturnType())
);
semanticServices.getTrace().recordDeclarationResolution(method, functionDescriptor);
writableFunctionGroup.addFunction(functionDescriptor);
......
package org.jetbrains.jet.lang.resolve.java;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.resolve.MutableClassDescriptor;
import org.jetbrains.jet.lang.resolve.WritableFunctionGroup;
import org.jetbrains.jet.lang.types.*;
......@@ -31,6 +33,7 @@ public class JavaDescriptorResolver {
};
protected final Map<String, ClassDescriptor> classDescriptorCache = new HashMap<String, ClassDescriptor>();
protected final Map<PsiTypeParameter, TypeParameterDescriptor> typeParameterDescriptorCache = Maps.newHashMap();
protected final Map<String, NamespaceDescriptor> namespaceDescriptorCache = new HashMap<String, NamespaceDescriptor>();
protected final JavaPsiFacade javaFacade;
protected final GlobalSearchScope javaSearchScope;
......@@ -67,25 +70,32 @@ public class JavaDescriptorResolver {
}
private ClassDescriptor createJavaClassDescriptor(@NotNull final PsiClass psiClass) {
assert !classDescriptorCache.containsKey(psiClass.getQualifiedName()) : psiClass.getQualifiedName();
classDescriptorCache.put(psiClass.getQualifiedName(), null); // TODO
String name = psiClass.getName();
PsiModifierList modifierList = psiClass.getModifierList();
ClassDescriptorImpl classDescriptor = new ClassDescriptorImpl(
JAVA_ROOT,
Collections.<Attribute>emptyList(), // TODO
name
MutableClassDescriptor classDescriptor = new MutableClassDescriptor(
JAVA_ROOT
);
classDescriptor.setName(name);
WritableFunctionGroup constructors = new WritableFunctionGroup("<init>");
classDescriptor.initialize(
List<JetType> supertypes = new ArrayList<JetType>();
classDescriptor.setTypeConstructor(new TypeConstructorImpl(
classDescriptor,
Collections.<Attribute>emptyList(), // TODO
// TODO
modifierList == null ? false : modifierList.hasModifierProperty(PsiModifier.FINAL),
name,
resolveTypeParameters(psiClass, classDescriptor),
getSupertypes(psiClass),
new JavaClassMembersScope(classDescriptor, psiClass, semanticServices, false),
constructors
);
supertypes
));
classDescriptorCache.put(psiClass.getQualifiedName(), classDescriptor);
// UGLY HACK
supertypes.addAll(getSupertypes(psiClass));
classDescriptor.setUnsubstitutedMemberScope(new JavaClassMembersScope(classDescriptor, psiClass, semanticServices, false));
// NOTE: this writes into constructors after it is remembered by the classDescriptor
PsiMethod[] psiConstructors = psiClass.getConstructors();
......@@ -95,7 +105,7 @@ public class JavaDescriptorResolver {
Collections.<Attribute>emptyList(), // TODO
false);
constructorDescriptor.initialize(resolveParameterDescriptors(constructorDescriptor, constructor.getParameterList().getParameters()));
constructors.addFunction(constructorDescriptor);
classDescriptor.addConstructor(constructorDescriptor);
semanticServices.getTrace().recordDeclarationResolution(constructor, constructorDescriptor);
}
......@@ -104,40 +114,54 @@ public class JavaDescriptorResolver {
}
private List<TypeParameterDescriptor> resolveTypeParameters(@NotNull PsiClass psiClass, @NotNull ClassDescriptor classDescriptor) {
if (1 < 2) return Collections.emptyList(); // TODO
List<TypeParameterDescriptor> result = Lists.newArrayList();
PsiTypeParameter[] typeParameters = psiClass.getTypeParameters();
for (PsiTypeParameter typeParameter : typeParameters) {
PsiClassType[] referencedTypes = typeParameter.getExtendsList().getReferencedTypes();
Set<JetType> upperBounds;
JetType boundsAsType;
if (referencedTypes.length == 0){
boundsAsType = JetStandardClasses.getNullableAnyType();
upperBounds = Collections.singleton(boundsAsType);
}
else if (referencedTypes.length == 1) {
boundsAsType = semanticServices.getTypeTransformer().transform(referencedTypes[0]);
upperBounds = Collections.singleton(boundsAsType);
}
else {
upperBounds = Sets.newLinkedHashSet();
for (PsiClassType referencedType : referencedTypes) {
upperBounds.add(semanticServices.getTypeTransformer().transform(referencedType));
}
boundsAsType = TypeUtils.safeIntersect(semanticServices.getTypeChecker(), upperBounds);
}
result.add(new TypeParameterDescriptor(
classDescriptor,
Collections.<Attribute>emptyList(), // TODO
Variance.INVARIANT,
typeParameter.getName(),
upperBounds,
boundsAsType
));
TypeParameterDescriptor typeParameterDescriptor = resolveTypeParameter(typeParameter);
result.add(typeParameterDescriptor);
}
return result;
}
private TypeParameterDescriptor createJavaTypeParameterDescriptor(@NotNull DeclarationDescriptor owner, @NotNull PsiTypeParameter typeParameter) {
PsiClassType[] referencedTypes = typeParameter.getExtendsList().getReferencedTypes();
Set<JetType> upperBounds;
JetType boundsAsType;
if (referencedTypes.length == 0){
boundsAsType = JetStandardClasses.getNullableAnyType();
upperBounds = Collections.singleton(boundsAsType);
}
else if (referencedTypes.length == 1) {
boundsAsType = semanticServices.getTypeTransformer().transformToType(referencedTypes[0]);
upperBounds = Collections.singleton(boundsAsType);
}
else {
upperBounds = Sets.newLinkedHashSet();
for (PsiClassType referencedType : referencedTypes) {
upperBounds.add(semanticServices.getTypeTransformer().transformToType(referencedType));
}
boundsAsType = TypeUtils.safeIntersect(semanticServices.getJetSemanticServices().getTypeChecker(), upperBounds);
}
return new TypeParameterDescriptor(
owner,
Collections.<Attribute>emptyList(), // TODO
Variance.INVARIANT,
typeParameter.getName(),
upperBounds,
boundsAsType
);
}
@NotNull
public TypeParameterDescriptor resolveTypeParameter(@NotNull PsiTypeParameter psiTypeParameter) {
TypeParameterDescriptor typeParameterDescriptor = typeParameterDescriptorCache.get(psiTypeParameter);
if (typeParameterDescriptor == null) {
typeParameterDescriptor = createJavaTypeParameterDescriptor(JAVA_ROOT, psiTypeParameter);
typeParameterDescriptorCache.put(psiTypeParameter, typeParameterDescriptor);
}
return typeParameterDescriptor;
}
private Collection<? extends JetType> getSupertypes(PsiClass psiClass) {
List<JetType> result = new ArrayList<JetType>();
result.add(JetStandardClasses.getAnyType());
......@@ -148,7 +172,7 @@ public class JavaDescriptorResolver {
private void transformSupertypeList(List<JetType> result, PsiClassType[] extendsListTypes) {
for (PsiClassType type : extendsListTypes) {
JetType transform = semanticServices.getTypeTransformer().transform(type);
JetType transform = semanticServices.getTypeTransformer().transformToType(type);
result.add(TypeUtils.makeNotNullable(transform));
}
......@@ -207,7 +231,7 @@ public class JavaDescriptorResolver {
Collections.<Attribute>emptyList(), // TODO
name == null ? "p" + i : name,
null, // TODO : review
semanticServices.getTypeTransformer().transform(parameter.getType()),
semanticServices.getTypeTransformer().transformToType(parameter.getType()),
false,
parameter.isVarArgs()
));
......
......@@ -4,7 +4,6 @@ import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.JetSemanticServices;
import org.jetbrains.jet.lang.types.BindingTrace;
import org.jetbrains.jet.lang.types.JetTypeChecker;
/**
* @author abreslav
......@@ -13,13 +12,13 @@ public class JavaSemanticServices {
private final JavaTypeTransformer typeTransformer;
private final JavaDescriptorResolver descriptorResolver;
private final BindingTrace trace;
private final JetTypeChecker typeChecker;
private final JetSemanticServices jetSemanticServices;
public JavaSemanticServices(Project project, JetSemanticServices jetSemanticServices, BindingTrace trace) {
this.trace = trace;
this.descriptorResolver = new JavaDescriptorResolver(project, this);
this.typeTransformer = new JavaTypeTransformer(jetSemanticServices.getStandardLibrary(), descriptorResolver);
this.typeChecker = new JetTypeChecker(jetSemanticServices.getStandardLibrary());
this.jetSemanticServices = jetSemanticServices;
}
@NotNull
......@@ -37,8 +36,7 @@ public class JavaSemanticServices {
return trace;
}
@NotNull
public JetTypeChecker getTypeChecker() {
return typeChecker;
public JetSemanticServices getJetSemanticServices() {
return jetSemanticServices;
}
}
......@@ -26,7 +26,36 @@ public class JavaTypeTransformer {
}
@NotNull
public JetType transform(PsiType javaType) {
public TypeProjection transformToTypeProjection(@NotNull final PsiType javaType, @NotNull final TypeParameterDescriptor typeParameterDescriptor) {
TypeProjection result = javaType.accept(new PsiTypeVisitor<TypeProjection>() {
@Override
public TypeProjection visitCapturedWildcardType(PsiCapturedWildcardType capturedWildcardType) {
throw new UnsupportedOperationException(); // TODO
}
@Override
public TypeProjection visitWildcardType(PsiWildcardType wildcardType) {
if (!wildcardType.isBounded()) {
return TypeUtils.makeStarProjection(typeParameterDescriptor);
}
Variance variance = wildcardType.isExtends() ? Variance.OUT_VARIANCE : Variance.IN_VARIANCE;
PsiType bound = wildcardType.getBound();
assert bound != null;
return new TypeProjection(variance, transformToType(bound));
}
@Override
public TypeProjection visitType(PsiType type) {
return new TypeProjection(transformToType(type));
}
});
return result;
}
@NotNull
public JetType transformToType(@NotNull PsiType javaType) {
return javaType.accept(new PsiTypeVisitor<JetType>() {
@Override
public JetType visitClassType(PsiClassType classType) {
......@@ -36,31 +65,46 @@ public class JavaTypeTransformer {
return ErrorUtils.createErrorType("Unresolved java class: " + classType.getPresentableText());
}
JetType jetAnalog = getClassTypesMap().get(psiClass.getQualifiedName());
if (jetAnalog != null) {
return jetAnalog;
if (psiClass instanceof PsiTypeParameter) {
PsiTypeParameter typeParameter = (PsiTypeParameter) psiClass;
TypeParameterDescriptor typeParameterDescriptor = resolver.resolveTypeParameter(typeParameter);
return new JetTypeImpl(
Collections.<Attribute>emptyList(),
typeParameterDescriptor.getTypeConstructor(),
!TypeUtils.hasNullableBound(typeParameterDescriptor),
Collections.<TypeProjection>emptyList(),
typeParameterDescriptor.getBoundsAsType().getMemberScope());
}
else {
JetType jetAnalog = getClassTypesMap().get(psiClass.getQualifiedName());
if (jetAnalog != null) {
return jetAnalog;
}
ClassDescriptor descriptor = resolver.resolveClass(psiClass);
ClassDescriptor descriptor = resolver.resolveClass(psiClass);
List<TypeProjection> arguments = Lists.newArrayList();
if (classType.isRaw()) { // TODO
// List<TypeParameterDescriptor> parameters = descriptor.getTypeConstructor().getParameters();
// for (TypeParameterDescriptor parameter : parameters) {
// arguments.add(TypeUtils.makeStarProjection(parameter));
// }
} else { // TODO
// PsiType[] psiArguments = classType.getParameters();
// for (PsiType psiArgument : psiArguments) {
// arguments.add(new TypeProjection(transform(psiArgument)));
// }
List<TypeProjection> arguments = Lists.newArrayList();
if (classType.isRaw()) {
List<TypeParameterDescriptor> parameters = descriptor.getTypeConstructor().getParameters();
for (TypeParameterDescriptor parameter : parameters) {
arguments.add(TypeUtils.makeStarProjection(parameter));
}
} else {
PsiType[] psiArguments = classType.getParameters();
for (int i = 0, psiArgumentsLength = psiArguments.length; i < psiArgumentsLength; i++) {
PsiType psiArgument = psiArguments[i];
TypeParameterDescriptor typeParameterDescriptor = descriptor.getTypeConstructor().getParameters().get(i);
arguments.add(transformToTypeProjection(psiArgument, typeParameterDescriptor));
}
}
return new JetTypeImpl(
Collections.<Attribute>emptyList(),
descriptor.getTypeConstructor(),
true,
arguments,
descriptor.getMemberScope(arguments));
}
return new JetTypeImpl(
Collections.<Attribute>emptyList(),
descriptor.getTypeConstructor(),
true,
arguments,
descriptor.getMemberScope(arguments));
}
@Override
......@@ -73,16 +117,10 @@ public class JavaTypeTransformer {
@Override
public JetType visitArrayType(PsiArrayType arrayType) {
JetType type = transform(arrayType.getComponentType());
JetType type = transformToType(arrayType.getComponentType());
return TypeUtils.makeNullable(standardLibrary.getArrayType(type));
}
@Override
public JetType visitWildcardType(PsiWildcardType wildcardType) {
System.out.println("!!!");
return JetStandardClasses.getNullableAnyType(); // TODO
}
@Override
public JetType visitType(PsiType type) {
throw new UnsupportedOperationException("Unsupported type: " + type.getPresentableText()); // TODO
......
......@@ -149,6 +149,10 @@ public class ErrorUtils {
return ERROR_CLASS;
}
public static boolean isError(@NotNull TypeConstructor typeConstructor) {
return typeConstructor == ERROR_CLASS.getTypeConstructor();
}
private static class ErrorTypeImpl implements JetType {
private final TypeConstructor constructor;
......
......@@ -55,7 +55,8 @@ public final class JetTypeImpl extends AnnotatedImpl implements JetType {
@Override
public JetScope getMemberScope() {
if (memberScope == null) {
// TODO
// TODO : this was supposed to mean something...
throw new IllegalStateException(this.toString());
}
return memberScope;
}
......
......@@ -226,4 +226,13 @@ public class TypeUtils {
collectAllSupertypes(type, result);
return result;
}
public static boolean hasNullableBound(@NotNull TypeParameterDescriptor typeParameterDescriptor) {
for (JetType bound : typeParameterDescriptor.getUpperBounds()) {
if (bound.isNullable()) {
return true;
}
}
return false;
}
}
......@@ -2,6 +2,7 @@ package org.jetbrains.jet.resolve;
import org.jetbrains.jet.lang.types.*;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
......@@ -91,6 +92,17 @@ public class DescriptorUtil {
public Void visitClassDescriptor(ClassDescriptor descriptor, StringBuilder builder) {
builder.append("class ").append(renderName(descriptor));
renderTypeParameters(descriptor.getTypeConstructor().getParameters(), builder);
Collection<? extends JetType> supertypes = descriptor.getTypeConstructor().getSupertypes();
if (!supertypes.isEmpty()) {
builder.append(" : ");
for (Iterator<? extends JetType> iterator = supertypes.iterator(); iterator.hasNext(); ) {
JetType supertype = iterator.next();
builder.append(supertype);
if (iterator.hasNext()) {
builder.append(", ");
}
}
}
return super.visitClassDescriptor(descriptor, builder);
}
},
......
......@@ -76,6 +76,6 @@ fun test() {
for (i in new Range0());
for (i in new Range1());
for (i in (new ArrayList() : List));
for (i in (new ArrayList<Int>() : List<Int>));
}
......@@ -2,10 +2,12 @@ import java.*
import util.*
import <error>utils</error>.*
fun test(l : java.util.List) {
val l : List<in Int> = new ArrayList<Int>()
fun test(l : java.util.List<Int>) {
val x : java.<error>List</error>
val y : java.util.List
val y : java.util.List<Int>
val b : java.lang.Object
val a : util.List
val z : java.<error>utils</error>.List
val a : util.List<Int>
val z : java.<error>utils</error>.List<Int>
}
class Foo : java.util.ArrayList
\ No newline at end of file
class Foo : java.util.ArrayList<*>
\ No newline at end of file
......@@ -59,7 +59,7 @@ fun f_plus(): Int {
}
fun <T> tt(t : T) : T {
val x : List = 0
val x : List<Int> = 0
x`java::java.util.List.get()`[1]
val foo = new `Bar()`Bar()
foo`!`[null, 1]
......
......@@ -267,6 +267,10 @@ public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase {
assertSubtype("Derived_outT<Int>", "Base_outT<Any>");
assertSubtype("Derived_T<Int>", "Base_T<out Any>");
assertSubtype("Derived_T<Any>", "Base_T<in Int>");
assertSubtype("Derived_T<Int>", "Base_T<in Int>");
assertSubtype("MDerived_T<Int>", "Base_T<in Int>");
assertSubtype("ArrayList<Int>", "List<in Int>");
}
public void testNullable() throws Exception {
......@@ -438,12 +442,12 @@ public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase {
assertEquals(expected, allSupertypes);
}
private void assertSubtype(String type1, String type2) {
assertSubtypingRelation(type1, type2, true);
private void assertSubtype(String subtype, String supertype) {
assertSubtypingRelation(subtype, supertype, true);
}
private void assertNotSubtype(String type1, String type2) {
assertSubtypingRelation(type1, type2, false);
private void assertNotSubtype(String subtype, String supertype) {
assertSubtypingRelation(subtype, supertype, false);
}
private void assertIntersection(String expected, String... types) {
......@@ -465,9 +469,9 @@ public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase {
assertTrue(result + " != " + expected, JetTypeImpl.equalTypes(result, makeType(expected)));
}
private void assertSubtypingRelation(String type1, String type2, boolean expected) {
JetType typeNode1 = makeType(type1);
JetType typeNode2 = makeType(type2);
private void assertSubtypingRelation(String subtype, String supertype, boolean expected) {
JetType typeNode1 = makeType(subtype);
JetType typeNode2 = makeType(supertype);
boolean result = semanticServices.getTypeChecker().isSubtypeOf(
typeNode1,
typeNode2);
......@@ -534,6 +538,7 @@ public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase {
"open class Derived1_inT<in T> : Base_inT<T>, Derived_T<T>",
"open class Base_outT<out T>",
"open class Derived_outT<out T> : Base_outT<T>",
"open class MDerived_T> : Base_outT<out T>, Base_T<T>",
"class Properties { val p : Int }",
"class Props<T> { val p : T }",
"class Functions<T> { " +
......@@ -547,7 +552,12 @@ public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase {
"fun isValid() : Boolean " +
"fun isValid(x : Int) : Boolean " +
"val p : Boolean " +
"}"
"}",
"open class List<E>",
"open class AbstractList<E> : List<E?>",
"open class ArrayList<E> : Any, AbstractList<E?>, List<E?>"
};
private String[] FUNCTION_DECLARATIONS = {
"fun f() : Unit {}",
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册