Generic Java classes supported
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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<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());
|
||||
|
||||
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)));
|
||||
// }
|
||||
}
|
||||
return new JetTypeImpl(
|
||||
Collections.<Attribute>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<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));
|
||||
}
|
||||
}
|
||||
|
||||
@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>
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
class Foo : java.util.ArrayList
|
||||
class Foo : java.util.ArrayList<*>
|
||||
@@ -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 {}",
|
||||
|
||||
Reference in New Issue
Block a user