Annotations on type aliases: generate synthetic method for type alias annotations.

This commit is contained in:
Dmitry Petrov
2016-10-10 17:13:48 +03:00
parent d2d8f72ffc
commit 3d0288ffed
11 changed files with 144 additions and 31 deletions
@@ -120,8 +120,8 @@ public abstract class ClassBodyCodegen extends MemberCodegen<KtClassOrObject> {
}
protected void generateDeclaration(KtDeclaration declaration) {
if (declaration instanceof KtProperty || declaration instanceof KtNamedFunction) {
genFunctionOrProperty(declaration);
if (declaration instanceof KtProperty || declaration instanceof KtNamedFunction || declaration instanceof KtTypeAlias) {
genSimpleMember(declaration);
}
else if (declaration instanceof KtClassOrObject) {
if (declaration instanceof KtEnumEntry && !enumEntryNeedSubclass(bindingContext, (KtEnumEntry) declaration)) {
@@ -24,6 +24,7 @@ import kotlin.jvm.functions.Function1;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.backend.common.CodegenUtil;
import org.jetbrains.kotlin.codegen.annotation.AnnotatedSimple;
import org.jetbrains.kotlin.codegen.context.*;
import org.jetbrains.kotlin.codegen.inline.*;
import org.jetbrains.kotlin.codegen.serialization.JvmSerializerExtension;
@@ -56,10 +57,7 @@ import org.jetbrains.kotlin.storage.LockBasedStorageManager;
import org.jetbrains.kotlin.storage.NotNullLazyValue;
import org.jetbrains.kotlin.types.ErrorUtils;
import org.jetbrains.kotlin.types.KotlinType;
import org.jetbrains.org.objectweb.asm.AnnotationVisitor;
import org.jetbrains.org.objectweb.asm.Label;
import org.jetbrains.org.objectweb.asm.MethodVisitor;
import org.jetbrains.org.objectweb.asm.Type;
import org.jetbrains.org.objectweb.asm.*;
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
import org.jetbrains.org.objectweb.asm.commons.Method;
@@ -67,6 +65,7 @@ import java.util.*;
import static org.jetbrains.kotlin.codegen.AsmUtil.*;
import static org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.SYNTHESIZED;
import static org.jetbrains.kotlin.resolve.BindingContext.TYPE_ALIAS;
import static org.jetbrains.kotlin.resolve.BindingContext.VARIABLE;
import static org.jetbrains.kotlin.resolve.DescriptorUtils.*;
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.*;
@@ -182,10 +181,10 @@ public abstract class MemberCodegen<T extends KtElement/* TODO: & JetDeclaration
v.done();
}
public void genFunctionOrProperty(@NotNull KtDeclaration functionOrProperty) {
if (functionOrProperty instanceof KtNamedFunction) {
public void genSimpleMember(@NotNull KtDeclaration declaration) {
if (declaration instanceof KtNamedFunction) {
try {
functionCodegen.gen((KtNamedFunction) functionOrProperty);
functionCodegen.gen((KtNamedFunction) declaration);
}
catch (ProcessCanceledException e) {
throw e;
@@ -194,12 +193,12 @@ public abstract class MemberCodegen<T extends KtElement/* TODO: & JetDeclaration
throw e;
}
catch (Exception e) {
throw new CompilationException("Failed to generate function " + functionOrProperty.getName(), e, functionOrProperty);
throw new CompilationException("Failed to generate function " + declaration.getName(), e, declaration);
}
}
else if (functionOrProperty instanceof KtProperty) {
else if (declaration instanceof KtProperty) {
try {
propertyCodegen.gen((KtProperty) functionOrProperty);
propertyCodegen.gen((KtProperty) declaration);
}
catch (ProcessCanceledException e) {
throw e;
@@ -208,14 +207,46 @@ public abstract class MemberCodegen<T extends KtElement/* TODO: & JetDeclaration
throw e;
}
catch (Exception e) {
throw new CompilationException("Failed to generate property " + functionOrProperty.getName(), e, functionOrProperty);
throw new CompilationException("Failed to generate property " + declaration.getName(), e, declaration);
}
}
else if (declaration instanceof KtTypeAlias) {
genTypeAlias((KtTypeAlias) declaration);
}
else {
throw new IllegalArgumentException("Unknown parameter: " + functionOrProperty);
throw new IllegalArgumentException("Unknown parameter: " + declaration);
}
}
private void genTypeAlias(@NotNull KtTypeAlias typeAlias) {
if (!state.getClassBuilderMode().generateMetadata) return;
TypeAliasDescriptor typeAliasDescriptor = bindingContext.get(TYPE_ALIAS, typeAlias);
if (typeAliasDescriptor == null) {
throw ExceptionLogger.logDescriptorNotFound("Type alias " + typeAlias.getName() + " should have a descriptor", typeAlias);
}
genTypeAliasAnnotationsMethodIfRequired(typeAliasDescriptor);
}
private void genTypeAliasAnnotationsMethodIfRequired(TypeAliasDescriptor typeAliasDescriptor) {
boolean isAnnotationsMethodOwner = CodegenContextUtil.isImplClassOwner(context);
Annotations annotations = typeAliasDescriptor.getAnnotations();
if (!isAnnotationsMethodOwner || annotations.getAllAnnotations().isEmpty()) return;
int flags = ACC_DEPRECATED | ACC_PRIVATE | ACC_STATIC | ACC_SYNTHETIC;
String name = JvmAbi.getSyntheticMethodNameForAnnotatedTypeAlias(typeAliasDescriptor.getName());
String desc = "()V";
Method syntheticMethod = new Method(name, desc);
MethodVisitor mv = v.newMethod(JvmDeclarationOriginKt.OtherOrigin(typeAliasDescriptor), flags, syntheticMethod.getName(),
syntheticMethod.getDescriptor(), null, null);
AnnotationCodegen.forMethod(mv, this, typeMapper).genAnnotations(new AnnotatedSimple(annotations), Type.VOID_TYPE, null);
mv.visitCode();
mv.visitInsn(Opcodes.RETURN);
mv.visitEnd();
}
public static void genClassOrObject(
@NotNull CodegenContext parentContext,
@NotNull KtClassOrObject aClass,
@@ -24,10 +24,7 @@ import org.jetbrains.kotlin.codegen.context.FieldOwnerContext
import org.jetbrains.kotlin.codegen.context.MethodContext
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.config.IncrementalCompilation
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.diagnostics.DiagnosticUtils
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil
import org.jetbrains.kotlin.load.java.JvmAnnotationNames
@@ -104,7 +101,7 @@ class MultifileClassCodegen(
result
}
private val delegateGenerationTasks = hashMapOf<CallableMemberDescriptor, () -> Unit>()
private val delegateGenerationTasks = hashMapOf<MemberDescriptor, () -> Unit>()
private fun getSuperClassForPart(partInternalName: String) =
if (shouldGeneratePartHierarchy)
@@ -249,17 +246,17 @@ class MultifileClassCodegen(
val facadeContext = state.rootContext.intoMultifileClass(packageFragment, facadeClassType, partType)
val memberCodegen = createCodegenForDelegatesInMultifileFacade(facadeContext)
for (declaration in file.declarations) {
if (declaration is KtNamedFunction || declaration is KtProperty) {
if (declaration is KtNamedFunction || declaration is KtProperty || declaration is KtTypeAlias) {
val descriptor = state.bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, declaration)
if (descriptor !is CallableMemberDescriptor) {
if (descriptor !is MemberDescriptor) {
throw AssertionError("Expected callable member, was " + descriptor + " for " + declaration.text)
}
addDelegateGenerationTaskIfNeeded(descriptor, { memberCodegen.genFunctionOrProperty(declaration) })
addDelegateGenerationTaskIfNeeded(descriptor, { memberCodegen.genSimpleMember(declaration) })
}
}
}
private fun shouldGenerateInFacade(descriptor: CallableMemberDescriptor): Boolean {
private fun shouldGenerateInFacade(descriptor: MemberDescriptor): Boolean {
if (Visibilities.isPrivate(descriptor.visibility)) return false
if (AsmUtil.getVisibilityAccessFlag(descriptor) == Opcodes.ACC_PRIVATE) return false
@@ -272,7 +269,7 @@ class MultifileClassCodegen(
return true
}
private fun addDelegateGenerationTaskIfNeeded(callable: CallableMemberDescriptor, task: () -> Unit) {
private fun addDelegateGenerationTaskIfNeeded(callable: MemberDescriptor, task: () -> Unit) {
if (shouldGenerateInFacade(callable)) {
delegateGenerationTasks[callable] = task
}
@@ -29,6 +29,7 @@ import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader.MultifileClassK
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.KtNamedFunction
import org.jetbrains.kotlin.psi.KtProperty
import org.jetbrains.kotlin.psi.KtTypeAlias
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.jvm.diagnostics.MultifileClass
import org.jetbrains.kotlin.resolve.jvm.diagnostics.OtherOrigin
@@ -127,8 +128,8 @@ class MultifileClassPartCodegen(
override fun generateBody() {
for (declaration in element.declarations) {
if (declaration is KtNamedFunction || declaration is KtProperty) {
genFunctionOrProperty(declaration)
if (declaration is KtNamedFunction || declaration is KtProperty || declaration is KtTypeAlias) {
genSimpleMember(declaration)
}
}
@@ -91,8 +91,8 @@ public class PackagePartCodegen extends MemberCodegen<KtFile> {
@Override
protected void generateBody() {
for (KtDeclaration declaration : element.getDeclarations()) {
if (declaration instanceof KtNamedFunction || declaration instanceof KtProperty) {
genFunctionOrProperty(declaration);
if (declaration instanceof KtNamedFunction || declaration instanceof KtProperty || declaration instanceof KtTypeAlias) {
genSimpleMember(declaration);
}
}
@@ -224,8 +224,8 @@ public class ScriptCodegen extends MemberCodegen<KtScript> {
private void genMembers() {
for (KtDeclaration declaration : scriptDeclaration.getDeclarations()) {
if (declaration instanceof KtProperty || declaration instanceof KtNamedFunction) {
genFunctionOrProperty(declaration);
if (declaration instanceof KtProperty || declaration instanceof KtNamedFunction || declaration instanceof KtTypeAlias) {
genSimpleMember(declaration);
}
else if (declaration instanceof KtClassOrObject) {
genClassOrObject((KtClassOrObject) declaration);