Introduce KotlinSyntheticClass annotation
Will be used instead of KotlinPackagePart, KotlinTraitImpl and other hypothetical annotations we were planning to write on our synthesized classes (lambdas, local functions, etc.)
This commit is contained in:
@@ -37,7 +37,8 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static org.jetbrains.asm4.Opcodes.*;
|
||||
import static org.jetbrains.jet.codegen.AsmUtil.asmDescByFqNameWithoutInnerClasses;
|
||||
import static org.jetbrains.jet.codegen.AsmUtil.asmTypeByFqNameWithoutInnerClasses;
|
||||
import static org.jetbrains.jet.lang.resolve.java.JvmAnnotationNames.KOTLIN_SYNTHETIC_CLASS;
|
||||
|
||||
public class PackagePartCodegen extends MemberCodegen {
|
||||
|
||||
@@ -77,7 +78,7 @@ public class PackagePartCodegen extends MemberCodegen {
|
||||
);
|
||||
v.visitSource(jetFile.getName(), null);
|
||||
|
||||
writeKotlinPackagePartAnnotation();
|
||||
writeKotlinAnnotation();
|
||||
|
||||
for (JetDeclaration declaration : jetFile.getDeclarations()) {
|
||||
if (declaration instanceof JetNamedFunction || declaration instanceof JetProperty) {
|
||||
@@ -90,9 +91,11 @@ public class PackagePartCodegen extends MemberCodegen {
|
||||
v.done();
|
||||
}
|
||||
|
||||
private void writeKotlinPackagePartAnnotation() {
|
||||
AnnotationVisitor av = v.newAnnotation(asmDescByFqNameWithoutInnerClasses(JvmAnnotationNames.KOTLIN_PACKAGE_PART), true);
|
||||
private void writeKotlinAnnotation() {
|
||||
Type type = asmTypeByFqNameWithoutInnerClasses(KOTLIN_SYNTHETIC_CLASS);
|
||||
AnnotationVisitor av = v.newAnnotation(type.getDescriptor(), true);
|
||||
av.visit(JvmAnnotationNames.ABI_VERSION_FIELD_NAME, JvmAbi.VERSION);
|
||||
av.visitEnum("kind", "L" + type.getInternalName() + "$Kind;", "PACKAGE_PART");
|
||||
av.visitEnd();
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ package org.jetbrains.jet.codegen;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.asm4.AnnotationVisitor;
|
||||
import org.jetbrains.asm4.Type;
|
||||
import org.jetbrains.jet.codegen.context.ClassContext;
|
||||
import org.jetbrains.jet.codegen.state.GenerationState;
|
||||
import org.jetbrains.jet.lang.psi.JetClassOrObject;
|
||||
@@ -26,7 +27,8 @@ import org.jetbrains.jet.lang.resolve.java.JvmAbi;
|
||||
import org.jetbrains.jet.lang.resolve.java.JvmAnnotationNames;
|
||||
|
||||
import static org.jetbrains.asm4.Opcodes.*;
|
||||
import static org.jetbrains.jet.codegen.AsmUtil.asmDescByFqNameWithoutInnerClasses;
|
||||
import static org.jetbrains.jet.codegen.AsmUtil.asmTypeByFqNameWithoutInnerClasses;
|
||||
import static org.jetbrains.jet.lang.resolve.java.JvmAnnotationNames.KOTLIN_SYNTHETIC_CLASS;
|
||||
|
||||
public class TraitImplBodyCodegen extends ClassBodyCodegen {
|
||||
|
||||
@@ -54,9 +56,11 @@ public class TraitImplBodyCodegen extends ClassBodyCodegen {
|
||||
|
||||
@Override
|
||||
protected void generateKotlinAnnotation() {
|
||||
AnnotationVisitor av =
|
||||
v.getVisitor().visitAnnotation(asmDescByFqNameWithoutInnerClasses(JvmAnnotationNames.KOTLIN_TRAIT_IMPL), true);
|
||||
Type type = asmTypeByFqNameWithoutInnerClasses(KOTLIN_SYNTHETIC_CLASS);
|
||||
AnnotationVisitor av = v.getVisitor().visitAnnotation(type.getDescriptor(), true);
|
||||
if (av == null) return;
|
||||
av.visit(JvmAnnotationNames.ABI_VERSION_FIELD_NAME, JvmAbi.VERSION);
|
||||
av.visitEnum("kind", "L" + type.getInternalName() + "$Kind;", "TRAIT_IMPL");
|
||||
av.visitEnd();
|
||||
}
|
||||
}
|
||||
|
||||
+21
-17
@@ -20,14 +20,15 @@ import org.jetbrains.jet.ConfigurationKind;
|
||||
import org.jetbrains.jet.OutputFile;
|
||||
import org.jetbrains.jet.OutputFileCollection;
|
||||
import org.jetbrains.jet.lang.resolve.java.AbiVersionUtil;
|
||||
import org.jetbrains.jet.lang.resolve.java.JvmAnnotationNames;
|
||||
import org.jetbrains.jet.lang.resolve.java.JvmClassName;
|
||||
import org.jetbrains.jet.lang.resolve.java.PackageClassUtils;
|
||||
import org.jetbrains.jet.lang.resolve.name.FqName;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
|
||||
public class KotlinPackagePartAnnotationTest extends CodegenTestCase {
|
||||
import static org.jetbrains.jet.lang.resolve.java.JvmAnnotationNames.KOTLIN_SYNTHETIC_CLASS;
|
||||
|
||||
public class KotlinSyntheticClassAnnotationTest extends CodegenTestCase {
|
||||
public static final FqName PACKAGE_NAME = new FqName("test");
|
||||
|
||||
@Override
|
||||
@@ -36,35 +37,38 @@ public class KotlinPackagePartAnnotationTest extends CodegenTestCase {
|
||||
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY);
|
||||
}
|
||||
|
||||
public void testKotlinPackagePartAnnotationIsWritten() throws Exception {
|
||||
public void testAnnotationIsWrittenOnPackagePart() throws Exception {
|
||||
loadText("package " + PACKAGE_NAME + "\n\nfun foo() = 42\n");
|
||||
String facadeFileName = JvmClassName.byFqNameWithoutInnerClasses(PackageClassUtils.getPackageClassFqName(PACKAGE_NAME)).getInternalName() + ".class";
|
||||
|
||||
OutputFileCollection outputFiles = generateClassesInFile();
|
||||
for (OutputFile outputFile : outputFiles.asList()) {
|
||||
// The file which is not a facade is a package part
|
||||
String filePath = outputFile.getRelativePath();
|
||||
if (filePath.equals(facadeFileName)) continue;
|
||||
|
||||
if (!filePath.equals(facadeFileName)) {
|
||||
// The file which is not a facade is a package part
|
||||
String fqName = filePath.substring(0, filePath.length() - ".class".length()).replace('/', '.');
|
||||
Class<?> aClass = generateClass(fqName);
|
||||
String fqName = filePath.substring(0, filePath.length() - ".class".length()).replace('/', '.');
|
||||
Class<?> aClass = generateClass(fqName);
|
||||
|
||||
Class<? extends Annotation> annotationClass = loadAnnotationClassQuietly(JvmAnnotationNames.KOTLIN_PACKAGE_PART.asString());
|
||||
Class<? extends Annotation> annotationClass = loadAnnotationClassQuietly(KOTLIN_SYNTHETIC_CLASS.asString());
|
||||
assertTrue("No KotlinSyntheticClass annotation found on a package part", aClass.isAnnotationPresent(annotationClass));
|
||||
|
||||
assertTrue("No KotlinPackagePart annotation on a package part",
|
||||
aClass.isAnnotationPresent(annotationClass));
|
||||
Annotation annotation = aClass.getAnnotation(annotationClass);
|
||||
|
||||
Annotation kotlinPackagePart = aClass.getAnnotation(annotationClass);
|
||||
Integer version = (Integer) CodegenTestUtil.getAnnotationAttribute(annotation, "abiVersion");
|
||||
assertNotNull(version);
|
||||
assertTrue("KotlinSyntheticClass annotation is written with an unsupported format",
|
||||
AbiVersionUtil.isAbiVersionCompatible(version));
|
||||
|
||||
Integer version = (Integer) CodegenTestUtil.getAnnotationAttribute(kotlinPackagePart, "abiVersion");
|
||||
assertNotNull(version);
|
||||
assertTrue("KotlinPackagePart annotation is written with an unsupported format",
|
||||
AbiVersionUtil.isAbiVersionCompatible(version));
|
||||
Object kind = CodegenTestUtil.getAnnotationAttribute(annotation, "kind");
|
||||
assertNotNull(kind);
|
||||
assertEquals("KotlinSyntheticClass annotation has the wrong kind", "PACKAGE_PART", kind.toString());
|
||||
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
fail("No package part was found: " + outputFiles.asList());
|
||||
}
|
||||
|
||||
// TODO: test that annotation is written on TImpl
|
||||
}
|
||||
+1
-2
@@ -23,8 +23,7 @@ import org.jetbrains.jet.lang.resolve.name.Name;
|
||||
public final class JvmAnnotationNames {
|
||||
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_PACKAGE_PART = new FqName("kotlin.jvm.internal.KotlinPackagePart");
|
||||
public static final FqName KOTLIN_TRAIT_IMPL = new FqName("kotlin.jvm.internal.KotlinTraitImpl");
|
||||
public static final FqName KOTLIN_SYNTHETIC_CLASS = new FqName("kotlin.jvm.internal.KotlinSyntheticClass");
|
||||
|
||||
public static final FqName KOTLIN_SIGNATURE = new FqName("kotlin.jvm.KotlinSignature");
|
||||
public static final FqName OLD_KOTLIN_SIGNATURE = new FqName("jet.runtime.typeinfo.KotlinSignature");
|
||||
|
||||
+1
-1
@@ -44,7 +44,7 @@ public final class DescriptorResolverUtils {
|
||||
public static boolean isCompiledKotlinPackageClass(@NotNull JavaClass javaClass) {
|
||||
if (javaClass.getOriginKind() == JavaClass.OriginKind.COMPILED) {
|
||||
return javaClass.findAnnotation(JvmAnnotationNames.KOTLIN_PACKAGE) != null
|
||||
|| javaClass.findAnnotation(JvmAnnotationNames.KOTLIN_PACKAGE_PART) != null;
|
||||
|| javaClass.findAnnotation(JvmAnnotationNames.KOTLIN_SYNTHETIC_CLASS) != null;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
+1
-2
@@ -24,8 +24,7 @@ public class KotlinClassHeader {
|
||||
public enum Kind {
|
||||
CLASS,
|
||||
PACKAGE_FACADE,
|
||||
PACKAGE_PART,
|
||||
TRAIT_IMPL,
|
||||
SYNTHETIC_CLASS,
|
||||
INCOMPATIBLE_ABI_VERSION
|
||||
}
|
||||
|
||||
|
||||
+5
-6
@@ -39,8 +39,7 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor
|
||||
static {
|
||||
HEADER_KINDS.put(JvmClassName.byFqNameWithoutInnerClasses(KOTLIN_CLASS), CLASS);
|
||||
HEADER_KINDS.put(JvmClassName.byFqNameWithoutInnerClasses(KOTLIN_PACKAGE), PACKAGE_FACADE);
|
||||
HEADER_KINDS.put(JvmClassName.byFqNameWithoutInnerClasses(KOTLIN_PACKAGE_PART), PACKAGE_PART);
|
||||
HEADER_KINDS.put(JvmClassName.byFqNameWithoutInnerClasses(KOTLIN_TRAIT_IMPL), TRAIT_IMPL);
|
||||
HEADER_KINDS.put(JvmClassName.byFqNameWithoutInnerClasses(KOTLIN_SYNTHETIC_CLASS), SYNTHETIC_CLASS);
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
List<FqName> incompatible = Arrays.asList(OLD_JET_CLASS_ANNOTATION, OLD_JET_PACKAGE_CLASS_ANNOTATION, OLD_KOTLIN_CLASS,
|
||||
@@ -100,8 +99,8 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor
|
||||
if (newKind == CLASS || newKind == PACKAGE_FACADE) {
|
||||
return kotlinClassOrPackageVisitor(annotationClassName);
|
||||
}
|
||||
else if (newKind == PACKAGE_PART || newKind == TRAIT_IMPL) {
|
||||
return annotationWithAbiVersionVisitor(annotationClassName);
|
||||
else if (newKind == SYNTHETIC_CLASS) {
|
||||
return syntheticClassAnnotationVisitor(annotationClassName);
|
||||
}
|
||||
|
||||
return null;
|
||||
@@ -175,7 +174,7 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private AnnotationArgumentVisitor annotationWithAbiVersionVisitor(@NotNull final JvmClassName annotationClassName) {
|
||||
private AnnotationArgumentVisitor syntheticClassAnnotationVisitor(@NotNull final JvmClassName annotationClassName) {
|
||||
return new AnnotationArgumentVisitor() {
|
||||
@Override
|
||||
public void visit(@Nullable Name name, @Nullable Object value) {
|
||||
@@ -184,7 +183,7 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor
|
||||
|
||||
@Override
|
||||
public void visitEnum(@NotNull Name name, @NotNull JvmClassName enumClassName, @NotNull Name enumEntryName) {
|
||||
unexpectedArgument(name, annotationClassName);
|
||||
// TODO: save kind to somewhere
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
+8
-1
@@ -20,6 +20,13 @@ import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface KotlinPackagePart {
|
||||
public @interface KotlinSyntheticClass {
|
||||
int abiVersion();
|
||||
|
||||
Kind kind();
|
||||
|
||||
public static enum Kind {
|
||||
PACKAGE_PART,
|
||||
TRAIT_IMPL
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2014 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.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface KotlinTraitImpl {
|
||||
int abiVersion();
|
||||
}
|
||||
+1
-1
@@ -46,7 +46,7 @@ public class EmptyPackageFragmentClsStubBuilderFactory extends ClsStubBuilderFac
|
||||
if (file.getName().contains(PackageClassUtils.PACKAGE_CLASS_NAME_SUFFIX + "-") &&
|
||||
StdFileTypes.CLASS.getDefaultExtension().equals(file.getExtension())) {
|
||||
KotlinClassHeader header = new VirtualFileKotlinClass(LockBasedStorageManager.NO_LOCKS, file).getClassHeader();
|
||||
return header != null && header.getKind() == KotlinClassHeader.Kind.PACKAGE_PART;
|
||||
return header != null && header.getKind() == KotlinClassHeader.Kind.SYNTHETIC_CLASS;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user