From 5bb47c8365660c6757058e7c1ec23015b288ef23 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Thu, 1 Oct 2015 15:25:41 +0300 Subject: [PATCH] Write KotlinInterfaceDefaultImpls annotation to DefaultImpls classes Instead of KotlinSyntheticClass with kind = TRAIT_IMPL --- .../codegen/InterfaceImplBodyCodegen.kt | 16 ++++++----- .../kotlin/codegen/InlineTestUtil.kt | 2 +- .../kotlin/load/java/JvmAnnotationNames.java | 2 ++ .../load/kotlin/header/KotlinClassHeader.kt | 3 +- ...eadKotlinClassHeaderAnnotationVisitor.java | 14 +++++++--- .../internal/KotlinInterfaceDefaultImpls.java | 28 +++++++++++++++++++ .../kotlin/idea/decompiler/DecompiledUtils.kt | 6 ++-- 7 files changed, 54 insertions(+), 17 deletions(-) create mode 100644 core/runtime.jvm/src/kotlin/jvm/internal/KotlinInterfaceDefaultImpls.java diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/InterfaceImplBodyCodegen.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/InterfaceImplBodyCodegen.kt index 57e5dfd50d0..cdd12ef601d 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/InterfaceImplBodyCodegen.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/InterfaceImplBodyCodegen.kt @@ -19,13 +19,13 @@ package org.jetbrains.kotlin.codegen import com.intellij.util.ArrayUtil import org.jetbrains.kotlin.backend.common.bridges.findImplementationFromInterface import org.jetbrains.kotlin.backend.common.bridges.firstSuperMethodFromKotlin -import org.jetbrains.kotlin.codegen.AsmUtil.writeKotlinSyntheticClassAnnotation import org.jetbrains.kotlin.codegen.context.ClassContext import org.jetbrains.kotlin.codegen.state.GenerationState import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorImpl import org.jetbrains.kotlin.load.java.JvmAbi -import org.jetbrains.kotlin.load.java.JvmAnnotationNames.KotlinSyntheticClass.Kind.LOCAL_TRAIT_IMPL +import org.jetbrains.kotlin.load.java.JvmAnnotationNames +import org.jetbrains.kotlin.load.java.JvmAnnotationNames.KOTLIN_INTERFACE_DEFAULT_IMPLS import org.jetbrains.kotlin.load.java.JvmAnnotationNames.KotlinSyntheticClass.Kind.TRAIT_IMPL import org.jetbrains.kotlin.load.java.descriptors.JavaMethodDescriptor import org.jetbrains.kotlin.name.Name @@ -35,7 +35,9 @@ import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.jvm.diagnostics.DelegationToTraitImpl import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature import org.jetbrains.kotlin.resolve.scopes.JetScope -import org.jetbrains.org.objectweb.asm.Opcodes.* +import org.jetbrains.org.objectweb.asm.Opcodes.ACC_FINAL +import org.jetbrains.org.objectweb.asm.Opcodes.ACC_PUBLIC +import org.jetbrains.org.objectweb.asm.Opcodes.ACC_STATIC import org.jetbrains.org.objectweb.asm.Opcodes.V1_6 import java.util.* @@ -144,9 +146,9 @@ public class InterfaceImplBodyCodegen( } override fun generateKotlinAnnotation() { - writeKotlinSyntheticClassAnnotation( - v, - if (DescriptorUtils.isTopLevelOrInnerClass(descriptor)) TRAIT_IMPL else LOCAL_TRAIT_IMPL - ) + val av = v.newAnnotation(AsmUtil.asmDescByFqNameWithoutInnerClasses(KOTLIN_INTERFACE_DEFAULT_IMPLS), true) + av.visit(JvmAnnotationNames.VERSION_FIELD_NAME, JvmAbi.VERSION.toArray()) + av.visitEnd() + AsmUtil.writeKotlinSyntheticClassAnnotation(v, TRAIT_IMPL) } } diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/InlineTestUtil.kt b/compiler/tests/org/jetbrains/kotlin/codegen/InlineTestUtil.kt index 351fb005b80..7befe7fc776 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/InlineTestUtil.kt +++ b/compiler/tests/org/jetbrains/kotlin/codegen/InlineTestUtil.kt @@ -187,7 +187,7 @@ public object InlineTestUtil { private fun isClassOrPackagePartKind(header: KotlinClassHeader): Boolean { return header.classKind == JvmAnnotationNames.KotlinClass.Kind.CLASS || header.syntheticClassKind == JvmAnnotationNames.KotlinSyntheticClass.Kind.PACKAGE_PART - || header.syntheticClassKind == JvmAnnotationNames.KotlinSyntheticClass.Kind.TRAIT_IMPL + || header.isInterfaceDefaultImpls } private fun getClassHeader(file: OutputFile): KotlinClassHeader { diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/JvmAnnotationNames.java b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/JvmAnnotationNames.java index 081b2c398b7..ab8f109babf 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/JvmAnnotationNames.java +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/JvmAnnotationNames.java @@ -34,6 +34,7 @@ public final class JvmAnnotationNames { 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 JAVA_LANG_DEPRECATED = new FqName("java.lang.Deprecated"); @@ -139,6 +140,7 @@ public final class JvmAnnotationNames { SPECIAL_ANNOTATIONS.add(JvmClassName.byFqNameWithoutInnerClasses(fqName)); } SPECIAL_ANNOTATIONS.add(KotlinSyntheticClass.CLASS_NAME); + SPECIAL_ANNOTATIONS.add(JvmClassName.byFqNameWithoutInnerClasses(KOTLIN_INTERFACE_DEFAULT_IMPLS)); for (FqName fqName : Arrays.asList(JETBRAINS_NOT_NULL_ANNOTATION, JETBRAINS_NULLABLE_ANNOTATION)) { NULLABILITY_ANNOTATIONS.add(JvmClassName.byFqNameWithoutInnerClasses(fqName)); diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/header/KotlinClassHeader.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/header/KotlinClassHeader.kt index 23d42d37600..9d2a5c4b167 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/header/KotlinClassHeader.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/header/KotlinClassHeader.kt @@ -29,7 +29,8 @@ public class KotlinClassHeader( public val classKind: KotlinClass.Kind?, public val syntheticClassKind: KotlinSyntheticClass.Kind?, public val filePartClassNames: Array?, - public val multifileClassName: String? + public val multifileClassName: String?, + public val isInterfaceDefaultImpls: Boolean ) { public val isCompatibleAbiVersion: Boolean get() = AbiVersionUtil.isAbiVersionCompatible(version) diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/header/ReadKotlinClassHeaderAnnotationVisitor.java b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/header/ReadKotlinClassHeaderAnnotationVisitor.java index 921241b4964..6a0a9d91c84 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/header/ReadKotlinClassHeaderAnnotationVisitor.java +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/header/ReadKotlinClassHeaderAnnotationVisitor.java @@ -68,6 +68,7 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor private KotlinClassHeader.Kind headerKind = null; private KotlinClass.Kind classKind = null; private KotlinSyntheticClass.Kind syntheticClassKind = null; + private boolean isInterfaceDefaultImpls = false; @Nullable public KotlinClassHeader createHeader() { @@ -81,17 +82,17 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor } if (!AbiVersionUtil.isAbiVersionCompatible(version)) { - return new KotlinClassHeader(headerKind, version, null, strings, classKind, syntheticClassKind, null, null); + annotationData = null; } - - if (shouldHaveData() && annotationData == null) { + else 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, strings, classKind, syntheticClassKind, filePartClassNames, multifileClassName + headerKind, version, annotationData, strings, classKind, syntheticClassKind, filePartClassNames, multifileClassName, + isInterfaceDefaultImpls ); } @@ -105,6 +106,11 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor @Nullable @Override public AnnotationArgumentVisitor visitAnnotation(@NotNull ClassId classId, @NotNull SourceElement source) { + if (KOTLIN_INTERFACE_DEFAULT_IMPLS.equals(classId.asSingleFqName())) { + isInterfaceDefaultImpls = true; + return null; + } + if (headerKind != null) { // Ignore all Kotlin annotations except the first found return null; diff --git a/core/runtime.jvm/src/kotlin/jvm/internal/KotlinInterfaceDefaultImpls.java b/core/runtime.jvm/src/kotlin/jvm/internal/KotlinInterfaceDefaultImpls.java new file mode 100644 index 00000000000..140e0b3344e --- /dev/null +++ b/core/runtime.jvm/src/kotlin/jvm/internal/KotlinInterfaceDefaultImpls.java @@ -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 KotlinInterfaceDefaultImpls { + int[] version() default {}; +} diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/DecompiledUtils.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/DecompiledUtils.kt index e8b3f2867e9..536d719e59c 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/DecompiledUtils.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/DecompiledUtils.kt @@ -41,10 +41,8 @@ public fun isKotlinJvmCompiledFile(file: VirtualFile): Boolean { return false } - val header = KotlinBinaryClassCache.getKotlinBinaryClass(file)?.getClassHeader() - return header != null && - header.syntheticClassKind != KotlinSyntheticClass.Kind.TRAIT_IMPL && - header.syntheticClassKind != KotlinSyntheticClass.Kind.LOCAL_TRAIT_IMPL + val header = KotlinBinaryClassCache.getKotlinBinaryClass(file)?.classHeader + return header != null && !header.isInterfaceDefaultImpls } public fun isKotlinJsMetaFile(file: VirtualFile): Boolean = file.getFileType() == KotlinJavaScriptMetaFileType