// Copyright (c) 2017, 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.shaking;

import com.android.tools.r8.dex.Constants;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexAnnotation;
import com.android.tools.r8.graph.DexAnnotationElement;
import com.android.tools.r8.graph.DexAnnotationSet;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexEncodedAnnotation;
import com.android.tools.r8.graph.DexEncodedField;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.GraphLense;
import com.android.tools.r8.graph.InnerClassAttribute;
import com.android.tools.r8.utils.InternalOptions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Sets;
import java.util.Collections;
import java.util.IdentityHashMap;
import java.util.Map;
import java.util.Set;

public class AnnotationRemover {

  private final AppView<AppInfoWithLiveness> appView;
  private final ProguardKeepAttributes keep;
  private final Set<DexType> classesToRetainInnerClassAttributeFor;

  public AnnotationRemover(
      AppView<AppInfoWithLiveness> appView, Set<DexType> classesToRetainInnerClassAttributeFor) {
    this.appView = appView;
    this.keep = appView.options().getProguardConfiguration().getKeepAttributes();
    this.classesToRetainInnerClassAttributeFor = classesToRetainInnerClassAttributeFor;
  }

  /**
   * Used to filter annotations on classes, methods and fields.
   */
  private boolean filterAnnotations(DexAnnotation annotation) {
    return shouldKeepAnnotation(
        annotation, isAnnotationTypeLive(annotation), appView.dexItemFactory(), appView.options());
  }

  static boolean shouldKeepAnnotation(
      DexAnnotation annotation,
      boolean isAnnotationTypeLive,
      DexItemFactory dexItemFactory,
      InternalOptions options) {
    ProguardKeepAttributes config =
        options.getProguardConfiguration() != null
            ? options.getProguardConfiguration().getKeepAttributes()
            : ProguardKeepAttributes.fromPatterns(ImmutableList.of());

    switch (annotation.visibility) {
      case DexAnnotation.VISIBILITY_SYSTEM:
        // InnerClass and EnclosingMember are represented in class attributes, not annotations.
        assert !DexAnnotation.isInnerClassAnnotation(annotation, dexItemFactory);
        assert !DexAnnotation.isMemberClassesAnnotation(annotation, dexItemFactory);
        assert !DexAnnotation.isEnclosingMethodAnnotation(annotation, dexItemFactory);
        assert !DexAnnotation.isEnclosingClassAnnotation(annotation, dexItemFactory);
        if (config.exceptions && DexAnnotation.isThrowingAnnotation(annotation, dexItemFactory)) {
          return true;
        }
        if (config.signature && DexAnnotation.isSignatureAnnotation(annotation, dexItemFactory)) {
          return true;
        }
        if (config.sourceDebugExtension
            && DexAnnotation.isSourceDebugExtension(annotation, dexItemFactory)) {
          return true;
        }
        if (config.methodParameters
            && DexAnnotation.isParameterNameAnnotation(annotation, dexItemFactory)) {
          return true;
        }
        if (DexAnnotation.isAnnotationDefaultAnnotation(annotation, dexItemFactory)) {
          // These have to be kept if the corresponding annotation class is kept to retain default
          // values.
          return true;
        }
        return false;

      case DexAnnotation.VISIBILITY_RUNTIME:
        if (!config.runtimeVisibleAnnotations) {
          return false;
        }
        return isAnnotationTypeLive;

      case DexAnnotation.VISIBILITY_BUILD:
        if (DexAnnotation.isSynthesizedClassMapAnnotation(annotation, dexItemFactory)) {
          // TODO(sgjesse) When should these be removed?
          return true;
        }
        if (!config.runtimeInvisibleAnnotations) {
          return false;
        }
        return isAnnotationTypeLive;

      default:
        throw new Unreachable("Unexpected annotation visibility.");
    }
  }

  private boolean isAnnotationTypeLive(DexAnnotation annotation) {
    DexType annotationType = annotation.annotation.type.toBaseType(appView.dexItemFactory());
    return appView.appInfo().isNonProgramTypeOrLiveProgramType(annotationType);
  }

  /**
   * Used to filter annotations on parameters.
   */
  private boolean filterParameterAnnotations(DexAnnotation annotation) {
    switch (annotation.visibility) {
      case DexAnnotation.VISIBILITY_SYSTEM:
        return false;
      case DexAnnotation.VISIBILITY_RUNTIME:
        if (!keep.runtimeVisibleParameterAnnotations) {
          return false;
        }
        break;
      case DexAnnotation.VISIBILITY_BUILD:
        if (!keep.runtimeInvisibleParameterAnnotations) {
          return false;
        }
        break;
      default:
        throw new Unreachable("Unexpected annotation visibility.");
    }
    return isAnnotationTypeLive(annotation);
  }

  public AnnotationRemover ensureValid(ProguardConfiguration.Builder compatibility) {
    keep.ensureValid(appView.options().forceProguardCompatibility, compatibility);
    return this;
  }

  private static boolean hasGenericEnclosingClass(
      DexProgramClass clazz,
      Map<DexType, DexProgramClass> enclosingClasses,
      Set<DexProgramClass> genericClasses) {
    while (true) {
      DexProgramClass enclosingClass = enclosingClasses.get(clazz.type);
      if (enclosingClass == null) {
        return false;
      }
      if (genericClasses.contains(enclosingClass)) {
        return true;
      }
      clazz = enclosingClass;
    }
  }

  private static boolean hasSignatureAnnotation(DexProgramClass clazz, DexItemFactory itemFactory) {
    for (DexAnnotation annotation : clazz.annotations.annotations) {
      if (DexAnnotation.isSignatureAnnotation(annotation, itemFactory)) {
        return true;
      }
    }
    return false;
  }

  public static Set<DexType> computeClassesToRetainInnerClassAttributeFor(
      AppView<? extends AppInfoWithLiveness> appView) {
    // In case of minification for certain inner classes we need to retain their InnerClass
    // attributes because their minified name still needs to be in hierarchical format
    // (enclosing$inner) otherwise the GenericSignatureRewriter can't produce the correct,
    // renamed signature.

    // More precisely:
    // - we're going to retain the InnerClass attribute that refers to the same class as 'inner'
    // - for live, inner, nonstatic classes
    // - that are enclosed by a class with a generic signature.

    // In compat mode we always keep all InnerClass attributes (if requested).
    // If not requested we never keep any. In these cases don't compute eligible classes.
    if (appView.options().forceProguardCompatibility
        || !appView.options().getProguardConfiguration().getKeepAttributes().innerClasses) {
      return Collections.emptySet();
    }

    // Build lookup table and set of the interesting classes.
    // enclosingClasses.get(clazz) gives the enclosing class of 'clazz'
    Map<DexType, DexProgramClass> enclosingClasses = new IdentityHashMap<>();
    Set<DexProgramClass> genericClasses = Sets.newIdentityHashSet();

    Iterable<DexProgramClass> programClasses = appView.appInfo().classes();
    for (DexProgramClass clazz : programClasses) {
      if (hasSignatureAnnotation(clazz, appView.dexItemFactory())) {
        genericClasses.add(clazz);
      }
      for (InnerClassAttribute innerClassAttribute : clazz.getInnerClasses()) {
        if ((innerClassAttribute.getAccess() & Constants.ACC_STATIC) == 0
            && innerClassAttribute.getOuter() == clazz.type) {
          enclosingClasses.put(innerClassAttribute.getInner(), clazz);
        }
      }
    }

    Set<DexType> result = Sets.newIdentityHashSet();
    for (DexProgramClass clazz : programClasses) {
      // If [clazz] is mentioned by a keep rule, it could be used for reflection, and we therefore
      // need to keep the enclosing method and inner classes attributes, if requested.
      if (appView.appInfo().isPinned(clazz.type)) {
        for (InnerClassAttribute innerClassAttribute : clazz.getInnerClasses()) {
          DexType inner = innerClassAttribute.getInner();
          if (appView.appInfo().isNonProgramTypeOrLiveProgramType(inner)) {
            result.add(inner);
          }
          DexType context = innerClassAttribute.getLiveContext(appView.appInfo());
          if (context != null && appView.appInfo().isNonProgramTypeOrLiveProgramType(context)) {
            result.add(context);
          }
        }
      }
      if (clazz.getInnerClassAttributeForThisClass() != null
          && appView.appInfo().isNonProgramTypeOrLiveProgramType(clazz.type)
          && hasGenericEnclosingClass(clazz, enclosingClasses, genericClasses)) {
        result.add(clazz.type);
      }
    }
    return result;
  }

  public void run() {
    for (DexProgramClass clazz : appView.appInfo().classes()) {
      stripAttributes(clazz);
      clazz.annotations = clazz.annotations.rewrite(this::rewriteAnnotation);
      clazz.forEachMethod(this::processMethod);
      clazz.forEachField(this::processField);
    }
  }

  private void processMethod(DexEncodedMethod method) {
    method.annotations = method.annotations.rewrite(this::rewriteAnnotation);
    method.parameterAnnotationsList =
        method.parameterAnnotationsList.keepIf(this::filterParameterAnnotations);
  }

  private void processField(DexEncodedField field) {
    field.annotations = field.annotations.rewrite(this::rewriteAnnotation);
  }

  private DexAnnotation rewriteAnnotation(DexAnnotation original) {
    // Check if we should keep this annotation first.
    if (!filterAnnotations(original)) {
      return null;
    }
    // Then, filter out values that refer to dead definitions.
    return original.rewrite(this::rewriteEncodedAnnotation);
  }

  private DexEncodedAnnotation rewriteEncodedAnnotation(DexEncodedAnnotation original) {
    GraphLense graphLense = appView.graphLense();
    DexType annotationType = original.type.toBaseType(appView.dexItemFactory());
    DexType rewrittenType = graphLense.lookupType(annotationType);
    DexEncodedAnnotation rewrite =
        original.rewrite(
            graphLense::lookupType, element -> rewriteAnnotationElement(rewrittenType, element));
    assert rewrite != null;
    DexClass annotationClass = appView.definitionFor(rewrittenType);
    assert annotationClass == null
        || appView.appInfo().isNonProgramTypeOrLiveProgramType(rewrittenType);
    return rewrite;
  }

  private DexAnnotationElement rewriteAnnotationElement(
      DexType annotationType, DexAnnotationElement original) {
    DexClass definition = appView.definitionFor(annotationType);
    // We cannot strip annotations where we cannot look up the definition, because this will break
    // apps that rely on the annotation to exist. See b/134766810 for more information.
    if (definition == null) {
      return original;
    }
    assert definition.isInterface();
    boolean liveGetter =
        definition.virtualMethods().stream()
            .anyMatch(method -> method.method.name == original.name);
    return liveGetter ? original : null;
  }

  private boolean enclosingMethodPinned(DexClass clazz) {
    return clazz.getEnclosingMethod() != null
        && clazz.getEnclosingMethod().getEnclosingClass() != null
        && appView.appInfo().isPinned(clazz.getEnclosingMethod().getEnclosingClass());
  }

  private static boolean hasInnerClassesFromSet(DexProgramClass clazz, Set<DexType> innerClasses) {
    for (InnerClassAttribute attr : clazz.getInnerClasses()) {
      if (attr.getOuter() == clazz.type && innerClasses.contains(attr.getInner())) {
        return true;
      }
    }
    return false;
  }

  private void stripAttributes(DexProgramClass clazz) {
    // If [clazz] is mentioned by a keep rule, it could be used for reflection, and we therefore
    // need to keep the enclosing method and inner classes attributes, if requested. In Proguard
    // compatibility mode we keep these attributes independent of whether the given class is kept.
    // To ensure reflection from both inner to outer and and outer to inner for kept classes - even
    // if only one side is kept - keep the attributes is any class mentioned in these attributes
    // is kept.
    boolean keptAnyway =
        appView.appInfo().isPinned(clazz.type)
            || enclosingMethodPinned(clazz)
            || appView.options().forceProguardCompatibility;
    boolean keepForThisInnerClass = false;
    boolean keepForThisEnclosingClass = false;
    if (!keptAnyway) {
      keepForThisInnerClass = classesToRetainInnerClassAttributeFor.contains(clazz.type);
      keepForThisEnclosingClass =
          hasInnerClassesFromSet(clazz, classesToRetainInnerClassAttributeFor);
    }
    if (keptAnyway || keepForThisInnerClass || keepForThisEnclosingClass) {
      if (!keep.enclosingMethod) {
        clazz.clearEnclosingMethod();
      }
      if (!keep.innerClasses) {
        clazz.clearInnerClasses();
      } else if (!keptAnyway) {
        // We're keeping this only because of classesToRetainInnerClassAttributeFor.
        final boolean finalKeepForThisInnerClass = keepForThisInnerClass;
        final boolean finalKeepForThisEnclosingClass = keepForThisEnclosingClass;
        clazz.removeInnerClasses(
            ica -> {
              if (appView.appInfo().isPinned(ica.getInner())) {
                return false;
              }
              if (appView.appInfo().isPinned(ica.getOuter())) {
                return false;
              }
              if (finalKeepForThisInnerClass && ica.getInner() == clazz.type) {
                return false;
              }
              if (finalKeepForThisEnclosingClass
                  && ica.getOuter() == clazz.type
                  && classesToRetainInnerClassAttributeFor.contains(ica.getInner())) {
                return false;
              }
              return true;
            });
      }
    } else {
      // These attributes are only relevant for reflection, and this class is not used for
      // reflection. (Note that clearing these attributes can enable more vertical class merging.)
      clazz.clearEnclosingMethod();
      clazz.clearInnerClasses();
    }
  }

  public static void clearAnnotations(AppView<?> appView) {
    for (DexProgramClass clazz : appView.appInfo().classes()) {
      clazz.annotations = DexAnnotationSet.empty();
      for (DexEncodedMethod method : clazz.methods()) {
        method.annotations = DexAnnotationSet.empty();
      }
      for (DexEncodedField field : clazz.fields()) {
        field.annotations = DexAnnotationSet.empty();
      }
    }
  }
}
