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,
@@ -0,0 +1,8 @@
fun foo() {}
class A {
fun baz() {}
}
val bar = <!REFLECTION_TYPES_NOT_LOADED!>::<!>foo
val quux = A<!REFLECTION_TYPES_NOT_LOADED!>::<!>baz
@@ -374,6 +374,11 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
doTest("compiler/testData/diagnostics/tests/RecursiveTypeInference.kt");
}
@TestMetadata("ReflectionTypesNotLoaded.kt")
public void testReflectionTypesNotLoaded() throws Exception {
doTest("compiler/testData/diagnostics/tests/ReflectionTypesNotLoaded.kt");
}
@TestMetadata("ResolveOfJavaGenerics.kt")
public void testResolveOfJavaGenerics() throws Exception {
doTest("compiler/testData/diagnostics/tests/ResolveOfJavaGenerics.kt");
@@ -227,7 +227,7 @@ public class ErrorUtils {
}
}
private static final ErrorClassDescriptor ERROR_CLASS = new ErrorClassDescriptor("");
private static final ErrorClassDescriptor ERROR_CLASS = new ErrorClassDescriptor(null);
@NotNull
public static JetScope createErrorScope(@NotNull String debugMessage) {
@@ -17,6 +17,7 @@
package org.jetbrains.jet.lang.types.error;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.annotations.Annotations;
import org.jetbrains.jet.lang.descriptors.impl.ClassDescriptorImpl;
@@ -32,13 +33,12 @@ import java.util.List;
import static org.jetbrains.jet.lang.types.ErrorUtils.*;
public final class ErrorClassDescriptor extends ClassDescriptorImpl {
public ErrorClassDescriptor(@NotNull String debugMessage) {
super(getErrorModule(), Name.special("<ERROR CLASS: " + debugMessage + ">"), Modality.OPEN, Collections.<JetType>emptyList());
ConstructorDescriptorImpl errorConstructor =
ConstructorDescriptorImpl.create(this, Annotations.EMPTY, true);
public class ErrorClassDescriptor extends ClassDescriptorImpl {
public ErrorClassDescriptor(@Nullable String name) {
super(getErrorModule(), Name.special(name == null ? "<ERROR CLASS>" : "<ERROR CLASS: " + name + ">"),
Modality.OPEN, Collections.<JetType>emptyList());
ConstructorDescriptorImpl errorConstructor = ConstructorDescriptorImpl.create(this, Annotations.EMPTY, true);
errorConstructor.initialize(Collections.<TypeParameterDescriptor>emptyList(), Collections.<ValueParameterDescriptor>emptyList(),
Visibilities.INTERNAL, false);
errorConstructor.setReturnType(createErrorType("<ERROR RETURN TYPE>"));