// 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()
                  || info.isPartitionFileNameInformation();
              if (info.isMapVersionMappingInformation()) {
                mapBuilder.setCurrentMapVersion(info.asMapVersionMappingInformation());
              } else if (info.isPartitionFileNameInformation()) {
                info.asPartitionFileNameInformation()
                    .getTypeNameToFileNameMapping()
                    .forEach(mapBuilder::addFileName);
              } 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)) {
      Signature lookupKey =
          getResidualSignatureForMemberNaming(residualSignature, originalSignature, renamedName);
      MemberNaming newMemberNaming = classNamingBuilder.lookupMemberEntry(lookupKey);
      if (newMemberNaming == null) {
        newMemberNaming =
            new MemberNaming(originalSignature, lookupKey, new LinePosition(lineNumber));
      }
      if (additionalMappingInformation.isSet()) {
        newMemberNaming.addAllMappingInformation(additionalMappingInformation.get());
      }
      classNamingBuilder.addMemberEntry(newMemberNaming);
      residualSignature.clear();
      additionalMappingInformation.clear();
      return newMemberNaming;
    }
    if (additionalMappingInformation.isSet()) {
      lastAddedNaming.addAllMappingInformation(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();
    if (from > to) {
      throw new ParseException("From is larger than to in range: " + from + ":" + to);
    }
    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 getMessage() {
      if (eol) {
        return "Parse error [" + lineNo + ":eol] " + msg;
      } else {
        return "Parse error [" + lineNo + ":" + lineOffset + "] " + msg;
      }
    }
  }
}
