// Copyright (c) 2017, the Dart 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.

import 'dart:collection';

import 'package:analysis_server/protocol/protocol_generated.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart';
import 'package:analyzer_plugin/protocol/protocol_generated.dart' as plugin;
import 'package:meta/meta.dart';

/**
 * An object used to merge partial lists of results that were contributed by
 * plugins.
 *
 * All of the methods in this class assume that the contributions from the
 * analysis server are the first partial result in the list of partial results
 * to be merged.
 */
class ResultMerger {
  /**
   * Return a list of fixes composed by merging the lists of fixes in the
   * [partialResultList].
   *
   * The resulting list of fixes will contain exactly one fix for every analysis
   * error for which there are fixes. If two or more plugins contribute the same
   * fix for a given error, the resulting list will contain duplications.
   */
  List<plugin.AnalysisErrorFixes> mergeAnalysisErrorFixes(
      List<List<plugin.AnalysisErrorFixes>> partialResultList) {
    /**
     * Return a key encoding the unique attributes of the given [error].
     */
    String computeKey(AnalysisError error) {
      StringBuffer buffer = new StringBuffer();
      buffer.write(error.location.offset);
      buffer.write(';');
      buffer.write(error.code);
      buffer.write(';');
      buffer.write(error.message);
      buffer.write(';');
      buffer.write(error.correction);
      return buffer.toString();
    }

    int count = partialResultList.length;
    if (count == 0) {
      return <plugin.AnalysisErrorFixes>[];
    } else if (count == 1) {
      return partialResultList[0];
    }
    Map<String, plugin.AnalysisErrorFixes> fixesMap =
        <String, plugin.AnalysisErrorFixes>{};
    for (plugin.AnalysisErrorFixes fix in partialResultList[0]) {
      fixesMap[computeKey(fix.error)] = fix;
    }
    for (int i = 1; i < count; i++) {
      for (plugin.AnalysisErrorFixes fix in partialResultList[i]) {
        String key = computeKey(fix.error);
        plugin.AnalysisErrorFixes mergedFix = fixesMap[key];
        if (mergedFix == null) {
          fixesMap[key] = fix;
        } else {
          // If more than two plugins contribute fixes for the same error, this
          // will result in extra copy operations.
          List<plugin.PrioritizedSourceChange> mergedChanges =
              mergedFix.fixes.toList();
          mergedChanges.addAll(fix.fixes);
          plugin.AnalysisErrorFixes copiedFix = new plugin.AnalysisErrorFixes(
              mergedFix.error,
              fixes: mergedChanges);
          fixesMap[key] = copiedFix;
        }
      }
    }
    List<plugin.AnalysisErrorFixes> mergedFixes = fixesMap.values.toList();
    for (plugin.AnalysisErrorFixes fixes in mergedFixes) {
      fixes.fixes.sort((first, second) => first.priority - second.priority);
    }
    return mergedFixes;
  }

  /**
   * Return a list of errors composed by merging the lists of errors in the
   * [partialResultList].
   *
   * The resulting list will contain all of the analysis errors from all of the
   * plugins. If two or more plugins contribute the same error the resulting
   * list will contain duplications.
   */
  List<AnalysisError> mergeAnalysisErrors(
      List<List<AnalysisError>> partialResultList) {
    // TODO(brianwilkerson) Consider merging duplicate errors (same code,
    // location, and messages). If we do that, we should return the logical-or
    // of the hasFix fields from the merged errors.
    int count = partialResultList.length;
    if (count == 0) {
      return <AnalysisError>[];
    } else if (count == 1) {
      return partialResultList[0];
    }
    List<AnalysisError> mergedErrors = <AnalysisError>[];
    for (List<AnalysisError> partialResults in partialResultList) {
      mergedErrors.addAll(partialResults);
    }
    return mergedErrors;
  }

  /**
   * Return a list of suggestions composed by merging the lists of suggestions
   * in the [partialResultList].
   *
   * The resulting list will contain all of the suggestions from all of the
   * plugins. If two or more plugins contribute the same suggestion the
   * resulting list will contain duplications.
   */
  List<CompletionSuggestion> mergeCompletionSuggestions(
      List<List<CompletionSuggestion>> partialResultList) {
    int count = partialResultList.length;
    if (count == 0) {
      return <CompletionSuggestion>[];
    } else if (count == 1) {
      return partialResultList[0];
    }
    List<CompletionSuggestion> mergedSuggestions = <CompletionSuggestion>[];
    for (List<CompletionSuggestion> partialResults in partialResultList) {
      mergedSuggestions.addAll(partialResults);
    }
    return mergedSuggestions;
  }

  /**
   * Return a list of regions composed by merging the lists of regions in the
   * [partialResultList].
   *
   * The resulting list will contain all of the folding regions from all of the
   * plugins. If a plugin contributes a folding region that overlaps a region
   * from a previous plugin, the overlapping region will be omitted. (For these
   * purposes, if either region is fully contained within the other they are not
   * considered to be overlapping.)
   */
  List<FoldingRegion> mergeFoldingRegions(
      List<List<FoldingRegion>> partialResultList) {
    int count = partialResultList.length;
    if (count == 0) {
      return <FoldingRegion>[];
    } else if (count == 1) {
      return partialResultList[0];
    }
    List<FoldingRegion> mergedRegions = partialResultList[0].toList();

    /**
     * Return `true` if the [newRegion] does not overlap any of the regions in
     * the collection of [mergedRegions].
     */
    bool isNonOverlapping(FoldingRegion newRegion) {
      int newStart = newRegion.offset;
      int newEnd = newStart + newRegion.length;
      for (FoldingRegion existingRegion in mergedRegions) {
        int existingStart = existingRegion.offset;
        int existingEnd = existingStart + existingRegion.length;
        if (overlaps(newStart, newEnd, existingStart, existingEnd,
            allowNesting: true)) {
          return false;
        }
      }
      return true;
    }

    for (int i = 1; i < count; i++) {
      List<FoldingRegion> partialResults = partialResultList[i];
      for (FoldingRegion region in partialResults) {
        if (isNonOverlapping(region)) {
          mergedRegions.add(region);
        }
      }
    }
    return mergedRegions;
  }

  /**
   * Return a list of regions composed by merging the lists of regions in the
   * [partialResultList].
   *
   * The resulting list will contain all of the highlight regions from all of
   * the plugins. If two or more plugins contribute the same highlight region
   * the resulting list will contain duplications.
   */
  List<HighlightRegion> mergeHighlightRegions(
      List<List<HighlightRegion>> partialResultList) {
    int count = partialResultList.length;
    if (count == 0) {
      return <HighlightRegion>[];
    } else if (count == 1) {
      return partialResultList[0];
    }
    List<HighlightRegion> mergedRegions = <HighlightRegion>[];
    for (List<HighlightRegion> partialResults in partialResultList) {
      mergedRegions.addAll(partialResults);
    }
    return mergedRegions;
  }

  /**
   * Return kythe entry result parameters composed by merging the parameters in
   * the [partialResultList].
   *
   * The resulting list will contain all of the kythe entries from all of the
   * plugins. If a plugin contributes a kythe entry that is the same as the
   * entry from a different plugin, the entry will appear twice in the list.
   */
  KytheGetKytheEntriesResult mergeKytheEntries(
      List<KytheGetKytheEntriesResult> partialResultList) {
    List<KytheEntry> mergedEntries = <KytheEntry>[];
    Set<String> mergedFiles = new Set<String>();
    for (KytheGetKytheEntriesResult partialResult in partialResultList) {
      mergedEntries.addAll(partialResult.entries);
      mergedFiles.addAll(partialResult.files);
    }
    return new KytheGetKytheEntriesResult(mergedEntries, mergedFiles.toList());
  }

  /**
   * Return navigation notification parameters composed by merging the
   * parameters in the [partialResultList].
   *
   * The resulting list will contain all of the navigation regions from all of
   * the plugins. If a plugin contributes a navigation region that overlaps a
   * region from a previous plugin, the overlapping region will be omitted. (For
   * these purposes, nested regions are considered to be overlapping.)
   */
  AnalysisNavigationParams mergeNavigation(
      List<AnalysisNavigationParams> partialResultList) {
    int count = partialResultList.length;
    if (count == 0) {
      return null;
    } else if (count == 1) {
      return partialResultList[0];
    }
    AnalysisNavigationParams base = partialResultList[0];
    String file = base.file;
    List<NavigationRegion> mergedRegions = base.regions.toList();
    List<NavigationTarget> mergedTargets = base.targets.toList();
    List<String> mergedFiles = base.files.toList();

    /**
     * Return `true` if the [newRegion] does not overlap any of the regions in
     * the collection of [mergedRegions].
     */
    bool isNonOverlapping(NavigationRegion newRegion) {
      int newStart = newRegion.offset;
      int newEnd = newStart + newRegion.length;
      for (NavigationRegion mergedRegion in mergedRegions) {
        int mergedStart = mergedRegion.offset;
        int mergedEnd = mergedStart + mergedRegion.length;
        if (overlaps(newStart, newEnd, mergedStart, mergedEnd)) {
          return false;
        }
      }
      return true;
    }

    /**
     * Return the index of the region in the collection of [mergedRegions] that
     * covers exactly the same region as the [newRegion], or `-1` if there is no
     * such region.
     */
    int matchingRegion(newRegion) {
      int newOffset = newRegion.offset;
      int newLength = newRegion.length;
      for (int i = 0; i < mergedRegions.length; i++) {
        NavigationRegion mergedRegion = mergedRegions[i];
        if (newOffset == mergedRegion.offset &&
            newLength == mergedRegion.length) {
          return i;
        }
      }
      return -1;
    }

    for (int i = 1; i < count; i++) {
      // For now we take the optimistic approach of assuming that most or all of
      // the regions will not overlap and that we therefore don't need to remove
      // any unreferenced files or targets from the lists. If that isn't true
      // then this could result in server sending more data to the client than
      // is necessary.
      AnalysisNavigationParams result = partialResultList[i];
      List<NavigationRegion> regions = result.regions;
      List<NavigationTarget> targets = result.targets;
      List<String> files = result.files;
      //
      // Merge the file data.
      //
      Map<int, int> fileMap = <int, int>{};
      for (int j = 0; j < files.length; j++) {
        String file = files[j];
        int index = mergedFiles.indexOf(file);
        if (index < 0) {
          index = mergedFiles.length;
          mergedFiles.add(file);
        }
        fileMap[j] = index;
      }
      //
      // Merge the target data.
      //
      Map<int, int> targetMap = <int, int>{};
      for (int j = 0; j < targets.length; j++) {
        NavigationTarget target = targets[j];
        int newIndex = fileMap[target.fileIndex];
        if (target.fileIndex != newIndex) {
          target = new NavigationTarget(target.kind, newIndex, target.offset,
              target.length, target.startLine, target.startColumn);
        }
        int index = mergedTargets.indexOf(target);
        if (index < 0) {
          index = mergedTargets.length;
          mergedTargets.add(target);
        }
        targetMap[j] = index;
      }
      //
      // Merge the region data.
      //
      for (int j = 0; j < regions.length; j++) {
        NavigationRegion region = regions[j];
        List<int> newTargets = region.targets
            .map((int oldTarget) => targetMap[oldTarget])
            .toList();
        if (region.targets != newTargets) {
          region =
              new NavigationRegion(region.offset, region.length, newTargets);
        }
        int index = matchingRegion(region);
        if (index >= 0) {
          NavigationRegion mergedRegion = mergedRegions[index];
          List<int> mergedTargets = mergedRegion.targets;
          bool added = false;
          for (int target in region.targets) {
            if (!mergedTargets.contains(target)) {
              if (added) {
                mergedTargets.add(target);
              } else {
                //
                // This is potentially inefficient. If a merged region matches
                // regions from multiple plugins it will be copied multiple
                // times. The likelihood seems small enough to not warrant
                // optimizing this further.
                //
                mergedTargets = mergedTargets.toList();
                mergedTargets.add(target);
                mergedRegion = new NavigationRegion(
                    mergedRegion.offset, mergedRegion.length, mergedTargets);
                mergedRegions[index] = mergedRegion;
                added = true;
              }
            }
          }
          if (added) {
            mergedTargets.sort();
          }
        } else if (isNonOverlapping(region)) {
          mergedRegions.add(region);
        }
      }
    }
    return new AnalysisNavigationParams(
        file, mergedRegions, mergedTargets, mergedFiles);
  }

  /**
   * Return a list of occurrences composed by merging the lists of occurrences
   * in the [partialResultList].
   *
   * The resulting list of occurrences will contain exactly one occurrences for
   * every element for which there is at least one occurrences. If two or more
   * plugins contribute an occurrences for the same element, the resulting
   * occurrences for that element will include all of the locations from all of
   * the plugins without duplications.
   */
  List<Occurrences> mergeOccurrences(
      List<List<Occurrences>> partialResultList) {
    int count = partialResultList.length;
    if (count == 0) {
      return <Occurrences>[];
    } else if (count == 1) {
      return partialResultList[0];
    }
    Map<Element, Set<int>> elementMap = <Element, Set<int>>{};
    for (List<Occurrences> partialResults in partialResultList) {
      for (Occurrences occurances in partialResults) {
        Element element = occurances.element;
        Set<int> offsets =
            elementMap.putIfAbsent(element, () => new HashSet<int>());
        offsets.addAll(occurances.offsets);
      }
    }
    List<Occurrences> mergedOccurrences = <Occurrences>[];
    elementMap.forEach((Element element, Set<int> offsets) {
      List<int> sortedOffsets = offsets.toList();
      sortedOffsets.sort();
      mergedOccurrences
          .add(new Occurrences(element, sortedOffsets, element.name.length));
    });
    return mergedOccurrences;
  }

  /**
   * Return a list of outlines composed by merging the lists of outlines in the
   * [partialResultList].
   *
   * The resulting list of outlines will contain ...
   *
   * Throw an exception if any of the outlines are associated with an element
   * that does not have a location.
   *
   * Throw an exception if any outline has children that are also children of
   * another outline. No exception is thrown if a plugin contributes a top-level
   * outline that is a child of an outline contributed by a different plugin.
   */
  List<Outline> mergeOutline(List<List<Outline>> partialResultList) {
    /**
     * Return a key encoding the unique attributes of the given [element].
     */
    String computeKey(Element element) {
      Location location = element.location;
      if (location == null) {
        throw new StateError(
            'Elements in an outline are expected to have a location');
      }
      StringBuffer buffer = new StringBuffer();
      buffer.write(location.offset);
      buffer.write(';');
      buffer.write(element.kind.name);
      return buffer.toString();
    }

    int count = partialResultList.length;
    if (count == 0) {
      return <Outline>[];
    } else if (count == 1) {
      return partialResultList[0];
    }
    List<Outline> mergedOutlines = partialResultList[0].toList();
    Map<String, Outline> outlineMap = <String, Outline>{};
    Map<Outline, Outline> copyMap = <Outline, Outline>{};

    /**
     * Add the given [outline] and all of its children to the [outlineMap].
     */
    void addToMap(Outline outline) {
      String key = computeKey(outline.element);
      if (outlineMap.containsKey(key)) {
        // TODO(brianwilkerson) Decide how to handle this more gracefully.
        throw new StateError('Inconsistent outlines');
      }
      outlineMap[key] = outline;
      outline.children?.forEach(addToMap);
    }

    /**
     * Merge the children of the [newOutline] into the list of children of the
     * [mergedOutline].
     */
    void mergeChildren(Outline mergedOutline, Outline newOutline) {
      for (Outline newChild in newOutline.children) {
        Outline mergedChild = outlineMap[computeKey(newChild.element)];
        if (mergedChild == null) {
          // The [newChild] isn't in the existing list.
          Outline copiedOutline = copyMap.putIfAbsent(
              mergedOutline,
              () => new Outline(mergedOutline.element, mergedOutline.offset,
                  mergedOutline.length,
                  children: mergedOutline.children.toList()));
          copiedOutline.children.add(newChild);
          addToMap(newChild);
        } else {
          mergeChildren(mergedChild, newChild);
        }
      }
    }

    mergedOutlines.forEach(addToMap);
    for (int i = 1; i < count; i++) {
      for (Outline outline in partialResultList[i]) {
        Outline mergedOutline = outlineMap[computeKey(outline.element)];
        if (mergedOutline == null) {
          // The [outline] does not correspond to any previously merged outline.
          mergedOutlines.add(outline);
          addToMap(outline);
        } else {
          // The [outline] corresponds to a previously merged outline, so we
          // just need to add its children to the merged outline's children.
          mergeChildren(mergedOutline, outline);
        }
      }
    }

    /**
     * Perform a depth first traversal of the outline structure rooted at the
     * given [outline] item, re-building each item if any of its children have
     * been updated by the merge process.
     */
    Outline traverse(Outline outline) {
      Outline copiedOutline = copyMap[outline];
      bool isCopied = copiedOutline != null;
      copiedOutline ??= outline;
      List<Outline> currentChildren = copiedOutline.children;
      if (currentChildren == null || currentChildren.isEmpty) {
        return outline;
      }
      List<Outline> updatedChildren =
          currentChildren.map((Outline child) => traverse(child)).toList();
      if (currentChildren != updatedChildren) {
        if (!isCopied) {
          return new Outline(
              copiedOutline.element, copiedOutline.offset, copiedOutline.length,
              children: updatedChildren);
        }
        copiedOutline.children = updatedChildren;
        return copiedOutline;
      }
      return outline;
    }

    for (int i = 0; i < mergedOutlines.length; i++) {
      mergedOutlines[i] = traverse(mergedOutlines[i]);
    }
    return mergedOutlines;
  }

  /**
   * Return a list of source changes composed by merging the lists of source
   * changes in the [partialResultList].
   *
   * The resulting list will contain all of the source changes from all of the
   * plugins. If two or more plugins contribute the same source change the
   * resulting list will contain duplications.
   */
  List<plugin.PrioritizedSourceChange> mergePrioritizedSourceChanges(
      List<List<plugin.PrioritizedSourceChange>> partialResultList) {
    int count = partialResultList.length;
    if (count == 0) {
      return <plugin.PrioritizedSourceChange>[];
    } else if (count == 1) {
      return partialResultList[0];
    }
    List<plugin.PrioritizedSourceChange> mergedChanges =
        <plugin.PrioritizedSourceChange>[];
    for (List<plugin.PrioritizedSourceChange> partialResults
        in partialResultList) {
      mergedChanges.addAll(partialResults);
    }
    mergedChanges.sort((first, second) => first.priority - second.priority);
    return mergedChanges;
  }

  /**
   * Return a refactoring feedback composed by merging the refactoring feedbacks
   * in the [partialResultList].
   *
   * The content of the resulting feedback depends on the kind of feedbacks
   * being merged.
   *
   * Throw an exception if the refactoring feedbacks are of an unhandled type.
   *
   * The feedbacks in the [partialResultList] are expected to all be of the same
   * type. If that expectation is violated, and exception might be thrown.
   */
  RefactoringFeedback mergeRefactoringFeedbacks(
      List<RefactoringFeedback> feedbacks) {
    int count = feedbacks.length;
    if (count == 0) {
      return null;
    } else if (count == 1) {
      return feedbacks[0];
    }
    RefactoringFeedback first = feedbacks[0];
    if (first is ConvertGetterToMethodFeedback) {
      // The feedbacks are empty, so there's nothing to merge.
      return first;
    } else if (first is ConvertMethodToGetterFeedback) {
      // The feedbacks are empty, so there's nothing to merge.
      return first;
    } else if (first is ExtractLocalVariableFeedback) {
      List<int> coveringExpressionOffsets =
          first.coveringExpressionOffsets == null
              ? <int>[]
              : first.coveringExpressionOffsets.toList();
      List<int> coveringExpressionLengths =
          first.coveringExpressionLengths == null
              ? <int>[]
              : first.coveringExpressionLengths.toList();
      List<String> names = first.names.toList();
      List<int> offsets = first.offsets.toList();
      List<int> lengths = first.lengths.toList();
      for (int i = 1; i < count; i++) {
        ExtractLocalVariableFeedback feedback = feedbacks[i];
        // TODO(brianwilkerson) This doesn't ensure that the covering data is in
        // the right order and consistent.
        if (feedback.coveringExpressionOffsets != null) {
          coveringExpressionOffsets.addAll(feedback.coveringExpressionOffsets);
        }
        if (feedback.coveringExpressionLengths != null) {
          coveringExpressionLengths.addAll(feedback.coveringExpressionLengths);
        }
        for (String name in feedback.names) {
          if (!names.contains(name)) {
            names.add(name);
          }
        }
        offsets.addAll(feedback.offsets);
        lengths.addAll(feedback.lengths);
      }
      return new ExtractLocalVariableFeedback(names.toList(), offsets, lengths,
          coveringExpressionOffsets: (coveringExpressionOffsets.isEmpty
              ? null
              : coveringExpressionOffsets),
          coveringExpressionLengths: (coveringExpressionLengths.isEmpty
              ? null
              : coveringExpressionLengths));
    } else if (first is ExtractMethodFeedback) {
      int offset = first.offset;
      int length = first.length;
      String returnType = first.returnType;
      List<String> names = first.names.toList();
      bool canCreateGetter = first.canCreateGetter;
      List<RefactoringMethodParameter> parameters = first.parameters;
      List<int> offsets = first.offsets.toList();
      List<int> lengths = first.lengths.toList();
      for (int i = 1; i < count; i++) {
        ExtractMethodFeedback feedback = feedbacks[i];
        if (returnType.isEmpty) {
          returnType = feedback.returnType;
        }
        for (String name in feedback.names) {
          if (!names.contains(name)) {
            names.add(name);
          }
        }
        canCreateGetter = canCreateGetter && feedback.canCreateGetter;
        // TODO(brianwilkerson) This doesn't allow plugins to add parameters.
        // TODO(brianwilkerson) This doesn't check for duplicate offsets.
        offsets.addAll(feedback.offsets);
        lengths.addAll(feedback.lengths);
      }
      return new ExtractMethodFeedback(offset, length, returnType,
          names.toList(), canCreateGetter, parameters, offsets, lengths);
    } else if (first is InlineLocalVariableFeedback) {
      int occurrences = first.occurrences;
      for (int i = 1; i < count; i++) {
        occurrences +=
            (feedbacks[i] as InlineLocalVariableFeedback).occurrences;
      }
      return new InlineLocalVariableFeedback(first.name, occurrences);
    } else if (first is InlineMethodFeedback) {
      // There is nothing in the feedback that can reasonably be extended or
      // modified by other plugins.
      return first;
    } else if (first is MoveFileFeedback) {
      // The feedbacks are empty, so there's nothing to merge.
      return first;
    } else if (first is RenameFeedback) {
      // There is nothing in the feedback that can reasonably be extended or
      // modified by other plugins.
      return first;
    }
    throw new StateError(
        'Unsupported class of refactoring feedback: ${first.runtimeType}');
  }

  /**
   * Return a list of refactoring kinds composed by merging the lists of
   * refactoring kinds in the [partialResultList].
   *
   * The resulting list will contain all of the refactoring kinds from all of
   * the plugins, but will not contain duplicate elements.
   */
  List<RefactoringKind> mergeRefactoringKinds(
      List<List<RefactoringKind>> partialResultList) {
    int count = partialResultList.length;
    if (count == 0) {
      return <RefactoringKind>[];
    } else if (count == 1) {
      return partialResultList[0];
    }
    Set<RefactoringKind> mergedKinds = new HashSet<RefactoringKind>();
    for (List<RefactoringKind> partialResults in partialResultList) {
      mergedKinds.addAll(partialResults);
    }
    return mergedKinds.toList();
  }

  /**
   * Return the result for a getRefactorings request composed by merging the
   * results in the [partialResultList].
   *
   * The returned result will contain the concatenation of the initial, options,
   * and final problems. If two or more plugins produce the same problem, then
   * the resulting list of problems will contain duplications.
   *
   * The returned result will contain a merged list of refactoring feedbacks (as
   * defined by [mergeRefactoringFeedbacks]) and a merged list of source changes
   * (as defined by [mergeChanges]).
   *
   * The returned result will contain the concatenation of the potential edits.
   * If two or more plugins produce the same potential edit, then the resulting
   * list of potential edits will contain duplications.
   */
  EditGetRefactoringResult mergeRefactorings(
      List<EditGetRefactoringResult> partialResultList) {
    /**
     * Return the result of merging the given list of source [changes] into a
     * single source change.
     *
     * The resulting change will have the first non-null message and the first
     * non-null selection. The linked edit groups will be a concatenation of all
     * of the individual linked edit groups because there's no way to determine
     * when two such groups should be merged. The resulting list of edits will
     * be merged at the level of the file being edited, but will be a
     * concatenation of the individual edits within each file, even if multiple
     * plugins contribute duplicate or conflicting edits.
     */
    SourceChange mergeChanges(List<SourceChange> changes) {
      int count = changes.length;
      if (count == 0) {
        return null;
      } else if (count == 1) {
        return changes[0];
      }
      SourceChange first = changes[0];
      String message = first.message;
      Map<String, SourceFileEdit> editMap = <String, SourceFileEdit>{};
      for (SourceFileEdit edit in first.edits) {
        editMap[edit.file] = edit;
      }
      List<LinkedEditGroup> linkedEditGroups = first.linkedEditGroups.toList();
      Position selection = first.selection;
      for (int i = 1; i < count; i++) {
        SourceChange change = changes[i];
        for (SourceFileEdit edit in change.edits) {
          SourceFileEdit mergedEdit = editMap[edit.file];
          if (mergedEdit == null) {
            editMap[edit.file] = edit;
          } else {
            // This doesn't detect if multiple plugins contribute the same (or
            // conflicting) edits.
            List<SourceEdit> edits = mergedEdit.edits.toList();
            edits.addAll(edit.edits);
            editMap[edit.file] = new SourceFileEdit(
                mergedEdit.file, mergedEdit.fileStamp,
                edits: edits);
          }
        }
        linkedEditGroups.addAll(change.linkedEditGroups);
        message ??= change.message;
        selection ??= change.selection;
      }
      return new SourceChange(message,
          edits: editMap.values.toList(),
          linkedEditGroups: linkedEditGroups,
          selection: selection);
    }

    int count = partialResultList.length;
    if (count == 0) {
      return null;
    } else if (count == 1) {
      return partialResultList[0];
    }
    EditGetRefactoringResult result = partialResultList[0];
    List<RefactoringProblem> initialProblems = result.initialProblems.toList();
    List<RefactoringProblem> optionsProblems = result.optionsProblems.toList();
    List<RefactoringProblem> finalProblems = result.finalProblems.toList();
    List<RefactoringFeedback> feedbacks = <RefactoringFeedback>[];
    if (result.feedback != null) {
      feedbacks.add(result.feedback);
    }
    List<SourceChange> changes = <SourceChange>[];
    if (result.change != null) {
      changes.add(result.change);
    }
    List<String> potentialEdits = result.potentialEdits.toList();
    for (int i = 1; i < count; i++) {
      EditGetRefactoringResult result = partialResultList[1];
      initialProblems.addAll(result.initialProblems);
      optionsProblems.addAll(result.optionsProblems);
      finalProblems.addAll(result.finalProblems);
      if (result.feedback != null) {
        feedbacks.add(result.feedback);
      }
      if (result.change != null) {
        changes.add(result.change);
      }
      potentialEdits.addAll(result.potentialEdits);
    }
    return new EditGetRefactoringResult(
        initialProblems, optionsProblems, finalProblems,
        feedback: mergeRefactoringFeedbacks(feedbacks),
        change: mergeChanges(changes),
        potentialEdits: potentialEdits);
  }

  /**
   * Return a list of source changes composed by merging the lists of source
   * changes in the [partialResultList].
   *
   * The resulting list will contain all of the source changes from all of the
   * plugins. If two or more plugins contribute the same source change the
   * resulting list will contain duplications.
   */
  List<SourceChange> mergeSourceChanges(
      List<List<SourceChange>> partialResultList) {
    int count = partialResultList.length;
    if (count == 0) {
      return <SourceChange>[];
    } else if (count == 1) {
      return partialResultList[0];
    }
    List<SourceChange> mergedChanges = <SourceChange>[];
    for (List<SourceChange> partialResults in partialResultList) {
      mergedChanges.addAll(partialResults);
    }
    return mergedChanges;
  }

  /**
   * Return `true` if a region extending from [leftStart] (inclusive) to
   * [leftEnd] (exclusive) overlaps a region extending from [rightStart]
   * (inclusive) to [rightEnd] (exclusive). If [allowNesting] is `true`, then
   * the regions are allowed to overlap as long as one region is completely
   * nested within the other region.
   */
  @visibleForTesting
  bool overlaps(int leftStart, int leftEnd, int rightStart, int rightEnd,
      {bool allowNesting: false}) {
    if (leftEnd < rightStart || leftStart > rightEnd) {
      return false;
    }
    if (!allowNesting) {
      return true;
    }
    return !((leftStart <= rightStart && rightEnd <= leftEnd) ||
        (rightStart <= leftStart && leftEnd <= rightEnd));
  }
}
