diff --git a/compiler/incremental-compilation-impl/test/org/jetbrains/kotlin/incremental/IncrementalJsCompilerRunnerTestGenerated.java b/compiler/incremental-compilation-impl/test/org/jetbrains/kotlin/incremental/IncrementalJsCompilerRunnerTestGenerated.java index 366a366d710..a435ccdfa34 100644 --- a/compiler/incremental-compilation-impl/test/org/jetbrains/kotlin/incremental/IncrementalJsCompilerRunnerTestGenerated.java +++ b/compiler/incremental-compilation-impl/test/org/jetbrains/kotlin/incremental/IncrementalJsCompilerRunnerTestGenerated.java @@ -296,6 +296,12 @@ public class IncrementalJsCompilerRunnerTestGenerated extends AbstractIncrementa doTest(fileName); } + @TestMetadata("functionReferencingClass") + public void testFunctionReferencingClass() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/pureKotlin/functionReferencingClass/"); + doTest(fileName); + } + @TestMetadata("independentClasses") public void testIndependentClasses() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/pureKotlin/independentClasses/"); diff --git a/compiler/incremental-compilation-impl/test/org/jetbrains/kotlin/incremental/IncrementalJvmCompilerRunnerTestGenerated.java b/compiler/incremental-compilation-impl/test/org/jetbrains/kotlin/incremental/IncrementalJvmCompilerRunnerTestGenerated.java index b61c9208955..d9fe2fa7f5e 100644 --- a/compiler/incremental-compilation-impl/test/org/jetbrains/kotlin/incremental/IncrementalJvmCompilerRunnerTestGenerated.java +++ b/compiler/incremental-compilation-impl/test/org/jetbrains/kotlin/incremental/IncrementalJvmCompilerRunnerTestGenerated.java @@ -296,6 +296,12 @@ public class IncrementalJvmCompilerRunnerTestGenerated extends AbstractIncrement doTest(fileName); } + @TestMetadata("functionReferencingClass") + public void testFunctionReferencingClass() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/pureKotlin/functionReferencingClass/"); + doTest(fileName); + } + @TestMetadata("independentClasses") public void testIndependentClasses() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/pureKotlin/independentClasses/"); diff --git a/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/ClassDeserializer.kt b/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/ClassDeserializer.kt index 89fad66b26f..97aa46d0f89 100644 --- a/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/ClassDeserializer.kt +++ b/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/ClassDeserializer.kt @@ -55,13 +55,8 @@ class ClassDeserializer(private val components: DeserializationComponents) { } else { val fragments = components.packageFragmentProvider.getPackageFragments(classId.packageFqName) - assert(fragments.size == 1) { "There should be exactly one package: $fragments, class id is $classId" } - - val fragment = fragments.single() - if (fragment is DeserializedPackageFragment) { - // Similarly, verify that the containing package has information about this class - if (!fragment.hasTopLevelClass(classId.shortClassName)) return null - } + val fragment = fragments.firstOrNull { it !is DeserializedPackageFragment || it.hasTopLevelClass(classId.shortClassName) } + ?: return null components.createContext( fragment, nameResolver, diff --git a/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/DeserializedClassDataFinder.kt b/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/DeserializedClassDataFinder.kt index 710e007c9a4..8d6e4d24f51 100644 --- a/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/DeserializedClassDataFinder.kt +++ b/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/DeserializedClassDataFinder.kt @@ -22,9 +22,12 @@ import org.jetbrains.kotlin.serialization.ClassDataWithSource class DeserializedClassDataFinder(private val packageFragmentProvider: PackageFragmentProvider) : ClassDataFinder { override fun findClassData(classId: ClassId): ClassDataWithSource? { - val packageFragment = - packageFragmentProvider.getPackageFragments(classId.packageFqName).singleOrNull() - as? DeserializedPackageFragment ?: return null - return packageFragment.classDataFinder.findClassData(classId) + val packageFragments = packageFragmentProvider.getPackageFragments(classId.packageFqName) + for (fragment in packageFragments) { + if (fragment !is DeserializedPackageFragment) continue + + fragment.classDataFinder.findClassData(classId)?.let { return it } + } + return null } } diff --git a/jps-plugin/jps-tests/test/org/jetbrains/kotlin/jps/build/IncrementalJpsTestGenerated.java b/jps-plugin/jps-tests/test/org/jetbrains/kotlin/jps/build/IncrementalJpsTestGenerated.java index 6189ddf2a6f..3829cc8aadc 100644 --- a/jps-plugin/jps-tests/test/org/jetbrains/kotlin/jps/build/IncrementalJpsTestGenerated.java +++ b/jps-plugin/jps-tests/test/org/jetbrains/kotlin/jps/build/IncrementalJpsTestGenerated.java @@ -467,6 +467,12 @@ public class IncrementalJpsTestGenerated extends AbstractIncrementalJpsTest { doTest(fileName); } + @TestMetadata("functionReferencingClass") + public void testFunctionReferencingClass() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/pureKotlin/functionReferencingClass/"); + doTest(fileName); + } + @TestMetadata("independentClasses") public void testIndependentClasses() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/pureKotlin/independentClasses/"); diff --git a/jps-plugin/testData/incremental/pureKotlin/functionReferencingClass/A.kt b/jps-plugin/testData/incremental/pureKotlin/functionReferencingClass/A.kt new file mode 100644 index 00000000000..109bca0ace7 --- /dev/null +++ b/jps-plugin/testData/incremental/pureKotlin/functionReferencingClass/A.kt @@ -0,0 +1 @@ +class A(val x: Int) \ No newline at end of file diff --git a/jps-plugin/testData/incremental/pureKotlin/functionReferencingClass/build.log b/jps-plugin/testData/incremental/pureKotlin/functionReferencingClass/build.log new file mode 100644 index 00000000000..33f783959c9 --- /dev/null +++ b/jps-plugin/testData/incremental/pureKotlin/functionReferencingClass/build.log @@ -0,0 +1,11 @@ +================ Step #1 ================= + +Cleaning output files: + out/production/module/META-INF/module.kotlin_module + out/production/module/UseAKt.class +End of files +Compiling files: + src/useA.kt +End of files +Exit code: OK +------------------------------------------ \ No newline at end of file diff --git a/jps-plugin/testData/incremental/pureKotlin/functionReferencingClass/useA.kt b/jps-plugin/testData/incremental/pureKotlin/functionReferencingClass/useA.kt new file mode 100644 index 00000000000..c15c6153a60 --- /dev/null +++ b/jps-plugin/testData/incremental/pureKotlin/functionReferencingClass/useA.kt @@ -0,0 +1 @@ +fun useA(a: A) { a.x } \ No newline at end of file diff --git a/jps-plugin/testData/incremental/pureKotlin/functionReferencingClass/useA.kt.touch b/jps-plugin/testData/incremental/pureKotlin/functionReferencingClass/useA.kt.touch new file mode 100644 index 00000000000..e69de29bb2d diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/BoxJsTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/BoxJsTestGenerated.java index f289e50a8a2..68d16e517e2 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/BoxJsTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/BoxJsTestGenerated.java @@ -3497,6 +3497,12 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest { doTest(fileName); } + @TestMetadata("classReferencingClass.kt") + public void testClassReferencingClass() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/incremental/classReferencingClass.kt"); + doTest(fileName); + } + @TestMetadata("coroutines.kt") public void testCoroutines() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/incremental/coroutines.kt"); @@ -3515,6 +3521,12 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest { doTest(fileName); } + @TestMetadata("functionReferencingClass.kt") + public void testFunctionReferencingClass() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/incremental/functionReferencingClass.kt"); + doTest(fileName); + } + @TestMetadata("inline.kt") public void testInline() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/incremental/inline.kt"); diff --git a/js/js.translator/testData/box/incremental/classReferencingClass.kt b/js/js.translator/testData/box/incremental/classReferencingClass.kt new file mode 100644 index 00000000000..4d30200e47e --- /dev/null +++ b/js/js.translator/testData/box/incremental/classReferencingClass.kt @@ -0,0 +1,25 @@ +// EXPECTED_REACHABLE_NODES: 1002 +// FILE: A.kt + +open class A { + open fun f(): Int = 1 +} + +// FILE: B.kt +// RECOMPILE + +class B : A() { + override fun f(): Int = super.f() + 2 +} + +// FILE: box.kt + +fun box(): String { + val af = A().f() + if (af != 1) return "fail: result of 'A().f()' is '$af', but '1' was expected" + + val bf = B().f() + if (bf != 3) return "fail: result of 'B().f()' is '$bf', but '3' was expected" + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/box/incremental/functionReferencingClass.kt b/js/js.translator/testData/box/incremental/functionReferencingClass.kt new file mode 100644 index 00000000000..a22d9c65906 --- /dev/null +++ b/js/js.translator/testData/box/incremental/functionReferencingClass.kt @@ -0,0 +1,21 @@ +// EXPECTED_REACHABLE_NODES: 995 +// FILE: A.kt + +open class A { + open fun f(): Int = 1 +} + +// FILE: useA.kt +// RECOMPILE + +fun useA(a: A): Int = a.f() +fun useList(xs: List) {} + +// FILE: box.kt + +fun box(): String { + val result = useA(A()) + if (result != 1) return "fail: result of 'useA(A())' is '$result', but '1' was expected" + + return "OK" +} \ No newline at end of file