Better error recovery
This commit is contained in:
@@ -325,6 +325,8 @@ public class ClassDescriptorResolver {
|
||||
continue;
|
||||
}
|
||||
TypeParameterDescriptor typeParameterDescriptor = parameterByName.get(referencedName);
|
||||
JetTypeReference boundTypeReference = constraint.getBoundTypeReference();
|
||||
JetType bound = boundTypeReference != null ? resolveAndCheckUpperBoundType(boundTypeReference, scope, constraint.isClassObjectContraint()) : null;
|
||||
if (typeParameterDescriptor == null) {
|
||||
// To tell the user that we look only for locally defined type parameters
|
||||
ClassifierDescriptor classifier = scope.getClassifier(referencedName);
|
||||
@@ -338,9 +340,7 @@ public class ClassDescriptorResolver {
|
||||
}
|
||||
else {
|
||||
trace.record(BindingContext.REFERENCE_TARGET, subjectTypeParameterName, typeParameterDescriptor);
|
||||
JetTypeReference boundTypeReference = constraint.getBoundTypeReference();
|
||||
if (boundTypeReference != null) {
|
||||
JetType bound = resolveAndCheckUpperBoundType(boundTypeReference, scope, constraint.isClassObjectContraint());
|
||||
if (bound != null) {
|
||||
if (constraint.isClassObjectContraint()) {
|
||||
typeParameterDescriptor.addClassObjectBound(bound);
|
||||
}
|
||||
|
||||
@@ -56,64 +56,68 @@ public class TypeResolver {
|
||||
}
|
||||
|
||||
ClassifierDescriptor classifierDescriptor = resolveClass(scope, type);
|
||||
if (classifierDescriptor != null) {
|
||||
if (classifierDescriptor instanceof TypeParameterDescriptor) {
|
||||
TypeParameterDescriptor typeParameterDescriptor = (TypeParameterDescriptor) classifierDescriptor;
|
||||
if (classifierDescriptor == null) {
|
||||
resolveTypeProjections(scope, ErrorUtils.createErrorType("No type").getConstructor(), type.getTypeArguments());
|
||||
return;
|
||||
}
|
||||
if (classifierDescriptor instanceof TypeParameterDescriptor) {
|
||||
TypeParameterDescriptor typeParameterDescriptor = (TypeParameterDescriptor) classifierDescriptor;
|
||||
|
||||
trace.record(BindingContext.REFERENCE_TARGET, referenceExpression, typeParameterDescriptor);
|
||||
trace.record(BindingContext.REFERENCE_TARGET, referenceExpression, typeParameterDescriptor);
|
||||
|
||||
result[0] = new JetTypeImpl(
|
||||
annotations,
|
||||
typeParameterDescriptor.getTypeConstructor(),
|
||||
nullable || TypeUtils.hasNullableBound(typeParameterDescriptor),
|
||||
Collections.<TypeProjection>emptyList(),
|
||||
getScopeForTypeParameter(typeParameterDescriptor)
|
||||
);
|
||||
|
||||
resolveTypeProjections(scope, ErrorUtils.createErrorType("No type").getConstructor(), type.getTypeArguments());
|
||||
}
|
||||
else if (classifierDescriptor instanceof ClassDescriptor) {
|
||||
ClassDescriptor classDescriptor = (ClassDescriptor) classifierDescriptor;
|
||||
|
||||
trace.record(BindingContext.REFERENCE_TARGET, referenceExpression, classifierDescriptor);
|
||||
TypeConstructor typeConstructor = classifierDescriptor.getTypeConstructor();
|
||||
List<TypeProjection> arguments = resolveTypeProjections(scope, typeConstructor, type.getTypeArguments());
|
||||
List<TypeParameterDescriptor> parameters = typeConstructor.getParameters();
|
||||
int expectedArgumentCount = parameters.size();
|
||||
int actualArgumentCount = arguments.size();
|
||||
if (ErrorUtils.isError(typeConstructor)) {
|
||||
result[0] = new JetTypeImpl(
|
||||
annotations,
|
||||
typeParameterDescriptor.getTypeConstructor(),
|
||||
nullable || TypeUtils.hasNullableBound(typeParameterDescriptor),
|
||||
Collections.<TypeProjection>emptyList(),
|
||||
getScopeForTypeParameter(typeParameterDescriptor)
|
||||
typeConstructor,
|
||||
nullable,
|
||||
arguments, // TODO : review
|
||||
classDescriptor.getMemberScope(Collections.<TypeProjection>emptyList())
|
||||
);
|
||||
}
|
||||
else if (classifierDescriptor instanceof ClassDescriptor) {
|
||||
ClassDescriptor classDescriptor = (ClassDescriptor) classifierDescriptor;
|
||||
|
||||
trace.record(BindingContext.REFERENCE_TARGET, referenceExpression, classifierDescriptor);
|
||||
TypeConstructor typeConstructor = classifierDescriptor.getTypeConstructor();
|
||||
List<TypeProjection> arguments = resolveTypeProjections(scope, typeConstructor, type.getTypeArguments());
|
||||
List<TypeParameterDescriptor> parameters = typeConstructor.getParameters();
|
||||
int expectedArgumentCount = parameters.size();
|
||||
int actualArgumentCount = arguments.size();
|
||||
if (ErrorUtils.isError(typeConstructor)) {
|
||||
else {
|
||||
if (actualArgumentCount != expectedArgumentCount) {
|
||||
String errorMessage = (expectedArgumentCount == 0 ? "No" : expectedArgumentCount) + " type arguments expected";
|
||||
if (actualArgumentCount == 0) {
|
||||
trace.getErrorHandler().genericError(type.getNode(), errorMessage);
|
||||
} else {
|
||||
trace.getErrorHandler().genericError(type.getTypeArgumentList().getNode(), errorMessage);
|
||||
}
|
||||
} else {
|
||||
result[0] = new JetTypeImpl(
|
||||
annotations,
|
||||
typeConstructor,
|
||||
nullable,
|
||||
arguments, // TODO : review
|
||||
classDescriptor.getMemberScope(Collections.<TypeProjection>emptyList())
|
||||
arguments,
|
||||
classDescriptor.getMemberScope(arguments)
|
||||
);
|
||||
}
|
||||
else {
|
||||
if (actualArgumentCount != expectedArgumentCount) {
|
||||
String errorMessage = (expectedArgumentCount == 0 ? "No" : expectedArgumentCount) + " type arguments expected";
|
||||
if (actualArgumentCount == 0) {
|
||||
trace.getErrorHandler().genericError(type.getNode(), errorMessage);
|
||||
} else {
|
||||
trace.getErrorHandler().genericError(type.getTypeArgumentList().getNode(), errorMessage);
|
||||
}
|
||||
} else {
|
||||
result[0] = new JetTypeImpl(
|
||||
annotations,
|
||||
typeConstructor,
|
||||
nullable,
|
||||
arguments,
|
||||
classDescriptor.getMemberScope(arguments)
|
||||
);
|
||||
if (checkBounds) {
|
||||
TypeSubstitutor substitutor = TypeSubstitutor.create(result[0]);
|
||||
for (int i = 0, parametersSize = parameters.size(); i < parametersSize; i++) {
|
||||
TypeParameterDescriptor parameter = parameters.get(i);
|
||||
JetType argument = arguments.get(i).getType();
|
||||
JetTypeReference typeReference = type.getTypeArguments().get(i).getTypeReference();
|
||||
if (checkBounds) {
|
||||
TypeSubstitutor substitutor = TypeSubstitutor.create(result[0]);
|
||||
for (int i = 0, parametersSize = parameters.size(); i < parametersSize; i++) {
|
||||
TypeParameterDescriptor parameter = parameters.get(i);
|
||||
JetType argument = arguments.get(i).getType();
|
||||
JetTypeReference typeReference = type.getTypeArguments().get(i).getTypeReference();
|
||||
|
||||
if (typeReference != null) {
|
||||
semanticServices.getClassDescriptorResolver(trace).checkBounds(typeReference, argument, parameter, substitutor);
|
||||
}
|
||||
if (typeReference != null) {
|
||||
semanticServices.getClassDescriptorResolver(trace).checkBounds(typeReference, argument, parameter, substitutor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,9 +60,9 @@ fun <T : A> test2(t : T)
|
||||
t.bar()
|
||||
}
|
||||
|
||||
val test1 = test2<<error>A</error>>(A())
|
||||
val test2 = test2<<error>B</error>>(B())
|
||||
val test3 = test2<C>(C())
|
||||
val t1 = test2<<error>A</error>>(A())
|
||||
val t2 = test2<<error>B</error>>(B())
|
||||
val t3 = test2<C>(C())
|
||||
|
||||
class Test<<error>T</error>>
|
||||
where
|
||||
|
||||
@@ -8,6 +8,10 @@ namespace a {
|
||||
|
||||
}
|
||||
|
||||
class Foo<T>() {
|
||||
val x : T<Int>
|
||||
}
|
||||
|
||||
namespace a {
|
||||
import java.util.*
|
||||
|
||||
|
||||
Reference in New Issue
Block a user