Write KotlinInterfaceDefaultImpls annotation to DefaultImpls classes

Instead of KotlinSyntheticClass with kind = TRAIT_IMPL
This commit is contained in:
Alexander Udalov
2015-10-01 15:25:41 +03:00
parent e4090d3f30
commit 5bb47c8365
7 changed files with 54 additions and 17 deletions
@@ -19,13 +19,13 @@ package org.jetbrains.kotlin.codegen
import com.intellij.util.ArrayUtil import com.intellij.util.ArrayUtil
import org.jetbrains.kotlin.backend.common.bridges.findImplementationFromInterface import org.jetbrains.kotlin.backend.common.bridges.findImplementationFromInterface
import org.jetbrains.kotlin.backend.common.bridges.firstSuperMethodFromKotlin 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.context.ClassContext
import org.jetbrains.kotlin.codegen.state.GenerationState import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorImpl
import org.jetbrains.kotlin.load.java.JvmAbi 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.JvmAnnotationNames.KotlinSyntheticClass.Kind.TRAIT_IMPL
import org.jetbrains.kotlin.load.java.descriptors.JavaMethodDescriptor import org.jetbrains.kotlin.load.java.descriptors.JavaMethodDescriptor
import org.jetbrains.kotlin.name.Name 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.diagnostics.DelegationToTraitImpl
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
import org.jetbrains.kotlin.resolve.scopes.JetScope 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 org.jetbrains.org.objectweb.asm.Opcodes.V1_6
import java.util.* import java.util.*
@@ -144,9 +146,9 @@ public class InterfaceImplBodyCodegen(
} }
override fun generateKotlinAnnotation() { override fun generateKotlinAnnotation() {
writeKotlinSyntheticClassAnnotation( val av = v.newAnnotation(AsmUtil.asmDescByFqNameWithoutInnerClasses(KOTLIN_INTERFACE_DEFAULT_IMPLS), true)
v, av.visit(JvmAnnotationNames.VERSION_FIELD_NAME, JvmAbi.VERSION.toArray())
if (DescriptorUtils.isTopLevelOrInnerClass(descriptor)) TRAIT_IMPL else LOCAL_TRAIT_IMPL av.visitEnd()
) AsmUtil.writeKotlinSyntheticClassAnnotation(v, TRAIT_IMPL)
} }
} }
@@ -187,7 +187,7 @@ public object InlineTestUtil {
private fun isClassOrPackagePartKind(header: KotlinClassHeader): Boolean { private fun isClassOrPackagePartKind(header: KotlinClassHeader): Boolean {
return header.classKind == JvmAnnotationNames.KotlinClass.Kind.CLASS return header.classKind == JvmAnnotationNames.KotlinClass.Kind.CLASS
|| header.syntheticClassKind == JvmAnnotationNames.KotlinSyntheticClass.Kind.PACKAGE_PART || header.syntheticClassKind == JvmAnnotationNames.KotlinSyntheticClass.Kind.PACKAGE_PART
|| header.syntheticClassKind == JvmAnnotationNames.KotlinSyntheticClass.Kind.TRAIT_IMPL || header.isInterfaceDefaultImpls
} }
private fun getClassHeader(file: OutputFile): KotlinClassHeader { private fun getClassHeader(file: OutputFile): KotlinClassHeader {
@@ -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 = 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_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_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"); 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(JvmClassName.byFqNameWithoutInnerClasses(fqName));
} }
SPECIAL_ANNOTATIONS.add(KotlinSyntheticClass.CLASS_NAME); 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)) { for (FqName fqName : Arrays.asList(JETBRAINS_NOT_NULL_ANNOTATION, JETBRAINS_NULLABLE_ANNOTATION)) {
NULLABILITY_ANNOTATIONS.add(JvmClassName.byFqNameWithoutInnerClasses(fqName)); NULLABILITY_ANNOTATIONS.add(JvmClassName.byFqNameWithoutInnerClasses(fqName));
@@ -29,7 +29,8 @@ public class KotlinClassHeader(
public val classKind: KotlinClass.Kind?, public val classKind: KotlinClass.Kind?,
public val syntheticClassKind: KotlinSyntheticClass.Kind?, public val syntheticClassKind: KotlinSyntheticClass.Kind?,
public val filePartClassNames: Array<String>?, public val filePartClassNames: Array<String>?,
public val multifileClassName: String? public val multifileClassName: String?,
public val isInterfaceDefaultImpls: Boolean
) { ) {
public val isCompatibleAbiVersion: Boolean get() = AbiVersionUtil.isAbiVersionCompatible(version) public val isCompatibleAbiVersion: Boolean get() = AbiVersionUtil.isAbiVersionCompatible(version)
@@ -68,6 +68,7 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor
private KotlinClassHeader.Kind headerKind = null; private KotlinClassHeader.Kind headerKind = null;
private KotlinClass.Kind classKind = null; private KotlinClass.Kind classKind = null;
private KotlinSyntheticClass.Kind syntheticClassKind = null; private KotlinSyntheticClass.Kind syntheticClassKind = null;
private boolean isInterfaceDefaultImpls = false;
@Nullable @Nullable
public KotlinClassHeader createHeader() { public KotlinClassHeader createHeader() {
@@ -81,17 +82,17 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor
} }
if (!AbiVersionUtil.isAbiVersionCompatible(version)) { if (!AbiVersionUtil.isAbiVersionCompatible(version)) {
return new KotlinClassHeader(headerKind, version, null, strings, classKind, syntheticClassKind, null, null); annotationData = null;
} }
else if (shouldHaveData() && 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. // 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 // We tell the outside world that there's really no annotation at all
return null; return null;
} }
return new KotlinClassHeader( 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 @Nullable
@Override @Override
public AnnotationArgumentVisitor visitAnnotation(@NotNull ClassId classId, @NotNull SourceElement source) { public AnnotationArgumentVisitor visitAnnotation(@NotNull ClassId classId, @NotNull SourceElement source) {
if (KOTLIN_INTERFACE_DEFAULT_IMPLS.equals(classId.asSingleFqName())) {
isInterfaceDefaultImpls = true;
return null;
}
if (headerKind != null) { if (headerKind != null) {
// Ignore all Kotlin annotations except the first found // Ignore all Kotlin annotations except the first found
return null; return null;
@@ -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 {};
}
@@ -41,10 +41,8 @@ public fun isKotlinJvmCompiledFile(file: VirtualFile): Boolean {
return false return false
} }
val header = KotlinBinaryClassCache.getKotlinBinaryClass(file)?.getClassHeader() val header = KotlinBinaryClassCache.getKotlinBinaryClass(file)?.classHeader
return header != null && return header != null && !header.isInterfaceDefaultImpls
header.syntheticClassKind != KotlinSyntheticClass.Kind.TRAIT_IMPL &&
header.syntheticClassKind != KotlinSyntheticClass.Kind.LOCAL_TRAIT_IMPL
} }
public fun isKotlinJsMetaFile(file: VirtualFile): Boolean = file.getFileType() == KotlinJavaScriptMetaFileType public fun isKotlinJsMetaFile(file: VirtualFile): Boolean = file.getFileType() == KotlinJavaScriptMetaFileType