diff --git a/compiler/backend-common/src/org/jetbrains/kotlin/backend/common/CodegenUtil.java b/compiler/backend-common/src/org/jetbrains/kotlin/backend/common/CodegenUtil.java index 2599c11fa13..4b5dc88d1c9 100644 --- a/compiler/backend-common/src/org/jetbrains/kotlin/backend/common/CodegenUtil.java +++ b/compiler/backend-common/src/org/jetbrains/kotlin/backend/common/CodegenUtil.java @@ -19,6 +19,7 @@ package org.jetbrains.kotlin.backend.common; import com.intellij.openapi.editor.Document; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; +import kotlin.KotlinPackage; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.backend.common.bridges.BridgesPackage; diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ClassFileFactory.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ClassFileFactory.java index 181981b3462..ab8c235196e 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ClassFileFactory.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ClassFileFactory.java @@ -38,6 +38,8 @@ import java.io.StringWriter; import java.io.UnsupportedEncodingException; import java.util.*; +import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.getMappingFileName; + public class ClassFileFactory implements OutputFileCollection { private final GenerationState state; private final ClassBuilderFactory builderFactory; @@ -86,7 +88,7 @@ public class ClassFileFactory implements OutputFileCollection { private void writeModuleMappings(Collection values) { String moduleName = KotlinPackage.removeSurrounding(state.getModule().getName().asString(), "<", ">"); - String outputFilePath = "META-INF/" + moduleName + ".kotlin_module"; + String outputFilePath = getMappingFileName(moduleName); final StringWriter moduleMapping = new StringWriter(1024); for (PackageCodegen codegen : values) { codegen.getFacades().serialize(moduleMapping); diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/GeneratedClassLoader.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/GeneratedClassLoader.java index 14282bd82ba..3b346ef7f13 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/GeneratedClassLoader.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/GeneratedClassLoader.java @@ -19,6 +19,8 @@ package org.jetbrains.kotlin.codegen; import org.jetbrains.annotations.NotNull; import org.jetbrains.kotlin.backend.common.output.OutputFile; +import java.io.ByteArrayInputStream; +import java.io.InputStream; import java.net.URL; import java.net.URLClassLoader; import java.util.List; @@ -32,6 +34,15 @@ public class GeneratedClassLoader extends URLClassLoader { this.factory = factory; } + @Override + public InputStream getResourceAsStream(String name) { + OutputFile outputFile = factory.get(name); + if (outputFile != null) { + return new ByteArrayInputStream(outputFile.asByteArray()); + } + return super.getResourceAsStream(name); + } + @NotNull @Override protected Class findClass(@NotNull String name) throws ClassNotFoundException { diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/JvmCodegenUtil.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/JvmCodegenUtil.java index 2a2e0a5a521..7297aa1c475 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/JvmCodegenUtil.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/JvmCodegenUtil.java @@ -245,4 +245,13 @@ public class JvmCodegenUtil { module == module.getBuiltIns().getBuiltInsModule() || DescriptorUtils.isAnnotationClass(descriptor); } + + public static String getModuleName(ModuleDescriptor module) { + return KotlinPackage.removeSurrounding(module.getName().asString(), "<", ">"); + } + + @NotNull + public static String getMappingFileName(@NotNull String moduleName) { + return "META-INF/" + moduleName + ".kotlin_module"; + } } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java index 8d04c8bd80f..80cadd4c543 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java @@ -467,6 +467,9 @@ public abstract class MemberCodegen", "()V", null, null); - Method method = method("createKotlinPackage", K_PACKAGE_TYPE, getType(Class.class)); + Method method = method("createKotlinPackage", K_PACKAGE_TYPE, getType(Class.class), getType(String.class)); InstructionAdapter iv = new InstructionAdapter(mv); MemberCodegen.generateReflectionObjectField(state, packageClassType, v, method, JvmAbi.KOTLIN_PACKAGE_FIELD_NAME, iv); iv.areturn(Type.VOID_TYPE); diff --git a/compiler/tests/org/jetbrains/kotlin/jvm/runtime/AbstractJvmRuntimeDescriptorLoaderTest.kt b/compiler/tests/org/jetbrains/kotlin/jvm/runtime/AbstractJvmRuntimeDescriptorLoaderTest.kt index 1672b1fbb92..a0f50d4390c 100644 --- a/compiler/tests/org/jetbrains/kotlin/jvm/runtime/AbstractJvmRuntimeDescriptorLoaderTest.kt +++ b/compiler/tests/org/jetbrains/kotlin/jvm/runtime/AbstractJvmRuntimeDescriptorLoaderTest.kt @@ -82,7 +82,7 @@ public abstract class AbstractJvmRuntimeDescriptorLoaderTest : TestCaseWithTmpdi val classLoader = URLClassLoader(arrayOf(tmpdir.toURI().toURL()), ForTestCompileRuntime.runtimeAndReflectJarClassLoader()) - val actual = createReflectedPackageView(classLoader) + val actual = createReflectedPackageView(classLoader, "") val expected = LoadDescriptorUtil.loadTestPackageAndBindingContextFromJavaRoot( tmpdir, getTestRootDisposable(), jdkKind, ConfigurationKind.ALL, true @@ -129,8 +129,8 @@ public abstract class AbstractJvmRuntimeDescriptorLoaderTest : TestCaseWithTmpdi } } - private fun createReflectedPackageView(classLoader: URLClassLoader): SyntheticPackageViewForTest { - val module = RuntimeModuleData.create(classLoader).module + private fun createReflectedPackageView(classLoader: URLClassLoader, moduleName: String): SyntheticPackageViewForTest { + val module = RuntimeModuleData.create(classLoader, moduleName).module val generatedPackageDir = File(tmpdir, LoadDescriptorUtil.TEST_PACKAGE_FQNAME.pathSegments().single().asString()) diff --git a/core/descriptors.runtime/src/org/jetbrains/kotlin/load/kotlin/reflect/RuntimeModuleData.kt b/core/descriptors.runtime/src/org/jetbrains/kotlin/load/kotlin/reflect/RuntimeModuleData.kt index d38a8485da6..6f68484c5a1 100644 --- a/core/descriptors.runtime/src/org/jetbrains/kotlin/load/kotlin/reflect/RuntimeModuleData.kt +++ b/core/descriptors.runtime/src/org/jetbrains/kotlin/load/kotlin/reflect/RuntimeModuleData.kt @@ -44,7 +44,7 @@ public class RuntimeModuleData private constructor(public val deserialization: D public val localClassResolver: LocalClassResolver get() = deserialization.localClassResolver companion object { - public fun create(classLoader: ClassLoader): RuntimeModuleData { + public fun create(classLoader: ClassLoader, moduleName: String?): RuntimeModuleData { val storageManager = LockBasedStorageManager() val module = ModuleDescriptorImpl(Name.special(""), storageManager, ModuleParameters(listOf(), JavaToKotlinClassMap.INSTANCE)) @@ -57,8 +57,10 @@ public class RuntimeModuleData private constructor(public val deserialization: D ExternalAnnotationResolver.EMPTY, ExternalSignatureResolver.DO_NOTHING, RuntimeErrorReporter, JavaResolverCache.EMPTY, JavaPropertyInitializerEvaluator.DoNothing, SamConversionResolver, RuntimeSourceElementFactory, singleModuleClassResolver ) + println("moduleName $moduleName") val lazyJavaPackageFragmentProvider = - LazyJavaPackageFragmentProvider(globalJavaResolverContext, module, ReflectionTypes(module), PackageMappingProvider.EMPTY) + LazyJavaPackageFragmentProvider(globalJavaResolverContext, module, ReflectionTypes(module), + if (moduleName == null) PackageMappingProvider.EMPTY else RuntimePackageMappingProvider(moduleName, classLoader)) val javaDescriptorResolver = JavaDescriptorResolver(lazyJavaPackageFragmentProvider, module) val javaClassDataFinder = JavaClassDataFinder(reflectKotlinClassFinder, deserializedDescriptorResolver) val binaryClassAnnotationAndConstantLoader = BinaryClassAnnotationAndConstantLoaderImpl(module, storageManager, reflectKotlinClassFinder, RuntimeErrorReporter) diff --git a/core/descriptors.runtime/src/org/jetbrains/kotlin/load/kotlin/reflect/RuntimePackageMappingProvider.kt b/core/descriptors.runtime/src/org/jetbrains/kotlin/load/kotlin/reflect/RuntimePackageMappingProvider.kt new file mode 100644 index 00000000000..867163bca17 --- /dev/null +++ b/core/descriptors.runtime/src/org/jetbrains/kotlin/load/kotlin/reflect/RuntimePackageMappingProvider.kt @@ -0,0 +1,52 @@ +/* + * 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.kotlin.reflect + +import org.jetbrains.kotlin.load.java.lazy.PackageMappingProvider +import org.jetbrains.kotlin.load.kotlin.ModuleMapping +import org.jetbrains.kotlin.load.kotlin.PackageFacades +import java.io.ByteArrayOutputStream + +class RuntimePackageMappingProvider(val moduleName: String, val classLoader : ClassLoader) : PackageMappingProvider { + + val mapping: ModuleMapping by lazy { + print("finding metainf for $moduleName") + val resourceAsStream = classLoader.getResourceAsStream("META-INF/$moduleName.kotlin_module") ?: return@lazy ModuleMapping("") + + print("OK") + + try { + val out = ByteArrayOutputStream(4096); + val buffer = ByteArray(4096); + while (true) { + val r = resourceAsStream.read(buffer); + if (r == -1) break; + out.write(buffer, 0, r); + } + + val ret = out.toByteArray(); + return@lazy ModuleMapping(String(ret, "UTF-8")) + } finally { + resourceAsStream.close() + } + } + + override fun findPackageMembers(packageName: String): List { + print("finding $packageName") + return mapping.package2MiniFacades.getOrElse (packageName, { PackageFacades("default") }).parts.toList() + } +} \ No newline at end of file diff --git a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KDeclarationContainerImpl.kt b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KDeclarationContainerImpl.kt index d9a37fc547e..287a51a57e9 100644 --- a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KDeclarationContainerImpl.kt +++ b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KDeclarationContainerImpl.kt @@ -39,7 +39,7 @@ import kotlin.reflect.KotlinReflectionInternalError abstract class KDeclarationContainerImpl : ClassBasedDeclarationContainer { // Note: this is stored here on a soft reference to prevent GC from destroying the weak reference to it in the moduleByClassLoader cache val moduleData by ReflectProperties.lazySoft { - jClass.getOrCreateModule() + jClass.getOrCreateModule(null) } abstract val constructorDescriptors: Collection diff --git a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KPackageImpl.kt b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KPackageImpl.kt index 33c507d8b9c..3e27cc9081d 100644 --- a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KPackageImpl.kt +++ b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KPackageImpl.kt @@ -27,9 +27,9 @@ import kotlin.jvm.internal.KotlinPackage import kotlin.reflect.KCallable import kotlin.reflect.KPackage -class KPackageImpl(override val jClass: Class<*>) : KDeclarationContainerImpl(), KPackage { +class KPackageImpl(override val jClass: Class<*>, val moduleName: String) : KDeclarationContainerImpl(), KPackage { val descriptor by ReflectProperties.lazySoft { - val moduleData = jClass.getOrCreateModule() + val moduleData = jClass.getOrCreateModule(moduleName) val fqName = jClass.classId.getPackageFqName() moduleData.module.getPackage(fqName) diff --git a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/ReflectionFactoryImpl.java b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/ReflectionFactoryImpl.java index 27f730367ef..b3a7eff7220 100644 --- a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/ReflectionFactoryImpl.java +++ b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/ReflectionFactoryImpl.java @@ -32,7 +32,12 @@ public class ReflectionFactoryImpl extends ReflectionFactory { @Override public KPackage createKotlinPackage(Class javaClass) { - return new KPackageImpl(javaClass); + return createKotlinPackage(javaClass, "undefined"); + } + + @Override + public KPackage createKotlinPackage(Class javaClass, String moduleName) { + return new KPackageImpl(javaClass, moduleName); } @Override diff --git a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/moduleByClassLoader.kt b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/moduleByClassLoader.kt index e4fb26a3e94..5d274af7c25 100644 --- a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/moduleByClassLoader.kt +++ b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/moduleByClassLoader.kt @@ -44,7 +44,7 @@ private class WeakClassLoaderBox(classLoader: ClassLoader) { ref.get()?.let { it.toString() } ?: "" } -internal fun Class<*>.getOrCreateModule(): RuntimeModuleData { +internal fun Class<*>.getOrCreateModule(moduleName: String?): RuntimeModuleData { val classLoader = this.safeClassLoader val key = WeakClassLoaderBox(classLoader) @@ -54,7 +54,7 @@ internal fun Class<*>.getOrCreateModule(): RuntimeModuleData { moduleByClassLoader.remove(key, cached) } - val module = RuntimeModuleData.create(classLoader) + val module = RuntimeModuleData.create(classLoader, moduleName) try { while (true) { val ref = moduleByClassLoader.putIfAbsent(key, WeakReference(module)) diff --git a/core/reflection.jvm/src/kotlin/reflect/jvm/mapping.kt b/core/reflection.jvm/src/kotlin/reflect/jvm/mapping.kt index 765e23fb253..4b8d90d7a3a 100644 --- a/core/reflection.jvm/src/kotlin/reflect/jvm/mapping.kt +++ b/core/reflection.jvm/src/kotlin/reflect/jvm/mapping.kt @@ -94,7 +94,7 @@ public val KType.javaType: Type */ public val Class<*>.kotlinPackage: KPackage? get() = if (getSimpleName().endsWith("Package") && - getAnnotation(javaClass()) != null) KPackageImpl(this) else null + getAnnotation(javaClass()) != null) KPackageImpl(this, "undefined") else null /** diff --git a/core/runtime.jvm/src/kotlin/jvm/internal/Reflection.java b/core/runtime.jvm/src/kotlin/jvm/internal/Reflection.java index 26bfe9fa704..4cdf824e9d0 100644 --- a/core/runtime.jvm/src/kotlin/jvm/internal/Reflection.java +++ b/core/runtime.jvm/src/kotlin/jvm/internal/Reflection.java @@ -55,6 +55,10 @@ public class Reflection { return factory.createKotlinPackage(javaClass); } + public static KPackage createKotlinPackage(Class javaClass, String moduleName) { + return factory.createKotlinPackage(javaClass, moduleName); + } + public static KClass foreignKotlinClass(Class javaClass) { return factory.foreignKotlinClass(javaClass); } diff --git a/core/runtime.jvm/src/kotlin/jvm/internal/ReflectionFactory.java b/core/runtime.jvm/src/kotlin/jvm/internal/ReflectionFactory.java index e6a2cc273b8..88aae99ba33 100644 --- a/core/runtime.jvm/src/kotlin/jvm/internal/ReflectionFactory.java +++ b/core/runtime.jvm/src/kotlin/jvm/internal/ReflectionFactory.java @@ -27,6 +27,10 @@ public class ReflectionFactory { return null; } + public KPackage createKotlinPackage(Class javaClass, String moduleName) { + return null; + } + public KClass foreignKotlinClass(Class javaClass) { return new ClassReference(javaClass); }