TypeResolutionContext introduced
This commit is contained in:
@@ -0,0 +1,16 @@
|
|||||||
|
package org.jetbrains.jet.lang.resolve;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||||
|
|
||||||
|
public class TypeResolutionContext {
|
||||||
|
public final JetScope scope;
|
||||||
|
public final BindingTrace trace;
|
||||||
|
public final boolean checkBounds;
|
||||||
|
|
||||||
|
public TypeResolutionContext(@NotNull JetScope scope, @NotNull BindingTrace trace, boolean checkBounds) {
|
||||||
|
this.scope = scope;
|
||||||
|
this.trace = trace;
|
||||||
|
this.checkBounds = checkBounds;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -66,22 +66,30 @@ public class TypeResolver {
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public JetType resolveType(@NotNull JetScope scope, @NotNull JetTypeReference typeReference, BindingTrace trace, boolean checkBounds) {
|
public JetType resolveType(@NotNull JetScope scope, @NotNull JetTypeReference typeReference, BindingTrace trace, boolean checkBounds) {
|
||||||
JetType cachedType = trace.getBindingContext().get(BindingContext.TYPE, typeReference);
|
return resolveType(new TypeResolutionContext(scope, trace, checkBounds, false), typeReference);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public JetType resolveType(@NotNull TypeResolutionContext c, @NotNull JetTypeReference typeReference) {
|
||||||
|
JetType cachedType = c.trace.getBindingContext().get(BindingContext.TYPE, typeReference);
|
||||||
if (cachedType != null) return cachedType;
|
if (cachedType != null) return cachedType;
|
||||||
|
|
||||||
List<AnnotationDescriptor> annotations = annotationResolver.getResolvedAnnotations(typeReference.getAnnotations(), trace);
|
List<AnnotationDescriptor> annotations = annotationResolver.getResolvedAnnotations(typeReference.getAnnotations(), c.trace);
|
||||||
|
|
||||||
JetTypeElement typeElement = typeReference.getTypeElement();
|
JetTypeElement typeElement = typeReference.getTypeElement();
|
||||||
JetType type = resolveTypeElement(scope, annotations, typeElement, trace, checkBounds);
|
JetType type = resolveTypeElement(c, annotations, typeElement);
|
||||||
trace.record(BindingContext.TYPE, typeReference, type);
|
c.trace.record(BindingContext.TYPE, typeReference, type);
|
||||||
trace.record(BindingContext.TYPE_RESOLUTION_SCOPE, typeReference, scope);
|
c.trace.record(BindingContext.TYPE_RESOLUTION_SCOPE, typeReference, c.scope);
|
||||||
|
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private JetType resolveTypeElement(final JetScope scope, final List<AnnotationDescriptor> annotations,
|
private JetType resolveTypeElement(
|
||||||
JetTypeElement typeElement, final BindingTrace trace, final boolean checkBounds) {
|
final TypeResolutionContext c,
|
||||||
|
final List<AnnotationDescriptor> annotations,
|
||||||
|
JetTypeElement typeElement
|
||||||
|
) {
|
||||||
|
|
||||||
final JetType[] result = new JetType[1];
|
final JetType[] result = new JetType[1];
|
||||||
if (typeElement != null) {
|
if (typeElement != null) {
|
||||||
@@ -94,18 +102,18 @@ public class TypeResolver {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ClassifierDescriptor classifierDescriptor = resolveClass(scope, type, trace);
|
ClassifierDescriptor classifierDescriptor = resolveClass(c.scope, type, c.trace);
|
||||||
if (classifierDescriptor == null) {
|
if (classifierDescriptor == null) {
|
||||||
resolveTypeProjections(scope, ErrorUtils.createErrorType("No type").getConstructor(), type.getTypeArguments(), trace, checkBounds);
|
resolveTypeProjections(c, ErrorUtils.createErrorType("No type").getConstructor(), type.getTypeArguments());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
trace.record(BindingContext.REFERENCE_TARGET, referenceExpression, classifierDescriptor);
|
c.trace.record(BindingContext.REFERENCE_TARGET, referenceExpression, classifierDescriptor);
|
||||||
|
|
||||||
if (classifierDescriptor instanceof TypeParameterDescriptor) {
|
if (classifierDescriptor instanceof TypeParameterDescriptor) {
|
||||||
TypeParameterDescriptor typeParameterDescriptor = (TypeParameterDescriptor) classifierDescriptor;
|
TypeParameterDescriptor typeParameterDescriptor = (TypeParameterDescriptor) classifierDescriptor;
|
||||||
|
|
||||||
JetScope scopeForTypeParameter = getScopeForTypeParameter(typeParameterDescriptor, checkBounds);
|
JetScope scopeForTypeParameter = getScopeForTypeParameter(c, typeParameterDescriptor);
|
||||||
if (scopeForTypeParameter instanceof ErrorUtils.ErrorScope) {
|
if (scopeForTypeParameter instanceof ErrorUtils.ErrorScope) {
|
||||||
result[0] = ErrorUtils.createErrorType("?");
|
result[0] = ErrorUtils.createErrorType("?");
|
||||||
}
|
}
|
||||||
@@ -119,19 +127,19 @@ public class TypeResolver {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
resolveTypeProjections(scope, ErrorUtils.createErrorType("No type").getConstructor(), type.getTypeArguments(), trace, checkBounds);
|
resolveTypeProjections(c, ErrorUtils.createErrorType("No type").getConstructor(), type.getTypeArguments());
|
||||||
|
|
||||||
DeclarationDescriptor containing = typeParameterDescriptor.getContainingDeclaration();
|
DeclarationDescriptor containing = typeParameterDescriptor.getContainingDeclaration();
|
||||||
if (containing instanceof ClassDescriptor) {
|
if (containing instanceof ClassDescriptor) {
|
||||||
// Type parameter can't be inherited from member of parent class, so we can skip subclass check
|
// Type parameter can't be inherited from member of parent class, so we can skip subclass check
|
||||||
DescriptorResolver.checkHasOuterClassInstance(scope, trace, referenceExpression, (ClassDescriptor) containing, false);
|
DescriptorResolver.checkHasOuterClassInstance(c.scope, c.trace, referenceExpression, (ClassDescriptor) containing, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (classifierDescriptor instanceof ClassDescriptor) {
|
else if (classifierDescriptor instanceof ClassDescriptor) {
|
||||||
ClassDescriptor classDescriptor = (ClassDescriptor) classifierDescriptor;
|
ClassDescriptor classDescriptor = (ClassDescriptor) classifierDescriptor;
|
||||||
|
|
||||||
TypeConstructor typeConstructor = classifierDescriptor.getTypeConstructor();
|
TypeConstructor typeConstructor = classifierDescriptor.getTypeConstructor();
|
||||||
List<TypeProjection> arguments = resolveTypeProjections(scope, typeConstructor, type.getTypeArguments(), trace, checkBounds);
|
List<TypeProjection> arguments = resolveTypeProjections(c, typeConstructor, type.getTypeArguments());
|
||||||
List<TypeParameterDescriptor> parameters = typeConstructor.getParameters();
|
List<TypeParameterDescriptor> parameters = typeConstructor.getParameters();
|
||||||
int expectedArgumentCount = parameters.size();
|
int expectedArgumentCount = parameters.size();
|
||||||
int actualArgumentCount = arguments.size();
|
int actualArgumentCount = arguments.size();
|
||||||
@@ -142,14 +150,14 @@ public class TypeResolver {
|
|||||||
if (actualArgumentCount != expectedArgumentCount) {
|
if (actualArgumentCount != expectedArgumentCount) {
|
||||||
if (actualArgumentCount == 0) {
|
if (actualArgumentCount == 0) {
|
||||||
if (rhsOfIsExpression(type) || rhsOfIsPattern(type)) {
|
if (rhsOfIsExpression(type) || rhsOfIsPattern(type)) {
|
||||||
trace.report(NO_TYPE_ARGUMENTS_ON_RHS_OF_IS_EXPRESSION.on(type, expectedArgumentCount, allStarProjectionsString(typeConstructor)));
|
c.trace.report(NO_TYPE_ARGUMENTS_ON_RHS_OF_IS_EXPRESSION.on(type, expectedArgumentCount, allStarProjectionsString(typeConstructor)));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
trace.report(WRONG_NUMBER_OF_TYPE_ARGUMENTS.on(type, expectedArgumentCount));
|
c.trace.report(WRONG_NUMBER_OF_TYPE_ARGUMENTS.on(type, expectedArgumentCount));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
trace.report(WRONG_NUMBER_OF_TYPE_ARGUMENTS.on(type.getTypeArgumentList(), expectedArgumentCount));
|
c.trace.report(WRONG_NUMBER_OF_TYPE_ARGUMENTS.on(type.getTypeArgumentList(), expectedArgumentCount));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -160,7 +168,7 @@ public class TypeResolver {
|
|||||||
arguments,
|
arguments,
|
||||||
classDescriptor.getMemberScope(arguments)
|
classDescriptor.getMemberScope(arguments)
|
||||||
);
|
);
|
||||||
if (checkBounds) {
|
if (c.checkBounds) {
|
||||||
TypeSubstitutor substitutor = TypeSubstitutor.create(result[0]);
|
TypeSubstitutor substitutor = TypeSubstitutor.create(result[0]);
|
||||||
for (int i = 0, parametersSize = parameters.size(); i < parametersSize; i++) {
|
for (int i = 0, parametersSize = parameters.size(); i < parametersSize; i++) {
|
||||||
TypeParameterDescriptor parameter = parameters.get(i);
|
TypeParameterDescriptor parameter = parameters.get(i);
|
||||||
@@ -168,7 +176,7 @@ public class TypeResolver {
|
|||||||
JetTypeReference typeReference = type.getTypeArguments().get(i).getTypeReference();
|
JetTypeReference typeReference = type.getTypeArguments().get(i).getTypeReference();
|
||||||
|
|
||||||
if (typeReference != null) {
|
if (typeReference != null) {
|
||||||
descriptorResolver.checkBounds(typeReference, argument, parameter, substitutor, trace);
|
DescriptorResolver.checkBounds(typeReference, argument, parameter, substitutor, c.trace);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -179,12 +187,12 @@ public class TypeResolver {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitNullableType(JetNullableType nullableType) {
|
public void visitNullableType(JetNullableType nullableType) {
|
||||||
JetType baseType = resolveTypeElement(scope, annotations, nullableType.getInnerType(), trace, checkBounds);
|
JetType baseType = resolveTypeElement(c, annotations, nullableType.getInnerType());
|
||||||
if (baseType.isNullable()) {
|
if (baseType.isNullable()) {
|
||||||
trace.report(REDUNDANT_NULLABLE.on(nullableType));
|
c.trace.report(REDUNDANT_NULLABLE.on(nullableType));
|
||||||
}
|
}
|
||||||
else if (TypeUtils.hasNullableSuperType(baseType)) {
|
else if (TypeUtils.hasNullableSuperType(baseType)) {
|
||||||
trace.report(BASE_WITH_NULLABLE_UPPER_BOUND.on(nullableType, baseType));
|
c.trace.report(BASE_WITH_NULLABLE_UPPER_BOUND.on(nullableType, baseType));
|
||||||
}
|
}
|
||||||
result[0] = TypeUtils.makeNullable(baseType);
|
result[0] = TypeUtils.makeNullable(baseType);
|
||||||
}
|
}
|
||||||
@@ -192,17 +200,17 @@ public class TypeResolver {
|
|||||||
@Override
|
@Override
|
||||||
public void visitFunctionType(JetFunctionType type) {
|
public void visitFunctionType(JetFunctionType type) {
|
||||||
JetTypeReference receiverTypeRef = type.getReceiverTypeRef();
|
JetTypeReference receiverTypeRef = type.getReceiverTypeRef();
|
||||||
JetType receiverType = receiverTypeRef == null ? null : resolveType(scope, receiverTypeRef, trace, checkBounds);
|
JetType receiverType = receiverTypeRef == null ? null : resolveType(c, receiverTypeRef);
|
||||||
|
|
||||||
List<JetType> parameterTypes = new ArrayList<JetType>();
|
List<JetType> parameterTypes = new ArrayList<JetType>();
|
||||||
for (JetParameter parameter : type.getParameters()) {
|
for (JetParameter parameter : type.getParameters()) {
|
||||||
parameterTypes.add(resolveType(scope, parameter.getTypeReference(), trace, checkBounds));
|
parameterTypes.add(resolveType(c, parameter.getTypeReference()));
|
||||||
}
|
}
|
||||||
|
|
||||||
JetTypeReference returnTypeRef = type.getReturnTypeRef();
|
JetTypeReference returnTypeRef = type.getReturnTypeRef();
|
||||||
JetType returnType;
|
JetType returnType;
|
||||||
if (returnTypeRef != null) {
|
if (returnTypeRef != null) {
|
||||||
returnType = resolveType(scope, returnTypeRef, trace, checkBounds);
|
returnType = resolveType(c, returnTypeRef);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
returnType = KotlinBuiltIns.getInstance().getUnitType();
|
returnType = KotlinBuiltIns.getInstance().getUnitType();
|
||||||
@@ -212,8 +220,7 @@ public class TypeResolver {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitJetElement(JetElement element) {
|
public void visitJetElement(JetElement element) {
|
||||||
trace.report(UNSUPPORTED.on(element, "Self-types are not supported yet"));
|
c.trace.report(UNSUPPORTED.on(element, "Self-types are not supported yet"));
|
||||||
// throw new IllegalArgumentException("Unsupported type: " + element);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -244,8 +251,8 @@ public class TypeResolver {
|
|||||||
return type.getParent() == outerPattern.getTypeRef();
|
return type.getParent() == outerPattern.getTypeRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
private JetScope getScopeForTypeParameter(final TypeParameterDescriptor typeParameterDescriptor, boolean checkBounds) {
|
private JetScope getScopeForTypeParameter(TypeResolutionContext c, final TypeParameterDescriptor typeParameterDescriptor) {
|
||||||
if (checkBounds) {
|
if (c.checkBounds) {
|
||||||
return typeParameterDescriptor.getUpperBoundsAsType().getMemberScope();
|
return typeParameterDescriptor.getUpperBoundsAsType().getMemberScope();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -267,7 +274,11 @@ public class TypeResolver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private List<TypeProjection> resolveTypeProjections(JetScope scope, TypeConstructor constructor, List<JetTypeProjection> argumentElements, BindingTrace trace, boolean checkBounds) {
|
private List<TypeProjection> resolveTypeProjections(
|
||||||
|
TypeResolutionContext c,
|
||||||
|
TypeConstructor constructor,
|
||||||
|
List<JetTypeProjection> argumentElements
|
||||||
|
) {
|
||||||
List<TypeProjection> arguments = new ArrayList<TypeProjection>();
|
List<TypeProjection> arguments = new ArrayList<TypeProjection>();
|
||||||
for (int i = 0, argumentElementsSize = argumentElements.size(); i < argumentElementsSize; i++) {
|
for (int i = 0, argumentElementsSize = argumentElements.size(); i < argumentElementsSize; i++) {
|
||||||
JetTypeProjection argumentElement = argumentElements.get(i);
|
JetTypeProjection argumentElement = argumentElements.get(i);
|
||||||
@@ -286,16 +297,16 @@ public class TypeResolver {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// TODO : handle the Foo<in *> case
|
// TODO : handle the Foo<in *> case
|
||||||
type = resolveType(scope, argumentElement.getTypeReference(), trace, checkBounds);
|
type = resolveType(c, argumentElement.getTypeReference());
|
||||||
Variance kind = resolveProjectionKind(projectionKind);
|
Variance kind = resolveProjectionKind(projectionKind);
|
||||||
if (constructor.getParameters().size() > i) {
|
if (constructor.getParameters().size() > i) {
|
||||||
TypeParameterDescriptor parameterDescriptor = constructor.getParameters().get(i);
|
TypeParameterDescriptor parameterDescriptor = constructor.getParameters().get(i);
|
||||||
if (kind != INVARIANT && parameterDescriptor.getVariance() != INVARIANT) {
|
if (kind != INVARIANT && parameterDescriptor.getVariance() != INVARIANT) {
|
||||||
if (kind == parameterDescriptor.getVariance()) {
|
if (kind == parameterDescriptor.getVariance()) {
|
||||||
trace.report(REDUNDANT_PROJECTION.on(argumentElement, constructor.getDeclarationDescriptor()));
|
c.trace.report(REDUNDANT_PROJECTION.on(argumentElement, constructor.getDeclarationDescriptor()));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
trace.report(CONFLICTING_PROJECTION.on(argumentElement, constructor.getDeclarationDescriptor()));
|
c.trace.report(CONFLICTING_PROJECTION.on(argumentElement, constructor.getDeclarationDescriptor()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user