Deprecate and don't write KotlinClass$Kind, to be removed later
This commit is contained in:
@@ -43,7 +43,6 @@ import org.jetbrains.kotlin.incremental.components.NoLookupLocation;
|
||||
import org.jetbrains.kotlin.lexer.JetTokens;
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi;
|
||||
import org.jetbrains.kotlin.load.java.JvmAnnotationNames;
|
||||
import org.jetbrains.kotlin.load.java.JvmAnnotationNames.KotlinClass;
|
||||
import org.jetbrains.kotlin.load.java.descriptors.JavaCallableMemberDescriptor;
|
||||
import org.jetbrains.kotlin.name.FqName;
|
||||
import org.jetbrains.kotlin.name.FqNameUnsafe;
|
||||
@@ -256,17 +255,12 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
protected void generateKotlinAnnotation() {
|
||||
if (state.getClassBuilderMode() != ClassBuilderMode.FULL) return;
|
||||
|
||||
KotlinClass.Kind kind;
|
||||
if (isAnonymousObject(descriptor)) {
|
||||
kind = KotlinClass.Kind.ANONYMOUS_OBJECT;
|
||||
}
|
||||
else if (isTopLevelOrInnerClass(descriptor)) {
|
||||
// Default value is Kind.CLASS
|
||||
kind = null;
|
||||
}
|
||||
else {
|
||||
// LOCAL_CLASS is also written to inner classes of local classes
|
||||
kind = KotlinClass.Kind.LOCAL_CLASS;
|
||||
if (!isTopLevelOrInnerClass(descriptor)) {
|
||||
AnnotationVisitor av = v.getVisitor().visitAnnotation(
|
||||
asmDescByFqNameWithoutInnerClasses(JvmAnnotationNames.KOTLIN_LOCAL_CLASS), true
|
||||
);
|
||||
av.visit(JvmAnnotationNames.VERSION_FIELD_NAME, JvmAbi.VERSION.toArray());
|
||||
av.visitEnd();
|
||||
}
|
||||
|
||||
DescriptorSerializer serializer =
|
||||
@@ -276,13 +270,6 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
|
||||
AnnotationVisitor av = v.getVisitor().visitAnnotation(asmDescByFqNameWithoutInnerClasses(JvmAnnotationNames.KOTLIN_CLASS), true);
|
||||
writeAnnotationData(av, serializer, classProto);
|
||||
if (kind != null) {
|
||||
av.visitEnum(
|
||||
JvmAnnotationNames.KIND_FIELD_NAME,
|
||||
Type.getObjectType(KotlinClass.KIND_INTERNAL_NAME).getDescriptor(),
|
||||
kind.toString()
|
||||
);
|
||||
}
|
||||
av.visitEnd();
|
||||
}
|
||||
|
||||
|
||||
@@ -270,9 +270,6 @@ public abstract class FileBasedKotlinClass implements KotlinJvmBinaryClass {
|
||||
if (name.equals(JvmAnnotationNames.KotlinSyntheticClass.KIND_INTERNAL_NAME)) {
|
||||
return JvmAnnotationNames.KotlinSyntheticClass.KIND_CLASS_ID;
|
||||
}
|
||||
else if (name.equals(JvmAnnotationNames.KotlinClass.KIND_INTERNAL_NAME)) {
|
||||
return JvmAnnotationNames.KotlinClass.KIND_CLASS_ID;
|
||||
}
|
||||
|
||||
List<String> classes = new ArrayList<String>(1);
|
||||
boolean local = false;
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
method <init>(p0: int): void
|
||||
}
|
||||
|
||||
@kotlin.jvm.internal.KotlinClass LiteralsKt$foo$3 {
|
||||
@kotlin.jvm.internal.KotlinLocalClass @kotlin.jvm.internal.KotlinClass LiteralsKt$foo$3 {
|
||||
inner class LiteralsKt$foo$3
|
||||
field $kotlinClass: kotlin.reflect.KClass
|
||||
method <clinit>(): void
|
||||
|
||||
@@ -185,7 +185,7 @@ public object InlineTestUtil {
|
||||
}
|
||||
|
||||
private fun isClassOrPackagePartKind(header: KotlinClassHeader): Boolean {
|
||||
return header.classKind == JvmAnnotationNames.KotlinClass.Kind.CLASS || header.isInterfaceDefaultImpls
|
||||
return (header.kind == KotlinClassHeader.Kind.CLASS && !header.isLocalClass) || header.isInterfaceDefaultImpls
|
||||
}
|
||||
|
||||
private fun getClassHeader(file: OutputFile): KotlinClassHeader {
|
||||
|
||||
+13
-33
@@ -19,14 +19,12 @@ package org.jetbrains.kotlin.codegen;
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.Collections2;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.backend.common.output.OutputFile;
|
||||
import org.jetbrains.kotlin.load.java.AbiVersionUtil;
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi;
|
||||
import org.jetbrains.kotlin.load.java.JvmAnnotationNames.KotlinClass;
|
||||
import org.jetbrains.kotlin.load.java.JvmAnnotationNames;
|
||||
import org.jetbrains.kotlin.load.java.JvmAnnotationNames.KotlinSyntheticClass;
|
||||
import org.jetbrains.kotlin.name.FqName;
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmClassName;
|
||||
import org.jetbrains.kotlin.serialization.deserialization.BinaryVersion;
|
||||
import org.jetbrains.kotlin.test.ConfigurationKind;
|
||||
|
||||
@@ -34,9 +32,6 @@ import java.lang.annotation.Annotation;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import static org.jetbrains.kotlin.load.java.JvmAnnotationNames.KIND_FIELD_NAME;
|
||||
import static org.jetbrains.kotlin.load.java.JvmAnnotationNames.KotlinClass.Kind.ANONYMOUS_OBJECT;
|
||||
import static org.jetbrains.kotlin.load.java.JvmAnnotationNames.KotlinClass.Kind.LOCAL_CLASS;
|
||||
import static org.jetbrains.kotlin.load.java.JvmAnnotationNames.VERSION_FIELD_NAME;
|
||||
|
||||
public class KotlinSyntheticClassAnnotationTest extends CodegenTestCase {
|
||||
@@ -93,8 +88,7 @@ public class KotlinSyntheticClassAnnotationTest extends CodegenTestCase {
|
||||
public void testLocalClass() {
|
||||
doTestKotlinClass(
|
||||
"fun foo() { class Local }",
|
||||
"Local",
|
||||
LOCAL_CLASS
|
||||
"Local"
|
||||
);
|
||||
}
|
||||
|
||||
@@ -108,24 +102,21 @@ public class KotlinSyntheticClassAnnotationTest extends CodegenTestCase {
|
||||
public void testLocalTraitInterface() {
|
||||
doTestKotlinClass(
|
||||
"fun foo() { interface Local { fun bar() = 42 } }",
|
||||
"Local.class",
|
||||
LOCAL_CLASS
|
||||
"Local.class"
|
||||
);
|
||||
}
|
||||
|
||||
public void testInnerClassOfLocalClass() {
|
||||
doTestKotlinClass(
|
||||
"fun foo() { class Local { inner class Inner } }",
|
||||
"Inner",
|
||||
LOCAL_CLASS
|
||||
"Inner"
|
||||
);
|
||||
}
|
||||
|
||||
public void testAnonymousObject() {
|
||||
doTestKotlinClass(
|
||||
"val o = object {}",
|
||||
"$1",
|
||||
ANONYMOUS_OBJECT
|
||||
"$1"
|
||||
);
|
||||
}
|
||||
|
||||
@@ -138,22 +129,17 @@ public class KotlinSyntheticClassAnnotationTest extends CodegenTestCase {
|
||||
}
|
||||
|
||||
private void doTestKotlinSyntheticClass(@NotNull String code, @NotNull String classFilePart) {
|
||||
doTest(code, classFilePart, KotlinSyntheticClass.CLASS_NAME, null);
|
||||
doTest(code, classFilePart, KotlinSyntheticClass.CLASS_NAME.getFqNameForClassNameWithoutDollars());
|
||||
}
|
||||
|
||||
private void doTestKotlinClass(
|
||||
@NotNull String code,
|
||||
@NotNull String classFilePart,
|
||||
@NotNull KotlinClass.Kind expectedKind
|
||||
) {
|
||||
doTest(code, classFilePart, KotlinClass.CLASS_NAME, expectedKind.toString());
|
||||
private void doTestKotlinClass(@NotNull String code, @NotNull String classFilePart) {
|
||||
doTest(code, classFilePart, JvmAnnotationNames.KOTLIN_CLASS, JvmAnnotationNames.KOTLIN_LOCAL_CLASS);
|
||||
}
|
||||
|
||||
private void doTest(
|
||||
@NotNull String code,
|
||||
@NotNull final String classFilePart,
|
||||
@NotNull JvmClassName annotationName,
|
||||
@Nullable String expectedKind
|
||||
@NotNull FqName... annotationFqNames
|
||||
) {
|
||||
loadText("package " + PACKAGE_NAME + "\n\n" + code);
|
||||
List<OutputFile> output = generateClassesInFile().asList();
|
||||
@@ -169,14 +155,12 @@ public class KotlinSyntheticClassAnnotationTest extends CodegenTestCase {
|
||||
String path = files.iterator().next().getRelativePath();
|
||||
String fqName = path.substring(0, path.length() - ".class".length()).replace('/', '.');
|
||||
Class<?> aClass = generateClass(fqName);
|
||||
assertAnnotatedWithKind(aClass, annotationName.getFqNameForClassNameWithoutDollars().asString(), expectedKind);
|
||||
for (FqName annotationFqName : annotationFqNames) {
|
||||
assertAnnotatedWith(aClass, annotationFqName.asString());
|
||||
}
|
||||
}
|
||||
|
||||
private void assertAnnotatedWithKind(
|
||||
@NotNull Class<?> aClass,
|
||||
@NotNull String annotationFqName,
|
||||
@Nullable String expectedKind
|
||||
) {
|
||||
private void assertAnnotatedWith(@NotNull Class<?> aClass, @NotNull String annotationFqName) {
|
||||
Class<? extends Annotation> annotationClass = loadAnnotationClassQuietly(annotationFqName);
|
||||
assertTrue("No annotation " + annotationFqName + " found in " + aClass, aClass.isAnnotationPresent(annotationClass));
|
||||
|
||||
@@ -186,9 +170,5 @@ public class KotlinSyntheticClassAnnotationTest extends CodegenTestCase {
|
||||
assertNotNull(version);
|
||||
assertTrue("Annotation " + annotationFqName + " is written with an unsupported format",
|
||||
AbiVersionUtil.isAbiVersionCompatible(BinaryVersion.create(version)));
|
||||
|
||||
Object actualKind = CodegenTestUtil.getAnnotationAttribute(annotation, KIND_FIELD_NAME);
|
||||
assertNotNull(actualKind);
|
||||
assertEquals("Annotation " + annotationFqName + " has the wrong kind", expectedKind, actualKind.toString());
|
||||
}
|
||||
}
|
||||
|
||||
+2
-3
@@ -150,11 +150,10 @@ public abstract class AbstractJvmRuntimeDescriptorLoaderTest : TestCaseWithTmpdi
|
||||
val packageView = module.getPackage(LoadDescriptorUtil.TEST_PACKAGE_FQNAME)
|
||||
packageScopes.add(packageView.memberScope)
|
||||
}
|
||||
else if (header == null ||
|
||||
(header.kind == KotlinClassHeader.Kind.CLASS && header.classKind == JvmAnnotationNames.KotlinClass.Kind.CLASS)) {
|
||||
else if (header == null || (header.kind == KotlinClassHeader.Kind.CLASS && !header.isLocalClass)) {
|
||||
// Either a normal Kotlin class or a Java class
|
||||
val classId = klass.classId
|
||||
if (!classId.isLocal()) {
|
||||
if (!classId.isLocal) {
|
||||
val classDescriptor = module.findClassAcrossModuleDependencies(classId).sure { "Couldn't resolve class $className" }
|
||||
if (DescriptorUtils.isTopLevelDeclaration(classDescriptor)) {
|
||||
classes.add(classDescriptor)
|
||||
|
||||
@@ -76,17 +76,13 @@ public abstract class AbstractLocalClassProtoTest : TestCaseWithTmpdir() {
|
||||
)
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
private fun assertHasAnnotationData(clazz: Class<*>) {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val annotation = clazz.getAnnotation(
|
||||
checkNotNull(clazz.getAnnotation(
|
||||
clazz.classLoader.loadClass(JvmAnnotationNames.KOTLIN_CLASS.asString()) as Class<Annotation>
|
||||
)
|
||||
assert(annotation != null) { "KotlinClass annotation is not found for class $clazz" }
|
||||
|
||||
val kindMethod = annotation.annotationType().getDeclaredMethod("kind")
|
||||
val kind = kindMethod(annotation)
|
||||
assert(kind.toString() != JvmAnnotationNames.KotlinClass.Kind.CLASS.toString()) {
|
||||
"'kind' should not be CLASS: $clazz (was $kind)"
|
||||
}
|
||||
)) { "KotlinClass annotation is not found for class $clazz" }
|
||||
checkNotNull(clazz.getAnnotation(
|
||||
clazz.classLoader.loadClass(JvmAnnotationNames.KOTLIN_LOCAL_CLASS.asString()) as Class<Annotation>
|
||||
)) { "KotlinLocalClass annotation is not found for class $clazz" }
|
||||
}
|
||||
}
|
||||
|
||||
+3
-18
@@ -28,13 +28,14 @@ import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public final class JvmAnnotationNames {
|
||||
public static final FqName KOTLIN_CLASS = KotlinClass.CLASS_NAME.getFqNameForClassNameWithoutDollars();
|
||||
public static final FqName KOTLIN_CLASS = new FqName("kotlin.jvm.internal.KotlinClass");
|
||||
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_INTERFACE_DEFAULT_IMPLS = new FqName("kotlin.jvm.internal.KotlinInterfaceDefaultImpls");
|
||||
public static final FqName KOTLIN_LOCAL_CLASS = new FqName("kotlin.jvm.internal.KotlinLocalClass");
|
||||
|
||||
public static final FqName JAVA_LANG_DEPRECATED = new FqName("java.lang.Deprecated");
|
||||
|
||||
@@ -68,23 +69,6 @@ public final class JvmAnnotationNames {
|
||||
public static final FqName ENHANCED_NULLABILITY_ANNOTATION = new FqName("kotlin.jvm.internal.EnhancedNullability");
|
||||
public static final FqName ENHANCED_MUTABILITY_ANNOTATION = new FqName("kotlin.jvm.internal.EnhancedMutability");
|
||||
|
||||
public static class KotlinClass {
|
||||
public static final JvmClassName CLASS_NAME = JvmClassName.byInternalName("kotlin/jvm/internal/KotlinClass");
|
||||
public static final ClassId KIND_CLASS_ID =
|
||||
ClassId.topLevel(CLASS_NAME.getFqNameForClassNameWithoutDollars()).createNestedClassId(Name.identifier("Kind"));
|
||||
public static final String KIND_INTERNAL_NAME = JvmClassName.byClassId(KIND_CLASS_ID).getInternalName();
|
||||
|
||||
/**
|
||||
* This enum duplicates {@link kotlin.jvm.internal.KotlinClass.Kind}. Both places should be updated simultaneously.
|
||||
*/
|
||||
public enum Kind {
|
||||
CLASS,
|
||||
LOCAL_CLASS,
|
||||
ANONYMOUS_OBJECT,
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
public static class KotlinSyntheticClass {
|
||||
public static final JvmClassName CLASS_NAME = JvmClassName.byInternalName("kotlin/jvm/internal/KotlinSyntheticClass");
|
||||
public static final ClassId KIND_CLASS_ID =
|
||||
@@ -125,6 +109,7 @@ public final class JvmAnnotationNames {
|
||||
}
|
||||
SPECIAL_ANNOTATIONS.add(KotlinSyntheticClass.CLASS_NAME);
|
||||
SPECIAL_ANNOTATIONS.add(JvmClassName.byFqNameWithoutInnerClasses(KOTLIN_INTERFACE_DEFAULT_IMPLS));
|
||||
SPECIAL_ANNOTATIONS.add(JvmClassName.byFqNameWithoutInnerClasses(KOTLIN_LOCAL_CLASS));
|
||||
|
||||
for (FqName fqName : Arrays.asList(JETBRAINS_NOT_NULL_ANNOTATION, JETBRAINS_NULLABLE_ANNOTATION)) {
|
||||
NULLABILITY_ANNOTATIONS.add(JvmClassName.byFqNameWithoutInnerClasses(fqName));
|
||||
|
||||
+18
-20
@@ -17,24 +17,22 @@
|
||||
package org.jetbrains.kotlin.load.kotlin.header
|
||||
|
||||
import org.jetbrains.kotlin.load.java.AbiVersionUtil
|
||||
import org.jetbrains.kotlin.load.java.JvmAnnotationNames.KotlinClass
|
||||
import org.jetbrains.kotlin.load.java.JvmAnnotationNames.KotlinSyntheticClass
|
||||
import org.jetbrains.kotlin.serialization.deserialization.BinaryVersion
|
||||
|
||||
public class KotlinClassHeader(
|
||||
public val kind: KotlinClassHeader.Kind,
|
||||
public val version: BinaryVersion,
|
||||
public val annotationData: Array<String>?,
|
||||
public val strings: Array<String>?,
|
||||
public val classKind: KotlinClass.Kind?,
|
||||
public val syntheticClassKind: String?,
|
||||
public val filePartClassNames: Array<String>?,
|
||||
public val multifileClassName: String?,
|
||||
public val isInterfaceDefaultImpls: Boolean
|
||||
class KotlinClassHeader(
|
||||
val kind: KotlinClassHeader.Kind,
|
||||
val version: BinaryVersion,
|
||||
val annotationData: Array<String>?,
|
||||
val strings: Array<String>?,
|
||||
val syntheticClassKind: String?,
|
||||
val filePartClassNames: Array<String>?,
|
||||
val multifileClassName: String?,
|
||||
val isInterfaceDefaultImpls: Boolean,
|
||||
val isLocalClass: Boolean
|
||||
) {
|
||||
public val isCompatibleAbiVersion: Boolean get() = AbiVersionUtil.isAbiVersionCompatible(version)
|
||||
val isCompatibleAbiVersion: Boolean get() = AbiVersionUtil.isAbiVersionCompatible(version)
|
||||
|
||||
public enum class Kind {
|
||||
enum class Kind {
|
||||
CLASS,
|
||||
PACKAGE_FACADE,
|
||||
FILE_FACADE,
|
||||
@@ -45,13 +43,13 @@ public class KotlinClassHeader(
|
||||
|
||||
override fun toString() =
|
||||
"$kind " +
|
||||
(if (classKind != null) "$classKind " else "") +
|
||||
(if (isLocalClass) "(local) " else "") +
|
||||
(if (syntheticClassKind != null) "$syntheticClassKind " else "") +
|
||||
"version=$version"
|
||||
}
|
||||
|
||||
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
|
||||
fun KotlinClassHeader.isCompatibleClassKind(): Boolean = isCompatibleAbiVersion && kind == KotlinClassHeader.Kind.CLASS
|
||||
fun KotlinClassHeader.isCompatiblePackageFacadeKind(): Boolean = isCompatibleAbiVersion && kind == KotlinClassHeader.Kind.PACKAGE_FACADE
|
||||
fun KotlinClassHeader.isCompatibleFileFacadeKind(): Boolean = isCompatibleAbiVersion && kind == KotlinClassHeader.Kind.FILE_FACADE
|
||||
fun KotlinClassHeader.isCompatibleMultifileClassKind(): Boolean = isCompatibleAbiVersion && kind == KotlinClassHeader.Kind.MULTIFILE_CLASS
|
||||
fun KotlinClassHeader.isCompatibleMultifileClassPartKind(): Boolean = isCompatibleAbiVersion && kind == KotlinClassHeader.Kind.MULTIFILE_CLASS_PART
|
||||
|
||||
+12
-30
@@ -21,6 +21,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.descriptors.SourceElement;
|
||||
import org.jetbrains.kotlin.load.java.AbiVersionUtil;
|
||||
import org.jetbrains.kotlin.name.ClassId;
|
||||
import org.jetbrains.kotlin.name.FqName;
|
||||
import org.jetbrains.kotlin.name.Name;
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmClassName;
|
||||
import org.jetbrains.kotlin.serialization.deserialization.BinaryVersion;
|
||||
@@ -39,7 +40,7 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor
|
||||
private static final Map<JvmClassName, KotlinClassHeader.Kind> OLD_DEPRECATED_ANNOTATIONS_KINDS = new HashMap<JvmClassName, KotlinClassHeader.Kind>();
|
||||
|
||||
static {
|
||||
HEADER_KINDS.put(KotlinClass.CLASS_NAME, CLASS);
|
||||
HEADER_KINDS.put(JvmClassName.byFqNameWithoutInnerClasses(KOTLIN_CLASS), 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);
|
||||
@@ -66,9 +67,9 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor
|
||||
private String[] annotationData = null;
|
||||
private String[] strings = null;
|
||||
private KotlinClassHeader.Kind headerKind = null;
|
||||
private KotlinClass.Kind classKind = null;
|
||||
private String syntheticClassKind = null;
|
||||
private boolean isInterfaceDefaultImpls = false;
|
||||
private boolean isLocalClass = false;
|
||||
|
||||
@Nullable
|
||||
public KotlinClassHeader createHeader() {
|
||||
@@ -76,11 +77,6 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor
|
||||
return null;
|
||||
}
|
||||
|
||||
if (headerKind == CLASS && classKind == null) {
|
||||
// Default class kind is Kind.CLASS
|
||||
classKind = KotlinClass.Kind.CLASS;
|
||||
}
|
||||
|
||||
if (!AbiVersionUtil.isAbiVersionCompatible(version)) {
|
||||
annotationData = null;
|
||||
}
|
||||
@@ -91,8 +87,8 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor
|
||||
}
|
||||
|
||||
return new KotlinClassHeader(
|
||||
headerKind, version, annotationData, strings, classKind, syntheticClassKind, filePartClassNames, multifileClassName,
|
||||
isInterfaceDefaultImpls
|
||||
headerKind, version, annotationData, strings, syntheticClassKind, filePartClassNames, multifileClassName,
|
||||
isInterfaceDefaultImpls, isLocalClass
|
||||
);
|
||||
}
|
||||
|
||||
@@ -106,10 +102,15 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor
|
||||
@Nullable
|
||||
@Override
|
||||
public AnnotationArgumentVisitor visitAnnotation(@NotNull ClassId classId, @NotNull SourceElement source) {
|
||||
if (KOTLIN_INTERFACE_DEFAULT_IMPLS.equals(classId.asSingleFqName())) {
|
||||
FqName fqName = classId.asSingleFqName();
|
||||
if (KOTLIN_INTERFACE_DEFAULT_IMPLS.equals(fqName)) {
|
||||
isInterfaceDefaultImpls = true;
|
||||
return null;
|
||||
}
|
||||
else if (KOTLIN_LOCAL_CLASS.equals(fqName)) {
|
||||
isLocalClass = true;
|
||||
return null;
|
||||
}
|
||||
|
||||
if (headerKind != null) {
|
||||
// Ignore all Kotlin annotations except the first found
|
||||
@@ -269,14 +270,7 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor
|
||||
|
||||
private class ClassHeaderReader extends HeaderAnnotationArgumentVisitor {
|
||||
public ClassHeaderReader() {
|
||||
super(KotlinClass.CLASS_NAME);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitEnum(@NotNull Name name, @NotNull ClassId enumClassId, @NotNull Name enumEntryName) {
|
||||
if (KotlinClass.KIND_CLASS_ID.equals(enumClassId) && KIND_FIELD_NAME.equals(name.asString())) {
|
||||
classKind = valueOfOrNull(KotlinClass.Kind.class, enumEntryName.asString());
|
||||
}
|
||||
super(JvmClassName.byFqNameWithoutInnerClasses(KOTLIN_CLASS));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -316,16 +310,4 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This function is needed here because Enum.valueOf() throws exception if there's no such value,
|
||||
// but we don't want to fail if we're loading the header with an _incompatible_ ABI version
|
||||
@Nullable
|
||||
private static <E extends Enum<E>> E valueOfOrNull(@NotNull Class<E> enumClass, @NotNull String entry) {
|
||||
try {
|
||||
return Enum.valueOf(enumClass, entry);
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,12 +29,14 @@ public @interface KotlinClass {
|
||||
|
||||
int[] version() default {};
|
||||
|
||||
Kind kind() default Kind.CLASS;
|
||||
|
||||
String[] data();
|
||||
|
||||
String[] strings();
|
||||
|
||||
@Deprecated
|
||||
Kind kind() default Kind.CLASS;
|
||||
|
||||
@Deprecated
|
||||
enum Kind {
|
||||
CLASS,
|
||||
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package kotlin.jvm.internal;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.TYPE)
|
||||
public @interface KotlinLocalClass {
|
||||
int[] version() default {};
|
||||
}
|
||||
@@ -21,7 +21,6 @@ import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.psi.ClassFileViewProvider
|
||||
import org.jetbrains.kotlin.idea.caches.JarUserDataManager
|
||||
import org.jetbrains.kotlin.idea.decompiler.textBuilder.DirectoryBasedClassFinder
|
||||
import org.jetbrains.kotlin.load.java.JvmAnnotationNames.KotlinClass
|
||||
import org.jetbrains.kotlin.load.kotlin.KotlinBinaryClassCache
|
||||
import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinaryClass
|
||||
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader
|
||||
@@ -71,9 +70,8 @@ public fun isKotlinInternalCompiledFile(file: VirtualFile): Boolean {
|
||||
val header = KotlinBinaryClassCache.getKotlinBinaryClass(file)?.classHeader ?: return false
|
||||
|
||||
return header.kind == KotlinClassHeader.Kind.SYNTHETIC_CLASS ||
|
||||
(header.kind == KotlinClassHeader.Kind.CLASS && header.classKind != null && header.classKind != KotlinClass.Kind.CLASS) ||
|
||||
header.kind == KotlinClassHeader.Kind.MULTIFILE_CLASS_PART ||
|
||||
header.syntheticClassKind == "PACKAGE_PART"
|
||||
header.isLocalClass || header.syntheticClassKind == "PACKAGE_PART"
|
||||
}
|
||||
|
||||
public fun isKotlinJavaScriptInternalCompiledFile(file: VirtualFile): Boolean =
|
||||
|
||||
+1
-2
@@ -27,7 +27,6 @@ import org.jetbrains.kotlin.idea.decompiler.isKotlinInternalCompiledFile
|
||||
import org.jetbrains.kotlin.idea.decompiler.textBuilder.DirectoryBasedClassFinder
|
||||
import org.jetbrains.kotlin.idea.decompiler.textBuilder.DirectoryBasedDataFinder
|
||||
import org.jetbrains.kotlin.idea.decompiler.textBuilder.LoggingErrorReporter
|
||||
import org.jetbrains.kotlin.load.java.JvmAnnotationNames
|
||||
import org.jetbrains.kotlin.load.kotlin.KotlinBinaryClassCache
|
||||
import org.jetbrains.kotlin.load.kotlin.header.isCompatibleClassKind
|
||||
import org.jetbrains.kotlin.load.kotlin.header.isCompatibleFileFacadeKind
|
||||
@@ -82,7 +81,7 @@ public open class KotlinClsStubBuilder : ClsStubBuilder() {
|
||||
createPackageFacadeStub(packageProto, packageFqName, context)
|
||||
}
|
||||
header.isCompatibleClassKind() -> {
|
||||
if (header.classKind != JvmAnnotationNames.KotlinClass.Kind.CLASS) return null
|
||||
if (header.isLocalClass) return null
|
||||
val (nameResolver, classProto) = JvmProtoBufUtil.readClassDataFrom(annotationData, strings)
|
||||
val context = components.createContext(nameResolver, packageFqName)
|
||||
createTopLevelClassStub(classId, classProto, context)
|
||||
|
||||
+2
-6
@@ -20,7 +20,6 @@ import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.psi.PsiManager
|
||||
import org.jetbrains.kotlin.idea.decompiler.navigation.NavigateToDecompiledLibraryTest
|
||||
import org.jetbrains.kotlin.idea.test.JetLightCodeInsightFixtureTestCase
|
||||
import org.jetbrains.kotlin.load.java.JvmAnnotationNames.KotlinClass
|
||||
import org.jetbrains.kotlin.load.kotlin.KotlinBinaryClassCache
|
||||
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader
|
||||
import org.junit.Assert
|
||||
@@ -34,11 +33,8 @@ public abstract class AbstractInternalCompiledClassesTest : JetLightCodeInsightF
|
||||
protected fun isSyntheticClass(): VirtualFile.() -> Boolean =
|
||||
isFileWithHeader { it.kind == KotlinClassHeader.Kind.SYNTHETIC_CLASS }
|
||||
|
||||
private fun isClassOfKind(kind: KotlinClass.Kind): VirtualFile.() -> Boolean =
|
||||
isFileWithHeader { it.classKind == kind }
|
||||
|
||||
protected fun doTestNoPsiFilesAreBuiltForLocalClass(kind: KotlinClass.Kind): Unit =
|
||||
doTestNoPsiFilesAreBuiltFor(kind.name(), isClassOfKind(kind))
|
||||
protected fun doTestNoPsiFilesAreBuiltForLocalClass(): Unit =
|
||||
doTestNoPsiFilesAreBuiltFor("local", isFileWithHeader { it.isLocalClass })
|
||||
|
||||
protected fun doTestNoPsiFilesAreBuiltForSyntheticClasses(): Unit =
|
||||
doTestNoPsiFilesAreBuiltFor("synthetic", isSyntheticClass())
|
||||
|
||||
@@ -20,17 +20,13 @@ import com.intellij.psi.ClassFileViewProvider
|
||||
import com.intellij.testFramework.LightProjectDescriptor
|
||||
import org.jetbrains.kotlin.idea.test.JdkAndMockLibraryProjectDescriptor
|
||||
import org.jetbrains.kotlin.idea.test.PluginTestCaseBase
|
||||
import org.jetbrains.kotlin.load.java.JvmAnnotationNames.KotlinClass.Kind.ANONYMOUS_OBJECT
|
||||
import org.jetbrains.kotlin.load.java.JvmAnnotationNames.KotlinClass.Kind.LOCAL_CLASS
|
||||
|
||||
public class InternalCompiledClassesTest : AbstractInternalCompiledClassesTest() {
|
||||
private val TEST_DATA_PATH = PluginTestCaseBase.getTestDataPathBase() + "/decompiler/internalClasses"
|
||||
|
||||
fun testSyntheticClassesAreInvisible() = doTestNoPsiFilesAreBuiltForSyntheticClasses()
|
||||
|
||||
fun testLocalClassIsInvisible() = doTestNoPsiFilesAreBuiltForLocalClass(LOCAL_CLASS)
|
||||
|
||||
fun testAnonymousObjectIsInvisible() = doTestNoPsiFilesAreBuiltForLocalClass(ANONYMOUS_OBJECT)
|
||||
fun testLocalClassesAreInvisible() = doTestNoPsiFilesAreBuiltForLocalClass()
|
||||
|
||||
fun testInnerClassIsInvisible() = doTestNoPsiFilesAreBuiltFor("inner or nested class") {
|
||||
ClassFileViewProvider.isInnerClass(this)
|
||||
|
||||
@@ -31,7 +31,6 @@ import org.jetbrains.kotlin.jps.build.GeneratedJvmClass
|
||||
import org.jetbrains.kotlin.jps.build.KotlinBuilder
|
||||
import org.jetbrains.kotlin.jps.incremental.storage.BasicMap
|
||||
import org.jetbrains.kotlin.jps.incremental.storage.BasicStringMap
|
||||
import org.jetbrains.kotlin.load.java.JvmAnnotationNames
|
||||
import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinaryClass
|
||||
import org.jetbrains.kotlin.load.kotlin.ModuleMapping
|
||||
import org.jetbrains.kotlin.load.kotlin.PackageClassUtils
|
||||
@@ -216,10 +215,11 @@ public class IncrementalCacheImpl(
|
||||
constantsMap.process(kotlinClass) +
|
||||
inlineFunctionsMap.process(kotlinClass)
|
||||
}
|
||||
header.isCompatibleClassKind() && JvmAnnotationNames.KotlinClass.Kind.CLASS == header.classKind ->
|
||||
header.isCompatibleClassKind() && !header.isLocalClass -> {
|
||||
protoMap.process(kotlinClass, isPackage = false) +
|
||||
constantsMap.process(kotlinClass) +
|
||||
inlineFunctionsMap.process(kotlinClass)
|
||||
}
|
||||
else -> ChangesInfo.NO_CHANGES
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user