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

import com.android.tools.r8.graph.AppInfoWithSubtyping;
import com.android.tools.r8.graph.DelegatingUseRegistry;
import com.android.tools.r8.graph.DexClass;
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.DexString;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.UseRegistry;
import com.android.tools.r8.utils.MethodJavaSignatureEquivalence;
import com.google.common.base.Equivalence;
import com.google.common.base.Equivalence.Wrapper;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

/**
 * Extends the tree shaker with special treatment for ProtoLite generated classes.
 * <p>
 * The goal is to remove unused fields from proto classes. To achieve this, we filter the
 * dependency processing of certain methods of ProtoLite classes. Read/write references to
 * fields or corresponding getters are ignored. If the fields or getters are not used otherwise
 * in the program, they will be pruned even though they are referenced from the processed
 * ProtoLite class.
 * <p>
 * The companion code rewriter in {@link ProtoLitePruner} then fixes up the code and removes
 * references to these dead fields and getters in a semantics preserving way. For proto2, the
 * fields are turned into unknown fields and hence are preserved over the wire. For proto3, the
 * fields are removed and, as with unknown fields in proto3, their data is lost on retransmission.
 * <p>
 * We have to process the following three methods specially:
 * <dl>
 *   <dt>dynamicMethod</dt>
 *   <dd>implements most proto operations, like merging, comparing, etc</dd>
 *   <dt>writeTo</dt>
 *   <dd>performs the actual write operations</dd>
 *   <dt>getSerializedSize</dt>
 *   <dd>implements computing the serialized size of a proto, very similar to writeTo</dd>
 * </dl>
 * As they access all fields of a proto, regardless of whether they are used, we have to mask
 * their accesses to ensure actually dead fields are not made live.
 * <p>
 * We also have to treat setters specially. While their code does not need to be rewritten, we
 * need to ensure that the fields they write are actually kept and marked as live. We achieve
 * this by also marking them read.
 */
public class ProtoLiteExtension extends ProtoLiteBase {

  private final Equivalence<DexMethod> equivalence = MethodJavaSignatureEquivalence.get();
  /**
   * Set of all methods directly defined on the GeneratedMessageLite class. Used to filter
   * getters from other methods that begin with get.
   */
  private final Set<Wrapper<DexMethod>> methodsOnMessageType;

  private final DexString caseGetterSuffix;
  private final DexString caseFieldSuffix;

  public ProtoLiteExtension(AppInfoWithSubtyping appInfo) {
    super(appInfo);
    DexItemFactory factory = appInfo.dexItemFactory;
    this.methodsOnMessageType = computeMethodsOnMessageType();
    this.caseGetterSuffix = factory.createString("Case");
    this.caseFieldSuffix = factory.createString("Case_");
  }

  private Set<Wrapper<DexMethod>> computeMethodsOnMessageType() {
    DexClass messageClass = appInfo.definitionFor(messageType);
    if (messageClass == null) {
      return Collections.emptySet();
    }
    Set<Wrapper<DexMethod>> superMethods = new HashSet<>();
    messageClass.forEachMethod(method -> superMethods.add(equivalence.wrap(method.method)));
    return superMethods;
  }

  @Override
  boolean isSetterThatNeedsProcessing(DexEncodedMethod method) {
    return method.accessFlags.isPrivate()
        && method.method.name.beginsWith(setterNamePrefix)
        && !methodsOnMessageType.contains(equivalence.wrap(method.method));
  }

  private boolean isGetter(DexMethod method, DexType instanceType) {
    return method.holder == instanceType
        && (method.proto.parameters.isEmpty() || hasSingleIntArgument(method))
        && method.name.beginsWith(getterNamePrefix)
        && !method.name.endsWith(caseGetterSuffix)
        && !methodsOnMessageType.contains(equivalence.wrap(method));
  }

  private boolean isProtoField(DexField field, DexType instanceType) {
    if (field.getHolder() != instanceType) {
      return false;
    }
    // All instance fields that end with _ are proto fields. For proto2, there are also the
    // bitField<n>_ fields that are used to store presence information. We process those normally.
    // Likewise, the XXXCase_ fields for oneOfs.
    DexString name = field.name;
    return name.endsWith(underscore)
        && !name.beginsWith(bitFieldPrefix)
        && !name.endsWith(caseFieldSuffix);
  }

  public void processMethod(DexEncodedMethod method, UseRegistry registry,
      Set<DexField> protoLiteFields) {
    assert protoLiteFields != null;
    if (isSetterThatNeedsProcessing(method)) {
      // If a field is accessed by a live setter, the field is live as it has to be written to the
      // serialized stream for this proto. As we mask all reads in the writing code and normally
      // remove fields that are only written but never read, we have to mark fields used in setters
      // as read and written.
      method.registerInstructionsReferences(
          new FieldWriteImpliesReadUseRegistry(registry, method.method.holder));
    } else {
      // Filter all getters and field accesses in these methods. We do not want fields to become
      // live just due to being referenced in a special method. The pruning phase will remove
      // all references to dead fields in the code later.
      method.registerInstructionsReferences(new FilteringUseRegistry(registry, method.method.holder,
          protoLiteFields));
    }
  }

  private class FieldWriteImpliesReadUseRegistry extends DelegatingUseRegistry {

    private final DexType instanceType;

    FieldWriteImpliesReadUseRegistry(UseRegistry delegate,
        DexType instanceType) {
      super(delegate);
      this.instanceType = instanceType;
    }

    @Override
    public boolean registerInstanceFieldWrite(DexField field) {
      if (isProtoField(field, instanceType)) {
        super.registerInstanceFieldRead(field);
      }
      return super.registerInstanceFieldWrite(field);
    }
  }

  private class FilteringUseRegistry extends DelegatingUseRegistry {

    private final DexType instanceType;
    private final Set<DexField> registerField;

    private FilteringUseRegistry(UseRegistry delegate,
        DexType instanceType, Set<DexField> registerField) {
      super(delegate);
      this.instanceType = instanceType;
      this.registerField = registerField;
    }

    @Override
    public boolean registerInstanceFieldWrite(DexField field) {
      if (isProtoField(field, instanceType)) {
        registerField.add(field);
        return false;
      }
      return super.registerInstanceFieldWrite(field);
    }

    @Override
    public boolean registerInstanceFieldRead(DexField field) {
      if (isProtoField(field, instanceType)) {
        registerField.add(field);
        return false;
      }
      return super.registerInstanceFieldRead(field);
    }

    @Override
    public boolean registerInvokeVirtual(DexMethod method) {
      if (isGetter(method, instanceType)) {
        // Try whether this is a getXXX method.
        DexField field = getterToField(method);
        if (isProtoField(field, instanceType)) {
          registerField.add(field);
          return false;
        }
        // Try whether this is a getXXXCount method.
        field = getterToField(method, COUNT_POSTFIX_LENGTH);
        if (isProtoField(field, instanceType)) {
          registerField.add(field);
          return false;
        }
      }
      return super.registerInvokeVirtual(method);
    }
  }
}
