Initial support of annotation loading at runtime
In order to locate an annotated entity, we need to implement almost the whole Java element model (which will be used anyway for Java descriptor loading)
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
// SKIP_IN_RUNTIME_TEST because there's no stable way to determine if a field is initialized with a non-null value in runtime
|
||||
|
||||
package test;
|
||||
|
||||
public interface StringConstantInParam {
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
// SKIP_IN_RUNTIME_TEST because there's no stable way to determine if a field is initialized with a non-null value in runtime
|
||||
|
||||
package test;
|
||||
|
||||
public class StaticFinal {
|
||||
public static final String foo = "aaa";
|
||||
public static final String publicNonNull = "aaa";
|
||||
public static final String publicNull = null;
|
||||
static final String packageNonNull = "bbb";
|
||||
static final String packageNull = null;
|
||||
private static final String privateNonNull = "bbb";
|
||||
private static final String privateNull = null;
|
||||
}
|
||||
|
||||
@@ -4,5 +4,10 @@ public open class StaticFinal {
|
||||
public constructor StaticFinal()
|
||||
|
||||
// Static members
|
||||
public final val foo: kotlin.String = "aaa"
|
||||
public/*package*/ final val packageNonNull: kotlin.String = "bbb"
|
||||
public/*package*/ final val packageNull: kotlin.String!
|
||||
private final val privateNonNull: kotlin.String = "bbb"
|
||||
private final val privateNull: kotlin.String!
|
||||
public final val publicNonNull: kotlin.String = "aaa"
|
||||
public final val publicNull: kotlin.String!
|
||||
}
|
||||
|
||||
+14
-5
@@ -16,7 +16,6 @@
|
||||
|
||||
package org.jetbrains.kotlin.jvm.runtime
|
||||
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import org.jetbrains.kotlin.cli.common.output.outputUtils.writeAllTo
|
||||
import org.jetbrains.kotlin.codegen.GeneratedClassLoader
|
||||
import org.jetbrains.kotlin.codegen.GenerationUtils
|
||||
@@ -64,11 +63,13 @@ public abstract class AbstractJvmRuntimeDescriptorLoaderTest : TestCaseWithTmpdi
|
||||
.build()
|
||||
}
|
||||
|
||||
// NOTE: this test does a dirty hack of text substitution to make all annotations defined in source code retain at runtime.
|
||||
// Specifically each "annotation class" is replaced by "Retention(RUNTIME) annotation class"
|
||||
protected fun doTest(ktFileName: String) {
|
||||
val ktFile = File(ktFileName)
|
||||
|
||||
val environment = JetTestUtils.createEnvironmentWithMockJdkAndIdeaAnnotations(myTestRootDisposable, ConfigurationKind.ALL)
|
||||
val jetFile = JetTestUtils.createFile(ktFileName, FileUtil.loadFile(ktFile, true), environment.getProject())
|
||||
val jetFile = JetTestUtils.createFile(ktFileName, loadFileAddingRuntimeRetention(ktFile), environment.getProject())
|
||||
val classFileFactory = GenerationUtils.compileFileGetClassFileFactoryForTest(jetFile)
|
||||
val classLoader = GeneratedClassLoader(classFileFactory, null, ForTestCompileRuntime.runtimeJarForTests().toURI().toURL())
|
||||
|
||||
@@ -103,7 +104,7 @@ public abstract class AbstractJvmRuntimeDescriptorLoaderTest : TestCaseWithTmpdi
|
||||
|
||||
val klass = classLoader.loadClass(className).sure("Couldn't load class $className")
|
||||
|
||||
when (ReflectKotlinClass(klass).getClassHeader().kind) {
|
||||
when (ReflectKotlinClass.create(klass)!!.getClassHeader().kind) {
|
||||
KotlinClassHeader.Kind.PACKAGE_FACADE -> {
|
||||
val packageView = module.getPackage(actual.getFqName()) ?: error("Couldn't resolve package ${actual.getFqName()}")
|
||||
for (descriptor in packageView.getMemberScope().getAllDescriptors()) {
|
||||
@@ -125,13 +126,21 @@ public abstract class AbstractJvmRuntimeDescriptorLoaderTest : TestCaseWithTmpdi
|
||||
|
||||
val expected = LoadDescriptorUtil.loadTestPackageAndBindingContextFromJavaRoot(tmpdir, getTestRootDisposable(),
|
||||
ConfigurationKind.ALL)
|
||||
val configuration = RecursiveDescriptorComparator.DONT_INCLUDE_METHODS_OF_OBJECT
|
||||
val comparatorConfiguration = RecursiveDescriptorComparator.DONT_INCLUDE_METHODS_OF_OBJECT
|
||||
.checkPrimaryConstructors(true)
|
||||
.checkPropertyAccessors(true)
|
||||
.withRenderer(renderer)
|
||||
RecursiveDescriptorComparator.validateAndCompareDescriptors(expected.first, actual, configuration, null)
|
||||
RecursiveDescriptorComparator.validateAndCompareDescriptors(expected.first, actual, comparatorConfiguration, null)
|
||||
}
|
||||
|
||||
private fun loadFileAddingRuntimeRetention(file: File): String {
|
||||
return file.readText().replace(
|
||||
"annotation class",
|
||||
"[java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME)] annotation class"
|
||||
)
|
||||
}
|
||||
|
||||
// Resolves not only top level classes, but also nested classes, including class objects and classes nested within them
|
||||
private fun resolveClassByFqNameInModule(module: ModuleDescriptor, fqName: FqNameUnsafe): ClassDescriptor? {
|
||||
if (fqName.isRoot()) return null
|
||||
|
||||
|
||||
Reference in New Issue
Block a user