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

import com.android.tools.r8.DiagnosticsHandler;
import com.android.tools.r8.naming.ClassNamingForNameMapper.MappedRange;
import com.android.tools.r8.naming.MemberNaming.FieldSignature;
import com.android.tools.r8.naming.MemberNaming.MethodSignature;
import com.android.tools.r8.naming.MemberNaming.Signature;
import com.android.tools.r8.naming.ProguardMap.Builder;
import com.android.tools.r8.naming.mappinginformation.MapVersionMappingInformation;
import com.android.tools.r8.naming.mappinginformation.MappingInformation;
import com.android.tools.r8.naming.mappinginformation.MappingInformationDiagnostics;
import com.android.tools.r8.position.TextPosition;
import com.android.tools.r8.utils.IdentifierUtils;
import com.android.tools.r8.utils.StringUtils;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import java.io.BufferedReader;
import java.io.IOException;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
import java.util.function.Consumer;

/**
 * Parses a Proguard mapping file and produces mappings from obfuscated class names to the original
 * name and from obfuscated member signatures to the original members the obfuscated member
 * was formed of.
 * <p>
 * The expected format is as follows
 * <p>
 * original-type-name ARROW obfuscated-type-name COLON starts a class mapping
 * description and maps original to obfuscated.
 * <p>
 * followed by one or more of
 * <p>
 * signature ARROW name
 * <p>
 * which maps the member with the given signature to the new name. This mapping is not
 * bidirectional as member names are overloaded by signature. To make it bidirectional, we extend
 * the name with the signature of the original member.
 * <p>
 * Due to inlining, we might have the above prefixed with a range (two numbers separated by :).
 * <p>
 * range COLON signature ARROW name
 * <p>
 * This has the same meaning as the above but also encodes the line number range of the member. This
 * may be followed by multiple inline mappings of the form
 * <p>
 * range COLON signature COLON range ARROW name
 * <p>
 * to identify that signature was inlined from the second range to the new line numbers in the first
 * range. This is then followed by information on the call trace to where the member was inlined.
 * These entries have the form
 * <p>
 * range COLON signature COLON number ARROW name
 * <p>
 * and are currently only stored to be able to reproduce them later.
 */
public class ProguardMapReader implements AutoCloseable {

  private final BufferedReader reader;
  private final JsonParser jsonParser = new JsonParser();
  private final DiagnosticsHandler diagnosticsHandler;
  private final boolean allowEmptyMappedRanges;
  private final boolean allowExperimentalMapping;

  @Override
  public void close() throws IOException {
    reader.close();
  }

  ProguardMapReader(
      BufferedReader reader,
      DiagnosticsHandler diagnosticsHandler,
      boolean allowEmptyMappedRanges,
      boolean allowExperimentalMapping) {
    this.reader = reader;
    this.diagnosticsHandler = diagnosticsHandler;
    this.allowEmptyMappedRanges = allowEmptyMappedRanges;
    this.allowExperimentalMapping = allowExperimentalMapping;
    assert reader != null;
    assert diagnosticsHandler != null;
  }

  // Internal parser state
  private int lineNo = 0;
  private int lineOffset = 0;
  private String line;
  private MapVersion version = MapVersion.MapVersionNone;

  private int peekCodePoint() {
    return lineOffset < line.length() ? line.codePointAt(lineOffset) : '\n';
  }

  private char peekChar(int distance) {
    return lineOffset + distance < line.length()
        ? line.charAt(lineOffset + distance)
        : '\n';
  }

  private boolean hasNext() {
    return lineOffset < line.length();
  }

  private int nextCodePoint() {
    try {
      int cp = line.codePointAt(lineOffset);
      lineOffset += Character.charCount(cp);
      return cp;
    } catch (ArrayIndexOutOfBoundsException e) {
      throw new ParseException("Unexpected end of line");
    }
  }

  private char nextChar() {
    assert hasNext();
    try {
      return line.charAt(lineOffset++);
    } catch (ArrayIndexOutOfBoundsException e) {
      throw new ParseException("Unexpected end of line");
    }
  }

  private boolean nextLine() throws IOException {
    if (line.length() != lineOffset) {
      throw new ParseException("Expected end of line");
    }
    return skipLine();
  }

  private boolean isEmptyOrCommentLine(String line) {
    if (line == null) {
      return true;
    }
    for (int i = 0; i < line.length(); ++i) {
      char c = line.charAt(i);
      if (c == '#') {
        return !hasFirstCharJsonBrace(line, i);
      } else if (!StringUtils.isWhitespace(c)) {
        return false;
      }
    }
    return true;
  }

  private boolean isCommentLineWithJsonBrace() {
    if (line == null) {
      return false;
    }
    for (int i = 0; i < line.length(); ++i) {
      char c = line.charAt(i);
      if (c == '#') {
        return hasFirstCharJsonBrace(line, i);
      } else if (!Character.isWhitespace(c)) {
        return false;
      }
    }
    return false;
  }

  private static boolean hasFirstCharJsonBrace(String line, int commentCharIndex) {
    for (int i = commentCharIndex + 1; i < line.length(); i++) {
      char c = line.charAt(i);
      if (c == '{') {
        return true;
      } else if (!Character.isWhitespace(c)) {
        return false;
      }
    }
    return false;
  }

  private boolean skipLine() throws IOException {
    lineOffset = 0;
    do {
      lineNo++;
      line = reader.readLine();
    } while (hasLine() && isEmptyOrCommentLine(line));
    return hasLine();
  }

  private boolean hasLine() {
    return line != null;
  }

  // Helpers for common pattern
  private void skipWhitespace() {
    while (hasNext() && StringUtils.isWhitespace(peekCodePoint())) {
      nextCodePoint();
    }
  }

  private void expectWhitespace() {
    boolean seen = false;
    while (hasNext() && StringUtils.isWhitespace(peekCodePoint())) {
      seen = seen || !StringUtils.isBOM(peekCodePoint());
      nextCodePoint();
    }
    if (!seen) {
      throw new ParseException("Expected whitespace", true);
    }
  }

  private void expect(char c) {
    if (!hasNext()) {
      throw new ParseException("Expected '" + c + "'", true);
    }
    if (nextChar() != c) {
      throw new ParseException("Expected '" + c + "'");
    }
  }

  void parse(ProguardMap.Builder mapBuilder) throws IOException {
    // Read the first line.
    do {
      line = reader.readLine();
      lineNo++;
    } while (hasLine() && isEmptyOrCommentLine(line));
    parseClassMappings(mapBuilder);
  }

  // Parsing of entries

  private void parseClassMappings(ProguardMap.Builder mapBuilder) throws IOException {
    while (hasLine()) {
      skipWhitespace();
      if (isCommentLineWithJsonBrace()) {
        parseMappingInformation(
            info -> {
              assert info.isMetaInfMappingInformation();
            });
        // Skip reading the rest of the line.
        lineOffset = line.length();
        nextLine();
      }
      String before = parseType(false);
      skipWhitespace();
      // Workaround for proguard map files that contain entries for package-info.java files.
      assert IdentifierUtils.isDexIdentifierPart('-');
      if (before.endsWith("-") && acceptString(">")) {
        // With - as a legal identifier part the grammar is ambiguous, and we treat a->b as a -> b,
        // and not as a- > b (which would be a parse error).
        before = before.substring(0, before.length() - 1);
      } else {
        skipWhitespace();
        acceptArrow();
      }
      skipWhitespace();
      String after = parseType(false);
      skipWhitespace();
      expect(':');
      ClassNaming.Builder currentClassBuilder =
          mapBuilder.classNamingBuilder(after, before, getPosition());
      skipWhitespace();
      if (nextLine()) {
        parseMemberMappings(mapBuilder, currentClassBuilder);
      }
    }
  }

  private void parseMappingInformation(Consumer<MappingInformation> onMappingInfo) {
    MappingInformation.fromJsonObject(
        version,
        parseJsonInComment(),
        diagnosticsHandler,
        lineNo,
        info -> {
          MapVersionMappingInformation generatorInfo = info.asMetaInfMappingInformation();
          if (generatorInfo != null) {
            if (generatorInfo.getMapVersion().equals(MapVersion.MapVersionExperimental)) {
              // A mapping file that is marked "experimental" will be treated as an unversioned
              // file if the compiler/tool is not explicitly running with experimental support.
              version =
                  allowExperimentalMapping
                      ? MapVersion.MapVersionExperimental
                      : MapVersion.MapVersionNone;
            } else {
              version = generatorInfo.getMapVersion();
            }
          }
          onMappingInfo.accept(info);
        });
  }

  private void parseMemberMappings(Builder mapBuilder, ClassNaming.Builder classNamingBuilder)
      throws IOException {
    MemberNaming lastAddedNaming = null;
    MemberNaming activeMemberNaming = null;
    MappedRange activeMappedRange = null;
    Range previousMappedRange = null;
    do {
      Object originalRange = null;
      Range mappedRange = null;
      // Try to parse any information added in comments above member namings
      if (isCommentLineWithJsonBrace()) {
        final MemberNaming currentMember = activeMemberNaming;
        final MappedRange currentRange = activeMappedRange;
        parseMappingInformation(
            info -> {
              if (currentMember == null) {
                classNamingBuilder.addMappingInformation(
                    info,
                    conflictingInfo ->
                        diagnosticsHandler.warning(
                            MappingInformationDiagnostics.notAllowedCombination(
                                info, conflictingInfo, lineNo)));
              } else if (currentRange != null) {
                currentRange.addMappingInformation(
                    info,
                    conflictingInfo ->
                        diagnosticsHandler.warning(
                            MappingInformationDiagnostics.notAllowedCombination(
                                info, conflictingInfo, lineNo)));
              }
            });
        // Skip reading the rest of the line.
        lineOffset = line.length();
        continue;
      }
      // Parse the member line '  x:y:name:z:q -> renamedName'.
      if (!StringUtils.isWhitespace(peekCodePoint())) {
        break;
      }
      skipWhitespace();
      Object maybeRangeOrInt = maybeParseRangeOrInt();
      if (maybeRangeOrInt != null) {
        if (!(maybeRangeOrInt instanceof Range)) {
          throw new ParseException(
              String.format("Invalid obfuscated line number range (%s).", maybeRangeOrInt));
        }
        mappedRange = (Range) maybeRangeOrInt;
        skipWhitespace();
        expect(':');
      }
      skipWhitespace();
      Signature signature = parseSignature();
      skipWhitespace();
      if (peekChar(0) == ':') {
        // This is a mapping or inlining definition
        nextChar();
        skipWhitespace();
        originalRange = maybeParseRangeOrInt();
        if (originalRange == null) {
          throw new ParseException("No number follows the colon after the method signature.");
        }
      }
      if (!allowEmptyMappedRanges && mappedRange == null && originalRange != null) {
        throw new ParseException("No mapping for original range " + originalRange + ".");
      }

      skipWhitespace();
      skipArrow();
      skipWhitespace();
      String renamedName = parseMethodName();

      if (signature instanceof MethodSignature) {
        activeMappedRange =
            classNamingBuilder.addMappedRange(
                mappedRange, (MethodSignature) signature, originalRange, renamedName);
      }

      assert mappedRange == null || signature instanceof MethodSignature;

      // If this line refers to a member that should be added to classNamingBuilder (as opposed to
      // an inner inlined callee) and it's different from the the previous activeMemberNaming, then
      // flush (add) the current activeMemberNaming.
      if (activeMemberNaming != null) {
        boolean changedName = !activeMemberNaming.getRenamedName().equals(renamedName);
        boolean changedMappedRange = !Objects.equals(previousMappedRange, mappedRange);
        if (changedName || previousMappedRange == null || changedMappedRange) {
          if (lastAddedNaming == null
              || !lastAddedNaming.getOriginalSignature().equals(activeMemberNaming.signature)) {
            classNamingBuilder.addMemberEntry(activeMemberNaming);
            lastAddedNaming = activeMemberNaming;
          }
        }
      }
      activeMemberNaming =
          new MemberNaming(signature, signature.asRenamed(renamedName), getPosition());
      previousMappedRange = mappedRange;
    } while (nextLine());

    if (activeMemberNaming != null) {
      boolean notAdded =
          lastAddedNaming == null
              || !lastAddedNaming.getOriginalSignature().equals(activeMemberNaming.signature);
      if (previousMappedRange == null || notAdded) {
        classNamingBuilder.addMemberEntry(activeMemberNaming);
      }
    }
  }

  private TextPosition getPosition() {
    return new TextPosition(0, lineNo, 1);
  }

  // Parsing of components

  private void skipIdentifier(boolean allowInit) {
    boolean isInit = false;
    if (allowInit && peekChar(0) == '<') {
      // swallow the leading < character
      nextChar();
      isInit = true;
    }
    // Progard sometimes outputs a ? as a method name. We have tools (dexsplitter) that depends
    // on being able to map class names back to the original, but does not care if methods are
    // correctly mapped. Using this on proguard output for anything else might not give correct
    // remappings.
    if (!IdentifierUtils.isDexIdentifierStart(peekCodePoint())
        && !IdentifierUtils.isQuestionMark(peekCodePoint())) {
      throw new ParseException("Identifier expected");
    }
    nextCodePoint();
    while (IdentifierUtils.isDexIdentifierPart(peekCodePoint())
        || IdentifierUtils.isQuestionMark(peekCodePoint())) {
      nextCodePoint();
    }
    if (isInit) {
      expect('>');
    }
    if (IdentifierUtils.isDexIdentifierPart(peekCodePoint())) {
      throw new ParseException(
          "End of identifier expected (was 0x" + Integer.toHexString(peekCodePoint()) + ")");
    }
  }

  // Cache for canonicalizing strings.
  // This saves 10% of heap space for large programs.
  final HashMap<String, String> cache = new HashMap<>();

  private String substring(int start) {
    String result = line.substring(start, lineOffset);
    if (cache.containsKey(result)) {
      return cache.get(result);
    }
    cache.put(result, result);
    return result;
  }

  private String parseMethodName() {
    int startPosition = lineOffset;
    skipIdentifier(true);
    while (peekChar(0) == '.') {
      nextChar();
      skipIdentifier(true);
    }
    return substring(startPosition);
  }

  private String parseType(boolean allowArray) {
    int startPosition = lineOffset;
    skipIdentifier(false);
    while (peekChar(0) == '.') {
      nextChar();
      skipIdentifier(false);
    }
    if (allowArray) {
      while (peekChar(0) == '[') {
        nextChar();
        expect(']');
      }
    }
    return substring(startPosition);
  }

  private Signature parseSignature() {
    String type = parseType(true);
    expectWhitespace();
    String name = parseMethodName();
    skipWhitespace();
    Signature signature;
    if (peekChar(0) == '(') {
      nextChar();
      skipWhitespace();
      String[] arguments;
      if (peekChar(0) == ')') {
        arguments = new String[0];
      } else {
        List<String> items = new LinkedList<>();
        items.add(parseType(true));
        skipWhitespace();
        while (peekChar(0) != ')') {
          skipWhitespace();
          expect(',');
          skipWhitespace();
          items.add(parseType(true));
        }
        arguments = items.toArray(StringUtils.EMPTY_ARRAY);
      }
      expect(')');
      signature = new MethodSignature(name, type, arguments);
    } else {
      signature = new FieldSignature(name, type);
    }
    return signature;
  }

  private void skipArrow() {
    expect('-');
    expect('>');
  }

  private boolean acceptArrow() {
    if (peekChar(0) == '-' && peekChar(1) == '>') {
      nextChar();
      nextChar();
      return true;
    }
    return false;
  }

  private boolean acceptString(String s) {
    for (int i = 0; i < s.length(); i++) {
      if (peekChar(i) != s.charAt(i)) {
        return false;
      }
    }
    for (int i = 0; i < s.length(); i++) {
      nextChar();
    }
    return true;
  }

  private boolean isSimpleDigit(char c) {
    return '0' <= c && c <= '9';
  }

  private Object maybeParseRangeOrInt() {
    if (!isSimpleDigit(peekChar(0))) {
      return null;
    }
    int from = parseNumber();
    skipWhitespace();
    if (peekChar(0) != ':') {
      return from;
    }
    expect(':');
    skipWhitespace();
    int to = parseNumber();
    return new Range(from, to);
  }

  private int parseNumber() {
    int result = 0;
    if (!isSimpleDigit(peekChar(0))) {
      throw new ParseException("Number expected");
    }
    do {
      result *= 10;
      result += Character.getNumericValue(nextChar());
    } while (isSimpleDigit(peekChar(0)));
    return result;
  }

  private JsonObject parseJsonInComment() {
    assert isCommentLineWithJsonBrace();
    try {
      int firstIndex = 0;
      while (line.charAt(firstIndex) != '{') {
        firstIndex++;
      }
      return jsonParser.parse(line.substring(firstIndex)).getAsJsonObject();
    } catch (com.google.gson.JsonSyntaxException ex) {
      // An info message is reported in MappingInformation.
      return null;
    }
  }

  public class ParseException extends RuntimeException {

    private final int lineNo;
    private final int lineOffset;
    private final boolean eol;
    private final String msg;

    ParseException(String msg) {
      this(msg, false);
    }

    ParseException(String msg, boolean eol) {
      lineNo = ProguardMapReader.this.lineNo;
      lineOffset = ProguardMapReader.this.lineOffset;
      this.eol = eol;
      this.msg = msg;
    }

    @Override
    public String toString() {
      if (eol) {
        return "Parse error [" + lineNo + ":eol] " + msg;
      } else {
        return "Parse error [" + lineNo + ":" + lineOffset + "] " + msg;
      }
    }
  }
}
