Initial annotation support
This commit is contained in:
committed by
Dmitry Petrov
parent
0bc3cc5e20
commit
4b6ddc4a9d
@@ -67,11 +67,11 @@ public abstract class AnnotationCodegen {
|
||||
|
||||
private static final AnnotationVisitor NO_ANNOTATION_VISITOR = new AnnotationVisitor(Opcodes.ASM5) {};
|
||||
|
||||
private final MemberCodegen<?> memberCodegen;
|
||||
private final InnerClassConsumer innerClassConsumer;
|
||||
private final KotlinTypeMapper typeMapper;
|
||||
|
||||
private AnnotationCodegen(@NotNull MemberCodegen<?> memberCodegen, @NotNull KotlinTypeMapper mapper) {
|
||||
this.memberCodegen = memberCodegen;
|
||||
private AnnotationCodegen(@NotNull InnerClassConsumer innerClassConsumer, @NotNull KotlinTypeMapper mapper) {
|
||||
this.innerClassConsumer = innerClassConsumer;
|
||||
this.typeMapper = mapper;
|
||||
}
|
||||
|
||||
@@ -288,7 +288,7 @@ public abstract class AnnotationCodegen {
|
||||
String descriptor = typeMapper.mapType(annotationDescriptor.getType()).getDescriptor();
|
||||
|
||||
if (classifierDescriptor instanceof ClassDescriptor) {
|
||||
memberCodegen.addInnerClassInfoFromAnnotation(((ClassDescriptor) classifierDescriptor));
|
||||
innerClassConsumer.addInnerClassInfoFromAnnotation(((ClassDescriptor) classifierDescriptor));
|
||||
}
|
||||
|
||||
AnnotationVisitor annotationVisitor = visitAnnotation(descriptor, rp == RetentionPolicy.RUNTIME);
|
||||
@@ -486,10 +486,10 @@ public abstract class AnnotationCodegen {
|
||||
|
||||
public static AnnotationCodegen forClass(
|
||||
final @NotNull ClassVisitor cv,
|
||||
@NotNull MemberCodegen<?> memberCodegen,
|
||||
@NotNull InnerClassConsumer innerClassConsumer,
|
||||
@NotNull KotlinTypeMapper mapper
|
||||
) {
|
||||
return new AnnotationCodegen(memberCodegen, mapper) {
|
||||
return new AnnotationCodegen(innerClassConsumer, mapper) {
|
||||
@NotNull
|
||||
@Override
|
||||
AnnotationVisitor visitAnnotation(String descr, boolean visible) {
|
||||
@@ -500,10 +500,10 @@ public abstract class AnnotationCodegen {
|
||||
|
||||
public static AnnotationCodegen forMethod(
|
||||
final @NotNull MethodVisitor mv,
|
||||
@NotNull MemberCodegen<?> memberCodegen,
|
||||
@NotNull InnerClassConsumer innerClassConsumer,
|
||||
@NotNull KotlinTypeMapper mapper
|
||||
) {
|
||||
return new AnnotationCodegen(memberCodegen, mapper) {
|
||||
return new AnnotationCodegen(innerClassConsumer, mapper) {
|
||||
@NotNull
|
||||
@Override
|
||||
AnnotationVisitor visitAnnotation(String descr, boolean visible) {
|
||||
@@ -514,10 +514,10 @@ public abstract class AnnotationCodegen {
|
||||
|
||||
public static AnnotationCodegen forField(
|
||||
final @NotNull FieldVisitor fv,
|
||||
@NotNull MemberCodegen<?> memberCodegen,
|
||||
@NotNull InnerClassConsumer innerClassConsumer,
|
||||
@NotNull KotlinTypeMapper mapper
|
||||
) {
|
||||
return new AnnotationCodegen(memberCodegen, mapper) {
|
||||
return new AnnotationCodegen(innerClassConsumer, mapper) {
|
||||
@NotNull
|
||||
@Override
|
||||
AnnotationVisitor visitAnnotation(String descr, boolean visible) {
|
||||
@@ -529,10 +529,10 @@ public abstract class AnnotationCodegen {
|
||||
public static AnnotationCodegen forParameter(
|
||||
final int parameter,
|
||||
final @NotNull MethodVisitor mv,
|
||||
@NotNull MemberCodegen<?> memberCodegen,
|
||||
@NotNull InnerClassConsumer innerClassConsumer,
|
||||
@NotNull KotlinTypeMapper mapper
|
||||
) {
|
||||
return new AnnotationCodegen(memberCodegen, mapper) {
|
||||
return new AnnotationCodegen(innerClassConsumer, mapper) {
|
||||
@NotNull
|
||||
@Override
|
||||
AnnotationVisitor visitAnnotation(String descr, boolean visible) {
|
||||
@@ -543,10 +543,10 @@ public abstract class AnnotationCodegen {
|
||||
|
||||
public static AnnotationCodegen forAnnotationDefaultValue(
|
||||
final @NotNull MethodVisitor mv,
|
||||
@NotNull MemberCodegen<?> memberCodegen,
|
||||
@NotNull InnerClassConsumer innerClassConsumer,
|
||||
@NotNull KotlinTypeMapper mapper
|
||||
) {
|
||||
return new AnnotationCodegen(memberCodegen, mapper) {
|
||||
return new AnnotationCodegen(innerClassConsumer, mapper) {
|
||||
@NotNull
|
||||
@Override
|
||||
AnnotationVisitor visitAnnotation(String descr, boolean visible) {
|
||||
|
||||
@@ -272,7 +272,17 @@ public class FunctionCodegen {
|
||||
Method asmMethod,
|
||||
MethodVisitor mv
|
||||
) {
|
||||
AnnotationCodegen annotationCodegen = AnnotationCodegen.forMethod(mv, memberCodegen, typeMapper);
|
||||
generateMethodAnnotations(functionDescriptor, asmMethod, mv, memberCodegen, typeMapper);
|
||||
}
|
||||
|
||||
public static void generateMethodAnnotations(
|
||||
@NotNull FunctionDescriptor functionDescriptor,
|
||||
Method asmMethod,
|
||||
MethodVisitor mv,
|
||||
@NotNull InnerClassConsumer consumer,
|
||||
@NotNull KotlinTypeMapper typeMapper
|
||||
) {
|
||||
AnnotationCodegen annotationCodegen = AnnotationCodegen.forMethod(mv, consumer, typeMapper);
|
||||
|
||||
if (functionDescriptor instanceof PropertyAccessorDescriptor) {
|
||||
AnnotationUseSiteTarget target = functionDescriptor instanceof PropertySetterDescriptor ? PROPERTY_SETTER : PROPERTY_GETTER;
|
||||
@@ -288,6 +298,17 @@ public class FunctionCodegen {
|
||||
@NotNull MethodVisitor mv,
|
||||
@NotNull JvmMethodSignature jvmSignature
|
||||
) {
|
||||
generateParameterAnnotations(functionDescriptor, mv, jvmSignature, memberCodegen, state);
|
||||
}
|
||||
|
||||
public static void generateParameterAnnotations(
|
||||
@NotNull FunctionDescriptor functionDescriptor,
|
||||
@NotNull MethodVisitor mv,
|
||||
@NotNull JvmMethodSignature jvmSignature,
|
||||
@NotNull InnerClassConsumer innerClassConsumer,
|
||||
@NotNull GenerationState state
|
||||
) {
|
||||
KotlinTypeMapper typeMapper = state.getTypeMapper();
|
||||
Iterator<ValueParameterDescriptor> iterator = functionDescriptor.getValueParameters().iterator();
|
||||
List<JvmMethodParameterSignature> kotlinParameterTypes = jvmSignature.getValueParameters();
|
||||
|
||||
@@ -295,13 +316,13 @@ public class FunctionCodegen {
|
||||
JvmMethodParameterSignature parameterSignature = kotlinParameterTypes.get(i);
|
||||
JvmMethodParameterKind kind = parameterSignature.getKind();
|
||||
if (kind.isSkippedInGenericSignature()) {
|
||||
markEnumOrInnerConstructorParameterAsSynthetic(mv, i);
|
||||
markEnumOrInnerConstructorParameterAsSynthetic(mv, i, state.getClassBuilderMode());
|
||||
continue;
|
||||
}
|
||||
|
||||
if (kind == JvmMethodParameterKind.VALUE) {
|
||||
ValueParameterDescriptor parameter = iterator.next();
|
||||
AnnotationCodegen annotationCodegen = AnnotationCodegen.forParameter(i, mv, memberCodegen, typeMapper);
|
||||
AnnotationCodegen annotationCodegen = AnnotationCodegen.forParameter(i, mv, innerClassConsumer, typeMapper);
|
||||
|
||||
if (functionDescriptor instanceof PropertySetterDescriptor) {
|
||||
PropertyDescriptor propertyDescriptor = ((PropertySetterDescriptor) functionDescriptor).getCorrespondingProperty();
|
||||
@@ -320,7 +341,7 @@ public class FunctionCodegen {
|
||||
ReceiverParameterDescriptor receiver = JvmCodegenUtil.getDirectMember(functionDescriptor).getExtensionReceiverParameter();
|
||||
|
||||
if (receiver != null) {
|
||||
AnnotationCodegen annotationCodegen = AnnotationCodegen.forParameter(i, mv, memberCodegen, typeMapper);
|
||||
AnnotationCodegen annotationCodegen = AnnotationCodegen.forParameter(i, mv, innerClassConsumer, typeMapper);
|
||||
Annotated targetedAnnotations = new AnnotatedWithOnlyTargetedAnnotations(receiver.getType());
|
||||
annotationCodegen.genAnnotations(targetedAnnotations, parameterSignature.getAsmType(), RECEIVER);
|
||||
|
||||
@@ -330,9 +351,9 @@ public class FunctionCodegen {
|
||||
}
|
||||
}
|
||||
|
||||
private void markEnumOrInnerConstructorParameterAsSynthetic(MethodVisitor mv, int i) {
|
||||
private static void markEnumOrInnerConstructorParameterAsSynthetic(MethodVisitor mv, int i, ClassBuilderMode mode) {
|
||||
// IDEA's ClsPsi builder fails to annotate synthetic parameters
|
||||
if (state.getClassBuilderMode() == ClassBuilderMode.LIGHT_CLASSES) return;
|
||||
if (mode == ClassBuilderMode.LIGHT_CLASSES) return;
|
||||
|
||||
// This is needed to avoid RuntimeInvisibleParameterAnnotations error in javac:
|
||||
// see MethodWriter.visitParameterAnnotation()
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright 2010-2016 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 org.jetbrains.kotlin.codegen
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
|
||||
interface InnerClassConsumer {
|
||||
fun addInnerClassInfoFromAnnotation(classDescriptor: ClassDescriptor)
|
||||
}
|
||||
@@ -73,7 +73,7 @@ import static org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin.
|
||||
import static org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKt.Synthetic;
|
||||
import static org.jetbrains.org.objectweb.asm.Opcodes.*;
|
||||
|
||||
public abstract class MemberCodegen<T extends KtElement/* TODO: & JetDeclarationContainer*/> {
|
||||
public abstract class MemberCodegen<T extends KtElement/* TODO: & JetDeclarationContainer*/> implements InnerClassConsumer {
|
||||
protected final GenerationState state;
|
||||
protected final T element;
|
||||
protected final FieldOwnerContext context;
|
||||
@@ -304,6 +304,7 @@ public abstract class MemberCodegen<T extends KtElement/* TODO: & JetDeclaration
|
||||
|
||||
// It's necessary for proper recovering of classId by plain string JVM descriptor when loading annotations
|
||||
// See FileBasedKotlinClass.convertAnnotationVisitor
|
||||
@Override
|
||||
public void addInnerClassInfoFromAnnotation(@NotNull ClassDescriptor classDescriptor) {
|
||||
DeclarationDescriptor current = classDescriptor;
|
||||
while (current != null && !isTopLevelDeclaration(current)) {
|
||||
|
||||
Reference in New Issue
Block a user