// 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.PositionRangeAllocator.CardinalPositionRangeAllocator;
import com.android.tools.r8.naming.PositionRangeAllocator.NonCardinalPositionRangeAllocator;
import com.android.tools.r8.naming.mappinginformation.MapVersionMappingInformation;
import com.android.tools.r8.naming.mappinginformation.MappingInformation;
import com.android.tools.r8.naming.mappinginformation.MappingInformation.ReferentialMappingInformation;
import com.android.tools.r8.naming.mappinginformation.MappingInformationDiagnostics;
import com.android.tools.r8.naming.mappinginformation.ResidualSignatureMappingInformation;
import com.android.tools.r8.naming.mappinginformation.ResidualSignatureMappingInformation.ResidualFieldSignatureMappingInformation;
import com.android.tools.r8.naming.mappinginformation.ResidualSignatureMappingInformation.ResidualMethodSignatureMappingInformation;
import com.android.tools.r8.position.Position;
import com.android.tools.r8.utils.ArrayUtils;
import com.android.tools.r8.utils.BooleanBox;
import com.android.tools.r8.utils.Box;
import com.android.tools.r8.utils.DescriptorUtils;
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.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.function.Function;

/**
 * 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 LineReader reader;
  private final JsonParser jsonParser = new JsonParser();
  private final DiagnosticsHandler diagnosticsHandler;
  private final boolean allowEmptyMappedRanges;
  private final boolean allowExperimentalMapping;
  private boolean seenClassMapping = false;

  private final CardinalPositionRangeAllocator cardinalRangeCache =
      PositionRangeAllocator.createCardinalPositionRangeAllocator();
  private final NonCardinalPositionRangeAllocator nonCardinalRangeCache =
      PositionRangeAllocator.createNonCardinalPositionRangeAllocator();

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

  ProguardMapReader(
      LineReader reader,
      DiagnosticsHandler diagnosticsHandler,
      boolean allowEmptyMappedRanges,
      boolean allowExperimentalMapping) {
    this(
        reader,
        diagnosticsHandler,
        allowEmptyMappedRanges,
        allowExperimentalMapping,
        MapVersion.MAP_VERSION_NONE);
  }

  ProguardMapReader(
      LineReader reader,
      DiagnosticsHandler diagnosticsHandler,
      boolean allowEmptyMappedRanges,
      boolean allowExperimentalMapping,
      MapVersion mapVersion) {
    this.reader = reader;
    this.diagnosticsHandler = diagnosticsHandler;
    this.allowEmptyMappedRanges = allowEmptyMappedRanges;
    this.allowExperimentalMapping = allowExperimentalMapping;
    this.version = mapVersion;
    assert reader != null;
    assert diagnosticsHandler != null;
  }

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

  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(ProguardMap.Builder mapBuilder) throws IOException {
    if (line.length() != lineOffset) {
      throw new ParseException("Expected end of line");
    }
    return skipLine(mapBuilder);
  }

  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(ProguardMap.Builder mapBuilder) throws IOException {
    lineOffset = 0;
    boolean isEmptyOrCommentLine;
    do {
      line = reader.readLine();
      lineNo++;
      isEmptyOrCommentLine = isEmptyOrCommentLine(line);
      if (!seenClassMapping && isEmptyOrCommentLine) {
        mapBuilder.addPreambleLine(line);
      }
    } while (hasLine() && isEmptyOrCommentLine);
    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.
    skipLine(mapBuilder);
    parseClassMappings(mapBuilder);
  }

  // Parsing of entries

  private void parseClassMappings(ProguardMap.Builder mapBuilder) throws IOException {
    while (hasLine()) {
      skipWhitespace();
      if (isCommentLineWithJsonBrace()) {
        if (!parseMappingInformation(
            info -> {
              assert info.isMapVersionMappingInformation()
                  || info.isUnknownJsonMappingInformation();
              if (info.isMapVersionMappingInformation()) {
                mapBuilder.setCurrentMapVersion(info.asMapVersionMappingInformation());
              } else if (!seenClassMapping) {
                mapBuilder.addPreambleLine(line);
              }
            })) {
          if (!seenClassMapping) {
            mapBuilder.addPreambleLine(line);
          }
        }
        // Skip reading the rest of the line.
        lineOffset = line.length();
        nextLine(mapBuilder);
        continue;
      }
      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(':');
      seenClassMapping = true;
      ClassNaming.Builder currentClassBuilder =
          mapBuilder.classNamingBuilder(after, before, getPosition());
      skipWhitespace();
      if (nextLine(mapBuilder)) {
        parseMemberMappings(mapBuilder, currentClassBuilder);
      }
    }
  }

  private boolean parseMappingInformation(Consumer<MappingInformation> onMappingInfo) {
    JsonObject object = parseJsonInComment();
    if (object != null) {
      MappingInformation.fromJsonObject(
          version,
          object,
          diagnosticsHandler,
          lineNo,
          info -> {
            MapVersionMappingInformation generatorInfo = info.asMapVersionMappingInformation();
            if (generatorInfo != null) {
              if (generatorInfo.getMapVersion().equals(MapVersion.MAP_VERSION_EXPERIMENTAL)) {
                // 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.MAP_VERSION_EXPERIMENTAL
                        : MapVersion.MAP_VERSION_NONE;
              } else {
                version = generatorInfo.getMapVersion();
              }
            }
            onMappingInfo.accept(info);
          });
      return true;
    }
    return false;
  }

  private void parseMemberMappings(
      ProguardMap.Builder mapBuilder, ClassNaming.Builder classNamingBuilder) throws IOException {
    MemberNaming lastAddedNaming = null;
    // To ensure we only commit a member if we have the residual signature, we delay creating the
    // object and have the variables out here.
    Signature previousOriginalSignature = null;
    String previousRenamedName = null;
    int previousLineNumber = -1;
    Range previousRange = null;
    Box<Signature> currentResidualSignature = new Box<>();
    Box<List<ReferentialMappingInformation>> currentMappingInfoForMemberNaming = new Box<>();
    MappedRange activeMappedRange = null;
    do {
      Range originalRange = null;
      // Try to parse any information added in comments above member namings
      if (isCommentLineWithJsonBrace()) {
        final String currentRenamedNameFinal = previousRenamedName;
        final MappedRange currentRange = activeMappedRange;
        // Reading global info should cause member mapping to return since we are now reading
        // headers pertaining to what could be a concatinated file.
        BooleanBox readGlobalInfo = new BooleanBox(false);
        parseMappingInformation(
            info -> {
              readGlobalInfo.set(info.isGlobalMappingInformation());
              if (currentRenamedNameFinal == null) {
                classNamingBuilder.addMappingInformation(
                    info,
                    conflictingInfo ->
                        diagnosticsHandler.warning(
                            MappingInformationDiagnostics.notAllowedCombination(
                                info, conflictingInfo, lineNo)));
                return;
              }
              // Always add information to the current range, this will ensure that additional
              // information is always placed the same place.
              if (currentRange != null) {
                currentRange.addMappingInformation(
                    info,
                    conflictingInfo ->
                        diagnosticsHandler.warning(
                            MappingInformationDiagnostics.notAllowedCombination(
                                info, conflictingInfo, lineNo)));
              }
              if (info.isReferentialMappingInformation()) {
                ReferentialMappingInformation referentialMappingInformation =
                    info.asReferentialMappingInformation();
                MappingInformation.addMappingInformation(
                    currentMappingInfoForMemberNaming.computeIfAbsent(ArrayList::new),
                    referentialMappingInformation,
                    conflictingInfo ->
                        diagnosticsHandler.warning(
                            MappingInformationDiagnostics.notAllowedCombination(
                                info, conflictingInfo, lineNo)));
                if (info.isResidualSignatureMappingInformation()) {
                  Signature residualSignature =
                      getResidualSignatureFromMappingInformation(
                          info.asResidualSignatureMappingInformation(), currentRenamedNameFinal);
                  currentResidualSignature.set(residualSignature);
                  if (currentRange != null) {
                    currentRange.setResidualSignatureInternal(
                        residualSignature.asMethodSignature());
                  }
                }
              }
            });
        if (readGlobalInfo.isTrue()) {
          break;
        }
        // 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();
      Range mappedRange = parseRange();
      if (mappedRange != null) {
        if (mappedRange.isCardinal) {
          throw new ParseException(
              String.format("Invalid obfuscated line number range (%s).", mappedRange));
        }
        skipWhitespace();
        expect(':');
      }
      skipWhitespace();
      Signature signature = parseSignature();
      skipWhitespace();
      if (peekChar(0) == ':') {
        // This is a mapping or inlining definition
        nextChar();
        skipWhitespace();
        originalRange = parseRange();
        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.isMethodSignature()) {
        MethodSignature residualSignature = null;
        // Propagate the active residual signature down to the next read mapped range if the
        // original signature and name is the same - that is, there are no inline frames.
        if (activeMappedRange != null
            && activeMappedRange.signature == signature
            && activeMappedRange.renamedName.equals(renamedName)) {
          residualSignature = activeMappedRange.getResidualSignature();
        }
        activeMappedRange =
            classNamingBuilder.addMappedRange(
                mappedRange, signature.asMethodSignature(), originalRange, renamedName);
        if (activeMappedRange != null) {
          if (residualSignature != null) {
            activeMappedRange.setResidualSignatureInternal(residualSignature);
          } else if (lastAddedNaming != null
              && lastAddedNaming
                  .getOriginalSignature()
                  .equals(activeMappedRange.getOriginalSignature())) {
            // If we already parsed a residual signature for the newly read mapped range and have
            // lost the information about the residual signature we re-create it again.
            activeMappedRange.setResidualSignatureInternal(
                lastAddedNaming.getResidualSignature().asMethodSignature());
          }
        }
      }

      assert mappedRange == null || signature.isMethodSignature();
      if (previousOriginalSignature != null) {
        boolean changedName = !previousRenamedName.equals(renamedName);
        boolean changedMappedRange =
            previousRange == null || !Objects.equals(previousRange, mappedRange);
        boolean originalRangeChange = originalRange == null || !originalRange.isCardinal;
        if (changedName || changedMappedRange || originalRangeChange) {
          lastAddedNaming =
              addMemberEntryOrCopyInformation(
                  lastAddedNaming,
                  previousOriginalSignature,
                  previousRenamedName,
                  previousLineNumber,
                  currentResidualSignature,
                  currentMappingInfoForMemberNaming,
                  previousRange,
                  classNamingBuilder);
        }
      }
      previousOriginalSignature = signature;
      previousRenamedName = renamedName;
      previousLineNumber = lineNo;
      previousRange = mappedRange;
    } while (nextLine(mapBuilder));

    if (previousOriginalSignature != null) {
      addMemberEntryOrCopyInformation(
          lastAddedNaming,
          previousOriginalSignature,
          previousRenamedName,
          previousLineNumber,
          currentResidualSignature,
          currentMappingInfoForMemberNaming,
          previousRange,
          classNamingBuilder);
    }
  }

  private MemberNaming addMemberEntryOrCopyInformation(
      MemberNaming lastAddedNaming,
      Signature originalSignature,
      String renamedName,
      int lineNumber,
      Box<Signature> residualSignature,
      Box<List<ReferentialMappingInformation>> additionalMappingInformation,
      Range previousMappedRange,
      ClassNaming.Builder classNamingBuilder) {
    // 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 (previousMappedRange == null
        || lastAddedNaming == null
        || !lastAddedNaming.getRenamedName().equals(renamedName)
        || !lastAddedNaming.getOriginalSignature().equals(originalSignature)) {
      MemberNaming newMemberNaming =
          new MemberNaming(
              originalSignature,
              getResidualSignatureForMemberNaming(
                  residualSignature, originalSignature, renamedName),
              new LinePosition(lineNumber));
      if (additionalMappingInformation.isSet()) {
        newMemberNaming.addAllMappingInformationInternal(additionalMappingInformation.get());
      }
      classNamingBuilder.addMemberEntry(newMemberNaming);
      residualSignature.clear();
      additionalMappingInformation.clear();
      return newMemberNaming;
    }
    if (additionalMappingInformation.isSet()) {
      lastAddedNaming.addAllMappingInformationInternal(additionalMappingInformation.get());
      additionalMappingInformation.clear();
    }
    residualSignature.clear();
    return lastAddedNaming;
  }

  private Signature getResidualSignatureFromMappingInformation(
      ResidualSignatureMappingInformation mappingInformation, String renamedName) {
    if (mappingInformation.isResidualMethodSignatureMappingInformation()) {
      ResidualMethodSignatureMappingInformation residualSignatureInfo =
          mappingInformation.asResidualMethodSignatureMappingInformation();
      MethodSignature residualSignature =
          new MethodSignature(
              renamedName,
              DescriptorUtils.descriptorToJavaType(residualSignatureInfo.getReturnType()),
              ArrayUtils.mapToStringArray(
                  residualSignatureInfo.getParameters(), DescriptorUtils::descriptorToJavaType));
      return signatureCache
          .computeIfAbsent(residualSignature, Function.identity())
          .asMethodSignature();
    } else {
      assert mappingInformation.isResidualFieldSignatureMappingInformation();
      ResidualFieldSignatureMappingInformation residualSignatureInfo =
          mappingInformation.asResidualFieldSignatureMappingInformation();
      FieldSignature residualSignature =
          new FieldSignature(
              renamedName, DescriptorUtils.descriptorToJavaType(residualSignatureInfo.getType()));
      return signatureCache
          .computeIfAbsent(residualSignature, Function.identity())
          .asFieldSignature();
    }
  }

  private Signature getResidualSignatureForMemberNaming(
      Box<Signature> residualSignature, Signature originalSignature, String renamedName) {
    if (residualSignature.isSet()) {
      return residualSignature.get();
    }
    Signature signature = originalSignature.asRenamed(renamedName);
    signature = signatureCache.computeIfAbsent(signature, Function.identity());
    return signature;
  }

  private Position getPosition() {
    return new LinePosition(lineNo);
  }

  private static final class LinePosition implements Position {
    private final int lineNo;

    LinePosition(int lineNo) {
      this.lineNo = lineNo;
    }

    @Override
    public String getDescription() {
      return "line " + lineNo;
    }

    @Override
    public int hashCode() {
      return lineNo;
    }

    @Override
    public boolean equals(Object o) {
      if (o == this) {
        return true;
      }
      if (o instanceof LinePosition) {
        return lineNo == ((LinePosition) o).lineNo;
      }
      return false;
    }
  }

  // Parsing of components

  private void skipIdentifier(boolean allowInit) {
    boolean isInit = false;
    if (allowInit && peekChar(0) == '<') {
      // swallow the leading < character
      nextChar();
      isInit = true;
    }
    // Proguard 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()) + ")");
    }
  }

  // Small direct-mapped cache for computing String.substring.
  //
  // Due to inlining, the same method names and parameter types will occur repeatedly on multiple
  // lines.  String.substring ends up allocating a lot of garbage, so we use this cache to find
  // String objects without having to allocate memory.
  //
  // "Direct-mapped" is inspired from computer architecture, where having a lookup policy in
  // which entries can only ever map to one cache line is often faster than a fancy LRU cache.
  private static final int SUBSTRING_CACHE_SIZE = 64;
  private final String[] substringCache = new String[SUBSTRING_CACHE_SIZE];
  // Cache for canonicalizing strings.
  // This saves 10% of heap space for large programs.
  private final HashMap<String, String> identifierCache = new HashMap<>();

  // Cache for canonicalizing signatures.
  //
  // Due to inlining, the same MethodSignature will come up many times in a ProguardMap.
  // This happens to help a bit for FieldSignature too, so lump those in.
  private final HashMap<Signature, Signature> signatureCache = new HashMap<>();

  private String substring(int start) {
    int cacheIdx;
    {
      // Check if there was a recent String accessed which matches the substring.
      int len = lineOffset - start;
      cacheIdx = len % SUBSTRING_CACHE_SIZE;
      String candidate = substringCache[cacheIdx];
      if (candidate != null
          && candidate.length() == len
          && line.regionMatches(start, candidate, 0, len)) {
        return candidate;
      }
    }

    String result = line.substring(start, lineOffset);
    return substringCache[cacheIdx] = identifierCache.computeIfAbsent(result, Function.identity());
  }

  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 = StringUtils.EMPTY_ARRAY;
      } else {
        List<String> items = new ArrayList<>();
        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 signatureCache.computeIfAbsent(signature, Function.identity());
  }

  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 Range parseRange() {
    if (!isSimpleDigit(peekChar(0))) {
      return null;
    }
    int from = parseNumber();
    skipWhitespace();
    if (peekChar(0) != ':') {
      return cardinalRangeCache.get(from);
    }
    expect(':');
    skipWhitespace();
    int to = parseNumber();
    return nonCardinalRangeCache.get(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;
      }
    }
  }
}
