| // 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 static com.android.tools.r8.utils.FunctionUtils.forEachApply; |
| |
| import com.android.tools.r8.graph.AppView; |
| import com.android.tools.r8.graph.DexDefinitionSupplier; |
| import com.android.tools.r8.graph.DexItemFactory; |
| import com.android.tools.r8.graph.DexType; |
| import com.android.tools.r8.graph.GraphLens; |
| import com.android.tools.r8.naming.NamingLens; |
| import com.android.tools.r8.shaking.EnqueuerMetadataTraceable; |
| import com.android.tools.r8.utils.Reporter; |
| import com.google.common.collect.ImmutableList; |
| import java.util.List; |
| import kotlinx.metadata.KmType; |
| import kotlinx.metadata.KmTypeProjection; |
| import kotlinx.metadata.KmTypeVisitor; |
| import kotlinx.metadata.jvm.JvmExtensionsKt; |
| import kotlinx.metadata.jvm.JvmTypeExtensionVisitor; |
| |
| // Provides access to Kotlin information about a kotlin type. |
| public class KotlinTypeInfo implements EnqueuerMetadataTraceable { |
| |
| private static final List<KotlinTypeProjectionInfo> EMPTY_ARGUMENTS = ImmutableList.of(); |
| |
| private final int flags; |
| private final KotlinClassifierInfo classifier; |
| private final KotlinTypeInfo abbreviatedType; |
| private final KotlinTypeInfo outerType; |
| private final List<KotlinTypeProjectionInfo> arguments; |
| private final List<KotlinAnnotationInfo> annotations; |
| private final KotlinFlexibleTypeUpperBoundInfo flexibleTypeUpperBound; |
| private final boolean isRaw; |
| |
| KotlinTypeInfo( |
| int flags, |
| KotlinClassifierInfo classifier, |
| KotlinTypeInfo abbreviatedType, |
| KotlinTypeInfo outerType, |
| List<KotlinTypeProjectionInfo> arguments, |
| List<KotlinAnnotationInfo> annotations, |
| KotlinFlexibleTypeUpperBoundInfo flexibleTypeUpperBound, |
| boolean isRaw) { |
| this.flags = flags; |
| this.classifier = classifier; |
| this.abbreviatedType = abbreviatedType; |
| this.outerType = outerType; |
| this.arguments = arguments; |
| this.annotations = annotations; |
| this.flexibleTypeUpperBound = flexibleTypeUpperBound; |
| this.isRaw = isRaw; |
| } |
| |
| static KotlinTypeInfo create(KmType kmType, DexItemFactory factory, Reporter reporter) { |
| if (kmType == null) { |
| return null; |
| } |
| return new KotlinTypeInfo( |
| kmType.getFlags(), |
| KotlinClassifierInfo.create(kmType.classifier, factory, reporter), |
| KotlinTypeInfo.create(kmType.getAbbreviatedType(), factory, reporter), |
| KotlinTypeInfo.create(kmType.getOuterType(), factory, reporter), |
| getArguments(kmType.getArguments(), factory, reporter), |
| KotlinAnnotationInfo.create(JvmExtensionsKt.getAnnotations(kmType), factory), |
| KotlinFlexibleTypeUpperBoundInfo.create( |
| kmType.getFlexibleTypeUpperBound(), factory, reporter), |
| JvmExtensionsKt.isRaw(kmType)); |
| } |
| |
| static List<KotlinTypeProjectionInfo> getArguments( |
| List<KmTypeProjection> projections, DexItemFactory factory, Reporter reporter) { |
| if (projections.isEmpty()) { |
| return EMPTY_ARGUMENTS; |
| } |
| ImmutableList.Builder<KotlinTypeProjectionInfo> arguments = ImmutableList.builder(); |
| for (KmTypeProjection projection : projections) { |
| arguments.add(KotlinTypeProjectionInfo.create(projection, factory, reporter)); |
| } |
| return arguments.build(); |
| } |
| |
| boolean rewrite(KmVisitorProviders.KmTypeVisitorProvider visitorProvider, AppView<?> appView) { |
| // TODO(b/154348683): Check for correct flags |
| KmTypeVisitor kmTypeVisitor = visitorProvider.get(flags); |
| NamingLens namingLens = appView.getNamingLens(); |
| boolean rewritten = classifier.rewrite(kmTypeVisitor, appView); |
| if (abbreviatedType != null) { |
| rewritten |= abbreviatedType.rewrite(kmTypeVisitor::visitAbbreviatedType, appView); |
| } |
| if (outerType != null) { |
| rewritten |= outerType.rewrite(kmTypeVisitor::visitOuterType, appView); |
| } |
| for (KotlinTypeProjectionInfo argument : arguments) { |
| rewritten |= |
| argument.rewrite( |
| kmTypeVisitor::visitArgument, kmTypeVisitor::visitStarProjection, appView); |
| } |
| rewritten |= |
| flexibleTypeUpperBound.rewrite(kmTypeVisitor::visitFlexibleTypeUpperBound, appView); |
| if (annotations.isEmpty() && !isRaw) { |
| return rewritten; |
| } |
| JvmTypeExtensionVisitor extensionVisitor = |
| (JvmTypeExtensionVisitor) kmTypeVisitor.visitExtensions(JvmTypeExtensionVisitor.TYPE); |
| if (extensionVisitor != null) { |
| for (KotlinAnnotationInfo annotation : annotations) { |
| rewritten |= annotation.rewrite(extensionVisitor::visitAnnotation, appView); |
| } |
| extensionVisitor.visit(isRaw); |
| } |
| return rewritten; |
| } |
| |
| @Override |
| public void trace(DexDefinitionSupplier definitionSupplier) { |
| classifier.trace(definitionSupplier); |
| if (abbreviatedType != null) { |
| abbreviatedType.trace(definitionSupplier); |
| } |
| if (outerType != null) { |
| outerType.trace(definitionSupplier); |
| } |
| forEachApply(arguments, argument -> argument::trace, definitionSupplier); |
| flexibleTypeUpperBound.trace(definitionSupplier); |
| forEachApply(annotations, annotation -> annotation::trace, definitionSupplier); |
| } |
| |
| public DexType rewriteType(GraphLens graphLens) { |
| return classifier.rewriteType(graphLens); |
| } |
| } |