// 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.registerCodeReferences(
          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.registerCodeReferences(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);
    }
  }
}
