Load class kind in KotlinSyntheticClass annotation

Fix some of the usages of KotlinSyntheticClass header where really package
parts were meant (they were committed by mistake).

DescriptorResolverUtils.isCompiledKotlinPackageClass no longer checks for class
being a compiled package part, because PSI classes are not built for package
parts (according to EmptyPackageFragmentClsStubBuilderFactory)
This commit is contained in:
Alexander Udalov
2014-03-03 20:59:56 +04:00
parent ea40389e34
commit eb5aba560e
10 changed files with 93 additions and 78 deletions
@@ -22,6 +22,7 @@ import com.intellij.openapi.util.Pair;
import com.intellij.psi.tree.IElementType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.asm4.AnnotationVisitor;
import org.jetbrains.asm4.Label;
import org.jetbrains.asm4.MethodVisitor;
import org.jetbrains.asm4.Type;
@@ -32,10 +33,7 @@ import org.jetbrains.jet.codegen.state.JetTypeMapper;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
import org.jetbrains.jet.lang.resolve.java.AsmTypeConstants;
import org.jetbrains.jet.lang.resolve.java.JavaVisibilities;
import org.jetbrains.jet.lang.resolve.java.JvmClassName;
import org.jetbrains.jet.lang.resolve.java.JvmPrimitiveType;
import org.jetbrains.jet.lang.resolve.java.*;
import org.jetbrains.jet.lang.resolve.java.descriptor.JavaCallableMemberDescriptor;
import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.types.JetType;
@@ -51,6 +49,8 @@ import static org.jetbrains.asm4.Opcodes.*;
import static org.jetbrains.jet.codegen.CodegenUtil.*;
import static org.jetbrains.jet.lang.resolve.DescriptorUtils.*;
import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.JAVA_STRING_TYPE;
import static org.jetbrains.jet.lang.resolve.java.JvmAnnotationNames.ABI_VERSION_FIELD_NAME;
import static org.jetbrains.jet.lang.resolve.java.JvmAnnotationNames.KotlinSyntheticClass;
import static org.jetbrains.jet.lang.resolve.java.mapping.PrimitiveTypesUtil.asmTypeForPrimitive;
public class AsmUtil {
@@ -664,6 +664,15 @@ public class AsmUtil {
}
}
public static void writeKotlinSyntheticClassAnnotation(@NotNull ClassBuilder v, @NotNull KotlinSyntheticClass.Kind kind) {
AnnotationVisitor av = v.newAnnotation(Type.getObjectType(KotlinSyntheticClass.INTERNAL_NAME).getDescriptor(), true);
av.visit(ABI_VERSION_FIELD_NAME, JvmAbi.VERSION);
av.visitEnum(KotlinSyntheticClass.KIND_FIELD_NAME.asString(),
Type.getObjectType(KotlinSyntheticClass.KIND_INTERNAL_NAME).getDescriptor(),
kind.toString());
av.visitEnd();
}
@NotNull
public static String asmDescByFqNameWithoutInnerClasses(@NotNull FqName fqName) {
return asmTypeByFqNameWithoutInnerClasses(fqName).getDescriptor();
@@ -19,7 +19,6 @@ package org.jetbrains.jet.codegen;
import com.google.common.collect.Lists;
import com.intellij.util.ArrayUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.asm4.AnnotationVisitor;
import org.jetbrains.asm4.MethodVisitor;
import org.jetbrains.asm4.Type;
import org.jetbrains.jet.codegen.context.FieldOwnerContext;
@@ -29,16 +28,14 @@ import org.jetbrains.jet.lang.descriptors.annotations.Annotations;
import org.jetbrains.jet.lang.descriptors.impl.SimpleFunctionDescriptorImpl;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.java.JvmAbi;
import org.jetbrains.jet.lang.resolve.java.JvmAnnotationNames;
import org.jetbrains.jet.lang.resolve.name.Name;
import java.util.Collections;
import java.util.List;
import static org.jetbrains.asm4.Opcodes.*;
import static org.jetbrains.jet.codegen.AsmUtil.asmTypeByFqNameWithoutInnerClasses;
import static org.jetbrains.jet.lang.resolve.java.JvmAnnotationNames.KOTLIN_SYNTHETIC_CLASS;
import static org.jetbrains.jet.codegen.AsmUtil.writeKotlinSyntheticClassAnnotation;
import static org.jetbrains.jet.lang.resolve.java.JvmAnnotationNames.KotlinSyntheticClass;
public class PackagePartCodegen extends MemberCodegen {
@@ -78,7 +75,7 @@ public class PackagePartCodegen extends MemberCodegen {
);
v.visitSource(jetFile.getName(), null);
writeKotlinAnnotation();
writeKotlinSyntheticClassAnnotation(v, KotlinSyntheticClass.Kind.PACKAGE_PART);
for (JetDeclaration declaration : jetFile.getDeclarations()) {
if (declaration instanceof JetNamedFunction || declaration instanceof JetProperty) {
@@ -91,15 +88,6 @@ public class PackagePartCodegen extends MemberCodegen {
v.done();
}
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();
}
private void generateStaticInitializers() {
List<JetProperty> properties = collectPropertiesToInitialize();
if (properties.isEmpty()) return;
@@ -18,17 +18,13 @@ 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;
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.asmTypeByFqNameWithoutInnerClasses;
import static org.jetbrains.jet.lang.resolve.java.JvmAnnotationNames.KOTLIN_SYNTHETIC_CLASS;
import static org.jetbrains.jet.codegen.AsmUtil.writeKotlinSyntheticClassAnnotation;
import static org.jetbrains.jet.lang.resolve.java.JvmAnnotationNames.KotlinSyntheticClass;
public class TraitImplBodyCodegen extends ClassBodyCodegen {
@@ -56,11 +52,6 @@ public class TraitImplBodyCodegen extends ClassBodyCodegen {
@Override
protected void generateKotlinAnnotation() {
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();
writeKotlinSyntheticClassAnnotation(v, KotlinSyntheticClass.Kind.TRAIT_IMPL);
}
}
@@ -26,7 +26,7 @@ import org.jetbrains.jet.lang.resolve.name.FqName;
import java.lang.annotation.Annotation;
import static org.jetbrains.jet.lang.resolve.java.JvmAnnotationNames.KOTLIN_SYNTHETIC_CLASS;
import static org.jetbrains.jet.lang.resolve.java.JvmAnnotationNames.KotlinSyntheticClass;
public class KotlinSyntheticClassAnnotationTest extends CodegenTestCase {
public static final FqName PACKAGE_NAME = new FqName("test");
@@ -50,7 +50,7 @@ public class KotlinSyntheticClassAnnotationTest extends CodegenTestCase {
String fqName = filePath.substring(0, filePath.length() - ".class".length()).replace('/', '.');
Class<?> aClass = generateClass(fqName);
Class<? extends Annotation> annotationClass = loadAnnotationClassQuietly(KOTLIN_SYNTHETIC_CLASS.asString());
Class<? extends Annotation> annotationClass = loadAnnotationClassQuietly(KotlinSyntheticClass.FQ_NAME.asString());
assertTrue("No KotlinSyntheticClass annotation found on a package part", aClass.isAnnotationPresent(annotationClass));
Annotation annotation = aClass.getAnnotation(annotationClass);
@@ -23,7 +23,6 @@ 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_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");
@@ -37,6 +36,26 @@ public final class JvmAnnotationNames {
public static final FqName JETBRAINS_MUTABLE_ANNOTATION = new FqName("org.jetbrains.annotations.Mutable");
public static final FqName JETBRAINS_READONLY_ANNOTATION = new FqName("org.jetbrains.annotations.ReadOnly");
public static class KotlinSyntheticClass {
public static final FqName FQ_NAME = new FqName("kotlin.jvm.internal.KotlinSyntheticClass");
public static final String INTERNAL_NAME = JvmClassName.byFqNameWithoutInnerClasses(FQ_NAME).getInternalName();
public static final String KIND_INTERNAL_NAME = "kotlin/jvm/internal/KotlinSyntheticClass$Kind";
public static final Name KIND_FIELD_NAME = Name.identifier("kind");
/**
* This enum duplicates {@link kotlin.jvm.internal.KotlinSyntheticClass.Kind}, because this code can't depend on "runtime.jvm".
* Both places should be updated simultaneously
*/
public enum Kind {
PACKAGE_PART,
TRAIT_IMPL
}
private KotlinSyntheticClass() {
}
}
@Deprecated
public static final FqName OLD_JET_CLASS_ANNOTATION = new FqName("jet.runtime.typeinfo.JetClass");
@Deprecated
@@ -42,7 +42,7 @@ public class LazyJavaPackageFragmentProvider(
}
else {
val jClass = c.findJavaClass(fqName)
if (jClass != null && DescriptorResolverUtils.isJavaClassVisibleAsPackage(jClass)) {
if (jClass != null && DescriptorResolverUtils.hasStaticMembers(jClass)) {
val correspondingClass = c.javaClassResolver.resolveClass(jClass)
if (correspondingClass != null) LazyPackageFragmentForJavaClass(c, _module, jClass) else null
}
@@ -21,7 +21,6 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.impl.TypeParameterDescriptorImpl;
import org.jetbrains.jet.lang.resolve.OverridingUtil;
import org.jetbrains.jet.lang.resolve.java.JvmAnnotationNames;
import org.jetbrains.jet.lang.resolve.java.sam.SingleAbstractMethodUtils;
import org.jetbrains.jet.lang.resolve.java.structure.*;
import org.jetbrains.jet.lang.resolve.name.FqName;
@@ -35,6 +34,9 @@ import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
import java.util.*;
import static org.jetbrains.jet.lang.resolve.java.JvmAnnotationNames.KOTLIN_CLASS;
import static org.jetbrains.jet.lang.resolve.java.JvmAnnotationNames.KOTLIN_PACKAGE;
public final class DescriptorResolverUtils {
public static final FqName OBJECT_FQ_NAME = new FqName("java.lang.Object");
@@ -42,22 +44,11 @@ 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_SYNTHETIC_CLASS) != null;
}
return false;
return javaClass.getOriginKind() == JavaClass.OriginKind.COMPILED && javaClass.findAnnotation(KOTLIN_PACKAGE) != null;
}
public static boolean isCompiledKotlinClass(@NotNull JavaClass javaClass) {
if (javaClass.getOriginKind() == JavaClass.OriginKind.COMPILED) {
return javaClass.findAnnotation(JvmAnnotationNames.KOTLIN_CLASS) != null;
}
return false;
}
private static boolean isCompiledKotlinClassOrPackageClass(@NotNull JavaClass javaClass) {
return isCompiledKotlinClass(javaClass) || isCompiledKotlinPackageClass(javaClass);
return javaClass.getOriginKind() == JavaClass.OriginKind.COMPILED && javaClass.findAnnotation(KOTLIN_CLASS) != null;
}
@NotNull
@@ -262,11 +253,7 @@ public final class DescriptorResolverUtils {
return TypeSubstitutor.create(typeSubstitutionContext);
}
public static boolean isJavaClassVisibleAsPackage(@NotNull JavaClass javaClass) {
return !isCompiledKotlinClassOrPackageClass(javaClass) && hasStaticMembers(javaClass);
}
private static boolean hasStaticMembers(@NotNull JavaClass javaClass) {
public static boolean hasStaticMembers(@NotNull JavaClass javaClass) {
for (JavaMethod method : javaClass.getMethods()) {
if (method.isStatic() && !shouldBeInEnumClassObject(method)) {
return true;
@@ -24,7 +24,8 @@ public class KotlinClassHeader {
public enum Kind {
CLASS,
PACKAGE_FACADE,
SYNTHETIC_CLASS,
PACKAGE_PART,
TRAIT_IMPL,
INCOMPATIBLE_ABI_VERSION
}
@@ -19,7 +19,6 @@ package org.jetbrains.jet.lang.resolve.kotlin.header;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
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.kotlin.KotlinJvmBinaryClass;
import org.jetbrains.jet.lang.resolve.name.FqName;
@@ -34,18 +33,21 @@ import static org.jetbrains.jet.lang.resolve.kotlin.KotlinJvmBinaryClass.Annotat
import static org.jetbrains.jet.lang.resolve.kotlin.header.KotlinClassHeader.Kind.*;
public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor {
private static final JvmClassName KOTLIN_CLASS_ANNOTATION = JvmClassName.byFqNameWithoutInnerClasses(KOTLIN_CLASS);
private static final JvmClassName KOTLIN_PACKAGE_ANNOTATION = JvmClassName.byFqNameWithoutInnerClasses(KOTLIN_PACKAGE);
private static final JvmClassName KOTLIN_SYNTHETIC_CLASS_ANNOTATION = JvmClassName.byInternalName(KotlinSyntheticClass.INTERNAL_NAME);
private static final Set<JvmClassName> ALL_SUPPORTED_ANNOTATIONS = new HashSet<JvmClassName>();
private static final Map<JvmClassName, KotlinClassHeader.Kind> HEADER_KINDS = new HashMap<JvmClassName, KotlinClassHeader.Kind>();
static {
HEADER_KINDS.put(JvmClassName.byFqNameWithoutInnerClasses(KOTLIN_CLASS), CLASS);
HEADER_KINDS.put(JvmClassName.byFqNameWithoutInnerClasses(KOTLIN_PACKAGE), PACKAGE_FACADE);
HEADER_KINDS.put(JvmClassName.byFqNameWithoutInnerClasses(KOTLIN_SYNTHETIC_CLASS), SYNTHETIC_CLASS);
ALL_SUPPORTED_ANNOTATIONS.add(KOTLIN_CLASS_ANNOTATION);
ALL_SUPPORTED_ANNOTATIONS.add(KOTLIN_PACKAGE_ANNOTATION);
ALL_SUPPORTED_ANNOTATIONS.add(KOTLIN_SYNTHETIC_CLASS_ANNOTATION);
@SuppressWarnings("deprecation")
List<FqName> incompatible = Arrays.asList(OLD_JET_CLASS_ANNOTATION, OLD_JET_PACKAGE_CLASS_ANNOTATION, OLD_KOTLIN_CLASS,
OLD_KOTLIN_PACKAGE, OLD_KOTLIN_PACKAGE_FRAGMENT, OLD_KOTLIN_TRAIT_IMPL);
for (FqName fqName : incompatible) {
HEADER_KINDS.put(JvmClassName.byFqNameWithoutInnerClasses(fqName), INCOMPATIBLE_ABI_VERSION);
ALL_SUPPORTED_ANNOTATIONS.add(JvmClassName.byFqNameWithoutInnerClasses(fqName));
}
}
@@ -85,22 +87,23 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor
@Nullable
@Override
public AnnotationArgumentVisitor visitAnnotation(@NotNull JvmClassName annotationClassName) {
KotlinClassHeader.Kind newKind = HEADER_KINDS.get(annotationClassName);
if (newKind == null) return null;
public AnnotationArgumentVisitor visitAnnotation(@NotNull JvmClassName annotation) {
if (!ALL_SUPPORTED_ANNOTATIONS.contains(annotation)) return null;
if (this.headerKind != null) {
if (headerKind != null) {
// Ignore all Kotlin annotations except the first found
return null;
}
headerKind = newKind;
if (newKind == CLASS || newKind == PACKAGE_FACADE) {
return kotlinClassOrPackageVisitor(annotationClassName);
if (annotation.equals(KOTLIN_CLASS_ANNOTATION) || annotation.equals(KOTLIN_PACKAGE_ANNOTATION)) {
headerKind = annotation.equals(KOTLIN_CLASS_ANNOTATION) ? CLASS : PACKAGE_FACADE;
return kotlinClassOrPackageVisitor(annotation);
}
else if (newKind == SYNTHETIC_CLASS) {
return syntheticClassAnnotationVisitor(annotationClassName);
else if (annotation.equals(KOTLIN_SYNTHETIC_CLASS_ANNOTATION)) {
return syntheticClassAnnotationVisitor();
}
else {
headerKind = INCOMPATIBLE_ABI_VERSION;
}
return null;
@@ -126,7 +129,7 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor
@Override
@Nullable
public AnnotationArgumentVisitor visitArray(@NotNull Name name) {
if (name.asString().equals(JvmAnnotationNames.DATA_FIELD_NAME)) {
if (name.asString().equals(DATA_FIELD_NAME)) {
return stringArrayVisitor();
}
else if (isAbiVersionCompatible(version)) {
@@ -174,22 +177,39 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor
}
@NotNull
private AnnotationArgumentVisitor syntheticClassAnnotationVisitor(@NotNull final JvmClassName annotationClassName) {
private AnnotationArgumentVisitor syntheticClassAnnotationVisitor() {
return new AnnotationArgumentVisitor() {
@Override
public void visit(@Nullable Name name, @Nullable Object value) {
visitIntValueForSupportedAnnotation(name, value, annotationClassName);
visitIntValueForSupportedAnnotation(name, value, KOTLIN_SYNTHETIC_CLASS_ANNOTATION);
}
@Override
public void visitEnum(@NotNull Name name, @NotNull JvmClassName enumClassName, @NotNull Name enumEntryName) {
// TODO: save kind to somewhere
if (enumClassName.getInternalName().equals(KotlinSyntheticClass.KIND_INTERNAL_NAME) &&
name.equals(KotlinSyntheticClass.KIND_FIELD_NAME)) {
String value = enumEntryName.asString();
// Don't call KotlinSyntheticClass.Kind.valueOf() here, because it will throw an 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
if (value.equals(KotlinSyntheticClass.Kind.PACKAGE_PART.toString())) {
headerKind = PACKAGE_PART;
return;
}
else if (value.equals(KotlinSyntheticClass.Kind.TRAIT_IMPL.toString())) {
headerKind = TRAIT_IMPL;
return;
}
}
if (isAbiVersionCompatible(version)) {
throw new IllegalStateException("Unexpected enum entry for synthetic class annotation: " +
name + "=" + enumClassName + "." + enumEntryName);
}
}
@Nullable
@Override
public AnnotationArgumentVisitor visitArray(@NotNull Name name) {
return unexpectedArgument(name, annotationClassName);
return unexpectedArgument(name, KOTLIN_SYNTHETIC_CLASS_ANNOTATION);
}
@Override
@@ -199,7 +219,7 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor
}
private void visitIntValueForSupportedAnnotation(@Nullable Name name, @Nullable Object value, @NotNull JvmClassName className) {
if (name != null && name.asString().equals(JvmAnnotationNames.ABI_VERSION_FIELD_NAME)) {
if (name != null && name.asString().equals(ABI_VERSION_FIELD_NAME)) {
version = value == null ? AbiVersionUtil.INVALID_VERSION : (Integer) value;
}
else {
@@ -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.SYNTHETIC_CLASS;
return header != null && header.getKind() == KotlinClassHeader.Kind.PACKAGE_PART;
}
return false;
}