// 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();
}
