Support Java symbols in runtime descriptor loading
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
//ALLOW_AST_ACCESS
|
||||
//SKIP_IN_RUNTIME_TEST
|
||||
package test
|
||||
|
||||
import java.lang.annotation.*
|
||||
|
||||
@@ -52,10 +52,7 @@ import org.junit.Assert;
|
||||
import java.io.File;
|
||||
import java.io.FileFilter;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static org.jetbrains.kotlin.jvm.compiler.LoadDescriptorUtil.*;
|
||||
@@ -82,7 +79,8 @@ public abstract class AbstractLoadJavaTest extends TestCaseWithTmpdir {
|
||||
|
||||
List<File> javaSources = FileUtil.findFilesByMask(Pattern.compile(".+\\.java"), sourcesDir);
|
||||
Pair<PackageViewDescriptor, BindingContext> binaryPackageAndContext = compileJavaAndLoadTestPackageAndBindingContextFromBinary(
|
||||
javaSources, tmpdir, myTestRootDisposable, ConfigurationKind.JDK_ONLY);
|
||||
javaSources, tmpdir, ConfigurationKind.JDK_ONLY
|
||||
);
|
||||
|
||||
checkJavaPackage(expectedFile, binaryPackageAndContext.first, binaryPackageAndContext.second, DONT_INCLUDE_METHODS_OF_OBJECT);
|
||||
}
|
||||
@@ -110,7 +108,8 @@ public abstract class AbstractLoadJavaTest extends TestCaseWithTmpdir {
|
||||
Assert.assertEquals("test", packageFromSource.getName().asString());
|
||||
|
||||
PackageViewDescriptor packageFromBinary = LoadDescriptorUtil.loadTestPackageAndBindingContextFromJavaRoot(
|
||||
tmpdir, getTestRootDisposable(), configurationKind).first;
|
||||
tmpdir, getTestRootDisposable(), TestJdkKind.MOCK_JDK, configurationKind
|
||||
).first;
|
||||
|
||||
for (DeclarationDescriptor descriptor : packageFromBinary.getMemberScope().getAllDescriptors()) {
|
||||
if (descriptor instanceof ClassDescriptor) {
|
||||
@@ -208,7 +207,8 @@ public abstract class AbstractLoadJavaTest extends TestCaseWithTmpdir {
|
||||
FileUtil.copy(originalJavaFile, new File(testPackageDir, originalJavaFile.getName()));
|
||||
|
||||
Pair<PackageViewDescriptor, BindingContext> javaPackageAndContext = loadTestPackageAndBindingContextFromJavaRoot(
|
||||
tmpdir, getTestRootDisposable(), ConfigurationKind.JDK_ONLY);
|
||||
tmpdir, getTestRootDisposable(), TestJdkKind.MOCK_JDK, ConfigurationKind.JDK_ONLY
|
||||
);
|
||||
|
||||
checkJavaPackage(expectedFile, javaPackageAndContext.first, javaPackageAndContext.second,
|
||||
DONT_INCLUDE_METHODS_OF_OBJECT.withValidationStrategy(errorTypesAllowed()));
|
||||
@@ -241,11 +241,22 @@ public abstract class AbstractLoadJavaTest extends TestCaseWithTmpdir {
|
||||
getTestRootDisposable(), ConfigurationKind.JDK_AND_ANNOTATIONS, TestJdkKind.MOCK_JDK);
|
||||
|
||||
Pair<PackageViewDescriptor, BindingContext> javaPackageAndContext = compileJavaAndLoadTestPackageAndBindingContextFromBinary(
|
||||
srcFiles, compiledDir, getTestRootDisposable(), ConfigurationKind.ALL);
|
||||
srcFiles, compiledDir, ConfigurationKind.ALL
|
||||
);
|
||||
|
||||
checkJavaPackage(getTxtFile(javaFileName), javaPackageAndContext.first, javaPackageAndContext.second, configuration);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private Pair<PackageViewDescriptor, BindingContext> compileJavaAndLoadTestPackageAndBindingContextFromBinary(
|
||||
@NotNull Collection<File> javaFiles,
|
||||
@NotNull File outDir,
|
||||
@NotNull ConfigurationKind configurationKind
|
||||
) throws IOException {
|
||||
compileJavaWithAnnotationsJar(javaFiles, outDir);
|
||||
return loadTestPackageAndBindingContextFromJavaRoot(outDir, myTestRootDisposable, TestJdkKind.MOCK_JDK, configurationKind);
|
||||
}
|
||||
|
||||
private static void checkJavaPackage(
|
||||
File txtFile,
|
||||
PackageViewDescriptor javaPackage,
|
||||
|
||||
@@ -80,10 +80,12 @@ public final class LoadDescriptorUtil {
|
||||
public static Pair<PackageViewDescriptor, BindingContext> loadTestPackageAndBindingContextFromJavaRoot(
|
||||
@NotNull File javaRoot,
|
||||
@NotNull Disposable disposable,
|
||||
@NotNull TestJdkKind testJdkKind,
|
||||
@NotNull ConfigurationKind configurationKind
|
||||
) {
|
||||
CompilerConfiguration configuration = JetTestUtils.compilerConfigurationForTests(
|
||||
configurationKind, TestJdkKind.MOCK_JDK,
|
||||
configurationKind,
|
||||
testJdkKind,
|
||||
JetTestUtils.getAnnotationsJar(),
|
||||
javaRoot,
|
||||
new File("compiler/tests") // for @ExpectLoadError annotation
|
||||
@@ -100,19 +102,7 @@ public final class LoadDescriptorUtil {
|
||||
return Pair.create(packageView, trace.getBindingContext());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Pair<PackageViewDescriptor, BindingContext> compileJavaAndLoadTestPackageAndBindingContextFromBinary(
|
||||
@NotNull Collection<File> javaFiles,
|
||||
@NotNull File outDir,
|
||||
@NotNull Disposable disposable,
|
||||
@NotNull ConfigurationKind configurationKind
|
||||
)
|
||||
throws IOException {
|
||||
compileJavaWithAnnotationsJar(javaFiles, outDir);
|
||||
return loadTestPackageAndBindingContextFromJavaRoot(outDir, disposable, configurationKind);
|
||||
}
|
||||
|
||||
private static void compileJavaWithAnnotationsJar(@NotNull Collection<File> javaFiles, @NotNull File outDir) throws IOException {
|
||||
public static void compileJavaWithAnnotationsJar(@NotNull Collection<File> javaFiles, @NotNull File outDir) throws IOException {
|
||||
String classPath = ForTestCompileRuntime.runtimeJarForTests() + File.pathSeparator +
|
||||
JetTestUtils.getAnnotationsJar().getPath();
|
||||
JetTestUtils.compileJavaFiles(javaFiles, Arrays.asList(
|
||||
|
||||
+110
-70
@@ -16,32 +16,40 @@
|
||||
|
||||
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
|
||||
import org.jetbrains.kotlin.codegen.forTestCompile.ForTestCompileRuntime
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptorVisitor
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PackageViewDescriptor
|
||||
import org.jetbrains.kotlin.jvm.compiler.ExpectedLoadErrorsUtil
|
||||
import org.jetbrains.kotlin.jvm.compiler.LoadDescriptorUtil
|
||||
import org.jetbrains.kotlin.load.java.JvmAnnotationNames
|
||||
import org.jetbrains.kotlin.load.java.structure.reflect.classId
|
||||
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader
|
||||
import org.jetbrains.kotlin.load.kotlin.reflect.ReflectKotlinClass
|
||||
import org.jetbrains.kotlin.load.kotlin.reflect.RuntimeModuleData
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.FqNameUnsafe
|
||||
import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
||||
import org.jetbrains.kotlin.renderer.DescriptorRendererBuilder
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.resolveTopLevelClass
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.scopes.JetScope
|
||||
import org.jetbrains.kotlin.resolve.scopes.RedeclarationHandler
|
||||
import org.jetbrains.kotlin.resolve.scopes.WritableScope.LockLevel
|
||||
import org.jetbrains.kotlin.resolve.scopes.WritableScope
|
||||
import org.jetbrains.kotlin.resolve.scopes.WritableScopeImpl
|
||||
import org.jetbrains.kotlin.test.ConfigurationKind
|
||||
import org.jetbrains.kotlin.test.JetTestUtils
|
||||
import org.jetbrains.kotlin.test.TestCaseWithTmpdir
|
||||
import org.jetbrains.kotlin.serialization.deserialization.findClassAcrossModuleDependencies
|
||||
import org.jetbrains.kotlin.test.*
|
||||
import org.jetbrains.kotlin.test.JetTestUtils.TestFileFactoryNoModules
|
||||
import org.jetbrains.kotlin.test.util.DescriptorValidator.ValidationVisitor.errorTypesForbidden
|
||||
import org.jetbrains.kotlin.test.util.RecursiveDescriptorComparator
|
||||
import org.jetbrains.kotlin.test.util.RecursiveDescriptorComparator.Configuration
|
||||
import org.jetbrains.kotlin.types.TypeSubstitutor
|
||||
import org.jetbrains.kotlin.utils.sure
|
||||
import java.io.File
|
||||
import java.net.URLClassLoader
|
||||
import java.util.regex.Pattern
|
||||
|
||||
public abstract class AbstractJvmRuntimeDescriptorLoaderTest : TestCaseWithTmpdir() {
|
||||
class object {
|
||||
@@ -49,8 +57,10 @@ public abstract class AbstractJvmRuntimeDescriptorLoaderTest : TestCaseWithTmpdi
|
||||
.setWithDefinedIn(false)
|
||||
.setExcludedAnnotationClasses(listOf(
|
||||
ExpectedLoadErrorsUtil.ANNOTATION_CLASS_NAME,
|
||||
// TODO: add these annotations when they are retained at runtime
|
||||
"kotlin.deprecated",
|
||||
"kotlin.data",
|
||||
"kotlin.inline",
|
||||
"org.jetbrains.annotations.NotNull",
|
||||
"org.jetbrains.annotations.Nullable",
|
||||
"org.jetbrains.annotations.Mutable",
|
||||
@@ -64,92 +74,122 @@ public abstract class AbstractJvmRuntimeDescriptorLoaderTest : TestCaseWithTmpdi
|
||||
}
|
||||
|
||||
// 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)
|
||||
// Specifically each "annotation class" in Kotlin sources is replaced by "Retention(RUNTIME) annotation class", and the same in Java
|
||||
protected fun doTest(fileName: String) {
|
||||
val file = File(fileName)
|
||||
val text = FileUtil.loadFile(file, true)
|
||||
|
||||
val environment = JetTestUtils.createEnvironmentWithMockJdkAndIdeaAnnotations(myTestRootDisposable, ConfigurationKind.ALL)
|
||||
val jetFile = JetTestUtils.createFile(ktFileName, loadFileAddingRuntimeRetention(ktFile), environment.getProject())
|
||||
val classFileFactory = GenerationUtils.compileFileGetClassFileFactoryForTest(jetFile)
|
||||
val classLoader = GeneratedClassLoader(classFileFactory, null, ForTestCompileRuntime.runtimeJarForTests().toURI().toURL())
|
||||
if (InTextDirectivesUtils.isDirectiveDefined(text, "SKIP_IN_RUNTIME_TEST")) return
|
||||
|
||||
classFileFactory.writeAllTo(tmpdir)
|
||||
compileFile(file, text)
|
||||
|
||||
val classLoader = URLClassLoader(array(tmpdir.toURI().toURL()), ForTestCompileRuntime.runtimeJarClassLoader())
|
||||
|
||||
val actual = createReflectedPackageView(classLoader)
|
||||
|
||||
val expected = LoadDescriptorUtil.loadTestPackageAndBindingContextFromJavaRoot(
|
||||
tmpdir, getTestRootDisposable(), TestJdkKind.FULL_JDK, ConfigurationKind.ALL
|
||||
).first
|
||||
|
||||
val comparatorConfiguration = Configuration(
|
||||
/* checkPrimaryConstructors = */ fileName.endsWith(".kt"),
|
||||
/* checkPropertyAccessors = */ true,
|
||||
/* includeMethodsOfKotlinAny = */ false,
|
||||
{ descriptor ->
|
||||
// Skip annotation constructors because order of their parameters is not retained at runtime
|
||||
!(descriptor is ConstructorDescriptor && DescriptorUtils.isAnnotationClass(descriptor.getContainingDeclaration()))
|
||||
},
|
||||
errorTypesForbidden(), renderer
|
||||
)
|
||||
RecursiveDescriptorComparator.validateAndCompareDescriptors(expected, actual, comparatorConfiguration, null)
|
||||
}
|
||||
|
||||
private fun compileFile(file: File, text: String) {
|
||||
val fileName = file.getName()
|
||||
when {
|
||||
fileName.endsWith(".java") -> {
|
||||
val sources = JetTestUtils.createTestFiles(fileName, text, object : TestFileFactoryNoModules<File>() {
|
||||
override fun create(fileName: String, text: String, directives: Map<String, String>): File {
|
||||
val targetFile = File(tmpdir, fileName)
|
||||
targetFile.writeText(addRuntimeRetentionToJavaSource(text))
|
||||
return targetFile
|
||||
}
|
||||
})
|
||||
LoadDescriptorUtil.compileJavaWithAnnotationsJar(sources, tmpdir)
|
||||
}
|
||||
fileName.endsWith(".kt") -> {
|
||||
val environment = JetTestUtils.createEnvironmentWithFullJdk(myTestRootDisposable)
|
||||
val jetFile = JetTestUtils.createFile(file.getPath(), addRuntimeRetentionToKotlinSource(text), environment.getProject())
|
||||
GenerationUtils.compileFileGetClassFileFactoryForTest(jetFile).writeAllTo(tmpdir)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun createReflectedPackageView(classLoader: URLClassLoader): SyntheticPackageViewForTest {
|
||||
val module = RuntimeModuleData.create(classLoader).module
|
||||
|
||||
// Since runtime package view descriptor doesn't support getAllDescriptors(), we construct a synthetic package view here.
|
||||
// It has in its scope descriptors for all the classes and top level members generated by the compiler
|
||||
val actual = object : PackageViewDescriptor {
|
||||
val scope = WritableScopeImpl(JetScope.Empty, this, RedeclarationHandler.THROW_EXCEPTION, "runtime descriptor loader test")
|
||||
|
||||
override fun getFqName() = LoadDescriptorUtil.TEST_PACKAGE_FQNAME
|
||||
override fun getMemberScope() = scope
|
||||
override fun getModule() = module
|
||||
override fun <R, D> accept(visitor: DeclarationDescriptorVisitor<R, D>, data: D): R =
|
||||
visitor.visitPackageViewDescriptor(this, data)
|
||||
|
||||
override fun getContainingDeclaration() = throw UnsupportedOperationException()
|
||||
override fun getOriginal() = throw UnsupportedOperationException()
|
||||
override fun substitute(substitutor: TypeSubstitutor) = throw UnsupportedOperationException()
|
||||
override fun acceptVoid(visitor: DeclarationDescriptorVisitor<Void, Void>?) = throw UnsupportedOperationException()
|
||||
override fun getAnnotations() = throw UnsupportedOperationException()
|
||||
override fun getName() = throw UnsupportedOperationException()
|
||||
}
|
||||
|
||||
val actual = SyntheticPackageViewForTest(module)
|
||||
val scope = actual.getMemberScope()
|
||||
scope.changeLockLevel(LockLevel.BOTH)
|
||||
|
||||
for (outputFile in classLoader.getAllGeneratedFiles()) {
|
||||
val className = outputFile.relativePath.substringBeforeLast(".class").replace('/', '.').replace('\\', '.')
|
||||
val generatedPackageDir = File(tmpdir, LoadDescriptorUtil.TEST_PACKAGE_FQNAME.pathSegments().single().asString())
|
||||
val allClassFiles = FileUtil.findFilesByMask(Pattern.compile(".*\\.class"), generatedPackageDir)
|
||||
|
||||
for (classFile in allClassFiles) {
|
||||
val className = tmpdir.relativePath(classFile).substringBeforeLast(".class").replace('/', '.').replace('\\', '.')
|
||||
|
||||
val klass = classLoader.loadClass(className).sure("Couldn't load class $className")
|
||||
val header = ReflectKotlinClass.create(klass)?.getClassHeader()
|
||||
|
||||
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()) {
|
||||
when (descriptor) {
|
||||
is FunctionDescriptor -> scope.addFunctionDescriptor(descriptor)
|
||||
is PropertyDescriptor -> scope.addPropertyDescriptor(descriptor)
|
||||
}
|
||||
}
|
||||
}
|
||||
KotlinClassHeader.Kind.CLASS -> {
|
||||
val classDescriptor =
|
||||
resolveClassByFqNameInModule(module, FqNameUnsafe(className)).sure("Couldn't resolve class $className")
|
||||
if (classDescriptor.getContainingDeclaration() is PackageFragmentDescriptor) {
|
||||
scope.addClassifierDescriptor(classDescriptor)
|
||||
}
|
||||
if (header?.kind == KotlinClassHeader.Kind.PACKAGE_FACADE) {
|
||||
val packageView = module.getPackage(actual.getFqName()).sure("Couldn't resolve package ${actual.getFqName()}")
|
||||
scope.importScope(packageView.getMemberScope())
|
||||
}
|
||||
else if (header == null ||
|
||||
(header.kind == KotlinClassHeader.Kind.CLASS && header.classKind == JvmAnnotationNames.KotlinClass.Kind.CLASS)) {
|
||||
// Either a normal Kotlin class or a Java class
|
||||
val classDescriptor = module.findClassAcrossModuleDependencies(klass.classId).sure("Couldn't resolve class $className")
|
||||
if (DescriptorUtils.isTopLevelDeclaration(classDescriptor)) {
|
||||
scope.addClassifierDescriptor(classDescriptor)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val expected = LoadDescriptorUtil.loadTestPackageAndBindingContextFromJavaRoot(tmpdir, getTestRootDisposable(),
|
||||
ConfigurationKind.ALL)
|
||||
val comparatorConfiguration = RecursiveDescriptorComparator.DONT_INCLUDE_METHODS_OF_OBJECT
|
||||
.checkPrimaryConstructors(true)
|
||||
.checkPropertyAccessors(true)
|
||||
.withRenderer(renderer)
|
||||
RecursiveDescriptorComparator.validateAndCompareDescriptors(expected.first, actual, comparatorConfiguration, null)
|
||||
return actual
|
||||
}
|
||||
|
||||
private fun loadFileAddingRuntimeRetention(file: File): String {
|
||||
return file.readText().replace(
|
||||
private fun addRuntimeRetentionToKotlinSource(text: String): String {
|
||||
return text.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
|
||||
private fun addRuntimeRetentionToJavaSource(text: String): String {
|
||||
return text.replace(
|
||||
"@interface",
|
||||
"@java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME) @interface"
|
||||
)
|
||||
}
|
||||
|
||||
if (fqName.isSafe()) {
|
||||
val topLevel = module.resolveTopLevelClass(fqName.toSafe())
|
||||
if (topLevel != null) return topLevel
|
||||
private class SyntheticPackageViewForTest(private val module: ModuleDescriptor) : PackageViewDescriptor {
|
||||
private val scope = WritableScopeImpl(JetScope.Empty, this, RedeclarationHandler.THROW_EXCEPTION, "runtime descriptor loader test")
|
||||
|
||||
;{
|
||||
scope.changeLockLevel(WritableScope.LockLevel.BOTH)
|
||||
}
|
||||
|
||||
val parent = resolveClassByFqNameInModule(module, fqName.parent()) ?: return null
|
||||
return parent.getUnsubstitutedInnerClassesScope().getClassifier(fqName.shortName()) as? ClassDescriptor
|
||||
override fun getFqName() = LoadDescriptorUtil.TEST_PACKAGE_FQNAME
|
||||
override fun getMemberScope() = scope
|
||||
override fun getModule() = module
|
||||
override fun <R, D> accept(visitor: DeclarationDescriptorVisitor<R, D>, data: D): R =
|
||||
visitor.visitPackageViewDescriptor(this, data)
|
||||
|
||||
override fun getContainingDeclaration() = throw UnsupportedOperationException()
|
||||
override fun getOriginal() = throw UnsupportedOperationException()
|
||||
override fun substitute(substitutor: TypeSubstitutor) = throw UnsupportedOperationException()
|
||||
override fun acceptVoid(visitor: DeclarationDescriptorVisitor<Void, Void>?) = throw UnsupportedOperationException()
|
||||
override fun getAnnotations() = throw UnsupportedOperationException()
|
||||
override fun getName() = throw UnsupportedOperationException()
|
||||
}
|
||||
}
|
||||
|
||||
+3593
-2517
File diff suppressed because it is too large
Load Diff
+7
-1
@@ -26,7 +26,13 @@ import org.jetbrains.kotlin.name.ClassId
|
||||
|
||||
public class ReflectJavaClassFinder(private val classLoader: ClassLoader) : JavaClassFinder {
|
||||
override fun findClass(classId: ClassId): JavaClass? {
|
||||
val klass = classLoader.tryLoadClass(classId.asSingleFqName().asString())
|
||||
val packageFqName = classId.getPackageFqName()
|
||||
val relativeClassName = classId.getRelativeClassName().asString().replace('.', '$')
|
||||
val name =
|
||||
if (packageFqName.isRoot()) relativeClassName
|
||||
else packageFqName.asString() + "." + relativeClassName
|
||||
|
||||
val klass = classLoader.tryLoadClass(name)
|
||||
return if (klass != null) ReflectJavaClass(klass) else null
|
||||
}
|
||||
|
||||
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.load.java.structure.reflect
|
||||
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaAnnotation
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaAnnotationArgument
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import java.lang.reflect.Method
|
||||
|
||||
public class ReflectJavaAnnotation(private val annotation: Annotation) : ReflectJavaElement(), JavaAnnotation {
|
||||
override fun findArgument(name: Name): JavaAnnotationArgument? {
|
||||
return getArgumentValue(annotation.annotationType().getDeclaredMethod(name.asString()))
|
||||
}
|
||||
|
||||
override fun getArguments(): Collection<JavaAnnotationArgument> {
|
||||
return annotation.annotationType().getDeclaredMethods().map { getArgumentValue(it) }
|
||||
}
|
||||
|
||||
private fun getArgumentValue(argument: Method): ReflectJavaAnnotationArgument {
|
||||
return argument.invoke(annotation).let { ReflectJavaAnnotationArgument.create(it, Name.identifier(argument.getName())) }
|
||||
}
|
||||
|
||||
override fun resolve() = ReflectJavaClass(annotation.annotationType())
|
||||
|
||||
override fun getClassId() = annotation.annotationType().classId
|
||||
}
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.load.java.structure.reflect
|
||||
|
||||
import org.jetbrains.kotlin.load.java.structure.*
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
abstract class ReflectJavaAnnotationArgument(
|
||||
override val name: Name?
|
||||
) : JavaAnnotationArgument {
|
||||
class object {
|
||||
fun create(value: Any, name: Name?): ReflectJavaAnnotationArgument {
|
||||
return when {
|
||||
value.javaClass.isEnum() -> ReflectJavaEnumValueAnnotationArgument(name, value)
|
||||
value is Annotation -> ReflectJavaAnnotationAsAnnotationArgument(name, value)
|
||||
value is Array<Any> -> ReflectJavaArrayAnnotationArgument(name, value)
|
||||
value is Class<*> -> ReflectJavaClassObjectAnnotationArgument(name, value)
|
||||
else -> ReflectJavaLiteralAnnotationArgument(name, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ReflectJavaLiteralAnnotationArgument(
|
||||
name: Name?,
|
||||
override val value: Any
|
||||
) : ReflectJavaAnnotationArgument(name), JavaLiteralAnnotationArgument
|
||||
|
||||
class ReflectJavaArrayAnnotationArgument(
|
||||
name: Name?,
|
||||
private val values: Array<Any>
|
||||
) : ReflectJavaAnnotationArgument(name), JavaArrayAnnotationArgument {
|
||||
override fun getElements() = values.map { ReflectJavaAnnotationArgument.create(it, null) }
|
||||
}
|
||||
|
||||
class ReflectJavaEnumValueAnnotationArgument(
|
||||
name: Name?,
|
||||
private val value: Any
|
||||
) : ReflectJavaAnnotationArgument(name), JavaEnumValueAnnotationArgument {
|
||||
override fun resolve() = ReflectJavaField(value.javaClass.getDeclaredField(value.toString()))
|
||||
}
|
||||
|
||||
class ReflectJavaClassObjectAnnotationArgument(
|
||||
name: Name?,
|
||||
private val klass: Class<*>
|
||||
) : ReflectJavaAnnotationArgument(name), JavaClassObjectAnnotationArgument {
|
||||
override fun getReferencedType(): JavaType = ReflectJavaType.create(klass)
|
||||
}
|
||||
|
||||
class ReflectJavaAnnotationAsAnnotationArgument(
|
||||
name: Name?,
|
||||
private val annotation: Annotation
|
||||
) : ReflectJavaAnnotationArgument(name), JavaAnnotationAsAnnotationArgument {
|
||||
override fun getAnnotation(): JavaAnnotation = ReflectJavaAnnotation(annotation)
|
||||
}
|
||||
+3
-3
@@ -16,9 +16,9 @@
|
||||
|
||||
package org.jetbrains.kotlin.load.java.structure.reflect
|
||||
|
||||
import java.lang.reflect.GenericArrayType
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaArrayType
|
||||
import java.lang.reflect.Type
|
||||
|
||||
public class ReflectJavaArrayType(private val arrayType: GenericArrayType) : ReflectJavaType(), JavaArrayType {
|
||||
override fun getComponentType() = ReflectJavaType.create(arrayType.getGenericComponentType()!!)
|
||||
public class ReflectJavaArrayType(private val componentType: Type) : ReflectJavaType(), JavaArrayType {
|
||||
override fun getComponentType() = ReflectJavaType.create(componentType)
|
||||
}
|
||||
|
||||
+57
-38
@@ -16,69 +16,88 @@
|
||||
|
||||
package org.jetbrains.kotlin.load.java.structure.reflect
|
||||
|
||||
import java.lang.reflect.Modifier
|
||||
import org.jetbrains.kotlin.load.java.structure.*
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.utils.emptyOrSingletonList
|
||||
import java.lang.reflect.Method
|
||||
import java.lang.reflect.Modifier
|
||||
import java.util.Arrays
|
||||
|
||||
public class ReflectJavaClass(private val klass: Class<*>) : ReflectJavaElement(), JavaClass {
|
||||
override fun getInnerClasses() =
|
||||
klass.getDeclaredClasses()
|
||||
.filter { it.getSimpleName().isNotEmpty() }
|
||||
.map { ReflectJavaClass(it) }
|
||||
override fun getInnerClasses() = klass.getDeclaredClasses()
|
||||
.stream()
|
||||
.filterNot {
|
||||
// getDeclaredClasses() returns anonymous classes sometimes, for example enums with specialized entries (which are in fact
|
||||
// anonymous classes) or in case of a special anonymous class created for the synthetic accessor to a private nested class
|
||||
// constructor accessed from the outer class
|
||||
it.getSimpleName().isEmpty()
|
||||
}
|
||||
.map(::ReflectJavaClass)
|
||||
.toList()
|
||||
|
||||
override fun getFqName(): FqName? {
|
||||
// TODO: can there be primitive types, arrays?
|
||||
return getOuterClass()?.getFqName()?.child(Name.identifier(klass.getSimpleName())) ?: FqName(klass.getName())
|
||||
}
|
||||
override fun getFqName() = klass.fqName
|
||||
|
||||
override fun getOuterClass(): JavaClass? {
|
||||
val container = klass.getDeclaringClass()
|
||||
return if (container != null) ReflectJavaClass(container) else null
|
||||
}
|
||||
override fun getOuterClass() = klass.getDeclaringClass()?.let(::ReflectJavaClass)
|
||||
|
||||
override fun getSupertypes(): Collection<JavaClassifierType> {
|
||||
// TODO: also call getSuperclass() / getInterfaces() for classes without generic signature
|
||||
val supertypes = emptyOrSingletonList(klass.getGenericSuperclass()) + klass.getGenericInterfaces()
|
||||
return supertypes.map { supertype -> ReflectJavaType.create(supertype) as JavaClassifierType }
|
||||
val supertype = klass.getGenericSuperclass()
|
||||
val superClassName = (supertype as? Class<*>)?.getName()
|
||||
val supertypes =
|
||||
(if (superClassName == "java.lang.Object") emptyList() else emptyOrSingletonList(supertype)) +
|
||||
klass.getGenericInterfaces()
|
||||
return supertypes.map(::ReflectJavaClassifierType)
|
||||
}
|
||||
|
||||
override fun getMethods() = klass.getDeclaredMethods().map { method -> ReflectJavaMethod(method) }
|
||||
override fun getMethods() = klass.getDeclaredMethods()
|
||||
.stream()
|
||||
.filter { method ->
|
||||
when {
|
||||
method.isSynthetic() -> false
|
||||
isEnum() -> !isEnumValuesOrValueOf(method)
|
||||
else -> true
|
||||
}
|
||||
}
|
||||
.map(::ReflectJavaMethod)
|
||||
.toList()
|
||||
|
||||
override fun getFields() = klass.getDeclaredFields().map { field -> ReflectJavaField(field) }
|
||||
|
||||
override fun getConstructors(): Collection<JavaConstructor> {
|
||||
// TODO
|
||||
return listOf()
|
||||
private fun isEnumValuesOrValueOf(method: Method): Boolean {
|
||||
return when (method.getName()) {
|
||||
"values" -> method.getParameterTypes().isEmpty()
|
||||
"valueOf" -> Arrays.equals(method.getParameterTypes(), array(javaClass<String>()))
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
|
||||
override fun getDefaultType() = ReflectJavaClassifierType(klass)
|
||||
override fun getFields() = klass.getDeclaredFields()
|
||||
.stream()
|
||||
.filter { field -> !field.isSynthetic() }
|
||||
.map(::ReflectJavaField)
|
||||
.toList()
|
||||
|
||||
// TODO: drop OriginKind?
|
||||
override fun getConstructors() = klass.getDeclaredConstructors().map(::ReflectJavaConstructor)
|
||||
|
||||
override fun getDefaultType(): ReflectJavaClassifierType = throw UnsupportedOperationException()
|
||||
|
||||
// TODO: drop OriginKind
|
||||
override fun getOriginKind() = JavaClass.OriginKind.COMPILED
|
||||
|
||||
override fun createImmediateType(substitutor: JavaTypeSubstitutor): JavaType {
|
||||
// TODO
|
||||
throw UnsupportedOperationException()
|
||||
}
|
||||
override fun createImmediateType(substitutor: JavaTypeSubstitutor): JavaType = throw UnsupportedOperationException()
|
||||
|
||||
override fun getName(): Name {
|
||||
// TODO: can there be primitive types, arrays?
|
||||
return Name.identifier(klass.getSimpleName())
|
||||
}
|
||||
override fun getName(): Name = Name.identifier(klass.getSimpleName())
|
||||
|
||||
override fun getAnnotations(): Collection<JavaAnnotation> {
|
||||
// TODO
|
||||
return listOf()
|
||||
}
|
||||
override fun getAnnotations() = klass.getDeclaredAnnotations().map { ReflectJavaAnnotation(it) }
|
||||
|
||||
override fun findAnnotation(fqName: FqName): JavaAnnotation? {
|
||||
// TODO
|
||||
for (annotation in klass.getDeclaredAnnotations()) {
|
||||
if (annotation.annotationType().fqName == fqName) {
|
||||
return ReflectJavaAnnotation(annotation)
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
override fun getTypeParameters() = klass.getTypeParameters().map { ReflectJavaTypeParameter(it!!) }
|
||||
override fun getTypeParameters() = klass.getTypeParameters().map { ReflectJavaTypeParameter(it) }
|
||||
|
||||
override fun isInterface() = klass.isInterface()
|
||||
override fun isAnnotationType() = klass.isAnnotation()
|
||||
|
||||
+10
-7
@@ -25,15 +25,18 @@ import java.lang.reflect.Type
|
||||
import java.lang.reflect.TypeVariable
|
||||
|
||||
public class ReflectJavaClassifierType(val classifierType: Type) : ReflectJavaType(), JavaClassifierType {
|
||||
override fun getClassifier(): JavaClassifier? {
|
||||
return when (classifierType) {
|
||||
is Class<*> -> ReflectJavaClass(classifierType)
|
||||
is TypeVariable<*> -> ReflectJavaTypeParameter(classifierType)
|
||||
is ParameterizedType -> ReflectJavaClass(classifierType.getRawType() as Class<*>)
|
||||
else -> throw IllegalStateException("Not a classifier type (${classifierType.javaClass}): $classifierType")
|
||||
}
|
||||
private val classifier: JavaClassifier = run {
|
||||
val type = classifierType
|
||||
when (type) {
|
||||
is Class<*> -> ReflectJavaClass(type)
|
||||
is TypeVariable<*> -> ReflectJavaTypeParameter(type)
|
||||
is ParameterizedType -> ReflectJavaClass(type.getRawType() as Class<*>)
|
||||
else -> throw IllegalStateException("Not a classifier type (${type.javaClass}): $type")
|
||||
} : JavaClassifier
|
||||
}
|
||||
|
||||
override fun getClassifier(): JavaClassifier = classifier
|
||||
|
||||
override fun getSubstitutor(): JavaTypeSubstitutor = throw UnsupportedOperationException()
|
||||
|
||||
override fun getSupertypes(): Collection<JavaClassifierType> = throw UnsupportedOperationException()
|
||||
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.load.java.structure.reflect
|
||||
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaAnnotation
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaConstructor
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaTypeParameter
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaValueParameter
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import java.lang.reflect.Constructor
|
||||
import java.lang.reflect.Modifier
|
||||
import java.util.Arrays
|
||||
|
||||
public class ReflectJavaConstructor(constructor: Constructor<*>) : ReflectJavaMember(constructor), JavaConstructor {
|
||||
private val constructor: Constructor<*>
|
||||
get() = member as Constructor<*>
|
||||
|
||||
override fun getAnnotations(): Collection<JavaAnnotation> {
|
||||
// TODO
|
||||
return listOf()
|
||||
}
|
||||
|
||||
override fun findAnnotation(fqName: FqName): JavaAnnotation? {
|
||||
// TODO
|
||||
return null
|
||||
}
|
||||
|
||||
override fun getValueParameters(): List<JavaValueParameter> =
|
||||
getValueParameters(
|
||||
dropSynthetic(constructor.getGenericParameterTypes()),
|
||||
dropSynthetic(constructor.getParameterAnnotations()),
|
||||
constructor.isVarArgs()
|
||||
)
|
||||
|
||||
// Constructors of inner classes have one additional synthetic parameter
|
||||
// TODO: test this code with annotations on constructor parameters of enums and inner classes
|
||||
private inline fun <reified T> dropSynthetic(array: Array<T>): Array<T> {
|
||||
val klass = constructor.getDeclaringClass()
|
||||
return if (klass.getDeclaringClass() != null && !Modifier.isStatic(klass.getModifiers())) {
|
||||
Arrays.copyOfRange(array, 1, array.size())
|
||||
}
|
||||
else array
|
||||
}
|
||||
|
||||
override fun getTypeParameters(): List<JavaTypeParameter> {
|
||||
// TODO
|
||||
return listOf()
|
||||
}
|
||||
}
|
||||
+1
-5
@@ -20,7 +20,6 @@ import java.lang.reflect.Field
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaField
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaAnnotation
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaType
|
||||
|
||||
public class ReflectJavaField(field: Field) : ReflectJavaMember(field), JavaField {
|
||||
val field: Field
|
||||
@@ -38,8 +37,5 @@ public class ReflectJavaField(field: Field) : ReflectJavaMember(field), JavaFiel
|
||||
|
||||
override fun isEnumEntry() = field.isEnumConstant()
|
||||
|
||||
override fun getType(): JavaType {
|
||||
// TODO
|
||||
throw UnsupportedOperationException()
|
||||
}
|
||||
override fun getType() = ReflectJavaType.create(field.getGenericType()!!)
|
||||
}
|
||||
|
||||
+18
-2
@@ -16,11 +16,14 @@
|
||||
|
||||
package org.jetbrains.kotlin.load.java.structure.reflect
|
||||
|
||||
import java.lang.reflect.Member
|
||||
import java.lang.reflect.Modifier
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaMember
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaValueParameter
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.name.SpecialNames
|
||||
import java.lang.reflect.Member
|
||||
import java.lang.reflect.Modifier
|
||||
import java.lang.reflect.Type
|
||||
import java.util.ArrayList
|
||||
|
||||
public abstract class ReflectJavaMember(protected val member: Member) : ReflectJavaElement(), JavaMember {
|
||||
override fun getName() = member.getName()?.let { Name.identifier(it) } ?: SpecialNames.NO_NAME_PROVIDED
|
||||
@@ -32,4 +35,17 @@ public abstract class ReflectJavaMember(protected val member: Member) : ReflectJ
|
||||
override fun isFinal() = Modifier.isFinal(member.getModifiers())
|
||||
|
||||
override fun getVisibility() = calculateVisibility(member.getModifiers())
|
||||
|
||||
protected fun getValueParameters(
|
||||
parameterTypes: Array<Type>,
|
||||
parameterAnnotations: Array<Array<Annotation>>,
|
||||
isVararg: Boolean
|
||||
): List<JavaValueParameter> {
|
||||
val result = ArrayList<JavaValueParameter>(parameterTypes.size())
|
||||
for (i in parameterTypes.indices) {
|
||||
val isParamVararg = isVararg && i == parameterTypes.lastIndex
|
||||
result.add(ReflectJavaValueParameter(ReflectJavaType.create(parameterTypes[i]), parameterAnnotations[i], isParamVararg))
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
+6
-16
@@ -16,13 +16,12 @@
|
||||
|
||||
package org.jetbrains.kotlin.load.java.structure.reflect
|
||||
|
||||
import java.lang.reflect.Method
|
||||
import java.util.ArrayList
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaMethod
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaAnnotation
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaValueParameter
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaMethod
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaType
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaValueParameter
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import java.lang.reflect.Method
|
||||
|
||||
public class ReflectJavaMethod(method: Method) : ReflectJavaMember(method), JavaMethod {
|
||||
private val method: Method
|
||||
@@ -38,17 +37,8 @@ public class ReflectJavaMethod(method: Method) : ReflectJavaMember(method), Java
|
||||
return null
|
||||
}
|
||||
|
||||
override fun getValueParameters(): List<JavaValueParameter> {
|
||||
val types = method.getGenericParameterTypes()!!
|
||||
val annotations = method.getParameterAnnotations()
|
||||
val result = ArrayList<JavaValueParameter>()
|
||||
val methodIsVararg = method.isVarArgs()
|
||||
for (i in types.indices) {
|
||||
val isVararg = methodIsVararg && i == types.lastIndex
|
||||
result.add(ReflectJavaValueParameter(ReflectJavaType.create(types[i]), annotations[i], isVararg))
|
||||
}
|
||||
return result
|
||||
}
|
||||
override fun getValueParameters(): List<JavaValueParameter> =
|
||||
getValueParameters(method.getGenericParameterTypes(), method.getParameterAnnotations(), method.isVarArgs())
|
||||
|
||||
override fun getReturnType(): JavaType? {
|
||||
// TODO
|
||||
|
||||
+6
-2
@@ -33,8 +33,12 @@ public abstract class ReflectJavaType : JavaType {
|
||||
fun create(reflectType: Type): ReflectJavaType {
|
||||
return when (reflectType) {
|
||||
in PRIMITIVE_TYPES -> ReflectJavaPrimitiveType(reflectType as Class<*>)
|
||||
is Class<*>, is TypeVariable<*>, is ParameterizedType -> ReflectJavaClassifierType(reflectType)
|
||||
is GenericArrayType -> ReflectJavaArrayType(reflectType)
|
||||
is GenericArrayType -> ReflectJavaArrayType(reflectType.getGenericComponentType()!!)
|
||||
is Class<*> -> {
|
||||
if (reflectType.isArray()) ReflectJavaArrayType(reflectType.getComponentType()!!)
|
||||
else ReflectJavaClassifierType(reflectType)
|
||||
}
|
||||
is TypeVariable<*>, is ParameterizedType -> ReflectJavaClassifierType(reflectType)
|
||||
is WildcardType -> ReflectJavaWildcardType(reflectType)
|
||||
else -> throw UnsupportedOperationException("Unsupported type (${reflectType.javaClass}): $reflectType")
|
||||
}
|
||||
|
||||
+3
-1
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.load.java.structure.JavaType
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaTypeParameter
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaTypeParameterListOwner
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import java.lang.reflect.Constructor
|
||||
import java.lang.reflect.Method
|
||||
import java.lang.reflect.TypeVariable
|
||||
|
||||
@@ -35,8 +36,9 @@ public class ReflectJavaTypeParameter(
|
||||
override fun getOwner(): JavaTypeParameterListOwner? {
|
||||
val owner = typeVariable.getGenericDeclaration()
|
||||
return when (owner) {
|
||||
is Method -> ReflectJavaMethod(owner)
|
||||
is Class<*> -> ReflectJavaClass(owner)
|
||||
is Method -> ReflectJavaMethod(owner)
|
||||
is Constructor<*> -> ReflectJavaConstructor(owner)
|
||||
else -> throw UnsupportedOperationException("Unsupported type parameter list owner (${owner.javaClass}): $owner")
|
||||
}
|
||||
}
|
||||
|
||||
+7
-4
@@ -16,13 +16,13 @@
|
||||
|
||||
package org.jetbrains.kotlin.load.java.structure.reflect
|
||||
|
||||
import java.lang.reflect.Modifier
|
||||
import org.jetbrains.kotlin.descriptors.Visibility
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.descriptors.Visibility
|
||||
import org.jetbrains.kotlin.load.java.JavaVisibilities
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import java.lang.reflect.Modifier
|
||||
|
||||
private fun calculateVisibility(modifiers: Int): Visibility {
|
||||
return when {
|
||||
@@ -34,5 +34,8 @@ private fun calculateVisibility(modifiers: Int): Visibility {
|
||||
}
|
||||
}
|
||||
|
||||
val Class<*>.classId: ClassId
|
||||
public val Class<*>.fqName: FqName
|
||||
get() = classId.asSingleFqName().toSafe()
|
||||
|
||||
public val Class<*>.classId: ClassId
|
||||
get() = getDeclaringClass()?.classId?.createNestedClassId(Name.identifier(getSimpleName())) ?: ClassId.topLevel(FqName(getName()))
|
||||
|
||||
@@ -221,6 +221,7 @@ fun main(args: Array<String>) {
|
||||
|
||||
testClass(javaClass<AbstractJvmRuntimeDescriptorLoaderTest>()) {
|
||||
model("loadJava/compiledKotlin")
|
||||
model("loadJava/compiledJava", extension = "java", excludeDirs = listOf("sam", "kotlinSignature/propagation"))
|
||||
}
|
||||
|
||||
testClass(javaClass<AbstractCompileJavaAgainstKotlinTest>()) {
|
||||
|
||||
Reference in New Issue
Block a user