Add Kotlin package FQ name to kotlin.Metadata

It might differ from the JVM package FQ name if the JvmPackageName
annotation is used. This will be useful for faster indexing in the IDE
and for reflection
This commit is contained in:
Alexander Udalov
2017-10-12 15:44:04 +02:00
parent 16b7bece46
commit 5f775497e2
7 changed files with 62 additions and 0 deletions
@@ -31,8 +31,10 @@ import org.jetbrains.kotlin.descriptors.annotations.Annotated;
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.kotlin.descriptors.annotations.AnnotationsImpl;
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader;
import org.jetbrains.kotlin.name.FqName;
import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.resolve.BindingContext;
import org.jetbrains.kotlin.resolve.jvm.JvmClassName;
import org.jetbrains.kotlin.serialization.DescriptorSerializer;
import org.jetbrains.kotlin.serialization.ProtoBuf;
import org.jetbrains.org.objectweb.asm.Type;
@@ -41,6 +43,7 @@ import java.util.ArrayList;
import java.util.List;
import static org.jetbrains.kotlin.codegen.AsmUtil.writeAnnotationData;
import static org.jetbrains.kotlin.load.java.JvmAnnotationNames.METADATA_PACKAGE_NAME_FIELD_NAME;
import static org.jetbrains.org.objectweb.asm.Opcodes.*;
public class PackagePartCodegen extends MemberCodegen<KtFile> {
@@ -104,6 +107,12 @@ public class PackagePartCodegen extends MemberCodegen<KtFile> {
WriteAnnotationUtilKt.writeKotlinMetadata(v, state, KotlinClassHeader.Kind.FILE_FACADE, 0, av -> {
writeAnnotationData(av, serializedPart.getFirst(), serializedPart.getSecond());
FqName kotlinPackageFqName = element.getPackageFqName();
if (!kotlinPackageFqName.equals(JvmClassName.byInternalName(packagePartType.getInternalName()).getPackageFqName())) {
av.visit(METADATA_PACKAGE_NAME_FIELD_NAME, kotlinPackageFqName.asString());
}
return Unit.INSTANCE;
});
}
@@ -0,0 +1,28 @@
// TARGET_BACKEND: JVM
// WITH_RUNTIME
// LANGUAGE_VERSION: 1.2
// FILE: foo.kt
@file:Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
@file:JvmPackageName("baz.foo.quux.bar")
package foo.bar
fun f() {}
// FILE: bar.kt
@file:Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
fun getPackageName(classFqName: String): String =
Class.forName(classFqName).getAnnotation(Metadata::class.java).pn
fun box(): String {
val bar = getPackageName("BarKt")
if (bar != "") return "Fail 1: $bar"
val foo = getPackageName("baz.foo.quux.bar.FooKt")
if (foo != "foo.bar") return "Fail 2: $foo"
return "OK"
}
@@ -10568,6 +10568,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/jvmPackageName"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
}
@TestMetadata("metadataField.kt")
public void testMetadataField() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/jvmPackageName/metadataField.kt");
doTest(fileName);
}
@TestMetadata("rootPackage.kt")
public void testRootPackage() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/jvmPackageName/rootPackage.kt");
@@ -10568,6 +10568,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/jvmPackageName"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
}
@TestMetadata("metadataField.kt")
public void testMetadataField() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/jvmPackageName/metadataField.kt");
doTest(fileName);
}
@TestMetadata("rootPackage.kt")
public void testRootPackage() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/jvmPackageName/rootPackage.kt");
@@ -10568,6 +10568,12 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/jvmPackageName"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
}
@TestMetadata("metadataField.kt")
public void testMetadataField() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/jvmPackageName/metadataField.kt");
doTest(fileName);
}
@TestMetadata("rootPackage.kt")
public void testRootPackage() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/jvmPackageName/rootPackage.kt");
@@ -31,6 +31,7 @@ public final class JvmAnnotationNames {
public static final String METADATA_DATA_FIELD_NAME = "d1";
public static final String METADATA_STRINGS_FIELD_NAME = "d2";
public static final String METADATA_EXTRA_STRING_FIELD_NAME = "xs";
public static final String METADATA_PACKAGE_NAME_FIELD_NAME = "pn";
public static final String METADATA_MULTIFILE_CLASS_NAME_FIELD_NAME = METADATA_EXTRA_STRING_FIELD_NAME;
public static final String METADATA_EXTRA_INT_FIELD_NAME = "xi";
+6
View File
@@ -56,6 +56,12 @@ internal annotation class Metadata(
* An extra string. For a multi-file part class, internal name of the facade class.
*/
val xs: String = "",
/**
* Fully qualified name of the package this class is located in, from Kotlin's point of view, or empty string if this name
* does not differ from the JVM's package FQ name. These names can be different in case the [JvmPackageName] annotation is used.
* Note that this information is also stored in the corresponding module's `.kotlin_module` file.
*/
val pn: String = "",
/**
* An extra int. Bits of this number represent the following flags:
*