Add script flag to kotlin.Metadata

This will allow to distinguish compiled scripts from ordinary classes in the
compiler, reflection, IDE, etc.

 #KT-13382 Fixed
This commit is contained in:
Alexander Udalov
2017-01-09 12:21:59 +03:00
parent 7c6d5c825c
commit e860d620c6
6 changed files with 20 additions and 11 deletions
@@ -248,7 +248,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
@Override
protected void generateKotlinMetadataAnnotation() {
generateKotlinClassMetadataAnnotation(descriptor);
generateKotlinClassMetadataAnnotation(descriptor, false);
}
private void writeEnclosingMethod() {
@@ -37,6 +37,7 @@ import org.jetbrains.kotlin.fileClasses.FileClasses;
import org.jetbrains.kotlin.fileClasses.JvmFileClassesProvider;
import org.jetbrains.kotlin.load.java.JavaVisibilities;
import org.jetbrains.kotlin.load.java.JvmAbi;
import org.jetbrains.kotlin.load.java.JvmAnnotationNames;
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader;
import org.jetbrains.kotlin.name.Name;
import org.jetbrains.kotlin.name.SpecialNames;
@@ -86,12 +87,12 @@ public abstract class MemberCodegen<T extends KtPureElement/* TODO: & KtDeclarat
public final KotlinTypeMapper typeMapper;
public final BindingContext bindingContext;
protected final JvmFileClassesProvider fileClassesProvider;
private final JvmFileClassesProvider fileClassesProvider;
private final MemberCodegen<?> parentCodegen;
private final ReifiedTypeParametersUsages reifiedTypeParametersUsages = new ReifiedTypeParametersUsages();
private final Collection<ClassDescriptor> innerClasses = new LinkedHashSet<ClassDescriptor>();
protected ExpressionCodegen clInit;
private ExpressionCodegen clInit;
private NameGenerator inlineNameGenerator;
private DefaultSourceMapper sourceMapper;
@@ -439,7 +440,7 @@ public abstract class MemberCodegen<T extends KtPureElement/* TODO: & KtDeclarat
}
@NotNull
protected SimpleFunctionDescriptorImpl createClInitFunctionDescriptor(@NotNull DeclarationDescriptor descriptor) {
private SimpleFunctionDescriptorImpl createClInitFunctionDescriptor(@NotNull DeclarationDescriptor descriptor) {
SimpleFunctionDescriptorImpl clInit = SimpleFunctionDescriptorImpl.create(descriptor, Annotations.Companion.getEMPTY(),
Name.special("<clinit>"), SYNTHESIZED, KotlinSourceElementKt.toSourceElement(element));
clInit.initialize(null, null, Collections.<TypeParameterDescriptor>emptyList(),
@@ -698,7 +699,7 @@ public abstract class MemberCodegen<T extends KtPureElement/* TODO: & KtDeclarat
class PropertyAccessorStrategy extends FunctionGenerationStrategy.CodegenBased {
private final PropertyAccessorDescriptor callableDescriptor;
public PropertyAccessorStrategy(@NotNull PropertyAccessorDescriptor callableDescriptor) {
private PropertyAccessorStrategy(@NotNull PropertyAccessorDescriptor callableDescriptor) {
super(MemberCodegen.this.state);
this.callableDescriptor = callableDescriptor;
}
@@ -799,13 +800,15 @@ public abstract class MemberCodegen<T extends KtPureElement/* TODO: & KtDeclarat
return StackValue.onStack(callableMethod.getReturnType());
}
protected void generateKotlinClassMetadataAnnotation(ClassDescriptor descriptor) {
protected void generateKotlinClassMetadataAnnotation(@NotNull ClassDescriptor descriptor, boolean isScript) {
final DescriptorSerializer serializer =
DescriptorSerializer.create(descriptor, new JvmSerializerExtension(v.getSerializationBindings(), state));
final ProtoBuf.Class classProto = serializer.classProto(descriptor).build();
WriteAnnotationUtilKt.writeKotlinMetadata(v, state, KotlinClassHeader.Kind.CLASS, 0, new Function1<AnnotationVisitor, Unit>() {
int flags = isScript ? JvmAnnotationNames.METADATA_SCRIPT_FLAG : 0;
WriteAnnotationUtilKt.writeKotlinMetadata(v, state, KotlinClassHeader.Kind.CLASS, flags, new Function1<AnnotationVisitor, Unit>() {
@Override
public Unit invoke(AnnotationVisitor av) {
writeAnnotationData(av, serializer, classProto);
@@ -22,7 +22,10 @@ import org.jetbrains.kotlin.codegen.context.CodegenContext;
import org.jetbrains.kotlin.codegen.context.MethodContext;
import org.jetbrains.kotlin.codegen.context.ScriptContext;
import org.jetbrains.kotlin.codegen.state.GenerationState;
import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.descriptors.ClassDescriptor;
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor;
import org.jetbrains.kotlin.descriptors.ScriptDescriptor;
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor;
import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.resolve.BindingContext;
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
@@ -33,7 +36,6 @@ import org.jetbrains.org.objectweb.asm.MethodVisitor;
import org.jetbrains.org.objectweb.asm.Type;
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
@@ -110,8 +112,7 @@ public class ScriptCodegen extends MemberCodegen<KtScript> {
@Override
protected void generateKotlinMetadataAnnotation() {
// TODO: copypaste from ImplementationBodyCodegen, so the script is seen as a KClass by reflection; implement separate kind with proper API
generateKotlinClassMetadataAnnotation(scriptDescriptor);
generateKotlinClassMetadataAnnotation(scriptDescriptor, true);
}
private void genConstructor(
@@ -36,6 +36,7 @@ public final class JvmAnnotationNames {
public static final int METADATA_MULTIFILE_PARTS_INHERIT_FLAG = 1 << 0;
public static final int METADATA_PRE_RELEASE_FLAG = 1 << 1;
public static final int METADATA_SCRIPT_FLAG = 1 << 2;
public static final Name DEFAULT_ANNOTATION_MEMBER_NAME = Name.identifier("value");
@@ -71,5 +71,8 @@ class KotlinClassHeader(
val isPreRelease: Boolean
get() = (extraInt and JvmAnnotationNames.METADATA_PRE_RELEASE_FLAG) != 0
val isScript: Boolean
get() = (extraInt and JvmAnnotationNames.METADATA_SCRIPT_FLAG) != 0
override fun toString() = "$kind version=$metadataVersion"
}
+1
View File
@@ -61,6 +61,7 @@ internal annotation class Metadata(
*
* 0 - this is a multi-file class facade or part, compiled with `-Xmultifile-parts-inherit`.
* 1 - this class file is compiled by a pre-release version of Kotlin and is not visible to release versions.
* 2 - this class file is a compiled Kotlin script source file (.kts).
*/
val xi: Int = 0
)