// 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()) {
                  ResidualSignatureMappingInformation mappingInfo =
                      info.asResidualSignatureMappingInformation();
                  if (!mappingInfo.isValid()) {
                    diagnosticsHandler.warning(
                        MappingInformationDiagnostics.invalidResidualSignature(
                            line.trim(), lineNo));
                    return;
                  }
                  Signature residualSignature =
                      getResidualSignatureFromMappingInformation(
                          info.asResidualSignatureMappingInformation(), currentRenamedNameFinal);
                  currentResidualSignature.set(residualSignature);
                  if (currentRange != null) {
                    if (!mappingInfo.isResidualMethodSignatureMappingInformation()) {
                      diagnosticsHandler.warning(
                          MappingInformationDiagnostics.invalidResidualSignatureType(
                              info.serialize(), lineNo));
                      currentResidualSignature.clear();
                      return;
                    }
                    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()) {
      if (residualSignature.get().kind() != originalSignature.kind()) {
        diagnosticsHandler.warning(
            MappingInformationDiagnostics.invalidResidualSignatureType(
                residualSignature.get().toString(), lineNo));

      } else {
        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) {
      super(msg);
      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;
      }
    }
  }
}
