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

import com.android.tools.r8.DiagnosticsHandler;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.references.ClassReference;
import com.android.tools.r8.references.FieldReference;
import com.android.tools.r8.references.Reference;
import com.android.tools.r8.references.TypeReference;
import com.android.tools.r8.retrace.RetraceClassResult.Element;
import com.android.tools.r8.retrace.RetraceRegularExpression.ClassNameGroup.ClassNameGroupHandler;
import com.android.tools.r8.utils.Box;
import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.StringDiagnostic;
import com.android.tools.r8.utils.StringUtils;
import com.google.common.collect.Lists;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

public class RetraceRegularExpression {

  private final RetraceApi retracer;
  private final List<String> stackTrace;
  private final DiagnosticsHandler diagnosticsHandler;
  private final String regularExpression;

  private static final int NO_MATCH = -1;

  private final SourceFileLineNumberGroup sourceFileLineNumberGroup =
      new SourceFileLineNumberGroup();
  private final TypeNameGroup typeNameGroup = new TypeNameGroup();
  private final BinaryNameGroup binaryNameGroup = new BinaryNameGroup();
  private final SourceFileGroup sourceFileGroup = new SourceFileGroup();
  private final LineNumberGroup lineNumberGroup = new LineNumberGroup();
  private final FieldOrReturnTypeGroup fieldOrReturnTypeGroup = new FieldOrReturnTypeGroup();
  private final MethodArgumentsGroup methodArgumentsGroup = new MethodArgumentsGroup();

  private final MethodNameGroup methodNameGroup;
  private final FieldNameGroup fieldNameGroup;

  private static final String CAPTURE_GROUP_PREFIX = "captureGroup";
  private static final int FIRST_CAPTURE_GROUP_INDEX = 0;

  RetraceRegularExpression(
      RetraceApi retracer,
      List<String> stackTrace,
      DiagnosticsHandler diagnosticsHandler,
      String regularExpression,
      boolean isVerbose) {
    this.retracer = retracer;
    this.stackTrace = stackTrace;
    this.diagnosticsHandler = diagnosticsHandler;
    this.regularExpression = regularExpression;
    methodNameGroup = new MethodNameGroup(isVerbose);
    fieldNameGroup = new FieldNameGroup(isVerbose);
  }

  public RetraceCommandLineResult retrace() {
    List<RegularExpressionGroupHandler> handlers = new ArrayList<>();
    StringBuilder refinedRegularExpressionBuilder = new StringBuilder();
    registerGroups(
        this.regularExpression,
        refinedRegularExpressionBuilder,
        handlers,
        FIRST_CAPTURE_GROUP_INDEX);
    String refinedRegularExpression = refinedRegularExpressionBuilder.toString();
    Pattern compiledPattern = Pattern.compile(refinedRegularExpression);
    List<String> result = new ArrayList<>();
    for (String string : stackTrace) {
      Matcher matcher = compiledPattern.matcher(string);
      if (!matcher.matches()) {
        result.add(string);
        continue;
      }
      // Iterate through handlers to set contexts. That will allow us to process all handlers from
      // left to right.
      RetraceStringContext initialContext = RetraceStringContext.empty();
      for (RegularExpressionGroupHandler handler : handlers) {
        initialContext = handler.buildInitial(initialContext, matcher, retracer);
      }
      final RetraceString initialRetraceString = RetraceString.start(initialContext);
      List<RetraceString> retracedStrings = Lists.newArrayList(initialRetraceString);
      for (RegularExpressionGroupHandler handler : handlers) {
        retracedStrings = handler.handleMatch(string, retracedStrings, matcher, retracer);
      }
      if (retracedStrings.isEmpty()) {
        // We could not find a match. Output the identity.
        result.add(string);
      }
      boolean isAmbiguous = retracedStrings.size() > 1 && retracedStrings.get(0).isAmbiguous();
      if (isAmbiguous) {
        retracedStrings.sort(new RetraceLineComparator());
      }
      ClassReference previousContext = null;
      for (RetraceString retracedString : retracedStrings) {
        String finalString = retracedString.builder.build(string);
        if (!isAmbiguous) {
          result.add(finalString);
          continue;
        }
        assert retracedString.getClassContext() != null;
        ClassReference currentContext = retracedString.getClassContext().getClassReference();
        if (currentContext.equals(previousContext)) {
          int firstNonWhitespaceCharacter = StringUtils.firstNonWhitespaceCharacter(finalString);
          finalString =
              finalString.substring(0, firstNonWhitespaceCharacter)
                  + "<OR> "
                  + finalString.substring(firstNonWhitespaceCharacter);
        }
        previousContext = currentContext;
        result.add(finalString);
      }
    }
    return new RetraceCommandLineResult(result);
  }

  static class RetraceLineComparator extends AmbiguousComparator<RetraceString> {

    RetraceLineComparator() {
      super(
          (line, t) -> {
            switch (t) {
              case CLASS:
                return line.getClassContext().getClassReference().getTypeName();
              case METHOD:
                return line.getMethodContext().getMethodReference().getMethodName();
              case SOURCE:
                return line.getSource();
              case LINE:
                return line.getLineNumber() + "";
              default:
                assert false;
            }
            throw new RuntimeException("Comparator key is unknown");
          });
    }
  }

  private int registerGroups(
      String regularExpression,
      StringBuilder refinedRegularExpression,
      List<RegularExpressionGroupHandler> handlers,
      int captureGroupIndex) {
    int lastCommittedIndex = 0;
    RegularExpressionGroupHandler lastHandler = null;
    boolean seenPercentage = false;
    boolean escaped = false;
    for (int i = 0; i < regularExpression.length(); i++) {
      if (seenPercentage) {
        assert !escaped;
        final RegularExpressionGroup group = getGroupFromVariable(regularExpression.charAt(i));
        refinedRegularExpression.append(regularExpression, lastCommittedIndex, i - 1);
        if (group.isSynthetic()) {
          captureGroupIndex =
              registerGroups(
                  group.subExpression(), refinedRegularExpression, handlers, captureGroupIndex);
        } else {
          String captureGroupName = CAPTURE_GROUP_PREFIX + (captureGroupIndex++);
          refinedRegularExpression
              .append("(?<")
              .append(captureGroupName)
              .append(">")
              .append(group.subExpression())
              .append(")");
          final RegularExpressionGroupHandler handler = group.createHandler(captureGroupName);
          // If we see a pattern as %c.%m or %C/%m, then register the groups to allow delaying
          // writing of the class string until we have the fully qualified member.
          if (lastHandler != null
              && handler.isQualifiedHandler()
              && lastHandler.isClassNameGroupHandler()
              && lastCommittedIndex == i - 3
              && isTypeOrBinarySeparator(regularExpression, lastCommittedIndex, i - 2)) {
            final ClassNameGroupHandler classNameGroupHandler =
                lastHandler.asClassNameGroupHandler();
            final QualifiedRegularExpressionGroupHandler qualifiedHandler =
                handler.asQualifiedHandler();
            classNameGroupHandler.setQualifiedHandler(qualifiedHandler);
            qualifiedHandler.setClassNameGroupHandler(classNameGroupHandler);
          }
          lastHandler = handler;
          handlers.add(handler);
        }
        lastCommittedIndex = i + 1;
        seenPercentage = false;
      } else {
        seenPercentage = !escaped && regularExpression.charAt(i) == '%';
        escaped = !escaped && regularExpression.charAt(i) == '\\';
      }
    }
    refinedRegularExpression.append(
        regularExpression, lastCommittedIndex, regularExpression.length());
    return captureGroupIndex;
  }

  private boolean isTypeOrBinarySeparator(String regularExpression, int startIndex, int endIndex) {
    assert endIndex < regularExpression.length();
    if (startIndex + 1 != endIndex) {
      return false;
    }
    if (regularExpression.charAt(startIndex) != '\\') {
      return false;
    }
    return regularExpression.charAt(startIndex + 1) == '.'
        || regularExpression.charAt(startIndex + 1) == '/';
  }

  private RegularExpressionGroup getGroupFromVariable(char variable) {
    switch (variable) {
      case 'c':
        return typeNameGroup;
      case 'C':
        return binaryNameGroup;
      case 'm':
        return methodNameGroup;
      case 'f':
        return fieldNameGroup;
      case 's':
        return sourceFileGroup;
      case 'l':
        return lineNumberGroup;
      case 'S':
        return sourceFileLineNumberGroup;
      case 't':
        return fieldOrReturnTypeGroup;
      case 'a':
        return methodArgumentsGroup;
      default:
        throw new Unreachable("Unexpected variable: " + variable);
    }
  }

  static class RetraceStringContext {
    private final Element classContext;
    private final ClassReference qualifiedContext;
    private final String methodName;
    private final RetraceMethodResult.Element methodContext;
    private final int minifiedLineNumber;
    private final int originalLineNumber;
    private final String source;
    private final boolean isAmbiguous;

    private RetraceStringContext(
        Element classContext,
        ClassReference qualifiedContext,
        String methodName,
        RetraceMethodResult.Element methodContext,
        int minifiedLineNumber,
        int originalLineNumber,
        String source,
        boolean isAmbiguous) {
      this.classContext = classContext;
      this.qualifiedContext = qualifiedContext;
      this.methodName = methodName;
      this.methodContext = methodContext;
      this.minifiedLineNumber = minifiedLineNumber;
      this.originalLineNumber = originalLineNumber;
      this.source = source;
      this.isAmbiguous = isAmbiguous;
    }

    private static RetraceStringContext empty() {
      return new RetraceStringContext(null, null, null, null, NO_MATCH, NO_MATCH, null, false);
    }

    private RetraceStringContext withClassContext(
        Element classContext, ClassReference qualifiedContext) {
      return new RetraceStringContext(
          classContext,
          qualifiedContext,
          methodName,
          methodContext,
          minifiedLineNumber,
          originalLineNumber,
          source,
          isAmbiguous);
    }

    private RetraceStringContext withMethodName(String methodName) {
      return new RetraceStringContext(
          classContext,
          qualifiedContext,
          methodName,
          methodContext,
          minifiedLineNumber,
          originalLineNumber,
          source,
          isAmbiguous);
    }

    private RetraceStringContext withMethodContext(
        RetraceMethodResult.Element methodContext,
        ClassReference qualifiedContext,
        boolean isAmbiguous) {
      return new RetraceStringContext(
          classContext,
          qualifiedContext,
          methodName,
          methodContext,
          minifiedLineNumber,
          originalLineNumber,
          source,
          isAmbiguous);
    }

    private RetraceStringContext withQualifiedContext(ClassReference qualifiedContext) {
      return new RetraceStringContext(
          classContext,
          qualifiedContext,
          methodName,
          methodContext,
          minifiedLineNumber,
          originalLineNumber,
          source,
          isAmbiguous);
    }

    public RetraceStringContext withSource(String source) {
      return new RetraceStringContext(
          classContext,
          qualifiedContext,
          methodName,
          methodContext,
          minifiedLineNumber,
          originalLineNumber,
          source,
          isAmbiguous);
    }

    public RetraceStringContext withLineNumbers(int minifiedLineNumber, int originalLineNumber) {
      return new RetraceStringContext(
          classContext,
          qualifiedContext,
          methodName,
          methodContext,
          minifiedLineNumber,
          originalLineNumber,
          source,
          isAmbiguous);
    }
  }

  static class RetraceStringBuilder {

    private final StringBuilder retracedString;
    private int lastCommittedIndex;

    private RetraceStringBuilder(String retracedString, int lastCommittedIndex) {
      this.retracedString = new StringBuilder(retracedString);
      this.lastCommittedIndex = lastCommittedIndex;
    }

    private void appendRetracedString(
        String source, String stringToAppend, int originalFromIndex, int originalToIndex) {
      retracedString.append(source, lastCommittedIndex, originalFromIndex);
      retracedString.append(stringToAppend);
      lastCommittedIndex = originalToIndex;
    }

    private String build(String source) {
      return retracedString.append(source, lastCommittedIndex, source.length()).toString();
    }
  }

  private static class RetraceString {

    private final RetraceStringBuilder builder;
    private final RetraceStringContext context;

    private RetraceString(RetraceStringBuilder builder, RetraceStringContext context) {
      this.builder = builder;
      this.context = context;
    }

    private Element getClassContext() {
      return context.classContext;
    }

    private RetraceMethodResult.Element getMethodContext() {
      return context.methodContext;
    }

    private String getSource() {
      return context.source;
    }

    private int getLineNumber() {
      return context.originalLineNumber;
    }

    private boolean isAmbiguous() {
      return context.isAmbiguous;
    }

    private static RetraceString start(RetraceStringContext initialContext) {
      return new RetraceString(new RetraceStringBuilder("", 0), initialContext);
    }

    private RetraceString updateContext(
        Function<RetraceStringContext, RetraceStringContext> update) {
      return new RetraceString(builder, update.apply(context));
    }

    private RetraceString duplicate(RetraceStringContext newContext) {
      return new RetraceString(
          new RetraceStringBuilder(builder.retracedString.toString(), builder.lastCommittedIndex),
          newContext);
    }

    private RetraceString appendRetracedString(
        String source, String stringToAppend, int originalFromIndex, int originalToIndex) {
      builder.appendRetracedString(source, stringToAppend, originalFromIndex, originalToIndex);
      return this;
    }
  }

  private interface RegularExpressionGroupHandler {

    List<RetraceString> handleMatch(
        String original, List<RetraceString> strings, Matcher matcher, RetraceApi retracer);

    default RetraceStringContext buildInitial(
        RetraceStringContext context, Matcher matcher, RetraceApi retracer) {
      return context;
    }

    default boolean isClassNameGroupHandler() {
      return false;
    }

    default ClassNameGroupHandler asClassNameGroupHandler() {
      return null;
    }

    default boolean isQualifiedHandler() {
      return false;
    }

    default QualifiedRegularExpressionGroupHandler asQualifiedHandler() {
      return null;
    }
  }

  private interface QualifiedRegularExpressionGroupHandler extends RegularExpressionGroupHandler {

    @Override
    default boolean isQualifiedHandler() {
      return true;
    }

    @Override
    default QualifiedRegularExpressionGroupHandler asQualifiedHandler() {
      return this;
    }

    void setClassNameGroupHandler(ClassNameGroupHandler handler);
  }

  private abstract static class RegularExpressionGroup {

    abstract String subExpression();

    abstract RegularExpressionGroupHandler createHandler(String captureGroup);

    boolean isSynthetic() {
      return false;
    }
  }

  // TODO(b/145731185): Extend support for identifiers with strings inside back ticks.
  private static final String javaIdentifierSegment =
      "\\p{javaJavaIdentifierStart}\\p{javaJavaIdentifierPart}*";

  private static final String METHOD_NAME_REGULAR_EXPRESSION =
      "(?:(" + javaIdentifierSegment + "|\\<init\\>|\\<clinit\\>))";

  abstract static class ClassNameGroup extends RegularExpressionGroup {

    abstract String getClassName(ClassReference classReference);

    abstract ClassReference classFromMatch(String match);

    @Override
    RegularExpressionGroupHandler createHandler(String captureGroup) {
      return new ClassNameGroupHandler(this, captureGroup);
    }

    static class ClassNameGroupHandler implements RegularExpressionGroupHandler {

      private RetraceClassResult retraceClassResult = null;
      private final ClassNameGroup classNameGroup;
      private final String captureGroup;
      private RegularExpressionGroupHandler qualifiedHandler;

      public ClassNameGroupHandler(ClassNameGroup classNameGroup, String captureGroup) {
        this.classNameGroup = classNameGroup;
        this.captureGroup = captureGroup;
      }

      @Override
      public List<RetraceString> handleMatch(
          String original, List<RetraceString> strings, Matcher matcher, RetraceApi retracer) {
        final int startOfGroup = matcher.start(captureGroup);
        if (startOfGroup == NO_MATCH) {
          return strings;
        }
        String typeName = matcher.group(captureGroup);
        RetraceClassResult retraceResult =
            retraceClassResult == null
                ? retracer.retrace(classNameGroup.classFromMatch(typeName))
                : retraceClassResult;
        assert !retraceResult.isAmbiguous();
        List<RetraceString> retraceStrings = new ArrayList<>(strings.size());
        for (RetraceString retraceString : strings) {
          retraceResult.forEach(
              element -> {
                final RetraceString newRetraceString =
                    retraceString.updateContext(
                        context -> context.withClassContext(element, element.getClassReference()));
                retraceStrings.add(newRetraceString);
                if (qualifiedHandler == null) {
                  // If there is no qualified handler, commit right away.
                  newRetraceString.builder.appendRetracedString(
                      original,
                      classNameGroup.getClassName(element.getClassReference()),
                      startOfGroup,
                      matcher.end(captureGroup));
                }
              });
        }
        return retraceStrings;
      }

      void commitClassName(
          String original,
          RetraceString retraceString,
          ClassReference qualifiedContext,
          Matcher matcher) {
        if (matcher.start(captureGroup) == NO_MATCH) {
          return;
        }
        retraceString.builder.appendRetracedString(
            original,
            classNameGroup.getClassName(qualifiedContext),
            matcher.start(captureGroup),
            matcher.end(captureGroup));
      }

      @Override
      public RetraceStringContext buildInitial(
          RetraceStringContext context, Matcher matcher, RetraceApi retracer) {
        // Reset the local class context since this the same handler is used for multiple lines.
        retraceClassResult = null;
        if (matcher.start(captureGroup) == NO_MATCH || context.classContext != null) {
          return context;
        }
        String typeName = matcher.group(captureGroup);
        retraceClassResult = retracer.retrace(classNameGroup.classFromMatch(typeName));
        assert !retraceClassResult.isAmbiguous();
        Box<RetraceStringContext> box = new Box<>();
        retraceClassResult.forEach(
            element -> box.set(context.withClassContext(element, element.getClassReference())));
        return box.get();
      }

      public void setQualifiedHandler(RegularExpressionGroupHandler handler) {
        assert handler.isQualifiedHandler();
        this.qualifiedHandler = handler;
      }

      @Override
      public boolean isClassNameGroupHandler() {
        return true;
      }

      @Override
      public ClassNameGroupHandler asClassNameGroupHandler() {
        return this;
      }
    }
  }

  private static class TypeNameGroup extends ClassNameGroup {

    @Override
    String subExpression() {
      return "(" + javaIdentifierSegment + "\\.)*" + javaIdentifierSegment;
    }

    @Override
    String getClassName(ClassReference classReference) {
      return classReference.getTypeName();
    }

    @Override
    ClassReference classFromMatch(String match) {
      return Reference.classFromTypeName(match);
    }
  }

  private static class BinaryNameGroup extends ClassNameGroup {

    @Override
    String subExpression() {
      return "(?:" + javaIdentifierSegment + "\\/)*" + javaIdentifierSegment;
    }

    @Override
    String getClassName(ClassReference classReference) {
      return classReference.getBinaryName();
    }

    @Override
    ClassReference classFromMatch(String match) {
      return Reference.classFromBinaryName(match);
    }
  }

  private static class MethodNameGroup extends RegularExpressionGroup {

    private final boolean printVerbose;

    public MethodNameGroup(boolean printVerbose) {
      this.printVerbose = printVerbose;
    }

    @Override
    String subExpression() {
      return METHOD_NAME_REGULAR_EXPRESSION;
    }

    @Override
    RegularExpressionGroupHandler createHandler(String captureGroup) {
      return new QualifiedRegularExpressionGroupHandler() {

        private ClassNameGroupHandler classNameGroupHandler;

        @Override
        public void setClassNameGroupHandler(ClassNameGroupHandler handler) {
          classNameGroupHandler = handler;
        }

        @Override
        public List<RetraceString> handleMatch(
            String original, List<RetraceString> strings, Matcher matcher, RetraceApi retracer) {
          final int startOfGroup = matcher.start(captureGroup);
          if (startOfGroup == NO_MATCH) {
            if (classNameGroupHandler != null) {
              for (RetraceString string : strings) {
                classNameGroupHandler.commitClassName(
                    original, string, string.context.qualifiedContext, matcher);
              }
            }
            return strings;
          }
          String methodName = matcher.group(captureGroup);
          List<RetraceString> retracedStrings = new ArrayList<>();
          for (RetraceString retraceString : strings) {
            retraceMethodForString(
                retraceString,
                methodName,
                (element, newContext) -> {
                  final RetraceString newRetraceString = retraceString.duplicate(newContext);
                  if (classNameGroupHandler != null) {
                    classNameGroupHandler.commitClassName(
                        original,
                        newRetraceString,
                        element.getMethodReference().getHolderClass(),
                        matcher);
                  }
                  retracedStrings.add(
                      newRetraceString.appendRetracedString(
                          original,
                          printVerbose
                              ? RetraceUtils.methodDescriptionFromMethodReference(
                                  element.getMethodReference(), false, true)
                              : element.getMethodReference().getMethodName(),
                          startOfGroup,
                          matcher.end(captureGroup)));
                });
          }
          return retracedStrings;
        }

        @Override
        public RetraceStringContext buildInitial(
            RetraceStringContext context, Matcher matcher, RetraceApi retracer) {
          final int startOfGroup = matcher.start(captureGroup);
          if (startOfGroup == NO_MATCH || context.methodName != null) {
            return context;
          }
          return context.withMethodName(matcher.group(captureGroup));
        }
      };
    }

    private static void retraceMethodForString(
        RetraceString retraceString,
        String methodName,
        BiConsumer<RetraceMethodResult.Element, RetraceStringContext> process) {
      if (retraceString.context.classContext == null) {
        return;
      }
      RetraceMethodResult retraceMethodResult =
          retraceString.getClassContext().lookupMethod(methodName);
      if (retraceString.context.minifiedLineNumber > NO_MATCH) {
        retraceMethodResult =
            retraceMethodResult.narrowByLine(retraceString.context.minifiedLineNumber);
      }
      retraceMethodResult.forEach(
          element ->
              process.accept(
                  element,
                  retraceString.context.withMethodContext(
                      element,
                      element.getMethodReference().getHolderClass(),
                      element.getRetraceMethodResult().isAmbiguous())));
    }
  }

  private static class FieldNameGroup extends RegularExpressionGroup {

    private final boolean printVerbose;

    public FieldNameGroup(boolean printVerbose) {
      this.printVerbose = printVerbose;
    }

    @Override
    String subExpression() {
      return javaIdentifierSegment;
    }

    @Override
    RegularExpressionGroupHandler createHandler(String captureGroup) {
      return new QualifiedRegularExpressionGroupHandler() {

        private ClassNameGroupHandler classNameGroupHandler;

        @Override
        public void setClassNameGroupHandler(ClassNameGroupHandler handler) {
          classNameGroupHandler = handler;
        }

        @Override
        public List<RetraceString> handleMatch(
            String original, List<RetraceString> strings, Matcher matcher, RetraceApi retracer) {
          final int startOfGroup = matcher.start(captureGroup);
          if (startOfGroup == NO_MATCH) {
            if (classNameGroupHandler != null) {
              for (RetraceString string : strings) {
                classNameGroupHandler.commitClassName(
                    original, string, string.context.qualifiedContext, matcher);
              }
            }
            return strings;
          }
          String methodName = matcher.group(captureGroup);
          List<RetraceString> retracedStrings = new ArrayList<>();
          for (RetraceString retraceString : strings) {
            if (retraceString.getClassContext() == null) {
              assert classNameGroupHandler == null;
              return strings;
            }
            final RetraceFieldResult retraceFieldResult =
                retraceString.getClassContext().lookupField(methodName);
            assert !retraceFieldResult.isAmbiguous();
            retraceFieldResult.forEach(
                element -> {
                  if (classNameGroupHandler != null) {
                    classNameGroupHandler.commitClassName(
                        original,
                        retraceString,
                        element.getFieldReference().getHolderClass(),
                        matcher);
                  }
                  retracedStrings.add(
                      retraceString
                          .updateContext(
                              context ->
                                  context.withQualifiedContext(
                                      element.getFieldReference().getHolderClass()))
                          .appendRetracedString(
                              original,
                              getFieldString(element.getFieldReference()),
                              startOfGroup,
                              matcher.end(captureGroup)));
                });
          }
          return retracedStrings;
        }
      };
    }

    private String getFieldString(FieldReference fieldReference) {
      if (!printVerbose) {
        return fieldReference.getFieldName();
      }
      return fieldReference.getFieldType().getTypeName() + " " + fieldReference.getFieldName();
    }
  }

  private static class SourceFileGroup extends RegularExpressionGroup {

    @Override
    String subExpression() {
      return "(?:(\\w*[\\. ])?(\\w*)?)";
    }

    @Override
    RegularExpressionGroupHandler createHandler(String captureGroup) {
      return (original, strings, matcher, retracer) -> {
        final int startOfGroup = matcher.start(captureGroup);
        if (startOfGroup == NO_MATCH) {
          return strings;
        }
        String fileName = matcher.group(captureGroup);
        List<RetraceString> retracedStrings = null;
        for (RetraceString retraceString : strings) {
          if (retraceString.context.classContext == null) {
            return strings;
          }
          if (retracedStrings == null) {
            retracedStrings = new ArrayList<>();
          }
          RetraceSourceFileResult sourceFileResult =
              retraceString.getMethodContext() != null
                  ? retraceString.getMethodContext().retraceSourceFile(fileName)
                  : RetraceUtils.getSourceFile(
                      retraceString.getClassContext(),
                      retraceString.context.qualifiedContext,
                      fileName);
          retracedStrings.add(
              retraceString
                  .updateContext(context -> context.withSource(sourceFileResult.getFilename()))
                  .appendRetracedString(
                      original,
                      sourceFileResult.getFilename(),
                      startOfGroup,
                      matcher.end(captureGroup)));
        }
        return retracedStrings;
      };
    }
  }

  private class LineNumberGroup extends RegularExpressionGroup {

    @Override
    String subExpression() {
      return "\\d*";
    }

    @Override
    RegularExpressionGroupHandler createHandler(String captureGroup) {
      return new RegularExpressionGroupHandler() {
        @Override
        public List<RetraceString> handleMatch(
            String original, List<RetraceString> strings, Matcher matcher, RetraceApi retracer) {
          final int startOfGroup = matcher.start(captureGroup);
          if (startOfGroup == NO_MATCH) {
            return strings;
          }
          String lineNumberAsString = matcher.group(captureGroup);
          if (lineNumberAsString.isEmpty()) {
            return strings;
          }
          int lineNumber = Integer.parseInt(lineNumberAsString);
          List<RetraceString> retracedStrings = new ArrayList<>();
          for (RetraceString retraceString : strings) {
            RetraceMethodResult.Element methodContext = retraceString.context.methodContext;
            if (methodContext == null) {
              if (retraceString.context.classContext == null
                  || retraceString.context.methodName == null) {
                // We have no way of retracing the line number.
                retracedStrings.add(retraceString);
                continue;
              }
              // This situation arises when we have a matched pattern as %l..%c.%m where the
              // line number handler is defined before the methodname handler.
              MethodNameGroup.retraceMethodForString(
                  retraceString,
                  retraceString.context.methodName,
                  (element, newContext) -> {
                    // The same method can be represented multiple times if it has multiple
                    // mappings.
                    if (element.hasNoLineNumberRange()
                        || !element.containsMinifiedLineNumber(lineNumber)) {
                      diagnosticsHandler.info(
                          new StringDiagnostic(
                              "Pruning "
                                  + retraceString.builder.retracedString.toString()
                                  + " from result because method is not in range on line number "
                                  + lineNumber));
                    }
                    final int originalLineNumber = element.getOriginalLineNumber(lineNumber);
                    retracedStrings.add(
                        retraceString
                            .updateContext(
                                context -> context.withLineNumbers(lineNumber, originalLineNumber))
                            .appendRetracedString(
                                original,
                                originalLineNumber + "",
                                startOfGroup,
                                matcher.end(captureGroup)));
                  });
              continue;
            }
            // If the method context is unknown, do nothing.
            if (methodContext.getMethodReference().isUnknown()
                || methodContext.hasNoLineNumberRange()) {
              retracedStrings.add(retraceString);
              continue;
            }
            int originalLineNumber = methodContext.getOriginalLineNumber(lineNumber);
            retracedStrings.add(
                retraceString
                    .updateContext(
                        context -> context.withLineNumbers(lineNumber, originalLineNumber))
                    .appendRetracedString(
                        original,
                        originalLineNumber + "",
                        startOfGroup,
                        matcher.end(captureGroup)));
          }
          return retracedStrings;
        }

        @Override
        public RetraceStringContext buildInitial(
            RetraceStringContext context, Matcher matcher, RetraceApi retracer) {
          if (matcher.start(captureGroup) == NO_MATCH || context.minifiedLineNumber > NO_MATCH) {
            return context;
          }
          String lineNumberAsString = matcher.group(captureGroup);
          return context.withLineNumbers(
              lineNumberAsString.isEmpty() ? NO_MATCH : Integer.parseInt(lineNumberAsString),
              NO_MATCH);
        }
      };
    }
  }

  private static class SourceFileLineNumberGroup extends RegularExpressionGroup {

    @Override
    String subExpression() {
      return "%s(?::%l)?";
    }

    @Override
    RegularExpressionGroupHandler createHandler(String captureGroup) {
      throw new Unreachable("Should never be called");
    }

    @Override
    boolean isSynthetic() {
      return true;
    }
  }

  private static final String JAVA_TYPE_REGULAR_EXPRESSION =
      "(" + javaIdentifierSegment + "\\.)*" + javaIdentifierSegment + "[\\[\\]]*";

  private static class FieldOrReturnTypeGroup extends RegularExpressionGroup {

    @Override
    String subExpression() {
      return JAVA_TYPE_REGULAR_EXPRESSION;
    }

    @Override
    RegularExpressionGroupHandler createHandler(String captureGroup) {
      return (original, strings, matcher, retracer) -> {
        final int startOfGroup = matcher.start(captureGroup);
        if (startOfGroup == NO_MATCH) {
          return strings;
        }
        String typeName = matcher.group(captureGroup);
        String descriptor = DescriptorUtils.javaTypeToDescriptor(typeName);
        if (!DescriptorUtils.isDescriptor(descriptor) && !"V".equals(descriptor)) {
          return strings;
        }
        TypeReference typeReference = Reference.returnTypeFromDescriptor(descriptor);
        RetraceTypeResult retracedType = retracer.retrace(typeReference);
        assert !retracedType.isAmbiguous();
        for (RetraceString retraceString : strings) {
          retracedType.forEach(
              element -> {
                TypeReference retracedReference = element.getTypeReference();
                retraceString.appendRetracedString(
                    original,
                    retracedReference == null ? "void" : retracedReference.getTypeName(),
                    startOfGroup,
                    matcher.end(captureGroup));
              });
        }
        return strings;
      };
    }
  }

  private static class MethodArgumentsGroup extends RegularExpressionGroup {

    @Override
    String subExpression() {
      return "((" + JAVA_TYPE_REGULAR_EXPRESSION + "\\,)*" + JAVA_TYPE_REGULAR_EXPRESSION + ")?";
    }

    @Override
    RegularExpressionGroupHandler createHandler(String captureGroup) {
      return (original, strings, matcher, retracer) -> {
        final int startOfGroup = matcher.start(captureGroup);
        if (startOfGroup == NO_MATCH) {
          return strings;
        }
        final String formals =
            Arrays.stream(matcher.group(captureGroup).split(","))
                .map(
                    typeName -> {
                      typeName = typeName.trim();
                      if (typeName.isEmpty()) {
                        return null;
                      }
                      String descriptor = DescriptorUtils.javaTypeToDescriptor(typeName);
                      if (!DescriptorUtils.isDescriptor(descriptor) && !"V".equals(descriptor)) {
                        return typeName;
                      }
                      final RetraceTypeResult retraceResult =
                          retracer.retrace(Reference.returnTypeFromDescriptor(descriptor));
                      assert !retraceResult.isAmbiguous();
                      final Box<TypeReference> elementBox = new Box<>();
                      retraceResult.forEach(element -> elementBox.set(element.getTypeReference()));
                      return elementBox.get().getTypeName();
                    })
                .filter(Objects::nonNull)
                .collect(Collectors.joining(","));
        for (RetraceString string : strings) {
          string.appendRetracedString(original, formals, startOfGroup, matcher.end(captureGroup));
        }
        return strings;
      };
    }
  }
}
