Report error on using reflection without kotlin-reflect.jar in classpath
Should be a warning because strictly speaking, the codegen doesn't need it during the compilation. It's an error at the moment only to let all clients of Kotlin reflection know that they must include kotlin-reflect.jar in the classpath
This commit is contained in:
@@ -65,6 +65,7 @@ import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant;
|
||||
import org.jetbrains.kotlin.resolve.constants.IntegerValueTypeConstant;
|
||||
import org.jetbrains.kotlin.resolve.constants.evaluate.EvaluatePackage;
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilPackage;
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm;
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature;
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.*;
|
||||
import org.jetbrains.kotlin.types.Approximation;
|
||||
@@ -97,6 +98,7 @@ import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.*;
|
||||
import static org.jetbrains.kotlin.resolve.jvm.diagnostics.DiagnosticsPackage.OtherOrigin;
|
||||
import static org.jetbrains.kotlin.resolve.jvm.diagnostics.DiagnosticsPackage.TraitImpl;
|
||||
import static org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue.NO_RECEIVER;
|
||||
import static org.jetbrains.kotlin.serialization.deserialization.DeserializationPackage.findClassAcrossModuleDependencies;
|
||||
import static org.jetbrains.org.objectweb.asm.Opcodes.ACC_PRIVATE;
|
||||
|
||||
public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implements LocalLookup {
|
||||
@@ -2665,6 +2667,8 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
||||
|
||||
@Override
|
||||
public StackValue visitClassLiteralExpression(@NotNull JetClassLiteralExpression expression, StackValue data) {
|
||||
checkReflectionIsAvailable(expression);
|
||||
|
||||
JetType type = bindingContext.get(EXPRESSION_TYPE, expression);
|
||||
assert type != null;
|
||||
|
||||
@@ -2687,25 +2691,34 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
||||
}
|
||||
|
||||
VariableDescriptor variableDescriptor = bindingContext.get(VARIABLE, expression);
|
||||
if (variableDescriptor != null) {
|
||||
VariableDescriptor descriptor = (VariableDescriptor) resolvedCall.getResultingDescriptor();
|
||||
|
||||
DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration();
|
||||
if (containingDeclaration instanceof PackageFragmentDescriptor) {
|
||||
return generateTopLevelPropertyReference(descriptor);
|
||||
}
|
||||
else if (containingDeclaration instanceof ClassDescriptor) {
|
||||
return generateMemberPropertyReference(descriptor, (ClassDescriptor) containingDeclaration);
|
||||
}
|
||||
else if (containingDeclaration instanceof ScriptDescriptor) {
|
||||
return generateMemberPropertyReference(descriptor, ((ScriptDescriptor) containingDeclaration).getClassDescriptor());
|
||||
}
|
||||
else {
|
||||
throw new UnsupportedOperationException("Unsupported callable reference container: " + containingDeclaration);
|
||||
}
|
||||
if (variableDescriptor == null) {
|
||||
throw new UnsupportedOperationException("Unsupported callable reference expression: " + expression.getText());
|
||||
}
|
||||
|
||||
throw new UnsupportedOperationException("Unsupported callable reference expression: " + expression.getText());
|
||||
// TODO: this diagnostic should also be reported on function references once they obtain reflection
|
||||
checkReflectionIsAvailable(expression);
|
||||
|
||||
VariableDescriptor descriptor = (VariableDescriptor) resolvedCall.getResultingDescriptor();
|
||||
|
||||
DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration();
|
||||
if (containingDeclaration instanceof PackageFragmentDescriptor) {
|
||||
return generateTopLevelPropertyReference(descriptor);
|
||||
}
|
||||
else if (containingDeclaration instanceof ClassDescriptor) {
|
||||
return generateMemberPropertyReference(descriptor, (ClassDescriptor) containingDeclaration);
|
||||
}
|
||||
else if (containingDeclaration instanceof ScriptDescriptor) {
|
||||
return generateMemberPropertyReference(descriptor, ((ScriptDescriptor) containingDeclaration).getClassDescriptor());
|
||||
}
|
||||
else {
|
||||
throw new UnsupportedOperationException("Unsupported callable reference container: " + containingDeclaration);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkReflectionIsAvailable(@NotNull JetExpression expression) {
|
||||
if (findClassAcrossModuleDependencies(state.getModule(), JvmAbi.REFLECTION_FACTORY_IMPL) == null) {
|
||||
state.getDiagnostics().report(ErrorsJvm.NO_REFLECTION_IN_CLASS_PATH.on(expression, expression));
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -124,6 +124,8 @@ public class GenerationState {
|
||||
@NotNull
|
||||
private final ModuleDescriptor module;
|
||||
|
||||
private final DiagnosticSink diagnostics;
|
||||
|
||||
@NotNull
|
||||
private final Collection<FqName> packagesWithObsoleteParts;
|
||||
|
||||
@@ -182,6 +184,7 @@ public class GenerationState {
|
||||
builderFactory = new OptimizationClassBuilderFactory(builderFactory);
|
||||
}
|
||||
|
||||
this.diagnostics = diagnostics;
|
||||
this.classFileFactory = new ClassFileFactory(this, new BuilderFactoryForDuplicateSignatureDiagnostics(
|
||||
builderFactory, this.bindingContext, diagnostics));
|
||||
|
||||
@@ -271,6 +274,11 @@ public class GenerationState {
|
||||
return runtimeTypes;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public DiagnosticSink getDiagnostics() {
|
||||
return diagnostics;
|
||||
}
|
||||
|
||||
public boolean isInlineEnabled() {
|
||||
return !disableInline;
|
||||
}
|
||||
|
||||
+2
@@ -53,6 +53,8 @@ public class DefaultErrorMessagesJvm implements DefaultErrorMessages.Extension {
|
||||
MAP.put(ErrorsJvm.NATIVE_DECLARATION_IN_TRAIT, "Members of traits can not be native");
|
||||
MAP.put(ErrorsJvm.NATIVE_DECLARATION_CANNOT_BE_INLINED, "Members of traits can not be inlined");
|
||||
|
||||
MAP.put(ErrorsJvm.NO_REFLECTION_IN_CLASS_PATH, "Expression ''{0}'' uses reflection which is not found in compilation classpath. Make sure you have kotlin-reflect.jar in the classpath", Renderers.ELEMENT_TEXT);
|
||||
|
||||
MAP.put(ErrorsJvm.NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS,
|
||||
"Expected type does not accept nulls in {0}, but the value may be null in {1}", Renderers.TO_STRING, Renderers.TO_STRING);
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.diagnostics.DiagnosticFactory2;
|
||||
import org.jetbrains.kotlin.diagnostics.Errors;
|
||||
import org.jetbrains.kotlin.psi.JetDeclaration;
|
||||
import org.jetbrains.kotlin.psi.JetElement;
|
||||
import org.jetbrains.kotlin.psi.JetExpression;
|
||||
|
||||
import static org.jetbrains.kotlin.diagnostics.PositioningStrategies.*;
|
||||
import static org.jetbrains.kotlin.diagnostics.Severity.ERROR;
|
||||
@@ -46,6 +47,9 @@ public interface ErrorsJvm {
|
||||
DiagnosticFactory0<JetDeclaration> NATIVE_DECLARATION_IN_TRAIT = DiagnosticFactory0.create(ERROR, DECLARATION_SIGNATURE);
|
||||
DiagnosticFactory0<JetDeclaration> NATIVE_DECLARATION_CANNOT_BE_INLINED = DiagnosticFactory0.create(ERROR, DECLARATION_SIGNATURE);
|
||||
|
||||
// TODO: make this a warning
|
||||
DiagnosticFactory1<JetExpression, JetExpression> NO_REFLECTION_IN_CLASS_PATH = DiagnosticFactory1.create(ERROR);
|
||||
|
||||
enum NullabilityInformationSource {
|
||||
KOTLIN {
|
||||
@NotNull
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
$TESTDATA_DIR$/noReflectionInClasspath.kt
|
||||
-d
|
||||
$TEMP_DIR$
|
||||
@@ -0,0 +1,4 @@
|
||||
class Foo(val prop: Any)
|
||||
|
||||
fun t1() = Foo::prop
|
||||
fun t2() = Foo::class
|
||||
@@ -0,0 +1,3 @@
|
||||
ERROR: compiler/testData/cli/jvm/noReflectionInClasspath.kt: (3, 12) Expression 'Foo::prop' uses reflection which is not found in compilation classpath. Make sure you have kotlin-reflect.jar in the classpath
|
||||
ERROR: compiler/testData/cli/jvm/noReflectionInClasspath.kt: (4, 12) Expression 'Foo::class' uses reflection which is not found in compilation classpath. Make sure you have kotlin-reflect.jar in the classpath
|
||||
COMPILATION_ERROR
|
||||
@@ -90,6 +90,12 @@ public class KotlincExecutableTestGenerated extends AbstractKotlincExecutableTes
|
||||
doJvmTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("noReflectionInClasspath.args")
|
||||
public void testNoReflectionInClasspath() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/cli/jvm/noReflectionInClasspath.args");
|
||||
doJvmTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("nonExistingClassPathAndAnnotationsPath.args")
|
||||
public void testNonExistingClassPathAndAnnotationsPath() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/cli/jvm/nonExistingClassPathAndAnnotationsPath.args");
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
package org.jetbrains.kotlin.load.java;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.kotlin.name.ClassId;
|
||||
import org.jetbrains.kotlin.name.FqName;
|
||||
import org.jetbrains.kotlin.name.Name;
|
||||
|
||||
public final class JvmAbi {
|
||||
@@ -41,6 +43,7 @@ public final class JvmAbi {
|
||||
|
||||
public static final String KOTLIN_CLASS_FIELD_NAME = "$kotlinClass";
|
||||
public static final String KOTLIN_PACKAGE_FIELD_NAME = "$kotlinPackage";
|
||||
public static final ClassId REFLECTION_FACTORY_IMPL = ClassId.topLevel(new FqName("kotlin.reflect.jvm.internal.ReflectionFactoryImpl"));
|
||||
|
||||
//TODO: To be removed after kotlin M11
|
||||
@Deprecated
|
||||
|
||||
Reference in New Issue
Block a user