// 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.references.ClassReference;
import com.android.tools.r8.references.MethodReference;
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.RetraceString.RetraceStringBuilder;
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.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

public class RetraceRegularExpression {

  private final RetraceBase retraceBase;
  private final List<String> stackTrace;
  private final DiagnosticsHandler diagnosticsHandler;
  private final String regularExpression;

  private static final int NO_MATCH = -1;

  private final RegularExpressionGroup[] groups =
      new RegularExpressionGroup[] {
        new TypeNameGroup(),
        new BinaryNameGroup(),
        new MethodNameGroup(),
        new FieldNameGroup(),
        new SourceFileGroup(),
        new LineNumberGroup(),
        new FieldOrReturnTypeGroup(),
        new MethodArgumentsGroup()
      };

  private static final String CAPTURE_GROUP_PREFIX = "captureGroup";

  RetraceRegularExpression(
      RetraceBase retraceBase,
      List<String> stackTrace,
      DiagnosticsHandler diagnosticsHandler,
      String regularExpression) {
    this.retraceBase = retraceBase;
    this.stackTrace = stackTrace;
    this.diagnosticsHandler = diagnosticsHandler;
    this.regularExpression = regularExpression;
  }

  public RetraceCommandLineResult retrace() {
    List<RegularExpressionGroupHandler> handlers = new ArrayList<>();
    String regularExpression = registerGroups(this.regularExpression, handlers);
    Pattern compiledPattern = Pattern.compile(regularExpression);
    List<String> result = new ArrayList<>();
    for (String string : stackTrace) {
      Matcher matcher = compiledPattern.matcher(string);
      List<RetraceString> retracedStrings =
          Lists.newArrayList(RetraceStringBuilder.create(string).build());
      if (matcher.matches()) {
        for (RegularExpressionGroupHandler handler : handlers) {
          retracedStrings = handler.handleMatch(retracedStrings, matcher, retraceBase);
        }
      }
      if (retracedStrings.isEmpty()) {
        // We could not find a match. Output the identity.
        result.add(string);
      } else {
        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.getRetracedString();
          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 String registerGroups(
      String regularExpression, List<RegularExpressionGroupHandler> handlers) {
    int currentIndex = 0;
    int captureGroupIndex = 0;
    while (currentIndex < regularExpression.length()) {
      RegularExpressionGroup firstGroup = null;
      int firstIndexFromCurrent = regularExpression.length();
      for (RegularExpressionGroup group : groups) {
        int nextIndexOf = regularExpression.indexOf(group.shortName(), currentIndex);
        if (nextIndexOf > NO_MATCH && nextIndexOf < firstIndexFromCurrent) {
          // Check if previous character in the regular expression is not \\ to ensure not
          // overriding a matching on shortName.
          if (nextIndexOf > 0 && regularExpression.charAt(nextIndexOf - 1) == '\\') {
            continue;
          }
          firstGroup = group;
          firstIndexFromCurrent = nextIndexOf;
        }
      }
      if (firstGroup != null) {
        String captureGroupName = CAPTURE_GROUP_PREFIX + (captureGroupIndex++);
        String patternToInsert = "(?<" + captureGroupName + ">" + firstGroup.subExpression() + ")";
        regularExpression =
            regularExpression.substring(0, firstIndexFromCurrent)
                + patternToInsert
                + regularExpression.substring(
                    firstIndexFromCurrent + firstGroup.shortName().length());
        handlers.add(firstGroup.createHandler(captureGroupName));
        firstIndexFromCurrent += patternToInsert.length();
      }
      currentIndex = firstIndexFromCurrent;
    }
    return regularExpression;
  }

  static class RetraceString {

    private final Element classContext;
    private final ClassNameGroup classNameGroup;
    private final ClassReference qualifiedContext;
    private final RetraceMethodResult.Element methodContext;
    private final TypeReference typeOrReturnTypeContext;
    private final boolean hasTypeOrReturnTypeContext;
    private final String retracedString;
    private final int adjustedIndex;
    private final boolean isAmbiguous;
    private final int lineNumber;
    private final String source;

    private RetraceString(
        Element classContext,
        ClassNameGroup classNameGroup,
        ClassReference qualifiedContext,
        RetraceMethodResult.Element methodContext,
        TypeReference typeOrReturnTypeContext,
        boolean hasTypeOrReturnTypeContext,
        String retracedString,
        int adjustedIndex,
        boolean isAmbiguous,
        int lineNumber,
        String source) {
      this.classContext = classContext;
      this.classNameGroup = classNameGroup;
      this.qualifiedContext = qualifiedContext;
      this.methodContext = methodContext;
      this.typeOrReturnTypeContext = typeOrReturnTypeContext;
      this.hasTypeOrReturnTypeContext = hasTypeOrReturnTypeContext;
      this.retracedString = retracedString;
      this.adjustedIndex = adjustedIndex;
      this.isAmbiguous = isAmbiguous;
      this.lineNumber = lineNumber;
      this.source = source;
    }

    String getRetracedString() {
      return retracedString;
    }

    boolean hasTypeOrReturnTypeContext() {
      return hasTypeOrReturnTypeContext;
    }

    Element getClassContext() {
      return classContext;
    }

    RetraceMethodResult.Element getMethodContext() {
      return methodContext;
    }

    TypeReference getTypeOrReturnTypeContext() {
      return typeOrReturnTypeContext;
    }

    public ClassReference getQualifiedContext() {
      return qualifiedContext;
    }

    RetraceStringBuilder transform() {
      return RetraceStringBuilder.create(this);
    }

    public int getLineNumber() {
      return lineNumber;
    }

    public String getSource() {
      return source;
    }

    static class RetraceStringBuilder {

      private Element classContext;
      private ClassNameGroup classNameGroup;
      private ClassReference qualifiedContext;
      private RetraceMethodResult.Element methodContext;
      private TypeReference typeOrReturnTypeContext;
      private boolean hasTypeOrReturnTypeContext;
      private String retracedString;
      private int adjustedIndex;
      private boolean isAmbiguous;
      private int lineNumber;
      private String source;

      private int maxReplaceStringIndex = NO_MATCH;

      private RetraceStringBuilder(
          Element classContext,
          ClassNameGroup classNameGroup,
          ClassReference qualifiedContext,
          RetraceMethodResult.Element methodContext,
          TypeReference typeOrReturnTypeContext,
          boolean hasTypeOrReturnTypeContext,
          String retracedString,
          int adjustedIndex,
          boolean isAmbiguous,
          int lineNumber,
          String source) {
        this.classContext = classContext;
        this.classNameGroup = classNameGroup;
        this.qualifiedContext = qualifiedContext;
        this.methodContext = methodContext;
        this.typeOrReturnTypeContext = typeOrReturnTypeContext;
        this.hasTypeOrReturnTypeContext = hasTypeOrReturnTypeContext;
        this.retracedString = retracedString;
        this.adjustedIndex = adjustedIndex;
        this.isAmbiguous = isAmbiguous;
        this.lineNumber = lineNumber;
        this.source = source;
      }

      static RetraceStringBuilder create(String string) {
        return new RetraceStringBuilder(
            null, null, null, null, null, false, string, 0, false, 0, "");
      }

      static RetraceStringBuilder create(RetraceString string) {
        return new RetraceStringBuilder(
            string.classContext,
            string.classNameGroup,
            string.qualifiedContext,
            string.methodContext,
            string.typeOrReturnTypeContext,
            string.hasTypeOrReturnTypeContext,
            string.retracedString,
            string.adjustedIndex,
            string.isAmbiguous,
            string.lineNumber,
            string.source);
      }

      RetraceStringBuilder setClassContext(Element classContext, ClassNameGroup classNameGroup) {
        this.classContext = classContext;
        this.classNameGroup = classNameGroup;
        return this;
      }

      RetraceStringBuilder setMethodContext(RetraceMethodResult.Element methodContext) {
        this.methodContext = methodContext;
        return this;
      }

      RetraceStringBuilder setTypeOrReturnTypeContext(TypeReference typeOrReturnTypeContext) {
        hasTypeOrReturnTypeContext = true;
        this.typeOrReturnTypeContext = typeOrReturnTypeContext;
        return this;
      }

      RetraceStringBuilder setQualifiedContext(ClassReference qualifiedContext) {
        this.qualifiedContext = qualifiedContext;
        return this;
      }

      RetraceStringBuilder setAmbiguous(boolean isAmbiguous) {
        this.isAmbiguous = isAmbiguous;
        return this;
      }

      RetraceStringBuilder setLineNumber(int lineNumber) {
        this.lineNumber = lineNumber;
        return this;
      }

      RetraceStringBuilder setSource(String source) {
        this.source = source;
        return this;
      }

      RetraceStringBuilder replaceInString(String oldString, String newString) {
        int oldStringStartIndex = retracedString.indexOf(oldString);
        assert oldStringStartIndex > NO_MATCH;
        int oldStringEndIndex = oldStringStartIndex + oldString.length();
        return replaceInStringRaw(newString, oldStringStartIndex, oldStringEndIndex);
      }

      RetraceStringBuilder replaceInString(String newString, int originalFrom, int originalTo) {
        return replaceInStringRaw(
            newString, originalFrom + adjustedIndex, originalTo + adjustedIndex);
      }

      RetraceStringBuilder replaceInStringRaw(String newString, int from, int to) {
        assert from <= to;
        assert from > maxReplaceStringIndex;
        String prefix = retracedString.substring(0, from);
        String postFix = retracedString.substring(to);
        this.retracedString = prefix + newString + postFix;
        this.adjustedIndex = adjustedIndex + newString.length() - (to - from);
        maxReplaceStringIndex = prefix.length() + newString.length();
        return this;
      }

      RetraceString build() {
        return new RetraceString(
            classContext,
            classNameGroup,
            qualifiedContext,
            methodContext,
            typeOrReturnTypeContext,
            hasTypeOrReturnTypeContext,
            retracedString,
            adjustedIndex,
            isAmbiguous,
            lineNumber,
            source);
      }
    }
  }

  private interface RegularExpressionGroupHandler {

    List<RetraceString> handleMatch(
        List<RetraceString> strings, Matcher matcher, RetraceBase retraceBase);
  }

  private abstract static class RegularExpressionGroup {

    abstract String shortName();

    abstract String subExpression();

    abstract RegularExpressionGroupHandler createHandler(String captureGroup);
  }

  // TODO(b/145731185): Extend support for identifiers with strings inside back ticks.
  private static final String javaIdentifierSegment = "[\\p{L}\\p{N}_\\p{Sc}]+";

  private abstract static class ClassNameGroup extends RegularExpressionGroup {

    abstract String getClassName(ClassReference classReference);

    abstract ClassReference classFromMatch(String match);

    @Override
    RegularExpressionGroupHandler createHandler(String captureGroup) {
      return (strings, matcher, retraceBase) -> {
        if (matcher.start(captureGroup) == NO_MATCH) {
          return strings;
        }
        String typeName = matcher.group(captureGroup);
        RetraceClassResult retraceResult = retraceBase.retrace(classFromMatch(typeName));
        List<RetraceString> retracedStrings = new ArrayList<>();
        for (RetraceString retraceString : strings) {
          retraceResult.forEach(
              element -> {
                retracedStrings.add(
                    retraceString
                        .transform()
                        .setClassContext(element, this)
                        .setMethodContext(null)
                        .replaceInString(
                            getClassName(element.getClassReference()),
                            matcher.start(captureGroup),
                            matcher.end(captureGroup))
                        .build());
              });
        }
        return retracedStrings;
      };
    }
  }

  private static class TypeNameGroup extends ClassNameGroup {

    @Override
    String shortName() {
      return "%c";
    }

    @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 shortName() {
      return "%C";
    }

    @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 {

    @Override
    String shortName() {
      return "%m";
    }

    @Override
    String subExpression() {
      return "(?:(" + javaIdentifierSegment + "|\\<init\\>|\\<clinit\\>))";
    }

    @Override
    RegularExpressionGroupHandler createHandler(String captureGroup) {
      return (strings, matcher, retraceBase) -> {
        if (matcher.start(captureGroup) == NO_MATCH) {
          return strings;
        }
        String methodName = matcher.group(captureGroup);
        List<RetraceString> retracedStrings = new ArrayList<>();
        for (RetraceString retraceString : strings) {
          if (retraceString.classContext == null) {
            retracedStrings.add(retraceString);
            continue;
          }
          retraceString
              .getClassContext()
              .lookupMethod(methodName)
              .forEach(
                  element -> {
                    MethodReference methodReference = element.getMethodReference();
                    if (retraceString.hasTypeOrReturnTypeContext()) {
                      if (methodReference.getReturnType() == null
                          && retraceString.getTypeOrReturnTypeContext() != null) {
                        return;
                      } else if (methodReference.getReturnType() != null
                          && !methodReference
                              .getReturnType()
                              .equals(retraceString.getTypeOrReturnTypeContext())) {
                        return;
                      }
                    }
                    RetraceStringBuilder newRetraceString = retraceString.transform();
                    ClassReference existingClass =
                        retraceString.getClassContext().getClassReference();
                    ClassReference holder = methodReference.getHolderClass();
                    if (holder != existingClass) {
                      // The element is defined on another holder.
                      newRetraceString
                          .replaceInString(
                              newRetraceString.classNameGroup.getClassName(existingClass),
                              newRetraceString.classNameGroup.getClassName(holder))
                          .setQualifiedContext(holder);
                    }
                    newRetraceString
                        .setMethodContext(element)
                        .setAmbiguous(element.getRetraceMethodResult().isAmbiguous())
                        .replaceInString(
                            methodReference.getMethodName(),
                            matcher.start(captureGroup),
                            matcher.end(captureGroup));
                    retracedStrings.add(newRetraceString.build());
                  });
        }
        return retracedStrings;
      };
    }
  }

  private static class FieldNameGroup extends RegularExpressionGroup {

    @Override
    String shortName() {
      return "%f";
    }

    @Override
    String subExpression() {
      return javaIdentifierSegment;
    }

    @Override
    RegularExpressionGroupHandler createHandler(String captureGroup) {
      return (strings, matcher, retraceBase) -> {
        if (matcher.start(captureGroup) == NO_MATCH) {
          return strings;
        }
        String methodName = matcher.group(captureGroup);
        List<RetraceString> retracedStrings = new ArrayList<>();
        for (RetraceString retraceString : strings) {
          if (retraceString.getClassContext() == null) {
            retracedStrings.add(retraceString);
            continue;
          }
          retraceString
              .getClassContext()
              .lookupField(methodName)
              .forEach(
                  element -> {
                    RetraceStringBuilder newRetraceString = retraceString.transform();
                    ClassReference existingClass =
                        retraceString.getClassContext().getClassReference();
                    ClassReference holder = element.getFieldReference().getHolderClass();
                    if (holder != existingClass) {
                      // The element is defined on another holder.
                      newRetraceString
                          .replaceInString(
                              newRetraceString.classNameGroup.getClassName(existingClass),
                              newRetraceString.classNameGroup.getClassName(holder))
                          .setQualifiedContext(holder);
                    }
                    newRetraceString.replaceInString(
                        element.getFieldReference().getFieldName(),
                        matcher.start(captureGroup),
                        matcher.end(captureGroup));
                    retracedStrings.add(newRetraceString.build());
                  });
        }
        return retracedStrings;
      };
    }
  }

  private static class SourceFileGroup extends RegularExpressionGroup {

    @Override
    String shortName() {
      return "%s";
    }

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

    @Override
    RegularExpressionGroupHandler createHandler(String captureGroup) {
      return (strings, matcher, retraceBase) -> {
        if (matcher.start(captureGroup) == NO_MATCH) {
          return strings;
        }
        String fileName = matcher.group(captureGroup);
        List<RetraceString> retracedStrings = new ArrayList<>();
        for (RetraceString retraceString : strings) {
          if (retraceString.classContext == null) {
            retracedStrings.add(retraceString);
            continue;
          }
          String newSourceFile =
              retraceString.getQualifiedContext() != null
                  ? retraceBase.retraceSourceFile(
                      retraceString.classContext.getClassReference(),
                      fileName,
                      retraceString.getQualifiedContext(),
                      true)
                  : retraceString.classContext.retraceSourceFile(fileName, retraceBase);
          retracedStrings.add(
              retraceString
                  .transform()
                  .setSource(fileName)
                  .replaceInString(
                      newSourceFile, matcher.start(captureGroup), matcher.end(captureGroup))
                  .build());
        }
        return retracedStrings;
      };
    }
  }

  private class LineNumberGroup extends RegularExpressionGroup {

    @Override
    String shortName() {
      return "%l";
    }

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

    @Override
    RegularExpressionGroupHandler createHandler(String captureGroup) {
      return (strings, matcher, retraceBase) -> {
        if (matcher.start(captureGroup) == NO_MATCH) {
          return strings;
        }
        String lineNumberAsString = matcher.group(captureGroup);
        int lineNumber =
            lineNumberAsString.isEmpty() ? NO_MATCH : Integer.parseInt(lineNumberAsString);
        List<RetraceString> retracedStrings = new ArrayList<>();
        boolean seenRange = false;
        for (RetraceString retraceString : strings) {
          RetraceMethodResult.Element methodContext = retraceString.methodContext;
          if (methodContext == null || methodContext.getMethodReference().isUnknown()) {
            retracedStrings.add(retraceString);
            continue;
          }
          if (methodContext.hasNoLineNumberRange()) {
            continue;
          }
          seenRange = true;
          Set<MethodReference> narrowedSet =
              methodContext.getRetraceMethodResult().narrowByLine(lineNumber).stream()
                  .map(RetraceMethodResult.Element::getMethodReference)
                  .collect(Collectors.toSet());
          if (!narrowedSet.contains(methodContext.getMethodReference())) {
            // Prune the retraceString since we now have line number information and this is not
            // a part of the result.
            diagnosticsHandler.info(
                new StringDiagnostic(
                    "Pruning "
                        + retraceString.getRetracedString()
                        + " from result because method is not defined on line number "
                        + lineNumber));
            continue;
          }
          // The same method can be represented multiple times if it has multiple mappings.
          if (!methodContext.containsMinifiedLineNumber(lineNumber)) {
            diagnosticsHandler.info(
                new StringDiagnostic(
                    "Pruning "
                        + retraceString.getRetracedString()
                        + " from result because method is not in range on line number "
                        + lineNumber));
            continue;
          }
          int originalLineNumber = methodContext.getOriginalLineNumber(lineNumber);
          retracedStrings.add(
              retraceString
                  .transform()
                  .setAmbiguous(false)
                  .setLineNumber(originalLineNumber)
                  .replaceInString(
                      originalLineNumber + "",
                      matcher.start(captureGroup),
                      matcher.end(captureGroup))
                  .build());
        }
        return seenRange ? retracedStrings : strings;
      };
    }
  }

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

  private static class FieldOrReturnTypeGroup extends RegularExpressionGroup {

    @Override
    String shortName() {
      return "%t";
    }

    @Override
    String subExpression() {
      return JAVA_TYPE_REGULAR_EXPRESSION;
    }

    @Override
    RegularExpressionGroupHandler createHandler(String captureGroup) {
      return (strings, matcher, retraceBase) -> {
        if (matcher.start(captureGroup) == 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);
        List<RetraceString> retracedStrings = new ArrayList<>();
        RetraceTypeResult retracedType = retraceBase.retrace(typeReference);
        for (RetraceString retraceString : strings) {
          retracedType.forEach(
              element -> {
                TypeReference retracedReference = element.getTypeReference();
                retracedStrings.add(
                    retraceString
                        .transform()
                        .setTypeOrReturnTypeContext(retracedReference)
                        .replaceInString(
                            retracedReference == null ? "void" : retracedReference.getTypeName(),
                            matcher.start(captureGroup),
                            matcher.end(captureGroup))
                        .build());
              });
        }
        return retracedStrings;
      };
    }
  }

  private class MethodArgumentsGroup extends RegularExpressionGroup {

    @Override
    String shortName() {
      return "%a";
    }

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

    @Override
    RegularExpressionGroupHandler createHandler(String captureGroup) {
      return (strings, matcher, retraceBase) -> {
        if (matcher.start(captureGroup) == NO_MATCH) {
          return strings;
        }
        Set<List<TypeReference>> initialValue = new LinkedHashSet<>();
        initialValue.add(new ArrayList<>());
        Set<List<TypeReference>> allRetracedReferences =
            Arrays.stream(matcher.group(captureGroup).split(","))
                .map(String::trim)
                .reduce(
                    initialValue,
                    (acc, typeName) -> {
                      String descriptor = DescriptorUtils.javaTypeToDescriptor(typeName);
                      if (!DescriptorUtils.isDescriptor(descriptor) && !"V".equals(descriptor)) {
                        return acc;
                      }
                      TypeReference typeReference = Reference.returnTypeFromDescriptor(descriptor);
                      Set<List<TypeReference>> retracedTypes = new LinkedHashSet<>();
                      retraceBase
                          .retrace(typeReference)
                          .forEach(
                              element -> {
                                for (List<TypeReference> currentReferences : acc) {
                                  ArrayList<TypeReference> newList =
                                      new ArrayList<>(currentReferences);
                                  newList.add(element.getTypeReference());
                                  retracedTypes.add(newList);
                                }
                              });
                      return retracedTypes;
                    },
                    (l1, l2) -> {
                      l1.addAll(l2);
                      return l1;
                    });
        List<RetraceString> retracedStrings = new ArrayList<>();
        for (RetraceString retraceString : strings) {
          if (retraceString.getMethodContext() != null
              && !allRetracedReferences.contains(
                  retraceString.getMethodContext().getMethodReference().getFormalTypes())) {
            // Prune the string since we now know the formals.
            String formals =
                retraceString.getMethodContext().getMethodReference().getFormalTypes().stream()
                    .map(TypeReference::getTypeName)
                    .collect(Collectors.joining(","));
            diagnosticsHandler.info(
                new StringDiagnostic(
                    "Pruning "
                        + retraceString.getRetracedString()
                        + " from result because formals ("
                        + formals
                        + ") do not match result set."));
            continue;
          }
          for (List<TypeReference> retracedReferences : allRetracedReferences) {
            retracedStrings.add(
                retraceString
                    .transform()
                    .replaceInString(
                        retracedReferences.stream()
                            .map(TypeReference::getTypeName)
                            .collect(Collectors.joining(",")),
                        matcher.start(captureGroup),
                        matcher.end(captureGroup))
                    .build());
          }
        }
        return retracedStrings;
      };
    }
  }
}
