// 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) {
      var buffer = 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();
    }

    var count = partialResultList.length;
    if (count == 0) {
      return <plugin.AnalysisErrorFixes>[];
    } else if (count == 1) {
      return partialResultList[0];
    }
    var fixesMap = <String, plugin.AnalysisErrorFixes>{};
    for (var fix in partialResultList[0]) {
      fixesMap[computeKey(fix.error)] = fix;
    }
    for (var i = 1; i < count; i++) {
      for (var fix in partialResultList[i]) {
        var key = computeKey(fix.error);
        var 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.
          var mergedChanges = mergedFix.fixes.toList();
          mergedChanges.addAll(fix.fixes);
          var copiedFix =
              plugin.AnalysisErrorFixes(mergedFix.error, fixes: mergedChanges);
          fixesMap[key] = copiedFix;
        }
      }
    }
    var mergedFixes = fixesMap.values.toList();
    for (var 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.
    var count = partialResultList.length;
    if (count == 0) {
      return <AnalysisError>[];
    } else if (count == 1) {
      return partialResultList[0];
    }
    var mergedErrors = <AnalysisError>[];
    for (var 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) {
    var count = partialResultList.length;
    if (count == 0) {
      return <CompletionSuggestion>[];
    } else if (count == 1) {
      return partialResultList[0];
    }
    var mergedSuggestions = <CompletionSuggestion>[];
    for (var 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) {
    var count = partialResultList.length;
    if (count == 0) {
      return <FoldingRegion>[];
    } else if (count == 1) {
      return partialResultList[0];
    }
    var 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) {
      var newStart = newRegion.offset;
      var newEnd = newStart + newRegion.length;
      for (var existingRegion in mergedRegions) {
        var existingStart = existingRegion.offset;
        var existingEnd = existingStart + existingRegion.length;
        if (overlaps(newStart, newEnd, existingStart, existingEnd,
            allowNesting: true)) {
          return false;
        }
      }
      return true;
    }

    for (var i = 1; i < count; i++) {
      var partialResults = partialResultList[i];
      for (var 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) {
    var count = partialResultList.length;
    if (count == 0) {
      return <HighlightRegion>[];
    } else if (count == 1) {
      return partialResultList[0];
    }
    var mergedRegions = <HighlightRegion>[];
    for (var partialResults in partialResultList) {
      mergedRegions.addAll(partialResults);
    }
    return mergedRegions;
  }

  /// 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) {
    var count = partialResultList.length;
    if (count == 0) {
      return null;
    } else if (count == 1) {
      return partialResultList[0];
    }
    var base = partialResultList[0];
    var file = base.file;
    var mergedRegions = base.regions.toList();
    var mergedTargets = base.targets.toList();
    var 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) {
      var newStart = newRegion.offset;
      var newEnd = newStart + newRegion.length;
      for (var mergedRegion in mergedRegions) {
        var mergedStart = mergedRegion.offset;
        var 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(NavigationRegion newRegion) {
      var newOffset = newRegion.offset;
      var newLength = newRegion.length;
      for (var i = 0; i < mergedRegions.length; i++) {
        var mergedRegion = mergedRegions[i];
        if (newOffset == mergedRegion.offset &&
            newLength == mergedRegion.length) {
          return i;
        }
      }
      return -1;
    }

    for (var 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.
      var result = partialResultList[i];
      var regions = result.regions;
      var targets = result.targets;
      var files = result.files;
      //
      // Merge the file data.
      //
      var fileMap = <int, int>{};
      for (var j = 0; j < files.length; j++) {
        var file = files[j];
        var index = mergedFiles.indexOf(file);
        if (index < 0) {
          index = mergedFiles.length;
          mergedFiles.add(file);
        }
        fileMap[j] = index;
      }
      //
      // Merge the target data.
      //
      var targetMap = <int, int>{};
      for (var j = 0; j < targets.length; j++) {
        var target = targets[j];
        var newIndex = fileMap[target.fileIndex];
        if (newIndex != null && target.fileIndex != newIndex) {
          target = NavigationTarget(target.kind, newIndex, target.offset,
              target.length, target.startLine, target.startColumn,
              codeOffset: target.codeOffset, codeLength: target.codeLength);
        }
        var index = mergedTargets.indexOf(target);
        if (index < 0) {
          index = mergedTargets.length;
          mergedTargets.add(target);
        }
        targetMap[j] = index;
      }
      //
      // Merge the region data.
      //
      for (var j = 0; j < regions.length; j++) {
        var region = regions[j];
        var newTargets = region.targets
            .map((int oldTarget) => targetMap[oldTarget])
            .toList()
            .cast<int>();
        if (region.targets != newTargets) {
          region = NavigationRegion(region.offset, region.length, newTargets);
        }
        var index = matchingRegion(region);
        if (index >= 0) {
          var mergedRegion = mergedRegions[index];
          var mergedTargets = mergedRegion.targets;
          var added = false;
          for (var 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 = NavigationRegion(
                    mergedRegion.offset, mergedRegion.length, mergedTargets);
                mergedRegions[index] = mergedRegion;
                added = true;
              }
            }
          }
          if (added) {
            mergedTargets.sort();
          }
        } else if (isNonOverlapping(region)) {
          mergedRegions.add(region);
        }
      }
    }
    return 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) {
    var count = partialResultList.length;
    if (count == 0) {
      return <Occurrences>[];
    } else if (count == 1) {
      return partialResultList[0];
    }
    var elementMap = <Element, Set<int>>{};
    for (var partialResults in partialResultList) {
      for (var occurrences in partialResults) {
        var element = occurrences.element;
        var offsets = elementMap.putIfAbsent(element, () => HashSet<int>());
        offsets.addAll(occurrences.offsets);
      }
    }
    var mergedOccurrences = <Occurrences>[];
    elementMap.forEach((Element element, Set<int> offsets) {
      var sortedOffsets = offsets.toList();
      sortedOffsets.sort();
      mergedOccurrences
          .add(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) {
      var location = element.location;
      if (location == null) {
        throw StateError(
            'Elements in an outline are expected to have a location');
      }
      var buffer = StringBuffer();
      buffer.write(location.offset);
      buffer.write(';');
      buffer.write(element.kind.name);
      return buffer.toString();
    }

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

    /// Add the given [outline] and all of its children to the [outlineMap].
    void addToMap(Outline outline) {
      var key = computeKey(outline.element);
      if (outlineMap.containsKey(key)) {
        // TODO(brianwilkerson): Decide how to handle this more gracefully.
        throw 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) {
      var newChildren = newOutline.children;
      if (newChildren != null) {
        for (var newChild in newChildren) {
          var mergedChild = outlineMap[computeKey(newChild.element)];
          if (mergedChild == null) {
            // The [newChild] isn't in the existing list.
            var mergedChildren = _copyList(mergedOutline.children);
            mergedChildren.add(newChild);
            copyMap.putIfAbsent(
                mergedOutline,
                () => Outline(
                    mergedOutline.element,
                    mergedOutline.offset,
                    mergedOutline.length,
                    mergedOutline.codeOffset,
                    mergedOutline.codeLength,
                    children: mergedChildren));
            addToMap(newChild);
          } else {
            mergeChildren(mergedChild, newChild);
          }
        }
      }
    }

    mergedOutlines.forEach(addToMap);
    for (var i = 1; i < count; i++) {
      for (var outline in partialResultList[i]) {
        var 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) {
      var copiedOutline = copyMap[outline];
      var isCopied = copiedOutline != null;
      copiedOutline ??= outline;
      var currentChildren = copiedOutline.children;
      if (currentChildren == null || currentChildren.isEmpty) {
        return outline;
      }
      var updatedChildren =
          currentChildren.map((Outline child) => traverse(child)).toList();
      if (currentChildren != updatedChildren) {
        if (!isCopied) {
          return Outline(
              copiedOutline.element,
              copiedOutline.offset,
              copiedOutline.length,
              copiedOutline.codeOffset,
              copiedOutline.codeLength,
              children: updatedChildren);
        }
        copiedOutline.children = updatedChildren;
        return copiedOutline;
      }
      return outline;
    }

    for (var 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) {
    var count = partialResultList.length;
    if (count == 0) {
      return <plugin.PrioritizedSourceChange>[];
    } else if (count == 1) {
      return partialResultList[0];
    }
    var mergedChanges = <plugin.PrioritizedSourceChange>[];
    for (var 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) {
    var count = feedbacks.length;
    if (count == 0) {
      return null;
    } else if (count == 1) {
      return feedbacks[0];
    }
    var 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) {
      var coveringExpressionOffsets =
          _copyList(first.coveringExpressionOffsets);
      var coveringExpressionLengths =
          _copyList(first.coveringExpressionLengths);
      var names = first.names.toList();
      var offsets = first.offsets.toList();
      var lengths = first.lengths.toList();
      for (var i = 1; i < count; i++) {
        var feedback = feedbacks[i] as ExtractLocalVariableFeedback;
        // TODO(brianwilkerson): This doesn't ensure that the covering data is in
        // the right order and consistent.
        var coveringOffsets = feedback.coveringExpressionOffsets;
        if (coveringOffsets != null) {
          coveringExpressionOffsets.addAll(coveringOffsets);
        }
        var coveringLengths = feedback.coveringExpressionLengths;
        if (coveringLengths != null) {
          coveringExpressionLengths.addAll(coveringLengths);
        }
        for (var name in feedback.names) {
          if (!names.contains(name)) {
            names.add(name);
          }
        }
        offsets.addAll(feedback.offsets);
        lengths.addAll(feedback.lengths);
      }
      return ExtractLocalVariableFeedback(names.toList(), offsets, lengths,
          coveringExpressionOffsets: coveringExpressionOffsets.isEmpty
              ? null
              : coveringExpressionOffsets,
          coveringExpressionLengths: coveringExpressionLengths.isEmpty
              ? null
              : coveringExpressionLengths);
    } else if (first is ExtractMethodFeedback) {
      var offset = first.offset;
      var length = first.length;
      var returnType = first.returnType;
      var names = first.names.toList();
      var canCreateGetter = first.canCreateGetter;
      var parameters = first.parameters;
      var offsets = first.offsets.toList();
      var lengths = first.lengths.toList();
      for (var i = 1; i < count; i++) {
        var feedback = feedbacks[i] as ExtractMethodFeedback;
        if (returnType.isEmpty) {
          returnType = feedback.returnType;
        }
        for (var 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 ExtractMethodFeedback(offset, length, returnType, names.toList(),
          canCreateGetter, parameters, offsets, lengths);
    } else if (first is InlineLocalVariableFeedback) {
      var occurrences = first.occurrences;
      for (var i = 1; i < count; i++) {
        occurrences +=
            (feedbacks[i] as InlineLocalVariableFeedback).occurrences;
      }
      return 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 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) {
    var count = partialResultList.length;
    if (count == 0) {
      return <RefactoringKind>[];
    } else if (count == 1) {
      return partialResultList[0];
    }
    Set<RefactoringKind> mergedKinds = HashSet<RefactoringKind>();
    for (var 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) {
      var count = changes.length;
      if (count == 0) {
        return null;
      } else if (count == 1) {
        return changes[0];
      }
      var first = changes[0];
      var message = first.message;
      var editMap = <String, SourceFileEdit>{};
      for (var edit in first.edits) {
        editMap[edit.file] = edit;
      }
      var linkedEditGroups = first.linkedEditGroups.toList();
      var selection = first.selection;
      for (var i = 1; i < count; i++) {
        var change = changes[i];
        for (var edit in change.edits) {
          var 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.
            var edits = mergedEdit.edits.toList();
            edits.addAll(edit.edits);
            editMap[edit.file] = SourceFileEdit(
                mergedEdit.file, mergedEdit.fileStamp,
                edits: edits);
          }
        }
        linkedEditGroups.addAll(change.linkedEditGroups);
        selection ??= change.selection;
      }
      return SourceChange(message,
          edits: editMap.values.toList(),
          linkedEditGroups: linkedEditGroups,
          selection: selection);
    }

    var count = partialResultList.length;
    if (count == 0) {
      return null;
    } else if (count == 1) {
      return partialResultList[0];
    }
    var result = partialResultList[0];
    var initialProblems = result.initialProblems.toList();
    var optionsProblems = result.optionsProblems.toList();
    var finalProblems = result.finalProblems.toList();
    var feedbacks = <RefactoringFeedback>[];
    var feedback = result.feedback;
    if (feedback != null) {
      feedbacks.add(feedback);
    }
    var changes = <SourceChange>[];
    var change = result.change;
    if (change != null) {
      changes.add(change);
    }
    var potentialEdits = _copyList(result.potentialEdits);
    for (var i = 1; i < count; i++) {
      var result = partialResultList[1];
      initialProblems.addAll(result.initialProblems);
      optionsProblems.addAll(result.optionsProblems);
      finalProblems.addAll(result.finalProblems);
      var feedback = result.feedback;
      if (feedback != null) {
        feedbacks.add(feedback);
      }
      var change = result.change;
      if (change != null) {
        changes.add(change);
      }
      var edits = result.potentialEdits;
      if (edits != null) {
        potentialEdits.addAll(edits);
      }
    }
    return 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) {
    var count = partialResultList.length;
    if (count == 0) {
      return <SourceChange>[];
    } else if (count == 1) {
      return partialResultList[0];
    }
    var mergedChanges = <SourceChange>[];
    for (var 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));
  }

  /// Return a copy of the [list], or an empty list if [list] is `null`.
  List<E> _copyList<E>(List<E>? list) => list == null ? <E>[] : list.toList();
}
