| // Copyright (c) 2020, the R8 project authors. Please see the AUTHORS file | |
| // for details. All rights reserved. Use of this source code is governed by a | |
| // BSD-style license that can be found in the LICENSE file. | |
| package com.android.tools.r8.kotlin; | |
| import com.android.tools.r8.graph.AppView; | |
| import com.android.tools.r8.graph.DexItemFactory; | |
| import com.android.tools.r8.shaking.EnqueuerMetadataTraceable; | |
| import com.android.tools.r8.utils.DescriptorUtils; | |
| import com.android.tools.r8.utils.internal.BooleanBox; | |
| import com.google.common.collect.ImmutableList; | |
| import java.util.LinkedHashMap; | |
| import java.util.List; | |
| import java.util.Map; | |
| import java.util.function.Consumer; | |
| import kotlin.metadata.KmAnnotation; | |
| import kotlin.metadata.KmAnnotationArgument; | |
| // Holds information about a KmAnnotation | |
| public class KotlinAnnotationInfo implements EnqueuerMetadataTraceable { | |
| private static final List<KotlinAnnotationInfo> EMPTY_ANNOTATIONS = ImmutableList.of(); | |
| private final KotlinTypeReference annotationType; | |
| private final Map<String, KotlinAnnotationArgumentInfo> arguments; | |
| private KotlinAnnotationInfo( | |
| KotlinTypeReference annotationType, Map<String, KotlinAnnotationArgumentInfo> arguments) { | |
| this.annotationType = annotationType; | |
| this.arguments = arguments; | |
| } | |
| static KotlinAnnotationInfo create(KmAnnotation annotation, DexItemFactory factory) { | |
| return new KotlinAnnotationInfo( | |
| KotlinTypeReference.fromBinaryNameOrKotlinClassifier( | |
| annotation.getClassName(), factory, annotation.getClassName()), | |
| KotlinAnnotationArgumentInfo.create(annotation.getArguments(), factory)); | |
| } | |
| static List<KotlinAnnotationInfo> create(List<KmAnnotation> annotations, DexItemFactory factory) { | |
| if (annotations.isEmpty()) { | |
| return EMPTY_ANNOTATIONS; | |
| } | |
| ImmutableList.Builder<KotlinAnnotationInfo> builder = ImmutableList.builder(); | |
| for (KmAnnotation annotation : annotations) { | |
| builder.add(create(annotation, factory)); | |
| } | |
| return builder.build(); | |
| } | |
| boolean rewrite(Consumer<KmAnnotation> annotationConsumer, AppView<?> appView) { | |
| BooleanBox rewritten = new BooleanBox(false); | |
| rewritten.or( | |
| annotationType.toRenamedDescriptorOrDefault( | |
| renamedDescriptor -> { | |
| if (renamedDescriptor == null) { | |
| // The type has been pruned | |
| rewritten.set(true); | |
| return; | |
| } | |
| String classifier = DescriptorUtils.descriptorToKotlinClassifier(renamedDescriptor); | |
| Map<String, KmAnnotationArgument> rewrittenArguments = new LinkedHashMap<>(); | |
| arguments.forEach( | |
| (key, arg) -> | |
| rewritten.or( | |
| arg.rewrite( | |
| rewrittenArg -> { | |
| if (rewrittenArg != null) { | |
| rewrittenArguments.put(key, rewrittenArg); | |
| } | |
| }, | |
| appView))); | |
| annotationConsumer.accept(new KmAnnotation(classifier, rewrittenArguments)); | |
| }, | |
| appView, | |
| null)); | |
| return rewritten.get(); | |
| } | |
| @Override | |
| public void trace(KotlinMetadataUseRegistry registry) { | |
| annotationType.trace(registry); | |
| arguments.forEach((ignored, arg) -> arg.trace(registry)); | |
| } | |
| } |