// Copyright (c) 2022, 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 static com.android.tools.r8.naming.MappedRangeUtils.isInlineMappedRange;
import static com.android.tools.r8.utils.FunctionUtils.ignoreArgument;

import com.android.tools.r8.naming.ClassNamingForNameMapper.MappedRange;
import com.android.tools.r8.naming.ClassNamingForNameMapper.MappedRangesOfName;
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.mappinginformation.MapVersionMappingInformation;
import com.android.tools.r8.naming.mappinginformation.MappingInformation;
import com.android.tools.r8.naming.mappinginformation.OutlineCallsiteMappingInformation;
import com.android.tools.r8.naming.mappinginformation.OutlineMappingInformation;
import com.android.tools.r8.naming.mappinginformation.ResidualSignatureMappingInformation;
import com.android.tools.r8.naming.mappinginformation.RewriteFrameMappingInformation;
import com.android.tools.r8.naming.mappinginformation.RewriteFrameMappingInformation.ThrowsCondition;
import com.android.tools.r8.references.ArrayReference;
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.utils.Box;
import com.android.tools.r8.utils.ChainableStringConsumer;
import com.android.tools.r8.utils.ConsumerUtils;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.ListUtils;
import com.android.tools.r8.utils.Pair;
import com.android.tools.r8.utils.SegmentTree;
import com.android.tools.r8.utils.ThrowingBiFunction;
import com.google.common.collect.Sets;
import it.unimi.dsi.fastutil.ints.Int2IntLinkedOpenHashMap;
import it.unimi.dsi.fastutil.ints.Int2IntSortedMap;
import it.unimi.dsi.fastutil.ints.Int2ReferenceMap;
import it.unimi.dsi.fastutil.ints.Int2ReferenceOpenHashMap;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Set;
import java.util.TreeMap;
import java.util.function.Consumer;

public class ComposingBuilder {

  private static final Range EMPTY_RANGE = new Range(0, 0);

  private MapVersionMappingInformation currentMapVersion = null;

  /**
   * When composing we store a view of the previously known mappings in committed and retain a
   * current working set. When composing of a new map is finished we commit everything in current
   * into the committed set.
   *
   * <p>The reason for not having just a single set is that we can have a circular mapping as
   * follows:
   *
   * <pre>
   *   a -> b:
   *   ...
   *   b -> a:
   * </pre>
   *
   * After composing our current view of a with the above, we could end up transforming 'a' into 'b'
   * and then later transforming 'b' back into 'a' again. To ensure we do not mess up namings while
   * composing classes and methods we resort to a working set and committed set.
   */
  private final ComposingData committed = new ComposingData();

  private ComposingData current;
  private final InternalOptions options;

  public ComposingBuilder(InternalOptions options) {
    this.options = options;
  }

  public void compose(ClassNameMapper classNameMapper) throws MappingComposeException {
    current = new ComposingData();
    MapVersionMappingInformation newMapVersionInfo =
        classNameMapper.getFirstMapVersionInformation();
    if (newMapVersionInfo == null) {
      throw new MappingComposeException(
          "Composition of mapping files supported from map version 2.2.");
    }
    MapVersion newMapVersion = newMapVersionInfo.getMapVersion();
    if (!ResidualSignatureMappingInformation.isSupported(newMapVersion)
        || newMapVersion.isUnknown()) {
      throw new MappingComposeException(
          "Composition of mapping files supported from map version "
              + ResidualSignatureMappingInformation.SUPPORTED_VERSION.getName()
              + ".");
    }
    if (currentMapVersion == null) {
      currentMapVersion = newMapVersionInfo;
    } else {
      currentMapVersion =
          newMapVersionInfo.compose(currentMapVersion).asMapVersionMappingInformation();
    }
    for (ClassNamingForNameMapper classMapping : classNameMapper.getClassNameMappings().values()) {
      compose(classNameMapper, classMapping);
    }
    committed.commit(current, classNameMapper);
  }

  private void compose(ClassNameMapper classNameMapper, ClassNamingForNameMapper classMapping)
      throws MappingComposeException {
    String originalName = classMapping.originalName;
    String renamedName = classMapping.renamedName;
    ComposingClassBuilder composingClassBuilder =
        new ComposingClassBuilder(originalName, renamedName, committed, current, options);
    ComposingClassBuilder duplicateMapping =
        current.classBuilders.put(renamedName, composingClassBuilder);
    if (duplicateMapping != null) {
      throw new MappingComposeException(
          "Duplicate class mapping. Both '"
              + duplicateMapping.getOriginalName()
              + "' and '"
              + originalName
              + "' maps to '"
              + renamedName
              + "'.");
    }
    composingClassBuilder.compose(classNameMapper, classMapping);
  }

  public String finish() {
    List<ComposingClassBuilder> classBuilders = new ArrayList<>(committed.classBuilders.values());
    classBuilders.sort(Comparator.comparing(ComposingClassBuilder::getOriginalName));
    StringBuilder sb = new StringBuilder();
    committed.preamble.forEach(preambleLine -> sb.append(preambleLine).append("\n"));
    if (currentMapVersion != null) {
      sb.append("# ").append(currentMapVersion.serialize()).append("\n");
    }
    ChainableStringConsumer wrap = ChainableStringConsumer.wrap(sb::append);
    for (ComposingClassBuilder classBuilder : classBuilders) {
      classBuilder.write(wrap);
    }
    return sb.toString();
  }

  public static class ComposingData {

    /**
     * A map of minified names to their class builders. When committing to a new minified name we
     * destructively remove the previous minified mapping and replace it with the up-to-date one.
     */
    private Map<String, ComposingClassBuilder> classBuilders = new HashMap<>();
    /**
     * RewriteFrameInformation contains condition clauses that are bound to the residual program. As
     * a result of that, we have to patch up the conditions when we compose new class mappings.
     */
    private final List<RewriteFrameMappingInformation> rewriteFrameInformation = new ArrayList<>();
    /** Map of newly added outline call site informations which do not require any rewriting. */
    private Map<ClassTypeNameAndMethodName, OutlineCallsiteMappingInformation>
        outlineCallsiteInformation = new HashMap<>();
    /**
     * Map of updated outline definitions which has to be committed. The positions in the caller are
     * fixed at this point since these are local to the method when rewriting.
     */
    private final Map<ClassTypeNameAndMethodName, UpdateOutlineCallsiteInformation>
        outlineSourcePositionsUpdated = new HashMap<>();

    /**
     * Map of signatures that should be removed when finalizing the composed map. The key is the
     * original name of a class.
     */
    private final Map<String, Set<Signature>> signaturesToRemove = new HashMap<>();

    private final List<String> preamble = new ArrayList<>();

    public void commit(ComposingData current, ClassNameMapper classNameMapper)
        throws MappingComposeException {
      preamble.addAll(classNameMapper.getPreamble());
      commitClassBuilders(current, classNameMapper);
      commitRewriteFrameInformation(current, classNameMapper);
      commitOutlineCallsiteInformation(current, classNameMapper);
    }

    private void commitClassBuilders(ComposingData current, ClassNameMapper classNameMapper)
        throws MappingComposeException {
      Set<String> updatedClassBuilders = new HashSet<>();
      Map<String, ComposingClassBuilder> newClassBuilders = new HashMap<>();
      for (Entry<String, ComposingClassBuilder> newEntry : current.classBuilders.entrySet()) {
        String renamedName = newEntry.getKey();
        ComposingClassBuilder classBuilder = newEntry.getValue();
        updatedClassBuilders.add(classBuilder.originalName);
        ComposingClassBuilder existingBuilder = classBuilders.get(classBuilder.originalName);
        if (existingBuilder != null) {
          removeSignaturesFromBuilder(current, existingBuilder);
          classBuilder = existingBuilder.commit(classBuilder);
        }
        newClassBuilders.put(renamedName, classBuilder);
      }
      for (Entry<String, ComposingClassBuilder> existingEntry : classBuilders.entrySet()) {
        if (!updatedClassBuilders.contains(existingEntry.getKey())) {
          ComposingClassBuilder classBuilder = existingEntry.getValue();
          removeSignaturesFromBuilder(current, classBuilder);
          ComposingClassBuilder duplicateMapping =
              newClassBuilders.put(existingEntry.getKey(), classBuilder);
          if (duplicateMapping != null) {
            throw new MappingComposeException(
                "Duplicate class mapping. Both '"
                    + classBuilder.getOriginalName()
                    + "' and '"
                    + classNameMapper.getClassNaming(existingEntry.getKey()).originalName
                    + "' maps to '"
                    + classBuilder.renamedName
                    + "'.");
          }
        }
      }
      classBuilders = newClassBuilders;
    }

    private void removeSignaturesFromBuilder(
        ComposingData current, ComposingClassBuilder classBuilder) {
      Set<Signature> signaturesToRemove =
          current.signaturesToRemove.get(classBuilder.getOriginalName());
      if (signaturesToRemove == null) {
        return;
      }
      signaturesToRemove.forEach(
          signatureToRemove -> {
            if (signatureToRemove.isFieldSignature()) {
              classBuilder.fieldMembers.remove(signatureToRemove.asFieldSignature());
            } else {
              classBuilder.methodsWithoutPosition.remove(signatureToRemove.asMethodSignature());
              classBuilder.methodsWithPosition.remove(signatureToRemove.asMethodSignature());
            }
          });
    }

    public void addSignatureToRemove(
        ComposingClassBuilder composingClassBuilder, Signature signature) {
      signaturesToRemove
          .computeIfAbsent(
              composingClassBuilder.getOriginalName(), ignoreArgument(Sets::newHashSet))
          .add(signature);
    }

    private void commitRewriteFrameInformation(
        ComposingData current, ClassNameMapper classNameMapper) {
      // First update the existing frame information to have new class name mappings.
      Map<String, String> inverse = classNameMapper.getObfuscatedToOriginalMapping().inverse;
      for (RewriteFrameMappingInformation rewriteMappingInfo : rewriteFrameInformation) {
        rewriteMappingInfo
            .getConditions()
            .forEach(
                rewriteCondition -> {
                  ThrowsCondition throwsCondition = rewriteCondition.asThrowsCondition();
                  if (throwsCondition != null) {
                    throwsCondition.setClassReferenceInternal(
                        mapTypeReference(inverse, throwsCondition.getClassReference()).asClass());
                  }
                });
      }
      rewriteFrameInformation.addAll(current.rewriteFrameInformation);
    }

    private void commitOutlineCallsiteInformation(
        ComposingData current, ClassNameMapper classNameMapper) {
      // To commit outline call site information, we take the previously committed and bring forward
      // to a new mapping, and potentially rewrite source positions if available.
      Map<ClassTypeNameAndMethodName, OutlineCallsiteMappingInformation> newOutlineCallsiteInfo =
          new HashMap<>();
      Map<String, String> inverse = classNameMapper.getObfuscatedToOriginalMapping().inverse;
      outlineCallsiteInformation.forEach(
          (holderAndMethodNameOfOutline, outlineInfo) -> {
            UpdateOutlineCallsiteInformation updateOutlineCallsiteInformation =
                current.outlineSourcePositionsUpdated.get(holderAndMethodNameOfOutline);
            String newMethodName = outlineInfo.getOutline().getMethodName();
            if (updateOutlineCallsiteInformation != null) {
              // We have a callsite mapping that we need to update.
              MappedRangeOriginalToMinifiedMap originalToMinifiedMap =
                  MappedRangeOriginalToMinifiedMap.build(
                      updateOutlineCallsiteInformation.newMappedRanges);
              Int2IntSortedMap newPositionMap = new Int2IntLinkedOpenHashMap();
              outlineInfo
                  .getPositions()
                  .forEach(
                      (originalPosition, destination) ->
                          originalToMinifiedMap.visitMinified(
                              originalPosition,
                              newMinified -> newPositionMap.put(newMinified, destination)));
              outlineInfo.setPositionsInternal(newPositionMap);
              newMethodName = updateOutlineCallsiteInformation.newMethodName;
            }
            // Holder, return type or formals could have changed the outline descriptor.
            MethodReference outline = outlineInfo.getOutline();
            ClassReference newHolder =
                mapTypeReference(inverse, outline.getHolderClass()).asClass();
            outlineInfo.setOutlineInternal(
                Reference.method(
                    newHolder,
                    newMethodName,
                    mapTypeReferences(inverse, outline.getFormalTypes()),
                    mapTypeReference(inverse, outline.getReturnType())));
            newOutlineCallsiteInfo.put(
                new ClassTypeNameAndMethodName(
                    newHolder.getTypeName(), holderAndMethodNameOfOutline.getMethodName()),
                outlineInfo);
          });
      newOutlineCallsiteInfo.putAll(current.outlineCallsiteInformation);
      outlineCallsiteInformation = newOutlineCallsiteInfo;
    }

    public void addNewOutlineCallsiteInformation(
        MethodReference outline, OutlineCallsiteMappingInformation outlineCallsiteInfo) {
      outlineCallsiteInformation.put(
          new ClassTypeNameAndMethodName(
              outline.getHolderClass().getTypeName(), outline.getMethodName()),
          outlineCallsiteInfo);
    }

    public UpdateOutlineCallsiteInformation getUpdateOutlineCallsiteInformation(
        String originalHolder, String originalMethodName, String newMethodName) {
      return outlineSourcePositionsUpdated.computeIfAbsent(
          new ClassTypeNameAndMethodName(originalHolder, originalMethodName),
          ignore -> new UpdateOutlineCallsiteInformation(newMethodName));
    }

    private List<TypeReference> mapTypeReferences(
        Map<String, String> typeNameMap, List<TypeReference> typeReferences) {
      return ListUtils.map(typeReferences, typeRef -> mapTypeReference(typeNameMap, typeRef));
    }

    private TypeReference mapTypeReference(
        Map<String, String> typeNameMap, TypeReference typeReference) {
      if (typeReference == null || typeReference.isPrimitive()) {
        return typeReference;
      }
      if (typeReference.isArray()) {
        ArrayReference arrayReference = typeReference.asArray();
        return Reference.array(
            mapTypeReference(typeNameMap, arrayReference.getBaseType()),
            arrayReference.getDimensions());
      } else {
        assert typeReference.isClass();
        String newTypeName = typeNameMap.get(typeReference.getTypeName());
        return newTypeName == null ? typeReference : Reference.classFromTypeName(newTypeName);
      }
    }
  }

  private static class ClassTypeNameAndMethodName {

    private final String holderTypeName;
    private final String methodName;

    public ClassTypeNameAndMethodName(String holderTypeName, String methodName) {
      this.holderTypeName = holderTypeName;
      this.methodName = methodName;
    }

    public String getHolderTypeName() {
      return holderTypeName;
    }

    public String getMethodName() {
      return methodName;
    }

    @Override
    public boolean equals(Object o) {
      if (this == o) {
        return true;
      }
      if (!(o instanceof ClassTypeNameAndMethodName)) {
        return false;
      }
      ClassTypeNameAndMethodName that = (ClassTypeNameAndMethodName) o;
      return holderTypeName.equals(that.holderTypeName) && methodName.equals(that.methodName);
    }

    @Override
    public int hashCode() {
      return Objects.hash(holderTypeName, methodName);
    }
  }

  private static class UpdateOutlineCallsiteInformation {

    private List<MappedRange> newMappedRanges;
    private final String newMethodName;

    private UpdateOutlineCallsiteInformation(String newMethodName) {
      this.newMethodName = newMethodName;
    }

    private void setNewMappedRanges(List<MappedRange> mappedRanges) {
      newMappedRanges = mappedRanges;
    }
  }

  private static class MappedRangeOriginalToMinifiedMap {

    private final Int2ReferenceMap<List<Integer>> originalToMinified;

    private MappedRangeOriginalToMinifiedMap(Int2ReferenceMap<List<Integer>> originalToMinified) {
      this.originalToMinified = originalToMinified;
    }

    private static MappedRangeOriginalToMinifiedMap build(List<MappedRange> mappedRanges) {
      Int2ReferenceMap<List<Integer>> positionMap = new Int2ReferenceOpenHashMap<>();
      for (MappedRange mappedRange : mappedRanges) {
        Range originalRange = mappedRange.originalRange;
        for (int position = originalRange.from; position <= originalRange.to; position++) {
          // It is perfectly fine to have multiple minified ranges mapping to the same source, we
          // just need to keep the additional information.
          positionMap
              .computeIfAbsent(position, ignoreArgument(ArrayList::new))
              .add(mappedRange.minifiedRange.from + (position - originalRange.from));
        }
      }
      return new MappedRangeOriginalToMinifiedMap(positionMap);
    }

    public int lookupFirst(int originalPosition) {
      List<Integer> minifiedPositions = originalToMinified.get(originalPosition);
      return minifiedPositions == null ? 0 : minifiedPositions.get(0);
    }

    public void visitMinified(int originalPosition, Consumer<Integer> consumer) {
      List<Integer> minifiedPositions = originalToMinified.get(originalPosition);
      if (minifiedPositions != null) {
        minifiedPositions.forEach(consumer);
      }
    }
  }

  public static class ComposingClassBuilder {

    private static final String INDENTATION = "    ";
    private static final int NO_RANGE_FROM = -1;

    private final String originalName;
    private final String renamedName;
    private final Map<FieldSignature, MemberNaming> fieldMembers = new HashMap<>();
    private final Map<MethodSignature, SegmentTree<List<MappedRange>>> methodsWithPosition =
        new HashMap<>();
    private final Map<MethodSignature, MappedRange> methodsWithoutPosition = new HashMap<>();
    private final List<MappingInformation> additionalMappingInfo = new ArrayList<>();

    private final ComposingData committed;
    private final ComposingData current;

    private final Map<String, ComposingClassBuilder> committedPreviousClassBuilders;
    private final ComposingClassBuilder committedPreviousClassBuilder;
    private final InternalOptions options;

    private ComposingClassBuilder(
        String originalName,
        String renamedName,
        ComposingData committed,
        ComposingData current,
        InternalOptions options) {
      this.originalName = originalName;
      this.renamedName = renamedName;
      this.current = current;
      this.committed = committed;
      this.options = options;
      committedPreviousClassBuilders = committed.classBuilders;
      committedPreviousClassBuilder = committedPreviousClassBuilders.get(originalName);
    }

    public String getOriginalName() {
      return originalName;
    }

    public String getRenamedName() {
      return renamedName;
    }

    public void compose(ClassNameMapper classNameMapper, ClassNamingForNameMapper mapper)
        throws MappingComposeException {
      List<MappingInformation> newMappingInfo = mapper.getAdditionalMappingInfo();
      if (newMappingInfo != null) {
        additionalMappingInfo.addAll(newMappingInfo);
      }
      composeFieldNamings(mapper, classNameMapper);
      composeMethodNamings(mapper, classNameMapper);
    }

    private void composeFieldNamings(
        ClassNamingForNameMapper mapper, ClassNameMapper classNameMapper) {
      Map<String, String> inverseClassMapping =
          classNameMapper.getObfuscatedToOriginalMapping().inverse;
      mapper.forAllFieldNaming(
          fieldNaming -> {
            MemberNaming fieldNamingToAdd = fieldNaming;
            FieldSignature originalSignature =
                fieldNaming.getOriginalSignature().asFieldSignature();
            FieldSignature residualSignature =
                fieldNaming
                    .computeResidualSignature(type -> inverseClassMapping.getOrDefault(type, type))
                    .asFieldSignature();
            MemberNaming existingMemberNaming = getExistingMemberNaming(originalSignature);
            if (existingMemberNaming != null) {
              Signature existingOriginalSignature = existingMemberNaming.getOriginalSignature();
              if (!existingOriginalSignature.isQualified() && originalSignature.isQualified()) {
                String previousCommittedClassName =
                    getPreviousCommittedClassName(originalSignature.toHolderFromQualified());
                if (previousCommittedClassName != null) {
                  existingOriginalSignature =
                      existingOriginalSignature.toQualifiedSignature(previousCommittedClassName);
                }
              }
              fieldNamingToAdd = new MemberNaming(existingOriginalSignature, residualSignature);
            }
            MemberNaming existing = fieldMembers.put(residualSignature, fieldNamingToAdd);
            assert existing == null;
          });
    }

    private String getPreviousCommittedClassName(String holder) {
      ComposingClassBuilder composingClassBuilder = committedPreviousClassBuilders.get(holder);
      return composingClassBuilder == null ? null : composingClassBuilder.getOriginalName();
    }

    private MemberNaming getExistingMemberNaming(FieldSignature originalSignature) {
      ComposingClassBuilder composingClassBuilder =
          originalSignature.isQualified()
              ? committedPreviousClassBuilders.get(originalSignature.toHolderFromQualified())
              : committedPreviousClassBuilder;
      if (composingClassBuilder == null) {
        return null;
      }
      FieldSignature signature =
          (originalSignature.isQualified()
                  ? originalSignature.toUnqualifiedSignature()
                  : originalSignature)
              .asFieldSignature();
      current.addSignatureToRemove(composingClassBuilder, signature);
      return composingClassBuilder.fieldMembers.get(signature);
    }

    private void composeMethodNamings(
        ClassNamingForNameMapper mapper, ClassNameMapper classNameMapper)
        throws MappingComposeException {
      Map<String, String> inverseClassMapping =
          classNameMapper.getObfuscatedToOriginalMapping().inverse;
      for (Entry<String, MappedRangesOfName> entry : mapper.mappedRangesByRenamedName.entrySet()) {
        List<MappedRangesOfName> mappedRangesOfNames =
            entry.getValue().partitionOnMethodSignature();
        for (MappedRangesOfName rangesOfName : mappedRangesOfNames) {
          MemberNaming memberNaming = rangesOfName.getMemberNaming(mapper);
          List<MappedRange> newMappedRanges = rangesOfName.getMappedRanges();
          RangeBuilder minified = new RangeBuilder();
          // The new minified ranges may have ranges that range over positions that has additional
          // information, such as inlinees:
          // Existing:
          //  1:2:void caller():14:15 -> x
          //  3:3:void inlinee():42:42 -> x
          //  3:3:void caller():16:16 -> x
          //  4:10:void caller():17:23 -> x
          //  ...
          // New mapping:
          //  1:5:void x():1:5 -> y
          //  6:10:void x():6:6 -> y
          //  ...
          // It is important that we therefore split up the new ranges to map everything back to the
          // existing original mappings:
          // Resulting mapping:
          //  1:2:void caller():14:15 -> y
          //  3:3:void inlinee():42:42 -> y
          //  3:3:void caller():16:16 -> y
          //  4:5:void caller():17:18 -> y
          //  6:10:void caller():19:19 -> y
          //  ...
          List<MappedRange> composedRanges = new ArrayList<>();
          ComputedOutlineInformation computedOutlineInformation = new ComputedOutlineInformation();
          List<List<MappedRange>> composedInlineFrames = new ArrayList<>();
          for (int i = 0; i < newMappedRanges.size(); i++) {
            MappedRange mappedRange = newMappedRanges.get(i);
            minified.addRange(mappedRange.minifiedRange);
            // Register mapping information that is dependent on the residual naming to allow
            // updating later on.
            registerMappingInformationFromMappedRanges(mappedRange);

            MethodSignature originalSignature =
                mappedRange.getOriginalSignature().asMethodSignature();

            // Remove the existing entry if it exists.
            List<MappedRange> existingMappedRanges = null;
            ComposingClassBuilder existingClassBuilder = getExistingClassBuilder(originalSignature);
            if (existingClassBuilder != null) {
              MethodSignature signature =
                  (originalSignature.isQualified()
                          ? originalSignature.toUnqualifiedSignature()
                          : originalSignature)
                      .asMethodSignature();
              current.addSignatureToRemove(existingClassBuilder, signature);
              SegmentTree<List<MappedRange>> listSegmentTree =
                  existingClassBuilder.methodsWithPosition.get(signature);
              if (listSegmentTree != null) {
                // Any new transformation can be lossy - for example, D8 only promises to keep line
                // positions if the method is not throwing (and is not debug). Additionally, R8/PG
                // emits `1:1:void foo() -> a` instead of `1:1:void foo():1:1 -> a`, so R8 must
                // capture the preamble position by explicitly inserting 0 as original range.
                int firstPositionOfOriginalRange =
                    mappedRange.getFirstPositionOfOriginalRange(NO_RANGE_FROM);
                Entry<Integer, List<MappedRange>> existingEntry =
                    listSegmentTree.findEntry(firstPositionOfOriginalRange);
                if (existingEntry == null
                    && firstPositionOfOriginalRange == 0
                    && !mappedRange.originalRange.isPreamble()) {
                  existingEntry =
                      listSegmentTree.findEntry(mappedRange.getLastPositionOfOriginalRange());
                }
                // We assume that all new minified ranges for a method are rewritten in the new map
                // such that no previous existing positions exists.
                if (existingEntry != null) {
                  existingMappedRanges = existingEntry.getValue();
                } else {
                  // The original can be discarded if it no longer exists or if the method is
                  // non-throwing.
                  if (mappedRange.originalRange != null
                      && !mappedRange.originalRange.isPreamble()
                      && !options.mappingComposeOptions().allowNonExistingOriginalRanges) {
                    throw new MappingComposeException(
                        "Could not find original starting position of '"
                            + mappedRange.minifiedRange.from
                            + "' which should be "
                            + firstPositionOfOriginalRange);
                  }
                }
                assert minified.hasValue();
              } else {
                MappedRange existingMappedRange =
                    existingClassBuilder.methodsWithoutPosition.get(signature);
                existingMappedRanges =
                    existingMappedRange == null
                        ? null
                        : Collections.singletonList(existingMappedRange);
              }
            }
            // Mapping the original ranges all the way back may cause the minified map range and the
            // original mapped range to have different spans. We therefore maintain a collection of
            // inline frames to add when we see the last mapped range.
            List<List<MappedRange>> newComposedInlineFrames = new ArrayList<>();
            if (composedInlineFrames.isEmpty()) {
              splitOnNewMinifiedRange(
                  composeMappedRangesForMethod(
                      existingMappedRanges, mappedRange, computedOutlineInformation),
                  Collections.emptyList(),
                  newComposedInlineFrames::add);
            } else {
              for (List<MappedRange> composedInlineFrame : composedInlineFrames) {
                MappedRange splitMappedRange =
                    mappedRange.partitionOnMinifiedRange(composedInlineFrame.get(0).minifiedRange);
                splitOnNewMinifiedRange(
                    composeMappedRangesForMethod(
                        existingMappedRanges, splitMappedRange, computedOutlineInformation),
                    composedInlineFrame,
                    newComposedInlineFrames::add);
              }
            }
            composedInlineFrames = newComposedInlineFrames;
            if (!isInlineMappedRange(newMappedRanges, i)) {
              for (List<MappedRange> composedInlineFrame : composedInlineFrames) {
                composedRanges.addAll(composedInlineFrame);
              }
              composedInlineFrames = Collections.emptyList();
            }
          }
          MappedRange lastComposedRange = ListUtils.last(composedRanges);
          if (computedOutlineInformation.seenOutlineMappingInformation != null) {
            current
                .getUpdateOutlineCallsiteInformation(
                    committedPreviousClassBuilder.getRenamedName(),
                    ListUtils.last(newMappedRanges).signature.getName(),
                    lastComposedRange.getRenamedName())
                .setNewMappedRanges(newMappedRanges);
            lastComposedRange.addMappingInformation(
                computedOutlineInformation.seenOutlineMappingInformation,
                ConsumerUtils.emptyConsumer());
          }
          if (!computedOutlineInformation.outlineCallsiteMappingInformationToPatchUp.isEmpty()) {
            MappedRangeOriginalToMinifiedMap originalToMinifiedMap =
                MappedRangeOriginalToMinifiedMap.build(newMappedRanges);
            List<OutlineCallsiteMappingInformation> outlineCallSites =
                new ArrayList<>(
                    computedOutlineInformation.outlineCallsiteMappingInformationToPatchUp);
            outlineCallSites.sort(Comparator.comparing(mapping -> mapping.getOutline().toString()));
            for (OutlineCallsiteMappingInformation outlineCallSite : outlineCallSites) {
              Int2IntSortedMap positionMap = outlineCallSite.getPositions();
              for (Integer keyPosition : positionMap.keySet()) {
                int keyPositionInt = keyPosition;
                int originalDestination = positionMap.get(keyPositionInt);
                int newDestination = originalToMinifiedMap.lookupFirst(originalDestination);
                positionMap.put(keyPositionInt, newDestination);
              }
              lastComposedRange.addMappingInformation(
                  outlineCallSite, ConsumerUtils.emptyConsumer());
            }
          }
          MethodSignature residualSignature =
              memberNaming
                  .computeResidualSignature(type -> inverseClassMapping.getOrDefault(type, type))
                  .asMethodSignature();
          if (lastComposedRange.minifiedRange != null) {
            SegmentTree<List<MappedRange>> listSegmentTree =
                methodsWithPosition.computeIfAbsent(
                    residualSignature, ignored -> new SegmentTree<>(false));
            listSegmentTree.add(
                minified.getStartOrNoRangeFrom(), minified.getEndOrNoRangeFrom(), composedRanges);
          } else {
            assert composedRanges.size() == 1;
            methodsWithoutPosition.put(residualSignature, lastComposedRange);
          }
        }
      }
    }

    private void splitOnNewMinifiedRange(
        List<MappedRange> mappedRanges,
        List<MappedRange> previouslyMapped,
        Consumer<List<MappedRange>> consumer) {
      assert !mappedRanges.isEmpty();
      Range minifiedRange = mappedRanges.get(0).minifiedRange;
      if (minifiedRange == null) {
        consumer.accept(ListUtils.joinNewArrayList(previouslyMapped, mappedRanges));
        return;
      }
      Box<Range> lastMinifiedRange = new Box<>(minifiedRange);
      int lastMappedIndex = 0;
      for (int i = 0; i < mappedRanges.size(); i++) {
        MappedRange mappedRange = mappedRanges.get(i);
        Range lastMinifiedRangeFinal = lastMinifiedRange.get();
        if (!mappedRange.minifiedRange.equals(lastMinifiedRangeFinal)) {
          consumer.accept(
              ListUtils.joinNewArrayList(
                  ListUtils.map(
                      previouslyMapped, x -> x.partitionOnMinifiedRange(lastMinifiedRangeFinal)),
                  mappedRanges.subList(lastMappedIndex, i)));
          lastMinifiedRange.set(mappedRange.minifiedRange);
          lastMappedIndex = i;
        }
      }
      consumer.accept(
          ListUtils.joinNewArrayList(
              ListUtils.map(
                  previouslyMapped, x -> x.partitionOnMinifiedRange(lastMinifiedRange.get())),
              mappedRanges.subList(lastMappedIndex, mappedRanges.size())));
    }

    private ComposingClassBuilder getExistingClassBuilder(MethodSignature originalSignature) {
      return originalSignature.isQualified()
          ? committedPreviousClassBuilders.get(originalSignature.toHolderFromQualified())
          : committedPreviousClassBuilder;
    }

    private void registerMappingInformationFromMappedRanges(MappedRange mappedRange)
        throws MappingComposeException {
      for (MappingInformation mappingInformation : mappedRange.getAdditionalMappingInformation()) {
        if (mappingInformation.isRewriteFrameMappingInformation()) {
          RewriteFrameMappingInformation rewriteFrameMappingInformation =
              mappingInformation.asRewriteFrameMappingInformation();
          rewriteFrameMappingInformation
              .getConditions()
              .forEach(
                  condition -> {
                    if (condition.isThrowsCondition()) {
                      current.rewriteFrameInformation.add(rewriteFrameMappingInformation);
                    }
                  });
        } else if (mappingInformation.isOutlineCallsiteInformation()) {
          OutlineCallsiteMappingInformation outlineCallsiteInfo =
              mappingInformation.asOutlineCallsiteInformation();
          MethodReference outline = outlineCallsiteInfo.getOutline();
          if (outline == null) {
            throw new MappingComposeException(
                "Unable to compose outline call site information without outline key: "
                    + outlineCallsiteInfo.serialize());
          }
          current.addNewOutlineCallsiteInformation(outline, outlineCallsiteInfo);
        }
      }
    }

    private List<MappedRange> composeMappedRangesForMethod(
        List<MappedRange> existingRanges,
        MappedRange newRange,
        ComputedOutlineInformation computedOutlineInformation)
        throws MappingComposeException {
      assert newRange != null;
      if (existingRanges == null || existingRanges.isEmpty()) {
        return Collections.singletonList(newRange);
      }
      MappedRange lastExistingRange = ListUtils.last(existingRanges);
      if (newRange.originalRange == null) {
        MappedRange newComposedRange =
            new MappedRange(
                newRange.minifiedRange, lastExistingRange.signature, null, newRange.renamedName);
        composeMappingInformation(
            newComposedRange.getAdditionalMappingInformation(),
            lastExistingRange.getAdditionalMappingInformation(),
            info -> newComposedRange.addMappingInformation(info, ConsumerUtils.emptyConsumer()));
        return Collections.singletonList(newComposedRange);
      }
      ExistingMapping mappedRangesForPosition = computeExistingMapping(existingRanges);
      List<MappedRange> newComposedRanges = new ArrayList<>();
      assert newRange.minifiedRange != null;
      // First check if the original range matches the existing minified range.
      List<MappedRange> existingMappedRanges =
          mappedRangesForPosition.getMappedRangesForPosition(
              newRange.getFirstPositionOfOriginalRange(NO_RANGE_FROM));
      MappedRange lastExistingMappedRange = ListUtils.lastOrNull(existingMappedRanges);
      int startingPosition = newRange.minifiedRange.from;
      if (existingMappedRanges == null) {
        // If we cannot lookup the original position because it has been removed we compose with
        // the existing method signature.
        if (newRange.originalRange.isPreamble()
            || (existingRanges.size() == 1 && lastExistingRange.minifiedRange == null)) {
          return Collections.singletonList(
              new MappedRange(
                  newRange.minifiedRange,
                  lastExistingRange.signature,
                  lastExistingRange.originalRange != null
                          && lastExistingRange.originalRange.span() == 1
                      ? lastExistingRange.originalRange
                      : EMPTY_RANGE,
                  newRange.renamedName));
        } else if (newRange.originalRange.from == 0) {
          // Similar to the trick below we create a synthetic range to map the preamble to.
          Pair<Integer, MappedRange> emptyRange =
              createEmptyRange(
                  newRange, lastExistingRange, mappedRangesForPosition, startingPosition);
          lastExistingMappedRange = emptyRange.getSecond();
          existingMappedRanges = Collections.singletonList(emptyRange.getSecond());
          startingPosition += emptyRange.getFirst() + 1;
        } else {
          throw new MappingComposeException(
              "Unexpected missing original position for '" + newRange + "'.");
        }
      }
      assert lastExistingMappedRange != null;
      // If the existing mapped minified range is equal to the original range of the new range
      // then we have a perfect mapping that we can translate directly.
      if (lastExistingMappedRange.minifiedRange.equals(newRange.originalRange)) {
        computeComposedMappedRange(
            newComposedRanges,
            newRange,
            existingMappedRanges,
            computedOutlineInformation,
            newRange.minifiedRange.from,
            newRange.minifiedRange.to);
        return newComposedRanges;
      }
      // Otherwise, we have a situation where the minified range references over multiple
      // existing ranges. We simply chop op when the range changes on the right hand side. To
      // ensure we do not mess up the spans from the original range, we have to check if the
      // current starting position is inside an original range, and then chop it off.
      // Similarly, when writing the last block, we have to cut it off to match.
      int lastStartingMinifiedFrom = newRange.minifiedRange.from;
      for (int position = startingPosition; position <= newRange.minifiedRange.to; position++) {
        List<MappedRange> existingMappedRangesForPosition =
            mappedRangesForPosition.getMappedRangesForPosition(
                newRange.getOriginalLineNumber(position));
        MappedRange lastExistingMappedRangeForPosition =
            ListUtils.lastOrNull(existingMappedRangesForPosition);
        if (lastExistingMappedRangeForPosition == null
            || !lastExistingMappedRange.minifiedRange.equals(
                lastExistingMappedRangeForPosition.minifiedRange)) {
          // We have seen an existing range we have to compute a splitting for.
          computeComposedMappedRange(
              newComposedRanges,
              newRange,
              existingMappedRanges,
              computedOutlineInformation,
              lastStartingMinifiedFrom,
              position - 1);
          // Advance the last starting position to this point and advance the existing mapped
          // ranges for this position.
          lastStartingMinifiedFrom = position;
          if (existingMappedRangesForPosition == null) {
            if (!options.mappingComposeOptions().allowNonExistingOriginalRanges) {
              throw new MappingComposeException(
                  "Unexpected missing original position for '" + newRange + "'.");
            }
            // We are at the first position of a hole. If we have existing ranges:
            // 1:1:void foo():41:41 -> a
            // 9:9:void foo():49:49 -> a
            // We may have a new range that is:
            // 21:29:void foo():1:9
            // We end up here at position 2 and we have already committed
            // 21:21:void foo():41:41.
            // We then introduce a "fake" normal range to simulate the result of retracing one after
            // the other to end up with:
            // 21:21:void foo():41:41
            // 22:28:void foo():2:8
            // 29:29:void foo():49:49.
            Pair<Integer, MappedRange> emptyRange =
                createEmptyRange(
                    newRange,
                    lastExistingMappedRange,
                    mappedRangesForPosition,
                    newRange.getOriginalLineNumber(position));
            lastExistingMappedRange = emptyRange.getSecond();
            existingMappedRanges = Collections.singletonList(emptyRange.getSecond());
            position += emptyRange.getFirst();
          } else {
            lastExistingMappedRange = lastExistingMappedRangeForPosition;
            existingMappedRanges = existingMappedRangesForPosition;
          }
        }
      }
      computeComposedMappedRange(
          newComposedRanges,
          newRange,
          existingMappedRanges,
          computedOutlineInformation,
          lastStartingMinifiedFrom,
          newRange.minifiedRange.to);
      return newComposedRanges;
    }

    private Pair<Integer, MappedRange> createEmptyRange(
        MappedRange newRange,
        MappedRange lastExistingMappedRange,
        ExistingMapping mappedRangesForPosition,
        int position) {
      int startOriginalPosition = newRange.getOriginalLineNumber(position);
      Integer endOriginalPosition =
          mappedRangesForPosition.getCeilingForPosition(startOriginalPosition);
      if (endOriginalPosition == null) {
        endOriginalPosition = newRange.getLastPositionOfOriginalRange();
      } else if (endOriginalPosition > startOriginalPosition) {
        endOriginalPosition = endOriginalPosition - 1;
      }
      Range newOriginalRange = new Range(startOriginalPosition, endOriginalPosition);
      MappedRange nonExistingMappedRange =
          new MappedRange(
              newOriginalRange,
              lastExistingMappedRange.getOriginalSignature().asMethodSignature(),
              newOriginalRange,
              lastExistingMappedRange.getRenamedName());
      nonExistingMappedRange.setResidualSignatureInternal(
          lastExistingMappedRange.getResidualSignature());
      return Pair.create((endOriginalPosition - startOriginalPosition), nonExistingMappedRange);
    }

    public interface ExistingMapping {

      Integer getCeilingForPosition(int i);

      List<MappedRange> getMappedRangesForPosition(int i);
    }

    /***
     * Builds a position to mapped ranges for mappings by looking up all mapped ranges for a given
     * position.
     */
    private ExistingMapping computeExistingMapping(List<MappedRange> existingRanges) {
      TreeMap<Integer, List<MappedRange>> mappedRangesForPosition = new TreeMap<>();
      List<MappedRange> currentRangesForPosition = new ArrayList<>();
      int startExisting = NO_RANGE_FROM;
      int endExisting = NO_RANGE_FROM;
      boolean isCatchAll = false;
      for (int i = 0; i < existingRanges.size(); i++) {
        MappedRange mappedRange = existingRanges.get(i);
        currentRangesForPosition.add(mappedRange);
        if (!isInlineMappedRange(existingRanges, i)) {
          if (startExisting == NO_RANGE_FROM) {
            startExisting = mappedRange.getFirstPositionOfOriginalRange(NO_RANGE_FROM);
          }
          endExisting = Math.max(mappedRange.getLastPositionOfOriginalRange(), endExisting);
          if (mappedRange.minifiedRange == null) {
            mappedRangesForPosition.put(NO_RANGE_FROM, currentRangesForPosition);
          } else if (mappedRange.minifiedRange.isCatchAll()) {
            isCatchAll = true;
          } else {
            for (int position = mappedRange.minifiedRange.from;
                position <= mappedRange.minifiedRange.to;
                position++) {
              mappedRangesForPosition.put(position, currentRangesForPosition);
            }
          }
          currentRangesForPosition = new ArrayList<>();
        }
      }
      boolean finalIsCatchAll = isCatchAll;
      List<MappedRange> finalCurrentRangesForPosition = currentRangesForPosition;
      return new ExistingMapping() {
        @Override
        public Integer getCeilingForPosition(int i) {
          return finalIsCatchAll ? i : mappedRangesForPosition.ceilingKey(i);
        }

        @Override
        public List<MappedRange> getMappedRangesForPosition(int i) {
          return finalIsCatchAll ? finalCurrentRangesForPosition : mappedRangesForPosition.get(i);
        }
      };
    }

    private void computeComposedMappedRange(
        List<MappedRange> newComposedRanges,
        MappedRange newMappedRange,
        List<MappedRange> existingMappedRanges,
        ComputedOutlineInformation computedOutlineInformation,
        int lastStartingMinifiedFrom,
        int position)
        throws MappingComposeException {
      Range existingRange = existingMappedRanges.get(0).minifiedRange;
      assert existingMappedRanges.stream().allMatch(x -> x.minifiedRange.equals(existingRange));
      Range newMinifiedRange = new Range(lastStartingMinifiedFrom, position);
      boolean copyOriginalRange = existingRange.equals(newMappedRange.originalRange);
      for (MappedRange existingMappedRange : existingMappedRanges) {
        Range existingOriginalRange = existingMappedRange.originalRange;
        Range newOriginalRange;
        if (copyOriginalRange
            || existingOriginalRange == null
            || existingOriginalRange.span() == 1) {
          newOriginalRange = existingOriginalRange;
        } else {
          // Find the window that the new range points to into the original range.
          int existingMinifiedPos = newMappedRange.getOriginalLineNumber(lastStartingMinifiedFrom);
          int newOriginalStart = existingMappedRange.getOriginalLineNumber(existingMinifiedPos);
          if (newMappedRange.originalRange.span() == 1) {
            newOriginalRange = new Range(newOriginalStart, newOriginalStart);
          } else {
            assert newMinifiedRange.span() <= existingOriginalRange.span();
            newOriginalRange =
                new Range(newOriginalStart, newOriginalStart + newMinifiedRange.span() - 1);
          }
        }
        MappedRange computedRange =
            new MappedRange(
                newMinifiedRange,
                existingMappedRange.signature,
                newOriginalRange,
                newMappedRange.renamedName);
        List<MappingInformation> mappingInformationToCompose = new ArrayList<>();
        existingMappedRange
            .getAdditionalMappingInformation()
            .forEach(
                info -> {
                  if (info.isOutlineMappingInformation()) {
                    computedOutlineInformation.seenOutlineMappingInformation =
                        info.asOutlineMappingInformation();
                  } else if (info.isOutlineCallsiteInformation()) {
                    computedOutlineInformation.outlineCallsiteMappingInformationToPatchUp.add(
                        info.asOutlineCallsiteInformation());
                  } else {
                    mappingInformationToCompose.add(info);
                  }
                });
        composeMappingInformation(
            computedRange.getAdditionalMappingInformation(),
            mappingInformationToCompose,
            info -> computedRange.addMappingInformation(info, ConsumerUtils.emptyConsumer()));
        newComposedRanges.add(computedRange);
      }
    }

    /***
     * Populates newMappingInformation with existingMappingInformation.
     */
    private void composeMappingInformation(
        List<MappingInformation> newMappingInformation,
        List<MappingInformation> existingMappingInformation,
        Consumer<MappingInformation> consumer)
        throws MappingComposeException {
      Set<MappingInformation> nonCompasableNewInfos = Sets.newIdentityHashSet();
      for (MappingInformation existingInfo : existingMappingInformation) {
        boolean hasBeenComposed = false;
        for (MappingInformation newInfo : newMappingInformation) {
          if (newInfo.shouldCompose(existingInfo)) {
            nonCompasableNewInfos.add(newInfo);
            consumer.accept(newInfo.compose(existingInfo));
            hasBeenComposed = true;
          }
        }
        if (!hasBeenComposed) {
          consumer.accept(existingInfo);
        }
      }
      newMappingInformation.forEach(
          info -> {
            if (!nonCompasableNewInfos.contains(info)) {
              consumer.accept(info);
            }
          });
    }

    public void write(ChainableStringConsumer consumer) {
      consumer.accept(originalName).accept(" -> ").accept(renamedName).accept(":\n");
      additionalMappingInfo.forEach(info -> consumer.accept("# " + info.serialize()).accept("\n"));
      writeFields(consumer);
      writeMethods(consumer);
    }

    private void writeFields(ChainableStringConsumer consumer) {
      ArrayList<MemberNaming> fieldNamings = new ArrayList<>(fieldMembers.values());
      fieldNamings.sort(Comparator.comparing(MemberNaming::getOriginalName));
      fieldNamings.forEach(
          naming -> consumer.accept(INDENTATION).accept(naming.toString()).accept("\n"));
    }

    private void writeMethods(ChainableStringConsumer consumer) {
      methodsWithoutPosition.forEach(
          (ignored, mapped) -> {
            consumer.accept(INDENTATION).accept(mapped.toString()).accept("\n");
            for (MappingInformation info : mapped.getAdditionalMappingInformation()) {
              consumer.accept(INDENTATION).accept("# ").accept(info.serialize()).accept("\n");
            }
          });
      ArrayList<MethodSignature> sortedSignatures = new ArrayList<>(methodsWithPosition.keySet());
      sortedSignatures.sort(Comparator.comparing(Signature::getName));
      for (MethodSignature key : sortedSignatures) {
        methodsWithPosition
            .get(key)
            .visitSegments(
                mappedRanges ->
                    mappedRanges.forEach(
                        mappedRange -> {
                          consumer.accept(INDENTATION).accept(mappedRange.toString()).accept("\n");
                          for (MappingInformation info :
                              mappedRange.getAdditionalMappingInformation()) {
                            consumer
                                .accept(INDENTATION)
                                .accept("# ")
                                .accept(info.serialize())
                                .accept("\n");
                          }
                        }));
      }
    }

    public ComposingClassBuilder commit(ComposingClassBuilder classBuilder)
        throws MappingComposeException {
      ComposingClassBuilder newClassBuilder =
          new ComposingClassBuilder(
              originalName, classBuilder.renamedName, committed, null, options);
      composeMappingInformation(
          classBuilder.additionalMappingInfo,
          additionalMappingInfo,
          newClassBuilder.additionalMappingInfo::add);
      // Composed field namings and method namings should be freely composable by addition since
      // any renaming/position change should have removed the existing committed mapping.
      putAll(
          newClassBuilder.fieldMembers,
          fieldMembers,
          classBuilder.fieldMembers,
          (committed, add) -> {
            assert committed == null;
            return add;
          });
      putAll(
          newClassBuilder.methodsWithoutPosition,
          methodsWithoutPosition,
          classBuilder.methodsWithoutPosition,
          (committed, add) -> {
            if (committed != null && add != null) {
              throw new MappingComposeException(
                  "Cannot compose duplicate methods without position in class '"
                      + renamedName
                      + "': '"
                      + committed
                      + "' and '"
                      + add);
            }
            return committed != null ? committed : add;
          });
      putAll(
          newClassBuilder.methodsWithPosition,
          methodsWithPosition,
          classBuilder.methodsWithPosition,
          (committed, add) -> add);
      return newClassBuilder;
    }

    private <S extends Signature, V> void putAll(
        Map<S, V> output,
        Map<S, V> committed,
        Map<S, V> toAdd,
        ThrowingBiFunction<V, V, V, MappingComposeException> compose)
        throws MappingComposeException {
      assert output.isEmpty();
      output.putAll(committed);
      for (Entry<S, V> kvEntry : toAdd.entrySet()) {
        output.put(
            kvEntry.getKey(), compose.apply(output.get(kvEntry.getKey()), kvEntry.getValue()));
      }
    }

    private static class RangeBuilder {

      private int start = Integer.MAX_VALUE;
      private int end = Integer.MIN_VALUE;

      private void addRange(Range range) {
        if (range != null) {
          start = Math.min(start, range.from);
          end = Math.max(end, range.to);
        }
      }

      private boolean hasValue() {
        return start < Integer.MAX_VALUE;
      }

      private int getStartOrNoRangeFrom() {
        return hasValue() ? start : NO_RANGE_FROM;
      }

      private int getEndOrNoRangeFrom() {
        return hasValue() ? end : NO_RANGE_FROM;
      }

      private boolean isPreamble() {
        return hasValue() && start == end && start == 0;
      }
    }

    private static class ComputedOutlineInformation {
      private final Set<OutlineCallsiteMappingInformation>
          outlineCallsiteMappingInformationToPatchUp = Sets.newIdentityHashSet();
      private OutlineMappingInformation seenOutlineMappingInformation = null;
    }
  }
}
