Create error type if reflection class isn't found

Introduce a new diagnostic fired when reflection types aren't found in the
classpath
This commit is contained in:
Alexander Udalov
2014-05-08 22:02:11 +04:00
parent 9503056dd5
commit 845e3323f9
9 changed files with 50 additions and 19 deletions
@@ -367,7 +367,9 @@ public interface Errors {
DiagnosticFactory1<PsiElement, InferenceErrorData> TYPE_INFERENCE_UPPER_BOUND_VIOLATED = DiagnosticFactory1.create(ERROR);
DiagnosticFactory2<JetExpression, JetType, JetType> TYPE_INFERENCE_EXPECTED_TYPE_MISMATCH = DiagnosticFactory2.create(ERROR);
// Callable references
// Reflection
DiagnosticFactory0<PsiElement> REFLECTION_TYPES_NOT_LOADED = DiagnosticFactory0.create(ERROR);
DiagnosticFactory1<JetExpression, CallableMemberDescriptor> EXTENSION_IN_CLASS_REFERENCE_NOT_ALLOWED = DiagnosticFactory1.create(ERROR);
DiagnosticFactory0<JetExpression> CALLABLE_REFERENCE_LHS_NOT_A_CLASS = DiagnosticFactory0.create(ERROR);
@@ -471,6 +471,8 @@ public class DefaultErrorMessages {
MAP.put(AMBIGUOUS_ANONYMOUS_TYPE_INFERRED, "Right-hand side has anonymous type. Please specify type explicitly", TO_STRING);
MAP.put(REFLECTION_TYPES_NOT_LOADED, "Reflection types can't be loaded. Please ensure that you have Kotlin Runtime in your classpath");
MAP.put(EXTENSION_IN_CLASS_REFERENCE_NOT_ALLOWED,
"''{0}'' is a member and an extension at the same time. References to such elements are not allowed", NAME);
MAP.put(CALLABLE_REFERENCE_LHS_NOT_A_CLASS, "Callable reference left-hand side cannot be a type parameter");
@@ -33,15 +33,20 @@ public class JetCallableReferenceExpression extends JetExpressionImpl {
return (JetTypeReference) findChildByType(JetNodeTypes.TYPE_REFERENCE);
}
@NotNull
public PsiElement getDoubleColonTokenReference() {
//noinspection ConstantConditions
return findChildByType(JetTokens.COLONCOLON);
}
@NotNull
public JetSimpleNameExpression getCallableReference() {
ASTNode node = getNode().findChildByType(JetTokens.COLONCOLON);
while (node != null) {
PsiElement psi = node.getPsi();
PsiElement psi = getDoubleColonTokenReference();
while (psi != null) {
if (psi instanceof JetSimpleNameExpression) {
return (JetSimpleNameExpression) psi;
}
node = node.getTreeNext();
psi = psi.getNextSibling();
}
throw new IllegalStateException("Callable reference simple name shouldn't be parsed to null");
@@ -25,18 +25,19 @@ import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns
import org.jetbrains.jet.lang.descriptors.annotations.Annotations
import org.jetbrains.jet.lang.types.JetType
import org.jetbrains.jet.lang.types.JetTypeImpl
import org.jetbrains.jet.lang.types.error.ErrorClassDescriptor
private val KOTLIN_REFLECT_FQ_NAME = FqName("kotlin.reflect")
public class ReflectionTypes(private val module: ModuleDescriptor) {
private val kotlinReflect: JetScope by Delegates.lazy {
// TODO: handle errors gracefully (error types)
val kotlin = module.getPackage(FqName("kotlin")) ?: error("Package kotlin not found in $module")
val reflect = kotlin.getMemberScope().getPackage(Name.identifier("reflect")) ?: error("Package reflect not found in $kotlin")
reflect.getMemberScope()
private val kotlinReflectScope: JetScope? by Delegates.lazy {
module.getPackage(KOTLIN_REFLECT_FQ_NAME)?.getMemberScope()
}
fun find(className: String): ClassDescriptor {
val name = Name.identifier(className)
return kotlinReflect.getClassifier(name) as? ClassDescriptor ?: error("Reflection class not found: $name")
return kotlinReflectScope?.getClassifier(name) as? ClassDescriptor
?: ErrorClassDescriptor(KOTLIN_REFLECT_FQ_NAME.child(name).asString())
}
public fun getKFunction(n: Int): ClassDescriptor = find("KFunction$n")
@@ -53,7 +54,10 @@ public class ReflectionTypes(private val module: ModuleDescriptor) {
val arguments = KotlinBuiltIns.getFunctionTypeArgumentProjections(receiverType, parameterTypes, returnType)
val classDescriptor = correspondingKFunctionClass(receiverType, extensionFunction, parameterTypes.size)
return JetTypeImpl(annotations, classDescriptor.getTypeConstructor(), false, arguments, classDescriptor.getMemberScope(arguments))
return if (classDescriptor is ErrorClassDescriptor)
classDescriptor.getDefaultType()
else
JetTypeImpl(annotations, classDescriptor.getTypeConstructor(), false, arguments, classDescriptor.getMemberScope(arguments))
}
private fun correspondingKFunctionClass(
@@ -503,6 +503,11 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
receiverParameter != null
);
if (type.isError()) {
context.trace.report(REFLECTION_TYPES_NOT_LOADED.on(expression.getDoubleColonTokenReference()));
return null;
}
AnonymousFunctionDescriptor functionDescriptor = new AnonymousFunctionDescriptor(
context.scope.getContainingDeclaration(),
Annotations.EMPTY,