Fix incremental recompilation of JvmMultifileClass with top level function

See 53b584f and previous changes where this behavior was broken (this was
untested, however). Fixes EA-90065
This commit is contained in:
Alexander Udalov
2016-10-18 16:06:39 +03:00
parent 0ac461927c
commit 7b2a80ffa4
10 changed files with 104 additions and 9 deletions
@@ -51,6 +51,7 @@ import org.jetbrains.kotlin.load.java.descriptors.JavaCallableMemberDescriptor;
import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor; import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor;
import org.jetbrains.kotlin.load.java.lazy.descriptors.LazyJavaPackageFragment; import org.jetbrains.kotlin.load.java.lazy.descriptors.LazyJavaPackageFragment;
import org.jetbrains.kotlin.load.kotlin.*; import org.jetbrains.kotlin.load.kotlin.*;
import org.jetbrains.kotlin.load.kotlin.incremental.IncrementalPackageFragmentProvider.IncrementalMultifileClassPackageFragment;
import org.jetbrains.kotlin.name.ClassId; import org.jetbrains.kotlin.name.ClassId;
import org.jetbrains.kotlin.name.FqName; import org.jetbrains.kotlin.name.FqName;
import org.jetbrains.kotlin.name.Name; import org.jetbrains.kotlin.name.Name;
@@ -83,7 +84,6 @@ import java.util.List;
import static org.jetbrains.kotlin.codegen.AsmUtil.isStaticMethod; import static org.jetbrains.kotlin.codegen.AsmUtil.isStaticMethod;
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.*; import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.*;
import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.*; import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.*;
import static org.jetbrains.kotlin.fileClasses.JvmFileClassUtil.getPartFqNameForDeserializedCallable;
import static org.jetbrains.kotlin.resolve.BindingContextUtils.getDelegationConstructorCall; import static org.jetbrains.kotlin.resolve.BindingContextUtils.getDelegationConstructorCall;
import static org.jetbrains.kotlin.resolve.BindingContextUtils.isVarCapturedInClosure; import static org.jetbrains.kotlin.resolve.BindingContextUtils.isVarCapturedInClosure;
import static org.jetbrains.kotlin.resolve.DescriptorUtils.*; import static org.jetbrains.kotlin.resolve.DescriptorUtils.*;
@@ -301,18 +301,27 @@ public class KotlinTypeMapper {
return new ContainingClassesInfo(FAKE_CLASS_ID_FOR_BUILTINS, FAKE_CLASS_ID_FOR_BUILTINS); return new ContainingClassesInfo(FAKE_CLASS_ID_FOR_BUILTINS, FAKE_CLASS_ID_FOR_BUILTINS);
} }
assert containingDeclaration instanceof LazyJavaPackageFragment :
"Unexpected package fragment for " + descriptor + ": " + containingDeclaration +
" (" + containingDeclaration.getClass().getSimpleName() + ")";
LazyJavaPackageFragment packageFragment = (LazyJavaPackageFragment) containingDeclaration;
Name implClassName = JvmFileClassUtil.getImplClassName(descriptor); Name implClassName = JvmFileClassUtil.getImplClassName(descriptor);
assert implClassName != null : "No implClassName for " + descriptor; assert implClassName != null : "No implClassName for " + descriptor;
String implSimpleName = implClassName.asString();
String facadeSimpleName = packageFragment.getFacadeSimpleNameForPartSimpleName(implClassName.asString()); String facadeSimpleName;
if (facadeSimpleName == null) return null;
return ContainingClassesInfo.forPackageMember(packageFragment.getFqName(), facadeSimpleName, implClassName.asString()); if (containingDeclaration instanceof LazyJavaPackageFragment) {
facadeSimpleName = ((LazyJavaPackageFragment) containingDeclaration).getFacadeSimpleNameForPartSimpleName(implSimpleName);
if (facadeSimpleName == null) return null;
}
else if (containingDeclaration instanceof IncrementalMultifileClassPackageFragment) {
facadeSimpleName = ((IncrementalMultifileClassPackageFragment) containingDeclaration).getMultifileClassName().asString();
}
else {
throw new AssertionError("Unexpected package fragment for " + descriptor + ": " +
containingDeclaration + " (" + containingDeclaration.getClass().getSimpleName() + ")");
}
return ContainingClassesInfo.forPackageMember(
((PackageFragmentDescriptor) containingDeclaration).getFqName(), facadeSimpleName, implSimpleName
);
} }
@NotNull @NotNull
@@ -93,6 +93,9 @@ class IncrementalPackageFragmentProvider(
) )
} }
val multifileClassName: Name
get() = multifileClassFqName.shortName()
override fun getMemberScope() = memberScope() override fun getMemberScope() = memberScope()
} }
} }
@@ -581,6 +581,12 @@ public class ExperimentalIncrementalJpsTestGenerated extends AbstractExperimenta
doTest(fileName); doTest(fileName);
} }
@TestMetadata("multifileClassAddTopLevelFunWithDefault")
public void testMultifileClassAddTopLevelFunWithDefault() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/pureKotlin/multifileClassAddTopLevelFunWithDefault/");
doTest(fileName);
}
@TestMetadata("multifileClassFileAdded") @TestMetadata("multifileClassFileAdded")
public void testMultifileClassFileAdded() throws Exception { public void testMultifileClassFileAdded() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/pureKotlin/multifileClassFileAdded/"); String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/pureKotlin/multifileClassFileAdded/");
@@ -581,6 +581,12 @@ public class IncrementalJpsTestGenerated extends AbstractIncrementalJpsTest {
doTest(fileName); doTest(fileName);
} }
@TestMetadata("multifileClassAddTopLevelFunWithDefault")
public void testMultifileClassAddTopLevelFunWithDefault() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/pureKotlin/multifileClassAddTopLevelFunWithDefault/");
doTest(fileName);
}
@TestMetadata("multifileClassFileAdded") @TestMetadata("multifileClassFileAdded")
public void testMultifileClassFileAdded() throws Exception { public void testMultifileClassFileAdded() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/pureKotlin/multifileClassFileAdded/"); String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/pureKotlin/multifileClassFileAdded/");
@@ -0,0 +1,4 @@
@file:[JvmName("Test") JvmMultifileClass]
package test
fun a() = "a"
@@ -0,0 +1,4 @@
@file:[JvmName("Test") JvmMultifileClass]
package test
fun b() = ""
@@ -0,0 +1,5 @@
@file:[JvmName("Test") JvmMultifileClass]
package test
fun b() = ""
fun b(s: String = "") = s
@@ -0,0 +1,24 @@
================ Step #1 =================
Cleaning output files:
out/production/module/META-INF/module.kotlin_module
out/production/module/test/Test.class
out/production/module/test/Test__BKt.class
End of files
Compiling files:
src/b.kt
End of files
Exit code: ADDITIONAL_PASS_REQUIRED
------------------------------------------
Cleaning output files:
out/production/module/META-INF/module.kotlin_module
out/production/module/test/Test.class
out/production/module/test/Test__AKt.class
out/production/module/usage/UsageKt.class
End of files
Compiling files:
src/a.kt
src/usage.kt
End of files
Exit code: OK
------------------------------------------
@@ -0,0 +1,26 @@
================ Step #1 =================
Cleaning output files:
out/production/module/META-INF/module.kotlin_module
out/production/module/test/Test.class
out/production/module/test/Test__BKt.class
End of files
Compiling files:
src/b.kt
End of files
Marked as dirty by Kotlin:
src/usage.kt
Exit code: ADDITIONAL_PASS_REQUIRED
------------------------------------------
Cleaning output files:
out/production/module/META-INF/module.kotlin_module
out/production/module/test/Test.class
out/production/module/test/Test__AKt.class
out/production/module/usage/UsageKt.class
End of files
Compiling files:
src/a.kt
src/usage.kt
End of files
Exit code: OK
------------------------------------------
@@ -0,0 +1,8 @@
package usage
import test.*
fun usage() {
a()
b()
}