diff --git a/idea/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java b/idea/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java index 18377fc1a9f..ad26483549d 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java @@ -48,11 +48,11 @@ public class ClassDescriptorResolver { List delegationSpecifiers = classElement.getDelegationSpecifiers(); // TODO : assuming that the hierarchy is acyclic - Collection superclasses = delegationSpecifiers.isEmpty() + Collection 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(""); for (JetConstructor constructor : classElement.getSecondaryConstructors()) { @@ -65,7 +65,7 @@ public class ClassDescriptorResolver { return classDescriptor.initialize( !open, typeParameters, - superclasses, + supertypes, members, constructors ); diff --git a/idea/src/org/jetbrains/jet/lang/resolve/MutableClassDescriptor.java b/idea/src/org/jetbrains/jet/lang/resolve/MutableClassDescriptor.java index 9440f7be2e1..e1a29b65a66 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/MutableClassDescriptor.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/MutableClassDescriptor.java @@ -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(""); 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 diff --git a/idea/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java b/idea/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java index 4fabaf44872..e27960523e8 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java @@ -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) { diff --git a/idea/src/org/jetbrains/jet/lang/resolve/TypeResolver.java b/idea/src/org/jetbrains/jet/lang/resolve/TypeResolver.java index d0f4073fcb1..972b4e1f997 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/TypeResolver.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/TypeResolver.java @@ -56,7 +56,7 @@ public class TypeResolver { result[0] = new JetTypeImpl( attributes, typeParameterDescriptor.getTypeConstructor(), - nullable || hasNullableBound(typeParameterDescriptor), + nullable || TypeUtils.hasNullableBound(typeParameterDescriptor), Collections.emptyList(), // TODO : joint domain JetStandardClasses.STUB @@ -70,22 +70,33 @@ public class TypeResolver { List 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.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 resolveTypes(JetScope scope, List argumentElements) { final List arguments = new ArrayList(); for (JetTypeReference argumentElement : argumentElements) { diff --git a/idea/src/org/jetbrains/jet/lang/resolve/java/JavaClassMembersScope.java b/idea/src/org/jetbrains/jet/lang/resolve/java/JavaClassMembersScope.java index f38e78711e3..d8caaf5ec09 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/java/JavaClassMembersScope.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/java/JavaClassMembersScope.java @@ -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.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); diff --git a/idea/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java b/idea/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java index 22b31f78a42..222e524f817 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java @@ -1,12 +1,14 @@ 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 classDescriptorCache = new HashMap(); + protected final Map typeParameterDescriptorCache = Maps.newHashMap(); protected final Map namespaceDescriptorCache = new HashMap(); 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.emptyList(), // TODO - name + MutableClassDescriptor classDescriptor = new MutableClassDescriptor( + JAVA_ROOT ); + classDescriptor.setName(name); WritableFunctionGroup constructors = new WritableFunctionGroup(""); - classDescriptor.initialize( + List supertypes = new ArrayList(); + classDescriptor.setTypeConstructor(new TypeConstructorImpl( + classDescriptor, + Collections.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.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 resolveTypeParameters(@NotNull PsiClass psiClass, @NotNull ClassDescriptor classDescriptor) { - if (1 < 2) return Collections.emptyList(); // TODO List result = Lists.newArrayList(); PsiTypeParameter[] typeParameters = psiClass.getTypeParameters(); for (PsiTypeParameter typeParameter : typeParameters) { - PsiClassType[] referencedTypes = typeParameter.getExtendsList().getReferencedTypes(); - Set 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.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 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.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 getSupertypes(PsiClass psiClass) { List result = new ArrayList(); result.add(JetStandardClasses.getAnyType()); @@ -148,7 +172,7 @@ public class JavaDescriptorResolver { private void transformSupertypeList(List 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.emptyList(), // TODO name == null ? "p" + i : name, null, // TODO : review - semanticServices.getTypeTransformer().transform(parameter.getType()), + semanticServices.getTypeTransformer().transformToType(parameter.getType()), false, parameter.isVarArgs() )); diff --git a/idea/src/org/jetbrains/jet/lang/resolve/java/JavaSemanticServices.java b/idea/src/org/jetbrains/jet/lang/resolve/java/JavaSemanticServices.java index a3d6dcd513b..dfb43be9812 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/java/JavaSemanticServices.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/java/JavaSemanticServices.java @@ -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; } } diff --git a/idea/src/org/jetbrains/jet/lang/resolve/java/JavaTypeTransformer.java b/idea/src/org/jetbrains/jet/lang/resolve/java/JavaTypeTransformer.java index 2f9ad2d1abc..07f96dbceb2 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/java/JavaTypeTransformer.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/java/JavaTypeTransformer.java @@ -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() { + + @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() { @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.emptyList(), + typeParameterDescriptor.getTypeConstructor(), + !TypeUtils.hasNullableBound(typeParameterDescriptor), + Collections.emptyList(), + typeParameterDescriptor.getBoundsAsType().getMemberScope()); - ClassDescriptor descriptor = resolver.resolveClass(psiClass); - - List arguments = Lists.newArrayList(); - if (classType.isRaw()) { // TODO -// List 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))); -// } } - return new JetTypeImpl( - Collections.emptyList(), - descriptor.getTypeConstructor(), - true, - arguments, - descriptor.getMemberScope(arguments)); + else { + JetType jetAnalog = getClassTypesMap().get(psiClass.getQualifiedName()); + if (jetAnalog != null) { + return jetAnalog; + } + + ClassDescriptor descriptor = resolver.resolveClass(psiClass); + + List arguments = Lists.newArrayList(); + if (classType.isRaw()) { + List 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.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 diff --git a/idea/src/org/jetbrains/jet/lang/types/ErrorUtils.java b/idea/src/org/jetbrains/jet/lang/types/ErrorUtils.java index c6b0b47ce18..5d87e93b6bb 100644 --- a/idea/src/org/jetbrains/jet/lang/types/ErrorUtils.java +++ b/idea/src/org/jetbrains/jet/lang/types/ErrorUtils.java @@ -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; diff --git a/idea/src/org/jetbrains/jet/lang/types/JetTypeImpl.java b/idea/src/org/jetbrains/jet/lang/types/JetTypeImpl.java index 3f519ef6fc0..49b4b43178c 100644 --- a/idea/src/org/jetbrains/jet/lang/types/JetTypeImpl.java +++ b/idea/src/org/jetbrains/jet/lang/types/JetTypeImpl.java @@ -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; } diff --git a/idea/src/org/jetbrains/jet/lang/types/TypeUtils.java b/idea/src/org/jetbrains/jet/lang/types/TypeUtils.java index 8a021b68000..756d655c420 100644 --- a/idea/src/org/jetbrains/jet/lang/types/TypeUtils.java +++ b/idea/src/org/jetbrains/jet/lang/types/TypeUtils.java @@ -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; + } } diff --git a/idea/src/org/jetbrains/jet/resolve/DescriptorUtil.java b/idea/src/org/jetbrains/jet/resolve/DescriptorUtil.java index ba189bf744b..e4933d4feac 100644 --- a/idea/src/org/jetbrains/jet/resolve/DescriptorUtil.java +++ b/idea/src/org/jetbrains/jet/resolve/DescriptorUtil.java @@ -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 supertypes = descriptor.getTypeConstructor().getSupertypes(); + if (!supertypes.isEmpty()) { + builder.append(" : "); + for (Iterator iterator = supertypes.iterator(); iterator.hasNext(); ) { + JetType supertype = iterator.next(); + builder.append(supertype); + if (iterator.hasNext()) { + builder.append(", "); + } + } + } return super.visitClassDescriptor(descriptor, builder); } }, diff --git a/idea/testData/checker/ForRangeConventions.jet b/idea/testData/checker/ForRangeConventions.jet index bb457ca1ba3..df1b5ff89b4 100644 --- a/idea/testData/checker/ForRangeConventions.jet +++ b/idea/testData/checker/ForRangeConventions.jet @@ -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() : List)); } diff --git a/idea/testData/checker/ResolveToJava.jet b/idea/testData/checker/ResolveToJava.jet index 54bff6ea596..e6897a69460 100644 --- a/idea/testData/checker/ResolveToJava.jet +++ b/idea/testData/checker/ResolveToJava.jet @@ -2,10 +2,12 @@ import java.* import util.* import utils.* -fun test(l : java.util.List) { +val l : List = new ArrayList() + +fun test(l : java.util.List) { val x : java.List - val y : java.util.List + val y : java.util.List val b : java.lang.Object - val a : util.List - val z : java.utils.List + val a : util.List + val z : java.utils.List } diff --git a/idea/testData/codegen/inheritingFromArrayList.jet b/idea/testData/codegen/inheritingFromArrayList.jet index 8caa9823b36..9a28bf5a303 100644 --- a/idea/testData/codegen/inheritingFromArrayList.jet +++ b/idea/testData/codegen/inheritingFromArrayList.jet @@ -1 +1 @@ -class Foo : java.util.ArrayList \ No newline at end of file +class Foo : java.util.ArrayList<*> \ No newline at end of file diff --git a/idea/testData/resolve/ResolveOfInfixExpressions.jet b/idea/testData/resolve/ResolveOfInfixExpressions.jet index 458921abd93..005e8b3b889 100644 --- a/idea/testData/resolve/ResolveOfInfixExpressions.jet +++ b/idea/testData/resolve/ResolveOfInfixExpressions.jet @@ -59,7 +59,7 @@ fun f_plus(): Int { } fun tt(t : T) : T { - val x : List = 0 + val x : List = 0 x`java::java.util.List.get()`[1] val foo = new `Bar()`Bar() foo`!`[null, 1] diff --git a/idea/tests/org/jetbrains/jet/types/JetTypeCheckerTest.java b/idea/tests/org/jetbrains/jet/types/JetTypeCheckerTest.java index bffb951936a..a81074ac0f1 100644 --- a/idea/tests/org/jetbrains/jet/types/JetTypeCheckerTest.java +++ b/idea/tests/org/jetbrains/jet/types/JetTypeCheckerTest.java @@ -267,6 +267,10 @@ public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase { assertSubtype("Derived_outT", "Base_outT"); assertSubtype("Derived_T", "Base_T"); assertSubtype("Derived_T", "Base_T"); + + assertSubtype("Derived_T", "Base_T"); + assertSubtype("MDerived_T", "Base_T"); + assertSubtype("ArrayList", "List"); } 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 : Base_inT, Derived_T", "open class Base_outT", "open class Derived_outT : Base_outT", + "open class MDerived_T> : Base_outT, Base_T", "class Properties { val p : Int }", "class Props { val p : T }", "class Functions { " + @@ -547,7 +552,12 @@ public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase { "fun isValid() : Boolean " + "fun isValid(x : Int) : Boolean " + "val p : Boolean " + - "}" + "}", + + "open class List", + "open class AbstractList : List", + "open class ArrayList : Any, AbstractList, List" + }; private String[] FUNCTION_DECLARATIONS = { "fun f() : Unit {}",