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:
@@ -367,7 +367,9 @@ public interface Errors {
|
|||||||
DiagnosticFactory1<PsiElement, InferenceErrorData> TYPE_INFERENCE_UPPER_BOUND_VIOLATED = DiagnosticFactory1.create(ERROR);
|
DiagnosticFactory1<PsiElement, InferenceErrorData> TYPE_INFERENCE_UPPER_BOUND_VIOLATED = DiagnosticFactory1.create(ERROR);
|
||||||
DiagnosticFactory2<JetExpression, JetType, JetType> TYPE_INFERENCE_EXPECTED_TYPE_MISMATCH = DiagnosticFactory2.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);
|
DiagnosticFactory1<JetExpression, CallableMemberDescriptor> EXTENSION_IN_CLASS_REFERENCE_NOT_ALLOWED = DiagnosticFactory1.create(ERROR);
|
||||||
DiagnosticFactory0<JetExpression> CALLABLE_REFERENCE_LHS_NOT_A_CLASS = DiagnosticFactory0.create(ERROR);
|
DiagnosticFactory0<JetExpression> CALLABLE_REFERENCE_LHS_NOT_A_CLASS = DiagnosticFactory0.create(ERROR);
|
||||||
|
|||||||
+2
@@ -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(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,
|
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);
|
"''{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");
|
MAP.put(CALLABLE_REFERENCE_LHS_NOT_A_CLASS, "Callable reference left-hand side cannot be a type parameter");
|
||||||
|
|||||||
+9
-4
@@ -33,15 +33,20 @@ public class JetCallableReferenceExpression extends JetExpressionImpl {
|
|||||||
return (JetTypeReference) findChildByType(JetNodeTypes.TYPE_REFERENCE);
|
return (JetTypeReference) findChildByType(JetNodeTypes.TYPE_REFERENCE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public PsiElement getDoubleColonTokenReference() {
|
||||||
|
//noinspection ConstantConditions
|
||||||
|
return findChildByType(JetTokens.COLONCOLON);
|
||||||
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public JetSimpleNameExpression getCallableReference() {
|
public JetSimpleNameExpression getCallableReference() {
|
||||||
ASTNode node = getNode().findChildByType(JetTokens.COLONCOLON);
|
PsiElement psi = getDoubleColonTokenReference();
|
||||||
while (node != null) {
|
while (psi != null) {
|
||||||
PsiElement psi = node.getPsi();
|
|
||||||
if (psi instanceof JetSimpleNameExpression) {
|
if (psi instanceof JetSimpleNameExpression) {
|
||||||
return (JetSimpleNameExpression) psi;
|
return (JetSimpleNameExpression) psi;
|
||||||
}
|
}
|
||||||
node = node.getTreeNext();
|
psi = psi.getNextSibling();
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new IllegalStateException("Callable reference simple name shouldn't be parsed to null");
|
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.descriptors.annotations.Annotations
|
||||||
import org.jetbrains.jet.lang.types.JetType
|
import org.jetbrains.jet.lang.types.JetType
|
||||||
import org.jetbrains.jet.lang.types.JetTypeImpl
|
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) {
|
public class ReflectionTypes(private val module: ModuleDescriptor) {
|
||||||
private val kotlinReflect: JetScope by Delegates.lazy {
|
private val kotlinReflectScope: JetScope? by Delegates.lazy {
|
||||||
// TODO: handle errors gracefully (error types)
|
module.getPackage(KOTLIN_REFLECT_FQ_NAME)?.getMemberScope()
|
||||||
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()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun find(className: String): ClassDescriptor {
|
fun find(className: String): ClassDescriptor {
|
||||||
val name = Name.identifier(className)
|
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")
|
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 arguments = KotlinBuiltIns.getFunctionTypeArgumentProjections(receiverType, parameterTypes, returnType)
|
||||||
val classDescriptor = correspondingKFunctionClass(receiverType, extensionFunction, parameterTypes.size)
|
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(
|
private fun correspondingKFunctionClass(
|
||||||
|
|||||||
+5
@@ -503,6 +503,11 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
receiverParameter != null
|
receiverParameter != null
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (type.isError()) {
|
||||||
|
context.trace.report(REFLECTION_TYPES_NOT_LOADED.on(expression.getDoubleColonTokenReference()));
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
AnonymousFunctionDescriptor functionDescriptor = new AnonymousFunctionDescriptor(
|
AnonymousFunctionDescriptor functionDescriptor = new AnonymousFunctionDescriptor(
|
||||||
context.scope.getContainingDeclaration(),
|
context.scope.getContainingDeclaration(),
|
||||||
Annotations.EMPTY,
|
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");
|
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")
|
@TestMetadata("ResolveOfJavaGenerics.kt")
|
||||||
public void testResolveOfJavaGenerics() throws Exception {
|
public void testResolveOfJavaGenerics() throws Exception {
|
||||||
doTest("compiler/testData/diagnostics/tests/ResolveOfJavaGenerics.kt");
|
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
|
@NotNull
|
||||||
public static JetScope createErrorScope(@NotNull String debugMessage) {
|
public static JetScope createErrorScope(@NotNull String debugMessage) {
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
package org.jetbrains.jet.lang.types.error;
|
package org.jetbrains.jet.lang.types.error;
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.jet.lang.descriptors.*;
|
import org.jetbrains.jet.lang.descriptors.*;
|
||||||
import org.jetbrains.jet.lang.descriptors.annotations.Annotations;
|
import org.jetbrains.jet.lang.descriptors.annotations.Annotations;
|
||||||
import org.jetbrains.jet.lang.descriptors.impl.ClassDescriptorImpl;
|
import org.jetbrains.jet.lang.descriptors.impl.ClassDescriptorImpl;
|
||||||
@@ -32,13 +33,12 @@ import java.util.List;
|
|||||||
|
|
||||||
import static org.jetbrains.jet.lang.types.ErrorUtils.*;
|
import static org.jetbrains.jet.lang.types.ErrorUtils.*;
|
||||||
|
|
||||||
public final class ErrorClassDescriptor extends ClassDescriptorImpl {
|
public class ErrorClassDescriptor extends ClassDescriptorImpl {
|
||||||
public ErrorClassDescriptor(@NotNull String debugMessage) {
|
public ErrorClassDescriptor(@Nullable String name) {
|
||||||
super(getErrorModule(), Name.special("<ERROR CLASS: " + debugMessage + ">"), Modality.OPEN, Collections.<JetType>emptyList());
|
super(getErrorModule(), Name.special(name == null ? "<ERROR CLASS>" : "<ERROR CLASS: " + name + ">"),
|
||||||
|
Modality.OPEN, Collections.<JetType>emptyList());
|
||||||
ConstructorDescriptorImpl errorConstructor =
|
|
||||||
ConstructorDescriptorImpl.create(this, Annotations.EMPTY, true);
|
|
||||||
|
|
||||||
|
ConstructorDescriptorImpl errorConstructor = ConstructorDescriptorImpl.create(this, Annotations.EMPTY, true);
|
||||||
errorConstructor.initialize(Collections.<TypeParameterDescriptor>emptyList(), Collections.<ValueParameterDescriptor>emptyList(),
|
errorConstructor.initialize(Collections.<TypeParameterDescriptor>emptyList(), Collections.<ValueParameterDescriptor>emptyList(),
|
||||||
Visibilities.INTERNAL, false);
|
Visibilities.INTERNAL, false);
|
||||||
errorConstructor.setReturnType(createErrorType("<ERROR RETURN TYPE>"));
|
errorConstructor.setReturnType(createErrorType("<ERROR RETURN TYPE>"));
|
||||||
|
|||||||
Reference in New Issue
Block a user