MultifileClassCodegen
- initial implementation - new Kotlin file kinds + stub builder
This commit is contained in:
@@ -31,6 +31,8 @@ public final class JvmAnnotationNames {
|
||||
public static final FqName KOTLIN_CLASS = KotlinClass.CLASS_NAME.getFqNameForClassNameWithoutDollars();
|
||||
public static final FqName KOTLIN_PACKAGE = new FqName("kotlin.jvm.internal.KotlinPackage");
|
||||
public static final FqName KOTLIN_FILE_FACADE = new FqName("kotlin.jvm.internal.KotlinFileFacade");
|
||||
public static final FqName KOTLIN_MULTIFILE_CLASS = new FqName("kotlin.jvm.internal.KotlinMultifileClass");
|
||||
public static final FqName KOTLIN_MULTIFILE_CLASS_PART = new FqName("kotlin.jvm.internal.KotlinMultifileClassPart");
|
||||
public static final FqName KOTLIN_CALLABLE = new FqName("kotlin.jvm.internal.KotlinCallable");
|
||||
|
||||
public static final FqName KOTLIN_SIGNATURE = new FqName("kotlin.jvm.KotlinSignature");
|
||||
@@ -38,6 +40,8 @@ public final class JvmAnnotationNames {
|
||||
|
||||
public static final String ABI_VERSION_FIELD_NAME = "abiVersion";
|
||||
public static final String KIND_FIELD_NAME = "kind";
|
||||
public static final String FILE_PART_CLASS_NAMES_FIELD_NAME = "filePartClassNames";
|
||||
public static final String MULTIFILE_CLASS_NAME_FIELD_NAME = "multifileClassName";
|
||||
public static final String DATA_FIELD_NAME = "data";
|
||||
public static final Name DEFAULT_ANNOTATION_MEMBER_NAME = Name.identifier("value");
|
||||
public static final Name TARGET_ANNOTATION_MEMBER_NAME = Name.identifier("allowedTargets");
|
||||
|
||||
+7
-1
@@ -25,7 +25,9 @@ public class KotlinClassHeader(
|
||||
public val version: Int,
|
||||
public val annotationData: Array<String>?,
|
||||
public val classKind: KotlinClass.Kind?,
|
||||
public val syntheticClassKind: KotlinSyntheticClass.Kind?
|
||||
public val syntheticClassKind: KotlinSyntheticClass.Kind?,
|
||||
public val filePartClassNames: Array<String>?,
|
||||
public val multifileClassName: String?
|
||||
) {
|
||||
public val isCompatibleAbiVersion: Boolean get() = AbiVersionUtil.isAbiVersionCompatible(version)
|
||||
|
||||
@@ -33,6 +35,8 @@ public class KotlinClassHeader(
|
||||
CLASS,
|
||||
PACKAGE_FACADE,
|
||||
FILE_FACADE,
|
||||
MULTIFILE_CLASS,
|
||||
MULTIFILE_CLASS_PART,
|
||||
SYNTHETIC_CLASS
|
||||
}
|
||||
|
||||
@@ -46,4 +50,6 @@ public class KotlinClassHeader(
|
||||
public fun KotlinClassHeader.isCompatibleClassKind(): Boolean = isCompatibleAbiVersion && kind == KotlinClassHeader.Kind.CLASS
|
||||
public fun KotlinClassHeader.isCompatiblePackageFacadeKind(): Boolean = isCompatibleAbiVersion && kind == KotlinClassHeader.Kind.PACKAGE_FACADE
|
||||
public fun KotlinClassHeader.isCompatibleFileFacadeKind(): Boolean = isCompatibleAbiVersion && kind == KotlinClassHeader.Kind.FILE_FACADE
|
||||
public fun KotlinClassHeader.isCompatibleMultifileClassKind(): Boolean = isCompatibleAbiVersion && kind == KotlinClassHeader.Kind.MULTIFILE_CLASS
|
||||
public fun KotlinClassHeader.isCompatibleMultifileClassPartKind(): Boolean = isCompatibleAbiVersion && kind == KotlinClassHeader.Kind.MULTIFILE_CLASS_PART
|
||||
public fun KotlinClassHeader.isCompatibleSyntheticClassKind(): Boolean = isCompatibleAbiVersion && kind == KotlinClassHeader.Kind.SYNTHETIC_CLASS
|
||||
|
||||
+73
-24
@@ -37,11 +37,12 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor
|
||||
private static final Map<JvmClassName, KotlinClassHeader.Kind> HEADER_KINDS = new HashMap<JvmClassName, KotlinClassHeader.Kind>();
|
||||
private static final Map<JvmClassName, KotlinClassHeader.Kind> OLD_DEPRECATED_ANNOTATIONS_KINDS = new HashMap<JvmClassName, KotlinClassHeader.Kind>();
|
||||
|
||||
private int version = AbiVersionUtil.INVALID_VERSION;
|
||||
static {
|
||||
HEADER_KINDS.put(KotlinClass.CLASS_NAME, CLASS);
|
||||
HEADER_KINDS.put(JvmClassName.byFqNameWithoutInnerClasses(KOTLIN_PACKAGE), PACKAGE_FACADE);
|
||||
HEADER_KINDS.put(JvmClassName.byFqNameWithoutInnerClasses(KOTLIN_FILE_FACADE), FILE_FACADE);
|
||||
HEADER_KINDS.put(JvmClassName.byFqNameWithoutInnerClasses(KOTLIN_MULTIFILE_CLASS), MULTIFILE_CLASS);
|
||||
HEADER_KINDS.put(JvmClassName.byFqNameWithoutInnerClasses(KOTLIN_MULTIFILE_CLASS_PART), MULTIFILE_CLASS_PART);
|
||||
HEADER_KINDS.put(KotlinSyntheticClass.CLASS_NAME, SYNTHETIC_CLASS);
|
||||
|
||||
initOldAnnotations();
|
||||
@@ -58,6 +59,9 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor
|
||||
OLD_DEPRECATED_ANNOTATIONS_KINDS.put(JvmClassName.byFqNameWithoutInnerClasses(OLD_KOTLIN_TRAIT_IMPL), SYNTHETIC_CLASS);
|
||||
}
|
||||
|
||||
private int version = AbiVersionUtil.INVALID_VERSION;
|
||||
private String multifileClassName = null;
|
||||
private String[] filePartClassNames = null;
|
||||
private String[] annotationData = null;
|
||||
private KotlinClassHeader.Kind headerKind = null;
|
||||
private KotlinClass.Kind classKind = null;
|
||||
@@ -75,16 +79,24 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor
|
||||
}
|
||||
|
||||
if (!AbiVersionUtil.isAbiVersionCompatible(version)) {
|
||||
return new KotlinClassHeader(headerKind, version, null, classKind, syntheticClassKind);
|
||||
return new KotlinClassHeader(headerKind, version, null, classKind, syntheticClassKind, null, null);
|
||||
}
|
||||
|
||||
if ((headerKind == CLASS || headerKind == PACKAGE_FACADE || headerKind == FILE_FACADE) && annotationData == null) {
|
||||
if (shouldHaveData() && annotationData == null) {
|
||||
// This means that the annotation is found and its ABI version is compatible, but there's no "data" string array in it.
|
||||
// We tell the outside world that there's really no annotation at all
|
||||
return null;
|
||||
}
|
||||
|
||||
return new KotlinClassHeader(headerKind, version, annotationData, classKind, syntheticClassKind);
|
||||
return new KotlinClassHeader(headerKind, version, annotationData, classKind, syntheticClassKind, filePartClassNames, multifileClassName);
|
||||
}
|
||||
|
||||
private boolean shouldHaveData() {
|
||||
return headerKind == CLASS ||
|
||||
headerKind == PACKAGE_FACADE ||
|
||||
headerKind == FILE_FACADE ||
|
||||
headerKind == MULTIFILE_CLASS ||
|
||||
headerKind == MULTIFILE_CLASS_PART;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -136,15 +148,38 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor
|
||||
|
||||
@Override
|
||||
public void visit(@Nullable Name name, @Nullable Object value) {
|
||||
if (name != null && name.asString().equals(ABI_VERSION_FIELD_NAME)) {
|
||||
version = value instanceof Integer ? (Integer) value : AbiVersionUtil.INVALID_VERSION;
|
||||
if (name != null) {
|
||||
if (name.asString().equals(ABI_VERSION_FIELD_NAME)) {
|
||||
version = value instanceof Integer ? (Integer) value : AbiVersionUtil.INVALID_VERSION;
|
||||
}
|
||||
else if (name.asString().equals(MULTIFILE_CLASS_NAME_FIELD_NAME)) {
|
||||
multifileClassName = value instanceof String ? (String) value : null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public AnnotationArrayArgumentVisitor visitArray(@NotNull Name name) {
|
||||
return name.asString().equals(DATA_FIELD_NAME) ? stringArrayVisitor() : null;
|
||||
if (name.asString().equals(DATA_FIELD_NAME)) {
|
||||
return dataArrayVisitor();
|
||||
}
|
||||
else if (name.asString().equals(FILE_PART_CLASS_NAMES_FIELD_NAME)) {
|
||||
return filePartClassNamesVisitor();
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private AnnotationArrayArgumentVisitor filePartClassNamesVisitor() {
|
||||
return new CollectStringArrayAnnotationVisitor() {
|
||||
@Override
|
||||
protected void visitEnd(String[] data) {
|
||||
filePartClassNames = data;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -158,24 +193,11 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private AnnotationArrayArgumentVisitor stringArrayVisitor() {
|
||||
final List<String> strings = new ArrayList<String>(1);
|
||||
return new AnnotationArrayArgumentVisitor() {
|
||||
private AnnotationArrayArgumentVisitor dataArrayVisitor() {
|
||||
return new CollectStringArrayAnnotationVisitor() {
|
||||
@Override
|
||||
public void visit(@Nullable Object value) {
|
||||
if (value instanceof String) {
|
||||
strings.add((String) value);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitEnum(@NotNull ClassId enumClassId, @NotNull Name enumEntryName) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitEnd() {
|
||||
//noinspection SSBasedInspection
|
||||
annotationData = strings.toArray(new String[strings.size()]);
|
||||
protected void visitEnd(String[] data) {
|
||||
annotationData = data;
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -183,6 +205,33 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor
|
||||
@Override
|
||||
public void visitEnd() {
|
||||
}
|
||||
|
||||
private abstract class CollectStringArrayAnnotationVisitor implements AnnotationArrayArgumentVisitor {
|
||||
private final List<String> strings;
|
||||
|
||||
public CollectStringArrayAnnotationVisitor() {
|
||||
this.strings = new ArrayList<String>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(@Nullable Object value) {
|
||||
if (value instanceof String) {
|
||||
strings.add((String) value);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitEnum(@NotNull ClassId enumClassId, @NotNull Name enumEntryName) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitEnd() {
|
||||
//noinspection SSBasedInspection
|
||||
visitEnd(strings.toArray(new String[strings.size()]));
|
||||
}
|
||||
|
||||
protected abstract void visitEnd(String[] data);
|
||||
}
|
||||
}
|
||||
|
||||
private class ClassHeaderReader extends HeaderAnnotationArgumentVisitor {
|
||||
|
||||
Reference in New Issue
Block a user