// 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.tracereferences;

import com.android.tools.r8.DiagnosticsHandler;
import com.android.tools.r8.dex.ApplicationReader;
import com.android.tools.r8.diagnostic.DefinitionContext;
import com.android.tools.r8.diagnostic.internal.DefinitionContextUtils;
import com.android.tools.r8.experimental.startup.StartupOrder;
import com.android.tools.r8.features.ClassToFeatureSplitMap;
import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.ClassResolutionResult;
import com.android.tools.r8.graph.DexAnnotation;
import com.android.tools.r8.graph.DexCallSite;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexClassAndField;
import com.android.tools.r8.graph.DexClassAndMethod;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexProto;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.DexTypeList;
import com.android.tools.r8.graph.DexValue;
import com.android.tools.r8.graph.DexValue.DexValueArray;
import com.android.tools.r8.graph.FieldResolutionResult;
import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.GraphLens.FieldLookupResult;
import com.android.tools.r8.graph.GraphLens.MethodLookupResult;
import com.android.tools.r8.graph.MethodResolutionResult;
import com.android.tools.r8.graph.MethodResolutionResult.SingleResolutionResult;
import com.android.tools.r8.graph.ProgramField;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.graph.UseRegistry;
import com.android.tools.r8.ir.desugar.LambdaDescriptor;
import com.android.tools.r8.references.ClassReference;
import com.android.tools.r8.references.FieldReference;
import com.android.tools.r8.references.MethodReference;
import com.android.tools.r8.references.Reference;
import com.android.tools.r8.shaking.MainDexInfo;
import com.android.tools.r8.synthesis.SyntheticItems.GlobalSyntheticsStrategy;
import com.android.tools.r8.tracereferences.TraceReferencesConsumer.TracedReference;
import com.android.tools.r8.tracereferences.internal.TracedClassImpl;
import com.android.tools.r8.tracereferences.internal.TracedFieldImpl;
import com.android.tools.r8.tracereferences.internal.TracedMethodImpl;
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.BooleanBox;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.Timing;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
import java.util.function.Function;
import java.util.function.Predicate;

public class Tracer {

  private final AppView<? extends AppInfoWithClassHierarchy> appView;
  private final DiagnosticsHandler diagnostics;
  private final Predicate<DexType> targetPredicate;

  Tracer(
      Set<String> targetDescriptors,
      AndroidApp inputApp,
      DiagnosticsHandler diagnostics,
      InternalOptions options)
      throws IOException {
    this(
        AppView.createForTracer(
            AppInfoWithClassHierarchy.createInitialAppInfoWithClassHierarchy(
                new ApplicationReader(inputApp, options, Timing.empty()).read().toDirect(),
                ClassToFeatureSplitMap.createEmptyClassToFeatureSplitMap(),
                MainDexInfo.none(),
                GlobalSyntheticsStrategy.forSingleOutputMode(),
                StartupOrder.empty())),
        diagnostics,
        type -> targetDescriptors.contains(type.toDescriptorString()));
  }

  public Tracer(
      AppView<? extends AppInfoWithClassHierarchy> appView,
      DiagnosticsHandler diagnostics,
      Predicate<DexType> targetPredicate) {
    this.appView = appView;
    this.diagnostics = diagnostics;
    this.targetPredicate = targetPredicate;
  }

  public void run(TraceReferencesConsumer consumer) {
    UseCollector useCollector = new UseCollector(appView, consumer, diagnostics, targetPredicate);
    for (DexProgramClass clazz : appView.appInfo().classes()) {
      DefinitionContext classContext = DefinitionContextUtils.create(clazz);
      if (clazz.superType != null) {
        useCollector.registerSuperType(clazz, clazz.superType, classContext);
      }
      for (DexType implementsType : clazz.getInterfaces()) {
        useCollector.registerSuperType(clazz, implementsType, classContext);
      }
      clazz.forEachProgramField(useCollector::registerField);
      clazz.forEachProgramMethod(
          method -> {
            useCollector.registerMethod(method);
            useCollector.traceCode(method);
          });
    }
    consumer.finished(diagnostics);
  }

  // The graph lens is intentionally only made accessible to the MethodUseCollector, since the
  // graph lens should only be applied to the code.
  static class UseCollector {

    private final AppView<? extends AppInfoWithClassHierarchy> appView;
    private final DexItemFactory factory;
    private final TraceReferencesConsumer consumer;
    private final DiagnosticsHandler diagnostics;
    private final Predicate<DexType> targetPredicate;

    private final Set<ClassReference> missingClasses = new HashSet<>();
    private final Set<FieldReference> missingFields = new HashSet<>();
    private final Set<MethodReference> missingMethods = new HashSet<>();

    UseCollector(
        AppView<? extends AppInfoWithClassHierarchy> appView,
        TraceReferencesConsumer consumer,
        DiagnosticsHandler diagnostics,
        Predicate<DexType> targetPredicate) {
      this.appView = appView;
      this.factory = appView.dexItemFactory();
      this.consumer = consumer;
      this.diagnostics = diagnostics;
      this.targetPredicate = targetPredicate;
    }

    AppInfoWithClassHierarchy appInfo() {
      return appView.appInfo();
    }

    GraphLens graphLens() {
      return appView.graphLens();
    }

    private boolean isTargetType(DexType type) {
      return targetPredicate.test(type);
    }

    private void addType(DexType type, DefinitionContext referencedFrom) {
      if (type.isArrayType()) {
        addType(type.toBaseType(factory), referencedFrom);
        return;
      }
      if (type.isPrimitiveType() || type.isVoidType()) {
        return;
      }
      assert type.isClassType();
      addClassType(type, referencedFrom);
    }

    private void addTypes(DexTypeList types, DefinitionContext referencedFrom) {
      for (DexType type : types) {
        addType(type, referencedFrom);
      }
    }

    private void addClassType(DexType type, DefinitionContext referencedFrom) {
      assert type.isClassType();
      ClassResolutionResult result =
          appView.contextIndependentDefinitionForWithResolutionResult(type);
      if (result.hasClassResolutionResult()) {
        result.forEachClassResolutionResult(clazz -> addClass(clazz, referencedFrom));
      } else {
        TracedClassImpl tracedClass = new TracedClassImpl(type, referencedFrom);
        collectMissingClass(tracedClass);
        consumer.acceptType(tracedClass, diagnostics);
      }
    }

    private void addClass(DexClass clazz, DefinitionContext referencedFrom) {
      if (isTargetType(clazz.getType())) {
        TracedClassImpl tracedClass = new TracedClassImpl(clazz, referencedFrom);
        consumer.acceptType(tracedClass, diagnostics);
        if (clazz.getAccessFlags().isVisibilityDependingOnPackage()) {
          consumer.acceptPackage(
              Reference.packageFromString(clazz.getType().getPackageName()), diagnostics);
        }
      }
    }

    private void addSuperMethodFromTarget(
        DexClassAndMethod method, DefinitionContext referencedFrom) {
      assert !method.isProgramMethod();
      assert isTargetType(method.getHolderType());

      // There should be no need to register the types referenced from the method signature:
      // - The return type and the parameter types are registered when visiting the source method
      //   that overrides this target method,
      // - The holder type is registered from visiting the extends/implements clause of the sub
      //   class.

      TracedMethodImpl tracedMethod = new TracedMethodImpl(method.getDefinition(), referencedFrom);
      if (isTargetType(method.getHolderType())) {
        consumer.acceptMethod(tracedMethod, diagnostics);
        if (method.getAccessFlags().isVisibilityDependingOnPackage()) {
          consumer.acceptPackage(
              Reference.packageFromString(method.getHolderType().getPackageName()), diagnostics);
        }
      }
    }

    private <R, T extends TracedReference<R, ?>> void collectMissing(
        T tracedReference, Set<R> missingCollection) {
      if (tracedReference.isMissingDefinition()) {
        missingCollection.add(tracedReference.getReference());
      }
    }

    private void collectMissingClass(TracedClassImpl tracedClass) {
      assert tracedClass.isMissingDefinition();
      collectMissing(tracedClass, missingClasses);
    }

    private void collectMissingField(TracedFieldImpl tracedField) {
      assert tracedField.isMissingDefinition();
      collectMissing(tracedField, missingFields);
    }

    private void collectMissingMethod(TracedMethodImpl tracedMethod) {
      assert tracedMethod.isMissingDefinition();
      collectMissing(tracedMethod, missingMethods);
    }

    private void registerField(ProgramField field) {
      DefinitionContext referencedFrom = DefinitionContextUtils.create(field);
      addType(field.getType(), referencedFrom);
    }

    private void registerMethod(ProgramMethod method) {
      DefinitionContext referencedFrom = DefinitionContextUtils.create(method);
      addTypes(method.getParameters(), referencedFrom);
      addType(method.getReturnType(), referencedFrom);
      for (DexAnnotation annotation : method.getDefinition().annotations().annotations) {
        if (annotation.getAnnotationType() == factory.annotationThrows) {
          DexValueArray dexValues = annotation.annotation.elements[0].value.asDexValueArray();
          for (DexValue dexValType : dexValues.getValues()) {
            addType(dexValType.asDexValueType().value, referencedFrom);
          }
        }
      }
      MethodResolutionResult methodResolutionResult =
          method.getHolder().isInterface()
              ? appInfo().resolveMethodOnInterface(method.getHolder(), method.getReference())
              : appInfo().resolveMethodOnClass(method.getHolder(), method.getReference());
      DexClassAndMethod superTarget =
          methodResolutionResult.lookupInvokeSpecialTarget(method.getHolder(), appInfo());
      if (superTarget != null
          && !superTarget.isProgramMethod()
          && isTargetType(superTarget.getHolderType())) {
        addSuperMethodFromTarget(superTarget, referencedFrom);
      }
    }

    private void traceCode(ProgramMethod method) {
      method.registerCodeReferences(new MethodUseCollector(method));
    }

    private void registerSuperType(
        DexProgramClass clazz, DexType superType, DefinitionContext referencedFrom) {
      addType(superType, referencedFrom);
      // If clazz overrides any methods in superType, we should keep those as well.
      clazz.forEachMethod(
          method -> {
            DexClassAndMethod resolvedMethod =
                appInfo()
                    .resolveMethodOn(superType, method.getReference(), superType != clazz.superType)
                    .getResolutionPair();
            if (resolvedMethod != null
                && !resolvedMethod.isProgramMethod()
                && isTargetType(resolvedMethod.getHolderType())) {
              addSuperMethodFromTarget(resolvedMethod, referencedFrom);
            }
          });
    }

    class MethodUseCollector extends UseRegistry<ProgramMethod> {

      private final DefinitionContext referencedFrom;

      public MethodUseCollector(ProgramMethod context) {
        super(appView, context);
        this.referencedFrom = DefinitionContextUtils.create(context);
      }

      // Method references.

      @Override
      public void registerInvokeDirect(DexMethod method) {
        MethodLookupResult lookupResult = graphLens().lookupInvokeDirect(method, getContext());
        assert lookupResult.getType().isDirect();
        DexMethod rewrittenMethod = lookupResult.getReference();
        BooleanBox seenMethod = new BooleanBox();
        appView
            .contextIndependentDefinitionForWithResolutionResult(rewrittenMethod.getHolderType())
            .forEachClassResolutionResult(
                holder -> {
                  DexClassAndMethod target = rewrittenMethod.lookupMemberOnClass(holder);
                  if (target != null) {
                    handleRewrittenMethodReference(rewrittenMethod, target);
                    seenMethod.set();
                  }
                });
        if (seenMethod.isFalse()) {
          handleRewrittenMethodReference(rewrittenMethod, (DexClassAndMethod) null);
        }
      }

      @Override
      public void registerInvokeInterface(DexMethod method) {
        MethodLookupResult lookupResult = graphLens().lookupInvokeInterface(method, getContext());
        assert lookupResult.getType().isInterface();
        handleInvokeWithDynamicDispatch(lookupResult);
      }

      @Override
      public void registerInvokeStatic(DexMethod method) {
        MethodLookupResult lookupResult = graphLens().lookupInvokeStatic(method, getContext());
        assert lookupResult.getType().isStatic();
        DexMethod rewrittenMethod = lookupResult.getReference();
        handleRewrittenMethodResolution(
            rewrittenMethod,
            appInfo().unsafeResolveMethodDueToDexFormat(rewrittenMethod),
            SingleResolutionResult::getResolutionPair);
      }

      @Override
      public void registerInvokeSuper(DexMethod method) {
        MethodLookupResult lookupResult = graphLens().lookupInvokeSuper(method, getContext());
        assert lookupResult.getType().isSuper();
        DexMethod rewrittenMethod = lookupResult.getReference();
        handleRewrittenMethodResolution(
            method,
            appInfo().unsafeResolveMethodDueToDexFormat(rewrittenMethod),
            result -> result.lookupInvokeSuperTarget(getContext().getHolder(), appInfo()));
      }

      @Override
      public void registerInvokeVirtual(DexMethod method) {
        MethodLookupResult lookupResult = graphLens().lookupInvokeVirtual(method, getContext());
        assert lookupResult.getType().isVirtual();
        handleInvokeWithDynamicDispatch(lookupResult);
      }

      private void handleInvokeWithDynamicDispatch(MethodLookupResult lookupResult) {
        DexMethod method = lookupResult.getReference();
        if (method.getHolderType().isArrayType()) {
          assert lookupResult.getType().isVirtual();
          addType(method.getHolderType(), referencedFrom);
          return;
        }
        assert lookupResult.getType().isInterface() || lookupResult.getType().isVirtual();
        handleRewrittenMethodResolution(
            method,
            lookupResult.getType().isInterface()
                ? appInfo().resolveMethodOnInterfaceHolder(method)
                : appInfo().resolveMethodOnClassHolder(method),
            SingleResolutionResult::getResolutionPair);
      }

      private void handleRewrittenMethodResolution(
          DexMethod method,
          MethodResolutionResult resolutionResult,
          Function<SingleResolutionResult<?>, DexClassAndMethod> getResult) {
        BooleanBox seenSingleResult = new BooleanBox();
        resolutionResult.forEachMethodResolutionResult(
            result -> {
              if (result.isFailedResolution()) {
                result
                    .asFailedResolution()
                    .forEachFailureDependency(
                        type -> addType(type, referencedFrom),
                        methodCausingFailure ->
                            handleRewrittenMethodReference(method, methodCausingFailure));
                return;
              }
              seenSingleResult.set();
              handleRewrittenMethodReference(method, getResult.apply(result.asSingleResolution()));
            });
        if (seenSingleResult.isFalse()) {
          resolutionResult.forEachMethodResolutionResult(
              failingResult -> {
                assert failingResult.isFailedResolution();
                if (!failingResult.asFailedResolution().hasMethodsCausingError()) {
                  handleRewrittenMethodReference(method, (DexEncodedMethod) null);
                }
              });
        }
      }

      private void handleRewrittenMethodReference(
          DexMethod method, DexClassAndMethod resolvedMethod) {
        handleRewrittenMethodReference(
            method, resolvedMethod == null ? null : resolvedMethod.getDefinition());
      }

      private void handleRewrittenMethodReference(
          DexMethod method, DexEncodedMethod resolvedMethod) {
        assert resolvedMethod == null
            || resolvedMethod.getReference().match(method)
            || DexClass.isSignaturePolymorphicMethod(resolvedMethod, factory);
        addType(method.getHolderType(), referencedFrom);
        addTypes(method.getParameters(), referencedFrom);
        addType(method.getReturnType(), referencedFrom);
        if (resolvedMethod != null) {
          if (isTargetType(resolvedMethod.getHolderType())) {
            if (resolvedMethod.getHolderType() != method.getHolderType()) {
              addType(resolvedMethod.getHolderType(), referencedFrom);
            }
            TracedMethodImpl tracedMethod = new TracedMethodImpl(resolvedMethod, referencedFrom);
            consumer.acceptMethod(tracedMethod, diagnostics);
            if (resolvedMethod.getAccessFlags().isVisibilityDependingOnPackage()) {
              consumer.acceptPackage(
                  Reference.packageFromString(resolvedMethod.getHolderType().getPackageName()),
                  diagnostics);
            }
          }
        } else {
          TracedMethodImpl tracedMethod = new TracedMethodImpl(method, referencedFrom);
          collectMissingMethod(tracedMethod);
          consumer.acceptMethod(tracedMethod, diagnostics);
        }
      }

      // Field references.

      @Override
      public void registerInitClass(DexType clazz) {
        DexType rewrittenClass = graphLens().lookupType(clazz);
        DexField clinitField = appView.initClassLens().getInitClassField(rewrittenClass);
        handleRewrittenFieldReference(clinitField);
      }

      @Override
      public void registerInstanceFieldRead(DexField field) {
        handleFieldAccess(field);
      }

      @Override
      public void registerInstanceFieldWrite(DexField field) {
        handleFieldAccess(field);
      }

      @Override
      public void registerStaticFieldRead(DexField field) {
        handleFieldAccess(field);
      }

      @Override
      public void registerStaticFieldWrite(DexField field) {
        handleFieldAccess(field);
      }

      private void handleFieldAccess(DexField field) {
        FieldLookupResult lookupResult = graphLens().lookupFieldResult(field);
        handleRewrittenFieldReference(lookupResult.getReference());
      }

      private void handleRewrittenFieldReference(DexField field) {
        addType(field.getHolderType(), referencedFrom);
        addType(field.getType(), referencedFrom);

        FieldResolutionResult resolutionResult = appInfo().resolveField(field);
        resolutionResult.forEachFieldResolutionResult(
            singleResolutionResult -> {
              if (!singleResolutionResult.isSingleFieldResolutionResult()) {
                return;
              }
              DexClassAndField resolvedField = singleResolutionResult.getResolutionPair();
              if (isTargetType(resolvedField.getHolderType())) {
                if (resolvedField.getHolderType() != field.getHolderType()) {
                  addClass(resolvedField.getHolder(), referencedFrom);
                }
                TracedFieldImpl tracedField = new TracedFieldImpl(resolvedField, referencedFrom);
                consumer.acceptField(tracedField, diagnostics);
                if (resolvedField.getAccessFlags().isVisibilityDependingOnPackage()) {
                  consumer.acceptPackage(
                      Reference.packageFromString(resolvedField.getHolderType().getPackageName()),
                      diagnostics);
                }
              }
            });
        if (!resolutionResult.hasSuccessfulResolutionResult()) {
          TracedFieldImpl tracedField = new TracedFieldImpl(field, referencedFrom);
          collectMissingField(tracedField);
          consumer.acceptField(tracedField, diagnostics);
        }
      }

      // Type references.

      @Override
      public void registerTypeReference(DexType type) {
        addType(graphLens().lookupType(type), referencedFrom);
      }

      // Call sites.

      @Override
      public void registerCallSite(DexCallSite callSite) {
        super.registerCallSite(callSite);

        // For lambdas that implement an interface, also keep the interface method by simulating an
        // invoke to it from the current context.
        LambdaDescriptor descriptor = LambdaDescriptor.tryInfer(callSite, appInfo(), getContext());
        if (descriptor != null) {
          for (DexType interfaceType : descriptor.interfaces) {
            ClassResolutionResult classResolutionResult =
                appView.contextIndependentDefinitionForWithResolutionResult(interfaceType);
            if (classResolutionResult.hasClassResolutionResult()) {
              classResolutionResult.forEachClassResolutionResult(
                  interfaceDefinition -> {
                    DexEncodedMethod mainMethod =
                        interfaceDefinition.lookupMethod(descriptor.getMainMethod());
                    if (mainMethod != null) {
                      registerInvokeInterface(mainMethod.getReference());
                    }
                    for (DexProto bridgeProto : descriptor.bridges) {
                      DexEncodedMethod bridgeMethod =
                          interfaceDefinition.lookupMethod(bridgeProto, descriptor.name);
                      if (bridgeMethod != null) {
                        registerInvokeInterface(bridgeMethod.getReference());
                      }
                    }
                  });
            } else {
              TracedClassImpl tracedClass = new TracedClassImpl(interfaceType, referencedFrom);
              collectMissingClass(tracedClass);
              consumer.acceptType(tracedClass, diagnostics);
            }
          }
        }
      }
    }
  }
}
