001 /*
002 * Copyright 2010-2016 JetBrains s.r.o.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017 package org.jetbrains.kotlin.codegen;
018
019 import org.jetbrains.annotations.NotNull;
020 import org.jetbrains.annotations.Nullable;
021 import org.jetbrains.kotlin.codegen.annotation.WrappedAnnotated;
022 import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
023 import org.jetbrains.kotlin.descriptors.*;
024 import org.jetbrains.kotlin.descriptors.annotations.*;
025 import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor;
026 import org.jetbrains.kotlin.load.java.JvmAnnotationNames;
027 import org.jetbrains.kotlin.name.FqName;
028 import org.jetbrains.kotlin.resolve.AnnotationChecker;
029 import org.jetbrains.kotlin.resolve.constants.*;
030 import org.jetbrains.kotlin.resolve.constants.StringValue;
031 import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
032 import org.jetbrains.kotlin.types.*;
033 import org.jetbrains.org.objectweb.asm.*;
034
035 import java.lang.annotation.*;
036 import java.util.*;
037
038 public abstract class AnnotationCodegen {
039
040 public static final class JvmFlagAnnotation {
041 private final FqName fqName;
042 private final int jvmFlag;
043
044 public JvmFlagAnnotation(@NotNull String fqName, int jvmFlag) {
045 this.fqName = new FqName(fqName);
046 this.jvmFlag = jvmFlag;
047 }
048
049 public boolean hasAnnotation(@NotNull Annotated annotated) {
050 return Annotations.Companion.findAnyAnnotation(annotated.getAnnotations(), fqName) != null;
051 }
052
053 public int getJvmFlag() {
054 return jvmFlag;
055 }
056 }
057
058 public static final List<JvmFlagAnnotation> FIELD_FLAGS = Arrays.asList(
059 new JvmFlagAnnotation("kotlin.jvm.Volatile", Opcodes.ACC_VOLATILE),
060 new JvmFlagAnnotation("kotlin.jvm.Transient", Opcodes.ACC_TRANSIENT)
061 );
062
063 public static final List<JvmFlagAnnotation> METHOD_FLAGS = Arrays.asList(
064 new JvmFlagAnnotation("kotlin.jvm.Strictfp", Opcodes.ACC_STRICT),
065 new JvmFlagAnnotation("kotlin.jvm.Synchronized", Opcodes.ACC_SYNCHRONIZED)
066 );
067
068 private static final AnnotationVisitor NO_ANNOTATION_VISITOR = new AnnotationVisitor(Opcodes.ASM5) {};
069
070 private final InnerClassConsumer innerClassConsumer;
071 private final KotlinTypeMapper typeMapper;
072
073 private AnnotationCodegen(@NotNull InnerClassConsumer innerClassConsumer, @NotNull KotlinTypeMapper mapper) {
074 this.innerClassConsumer = innerClassConsumer;
075 this.typeMapper = mapper;
076 }
077
078 /**
079 * @param returnType can be null if not applicable (e.g. {@code annotated} is a class)
080 */
081 public void genAnnotations(@Nullable Annotated annotated, @Nullable Type returnType) {
082 genAnnotations(annotated, returnType, null);
083 }
084
085 public void genAnnotations(@Nullable Annotated annotated, @Nullable Type returnType, @Nullable AnnotationUseSiteTarget allowedTarget) {
086 if (annotated == null) {
087 return;
088 }
089
090 Set<String> annotationDescriptorsAlreadyPresent = new HashSet<String>();
091
092 Annotations annotations = annotated.getAnnotations();
093
094 for (AnnotationWithTarget annotationWithTarget : annotations.getAllAnnotations()) {
095 AnnotationDescriptor annotation = annotationWithTarget.getAnnotation();
096 AnnotationUseSiteTarget annotationTarget = annotationWithTarget.getTarget();
097
098 // Skip targeted annotations by default
099 if (allowedTarget == null && annotationTarget != null) continue;
100
101 // Skip if the target is not the same
102 if (allowedTarget != null && annotationTarget != null && allowedTarget != annotationTarget) continue;
103
104 Set<KotlinTarget> applicableTargets = AnnotationChecker.applicableTargetSet(annotation);
105 if (annotated instanceof AnonymousFunctionDescriptor
106 && !applicableTargets.contains(KotlinTarget.FUNCTION)
107 && !applicableTargets.contains(KotlinTarget.PROPERTY_GETTER)
108 && !applicableTargets.contains(KotlinTarget.PROPERTY_SETTER)) {
109 assert (applicableTargets.contains(KotlinTarget.EXPRESSION)) :
110 "Inconsistent target list for lambda annotation: " + applicableTargets + " on " + annotated;
111 continue;
112 }
113 if (annotated instanceof ClassDescriptor
114 && !applicableTargets.contains(KotlinTarget.CLASS)
115 && !applicableTargets.contains(KotlinTarget.ANNOTATION_CLASS)) {
116 ClassDescriptor classDescriptor = (ClassDescriptor) annotated;
117 if (classDescriptor.getVisibility() == Visibilities.LOCAL) {
118 assert applicableTargets.contains(KotlinTarget.EXPRESSION) :
119 "Inconsistent target list for object literal annotation: " + applicableTargets + " on " + annotated;
120 continue;
121 }
122 }
123
124 String descriptor = genAnnotation(annotation);
125 if (descriptor != null) {
126 annotationDescriptorsAlreadyPresent.add(descriptor);
127 }
128 }
129
130 generateAdditionalAnnotations(annotated, returnType, annotationDescriptorsAlreadyPresent);
131 }
132
133 private void generateAdditionalAnnotations(
134 @NotNull Annotated annotated,
135 @Nullable Type returnType,
136 @NotNull Set<String> annotationDescriptorsAlreadyPresent
137 ) {
138 Annotated unwrapped = annotated;
139 if (annotated instanceof WrappedAnnotated) {
140 unwrapped = ((WrappedAnnotated) annotated).getOriginalAnnotated();
141 }
142
143 if (unwrapped instanceof CallableDescriptor) {
144 CallableDescriptor descriptor = (CallableDescriptor) unwrapped;
145
146 // No need to annotate privates, synthetic accessors and their parameters
147 if (isInvisibleFromTheOutside(descriptor)) return;
148 if (descriptor instanceof ValueParameterDescriptor && isInvisibleFromTheOutside(descriptor.getContainingDeclaration())) return;
149
150 if (returnType != null && !AsmUtil.isPrimitive(returnType)) {
151 generateNullabilityAnnotation(descriptor.getReturnType(), annotationDescriptorsAlreadyPresent);
152 }
153 }
154 if (unwrapped instanceof ClassDescriptor) {
155 ClassDescriptor classDescriptor = (ClassDescriptor) unwrapped;
156 if (classDescriptor.getKind() == ClassKind.ANNOTATION_CLASS) {
157 generateDocumentedAnnotation(classDescriptor, annotationDescriptorsAlreadyPresent);
158 generateRetentionAnnotation(classDescriptor, annotationDescriptorsAlreadyPresent);
159 generateTargetAnnotation(classDescriptor, annotationDescriptorsAlreadyPresent);
160 }
161 }
162 }
163
164 private static boolean isInvisibleFromTheOutside(@Nullable DeclarationDescriptor descriptor) {
165 if (descriptor instanceof CallableMemberDescriptor && KotlinTypeMapper.isAccessor((CallableMemberDescriptor) descriptor)) return false;
166 if (descriptor instanceof MemberDescriptor) {
167 return AsmUtil.getVisibilityAccessFlag((MemberDescriptor) descriptor) == Opcodes.ACC_PRIVATE;
168 }
169 return false;
170 }
171
172 private void generateNullabilityAnnotation(@Nullable KotlinType type, @NotNull Set<String> annotationDescriptorsAlreadyPresent) {
173 if (type == null) return;
174
175 if (isBareTypeParameterWithNullableUpperBound(type)) {
176 // This is to account for the case of, say
177 // class Function<R> { fun invoke(): R }
178 // it would be a shame to put @Nullable on the return type of the function, and force all callers to check for null,
179 // so we put no annotations
180 return;
181 }
182
183 if (FlexibleTypesKt.isFlexible(type)) {
184 // A flexible type whose lower bound in not-null and upper bound is nullable, should not be annotated
185 FlexibleType flexibleType = FlexibleTypesKt.asFlexibleType(type);
186
187 if (!TypeUtils.isNullableType(flexibleType.getLowerBound()) && TypeUtils.isNullableType(flexibleType.getUpperBound())) {
188 AnnotationDescriptor notNull = type.getAnnotations().findAnnotation(JvmAnnotationNames.JETBRAINS_NOT_NULL_ANNOTATION);
189 if (notNull != null) {
190 generateAnnotationIfNotPresent(annotationDescriptorsAlreadyPresent, NotNull.class);
191 }
192 return;
193 }
194 }
195
196 boolean isNullableType = TypeUtils.isNullableType(type);
197
198 Class<?> annotationClass = isNullableType ? Nullable.class : NotNull.class;
199
200 generateAnnotationIfNotPresent(annotationDescriptorsAlreadyPresent, annotationClass);
201 }
202
203 private static final Map<KotlinTarget, ElementType> annotationTargetMap =
204 new EnumMap<KotlinTarget, ElementType>(KotlinTarget.class);
205
206 static {
207 annotationTargetMap.put(KotlinTarget.CLASS, ElementType.TYPE);
208 annotationTargetMap.put(KotlinTarget.ANNOTATION_CLASS, ElementType.ANNOTATION_TYPE);
209 annotationTargetMap.put(KotlinTarget.CONSTRUCTOR, ElementType.CONSTRUCTOR);
210 annotationTargetMap.put(KotlinTarget.LOCAL_VARIABLE, ElementType.LOCAL_VARIABLE);
211 annotationTargetMap.put(KotlinTarget.FUNCTION, ElementType.METHOD);
212 annotationTargetMap.put(KotlinTarget.PROPERTY_GETTER, ElementType.METHOD);
213 annotationTargetMap.put(KotlinTarget.PROPERTY_SETTER, ElementType.METHOD);
214 annotationTargetMap.put(KotlinTarget.FIELD, ElementType.FIELD);
215 annotationTargetMap.put(KotlinTarget.VALUE_PARAMETER, ElementType.PARAMETER);
216 }
217
218 private void generateTargetAnnotation(@NotNull ClassDescriptor classDescriptor, @NotNull Set<String> annotationDescriptorsAlreadyPresent) {
219 String descriptor = Type.getType(Target.class).getDescriptor();
220 if (!annotationDescriptorsAlreadyPresent.add(descriptor)) return;
221 Set<KotlinTarget> targets = AnnotationChecker.Companion.applicableTargetSet(classDescriptor);
222 Set<ElementType> javaTargets;
223 if (targets == null) {
224 javaTargets = getJavaTargetList(classDescriptor);
225 if (javaTargets == null) return;
226 }
227 else {
228 javaTargets = EnumSet.noneOf(ElementType.class);
229 for (KotlinTarget target : targets) {
230 if (annotationTargetMap.get(target) == null) continue;
231 javaTargets.add(annotationTargetMap.get(target));
232 }
233 }
234 AnnotationVisitor visitor = visitAnnotation(descriptor, true);
235 AnnotationVisitor arrayVisitor = visitor.visitArray("value");
236 for (ElementType javaTarget : javaTargets) {
237 arrayVisitor.visitEnum(null, Type.getType(ElementType.class).getDescriptor(), javaTarget.name());
238 }
239 arrayVisitor.visitEnd();
240 visitor.visitEnd();
241 }
242
243 private void generateRetentionAnnotation(@NotNull ClassDescriptor classDescriptor, @NotNull Set<String> annotationDescriptorsAlreadyPresent) {
244 RetentionPolicy policy = getRetentionPolicy(classDescriptor);
245 String descriptor = Type.getType(Retention.class).getDescriptor();
246 if (!annotationDescriptorsAlreadyPresent.add(descriptor)) return;
247 AnnotationVisitor visitor = visitAnnotation(descriptor, true);
248 visitor.visitEnum("value", Type.getType(RetentionPolicy.class).getDescriptor(), policy.name());
249 visitor.visitEnd();
250 }
251
252 private void generateDocumentedAnnotation(@NotNull ClassDescriptor classDescriptor, @NotNull Set<String> annotationDescriptorsAlreadyPresent) {
253 boolean documented = DescriptorUtilsKt.isDocumentedAnnotation(classDescriptor);
254 if (!documented) return;
255 String descriptor = Type.getType(Documented.class).getDescriptor();
256 if (!annotationDescriptorsAlreadyPresent.add(descriptor)) return;
257 AnnotationVisitor visitor = visitAnnotation(descriptor, true);
258 visitor.visitEnd();
259 }
260
261 private void generateAnnotationIfNotPresent(Set<String> annotationDescriptorsAlreadyPresent, Class<?> annotationClass) {
262 String descriptor = Type.getType(annotationClass).getDescriptor();
263 if (!annotationDescriptorsAlreadyPresent.contains(descriptor)) {
264 visitAnnotation(descriptor, false).visitEnd();
265 }
266 }
267
268 private static boolean isBareTypeParameterWithNullableUpperBound(@NotNull KotlinType type) {
269 ClassifierDescriptor classifier = type.getConstructor().getDeclarationDescriptor();
270 return !type.isMarkedNullable() && classifier instanceof TypeParameterDescriptor && TypeUtils.hasNullableSuperType(type);
271 }
272
273 public void generateAnnotationDefaultValue(@NotNull ConstantValue<?> value, @NotNull KotlinType expectedType) {
274 AnnotationVisitor visitor = visitAnnotation(null, false); // Parameters are unimportant
275 genCompileTimeValue(null, value, visitor);
276 visitor.visitEnd();
277 }
278
279 @Nullable
280 private String genAnnotation(@NotNull AnnotationDescriptor annotationDescriptor) {
281 ClassifierDescriptor classifierDescriptor = annotationDescriptor.getType().getConstructor().getDeclarationDescriptor();
282 assert classifierDescriptor != null : "Annotation descriptor has no class: " + annotationDescriptor;
283 RetentionPolicy rp = getRetentionPolicy(classifierDescriptor);
284 if (rp == RetentionPolicy.SOURCE && !typeMapper.getClassBuilderMode().generateSourceRetentionAnnotations) {
285 return null;
286 }
287
288 String descriptor = typeMapper.mapType(annotationDescriptor.getType()).getDescriptor();
289
290 if (classifierDescriptor instanceof ClassDescriptor) {
291 innerClassConsumer.addInnerClassInfoFromAnnotation(((ClassDescriptor) classifierDescriptor));
292 }
293
294 AnnotationVisitor annotationVisitor = visitAnnotation(descriptor, rp == RetentionPolicy.RUNTIME);
295
296 genAnnotationArguments(annotationDescriptor, annotationVisitor);
297 annotationVisitor.visitEnd();
298
299 return descriptor;
300 }
301
302 private void genAnnotationArguments(AnnotationDescriptor annotationDescriptor, AnnotationVisitor annotationVisitor) {
303 for (Map.Entry<ValueParameterDescriptor, ConstantValue<?>> entry : annotationDescriptor.getAllValueArguments().entrySet()) {
304 ValueParameterDescriptor descriptor = entry.getKey();
305 String name = descriptor.getName().asString();
306 genCompileTimeValue(name, entry.getValue(), annotationVisitor);
307 }
308 }
309
310 private void genCompileTimeValue(
311 @Nullable final String name,
312 @NotNull ConstantValue<?> value,
313 @NotNull final AnnotationVisitor annotationVisitor
314 ) {
315 AnnotationArgumentVisitor argumentVisitor = new AnnotationArgumentVisitor<Void, Void>() {
316 @Override
317 public Void visitLongValue(@NotNull LongValue value, Void data) {
318 return visitSimpleValue(value);
319 }
320
321 @Override
322 public Void visitIntValue(IntValue value, Void data) {
323 return visitSimpleValue(value);
324 }
325
326 @Override
327 public Void visitShortValue(ShortValue value, Void data) {
328 return visitSimpleValue(value);
329 }
330
331 @Override
332 public Void visitByteValue(ByteValue value, Void data) {
333 return visitSimpleValue(value);
334 }
335
336 @Override
337 public Void visitDoubleValue(DoubleValue value, Void data) {
338 return visitSimpleValue(value);
339 }
340
341 @Override
342 public Void visitFloatValue(FloatValue value, Void data) {
343 return visitSimpleValue(value);
344 }
345
346 @Override
347 public Void visitBooleanValue(BooleanValue value, Void data) {
348 return visitSimpleValue(value);
349 }
350
351 @Override
352 public Void visitCharValue(CharValue value, Void data) {
353 return visitSimpleValue(value);
354 }
355
356 @Override
357 public Void visitStringValue(StringValue value, Void data) {
358 return visitSimpleValue(value);
359 }
360
361 @Override
362 public Void visitEnumValue(EnumValue value, Void data) {
363 String propertyName = value.getValue().getName().asString();
364 annotationVisitor.visitEnum(name, typeMapper.mapType(value.getType()).getDescriptor(), propertyName);
365 return null;
366 }
367
368 @Override
369 public Void visitArrayValue(ArrayValue value, Void data) {
370 AnnotationVisitor visitor = annotationVisitor.visitArray(name);
371 for (ConstantValue<?> argument : value.getValue()) {
372 genCompileTimeValue(null, argument, visitor);
373 }
374 visitor.visitEnd();
375 return null;
376 }
377
378 @Override
379 public Void visitAnnotationValue(AnnotationValue value, Void data) {
380 String internalAnnName = typeMapper.mapType(value.getValue().getType()).getDescriptor();
381 AnnotationVisitor visitor = annotationVisitor.visitAnnotation(name, internalAnnName);
382 genAnnotationArguments(value.getValue(), visitor);
383 visitor.visitEnd();
384 return null;
385 }
386
387 @Override
388 public Void visitKClassValue(KClassValue value, Void data) {
389 annotationVisitor.visit(name, typeMapper.mapType(value.getValue()));
390 return null;
391 }
392
393 private Void visitSimpleValue(ConstantValue<?> value) {
394 annotationVisitor.visit(name, value.getValue());
395 return null;
396 }
397
398 @Override
399 public Void visitErrorValue(ErrorValue value, Void data) {
400 return visitUnsupportedValue(value);
401 }
402
403 @Override
404 public Void visitNullValue(NullValue value, Void data) {
405 return visitUnsupportedValue(value);
406 }
407
408 private Void visitUnsupportedValue(ConstantValue<?> value) {
409 ClassBuilderMode mode = typeMapper.getClassBuilderMode();
410 if (mode.generateBodies) {
411 throw new IllegalStateException("Don't know how to compile annotation value " + value);
412 } else {
413 return null;
414 }
415 }
416 };
417
418 value.accept(argumentVisitor, null);
419 }
420
421 private static final Map<KotlinRetention, RetentionPolicy> annotationRetentionMap =
422 new EnumMap<KotlinRetention, RetentionPolicy>(KotlinRetention.class);
423
424 static {
425 annotationRetentionMap.put(KotlinRetention.SOURCE, RetentionPolicy.SOURCE);
426 annotationRetentionMap.put(KotlinRetention.BINARY, RetentionPolicy.CLASS);
427 annotationRetentionMap.put(KotlinRetention.RUNTIME, RetentionPolicy.RUNTIME);
428 }
429
430 @Nullable
431 private Set<ElementType> getJavaTargetList(ClassDescriptor descriptor) {
432 AnnotationDescriptor targetAnnotation = descriptor.getAnnotations().findAnnotation(new FqName(Target.class.getName()));
433 if (targetAnnotation != null) {
434 Collection<ConstantValue<?>> valueArguments = targetAnnotation.getAllValueArguments().values();
435 if (!valueArguments.isEmpty()) {
436 ConstantValue<?> compileTimeConstant = valueArguments.iterator().next();
437 if (compileTimeConstant instanceof ArrayValue) {
438 List<? extends ConstantValue<?>> values = ((ArrayValue) compileTimeConstant).getValue();
439 Set<ElementType> result = EnumSet.noneOf(ElementType.class);
440 for (ConstantValue<?> value : values) {
441 if (value instanceof EnumValue) {
442 ClassDescriptor enumEntry = ((EnumValue) value).getValue();
443 KotlinType classObjectType = DescriptorUtilsKt.getClassValueType(enumEntry);
444 if (classObjectType != null) {
445 if ("java/lang/annotation/ElementType".equals(typeMapper.mapType(classObjectType).getInternalName())) {
446 result.add(ElementType.valueOf(enumEntry.getName().asString()));
447 }
448 }
449 }
450 }
451 return result;
452 }
453 }
454 }
455 return null;
456 }
457
458 @NotNull
459 private RetentionPolicy getRetentionPolicy(@NotNull Annotated descriptor) {
460 KotlinRetention retention = DescriptorUtilsKt.getAnnotationRetention(descriptor);
461 if (retention != null) {
462 return annotationRetentionMap.get(retention);
463 }
464 AnnotationDescriptor retentionAnnotation = descriptor.getAnnotations().findAnnotation(new FqName(Retention.class.getName()));
465 if (retentionAnnotation != null) {
466 Collection<ConstantValue<?>> valueArguments = retentionAnnotation.getAllValueArguments().values();
467 if (!valueArguments.isEmpty()) {
468 ConstantValue<?> compileTimeConstant = valueArguments.iterator().next();
469 if (compileTimeConstant instanceof EnumValue) {
470 ClassDescriptor enumEntry = ((EnumValue) compileTimeConstant).getValue();
471 KotlinType classObjectType = DescriptorUtilsKt.getClassValueType(enumEntry);
472 if (classObjectType != null) {
473 if ("java/lang/annotation/RetentionPolicy".equals(typeMapper.mapType(classObjectType).getInternalName())) {
474 return RetentionPolicy.valueOf(enumEntry.getName().asString());
475 }
476 }
477 }
478 }
479 }
480
481 return RetentionPolicy.RUNTIME;
482 }
483
484 @NotNull
485 abstract AnnotationVisitor visitAnnotation(String descr, boolean visible);
486
487 public static AnnotationCodegen forClass(
488 final @NotNull ClassVisitor cv,
489 @NotNull InnerClassConsumer innerClassConsumer,
490 @NotNull KotlinTypeMapper mapper
491 ) {
492 return new AnnotationCodegen(innerClassConsumer, mapper) {
493 @NotNull
494 @Override
495 AnnotationVisitor visitAnnotation(String descr, boolean visible) {
496 return safe(cv.visitAnnotation(descr, visible));
497 }
498 };
499 }
500
501 public static AnnotationCodegen forMethod(
502 final @NotNull MethodVisitor mv,
503 @NotNull InnerClassConsumer innerClassConsumer,
504 @NotNull KotlinTypeMapper mapper
505 ) {
506 return new AnnotationCodegen(innerClassConsumer, mapper) {
507 @NotNull
508 @Override
509 AnnotationVisitor visitAnnotation(String descr, boolean visible) {
510 return safe(mv.visitAnnotation(descr, visible));
511 }
512 };
513 }
514
515 public static AnnotationCodegen forField(
516 final @NotNull FieldVisitor fv,
517 @NotNull InnerClassConsumer innerClassConsumer,
518 @NotNull KotlinTypeMapper mapper
519 ) {
520 return new AnnotationCodegen(innerClassConsumer, mapper) {
521 @NotNull
522 @Override
523 AnnotationVisitor visitAnnotation(String descr, boolean visible) {
524 return safe(fv.visitAnnotation(descr, visible));
525 }
526 };
527 }
528
529 public static AnnotationCodegen forParameter(
530 final int parameter,
531 final @NotNull MethodVisitor mv,
532 @NotNull InnerClassConsumer innerClassConsumer,
533 @NotNull KotlinTypeMapper mapper
534 ) {
535 return new AnnotationCodegen(innerClassConsumer, mapper) {
536 @NotNull
537 @Override
538 AnnotationVisitor visitAnnotation(String descr, boolean visible) {
539 return safe(mv.visitParameterAnnotation(parameter, descr, visible));
540 }
541 };
542 }
543
544 public static AnnotationCodegen forAnnotationDefaultValue(
545 final @NotNull MethodVisitor mv,
546 @NotNull InnerClassConsumer innerClassConsumer,
547 @NotNull KotlinTypeMapper mapper
548 ) {
549 return new AnnotationCodegen(innerClassConsumer, mapper) {
550 @NotNull
551 @Override
552 AnnotationVisitor visitAnnotation(String descr, boolean visible) {
553 return safe(mv.visitAnnotationDefault());
554 }
555 };
556 }
557
558 @NotNull
559 private static AnnotationVisitor safe(@Nullable AnnotationVisitor av) {
560 return av == null ? NO_ANNOTATION_VISITOR : av;
561 }
562 }