// Copyright (c) 2014, 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 'package:analysis_server/src/protocol_server.dart' hide Element;
import 'package:analysis_server/src/services/correction/name_suggestion.dart';
import 'package:analysis_server/src/services/correction/selection_analyzer.dart';
import 'package:analysis_server/src/services/correction/statement_analyzer.dart';
import 'package:analysis_server/src/services/correction/status.dart';
import 'package:analysis_server/src/services/correction/util.dart';
import 'package:analysis_server/src/services/refactoring/naming_conventions.dart';
import 'package:analysis_server/src/services/refactoring/refactoring.dart';
import 'package:analysis_server/src/services/refactoring/refactoring_internal.dart';
import 'package:analysis_server/src/services/refactoring/rename_class_member.dart';
import 'package:analysis_server/src/services/refactoring/rename_unit_member.dart';
import 'package:analysis_server/src/services/refactoring/visible_ranges_computer.dart';
import 'package:analysis_server/src/services/search/search_engine.dart';
import 'package:analysis_server/src/utilities/extensions/ast.dart';
import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/dart/element/type_system.dart';
import 'package:analyzer/src/dart/analysis/session_helper.dart';
import 'package:analyzer/src/dart/ast/extensions.dart';
import 'package:analyzer/src/dart/ast/utilities.dart';
import 'package:analyzer/src/dart/resolver/exit_detector.dart';
import 'package:analyzer/src/generated/java_core.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer_plugin/utilities/range_factory.dart';

const String _TOKEN_SEPARATOR = '\uFFFF';

Element? _getLocalElement(SimpleIdentifier node) {
  var element = node.writeOrReadElement;
  if (element is LocalVariableElement ||
      element is ParameterElement ||
      element is FunctionElement &&
          element.enclosingElement is! CompilationUnitElement) {
    return element;
  }
  return null;
}

/// Returns the "normalized" version of the given source, which is reconstructed
/// from tokens, so ignores all the comments and spaces.
String _getNormalizedSource(String src, FeatureSet featureSet) {
  var selectionTokens = TokenUtils.getTokens(src, featureSet);
  return selectionTokens.join(_TOKEN_SEPARATOR);
}

/// Returns the [Map] which maps [map] values to their keys.
Map<String, String> _inverseMap(Map<String, String> map) {
  var result = <String, String>{};
  map.forEach((String key, String value) {
    result[value] = key;
  });
  return result;
}

/// [ExtractMethodRefactoring] implementation.
class ExtractMethodRefactoringImpl extends RefactoringImpl
    implements ExtractMethodRefactoring {
  static const ERROR_EXITS =
      'Selected statements contain a return statement, but not all possible '
      'execution flows exit. Semantics may not be preserved.';

  final SearchEngine searchEngine;
  final ResolvedUnitResult resolveResult;
  final int selectionOffset;
  final int selectionLength;
  late SourceRange selectionRange;
  late CorrectionUtils utils;
  final Set<Source> librariesToImport = <Source>{};

  @override
  String returnType = '';
  String? variableType;
  late String name;
  bool extractAll = true;
  @override
  bool canCreateGetter = false;
  bool createGetter = false;
  @override
  final List<String> names = <String>[];
  @override
  final List<int> offsets = <int>[];
  @override
  final List<int> lengths = <int>[];

  /// The map of local elements to their visibility ranges.
  late Map<LocalElement, SourceRange> _visibleRangeMap;

  /// The map of local names to their visibility ranges.
  final Map<String, List<SourceRange>> _localNames =
      <String, List<SourceRange>>{};

  /// The set of names that are referenced without any qualifier.
  final Set<String> _unqualifiedNames = <String>{};

  final Set<String> _excludedNames = <String>{};
  List<RefactoringMethodParameter> _parameters = <RefactoringMethodParameter>[];
  final Map<String, RefactoringMethodParameter> _parametersMap =
      <String, RefactoringMethodParameter>{};
  final Map<String, List<SourceRange>> _parameterReferencesMap =
      <String, List<SourceRange>>{};
  bool _hasAwait = false;
  DartType? _returnType;
  String? _returnVariableName;
  AstNode? _parentMember;
  Expression? _selectionExpression;
  FunctionExpression? _selectionFunctionExpression;
  List<Statement>? _selectionStatements;
  final List<_Occurrence> _occurrences = [];
  bool _staticContext = false;

  ExtractMethodRefactoringImpl(this.searchEngine, this.resolveResult,
      this.selectionOffset, this.selectionLength) {
    selectionRange = SourceRange(selectionOffset, selectionLength);
    utils = CorrectionUtils(resolveResult);
  }

  @override
  List<RefactoringMethodParameter> get parameters => _parameters;

  @override
  set parameters(List<RefactoringMethodParameter> parameters) {
    _parameters = parameters.toList();
  }

  @override
  String get refactoringName {
    var node = NodeLocator(selectionOffset).searchWithin(resolveResult.unit);
    if (node != null && node.thisOrAncestorOfType<ClassDeclaration>() != null) {
      return 'Extract Method';
    }
    return 'Extract Function';
  }

  String get signature {
    var sb = StringBuffer();
    if (createGetter) {
      sb.write('get ');
      sb.write(name);
    } else {
      sb.write(name);
      sb.write('(');
      // add all parameters
      var firstParameter = true;
      for (var parameter in _parameters) {
        // may be comma
        if (firstParameter) {
          firstParameter = false;
        } else {
          sb.write(', ');
        }
        // type
        {
          var typeSource = parameter.type;
          if ('dynamic' != typeSource && '' != typeSource) {
            sb.write(typeSource);
            sb.write(' ');
          }
        }
        // name
        sb.write(parameter.name);
        // optional function-typed parameter parameters
        if (parameter.parameters != null) {
          sb.write(parameter.parameters);
        }
      }
      sb.write(')');
    }
    // done
    return sb.toString();
  }

  @override
  Future<RefactoringStatus> checkFinalConditions() async {
    var result = RefactoringStatus();
    result.addStatus(validateMethodName(name));
    result.addStatus(_checkParameterNames());
    var status = await _checkPossibleConflicts();
    result.addStatus(status);
    return result;
  }

  @override
  Future<RefactoringStatus> checkInitialConditions() async {
    var result = RefactoringStatus();
    // selection
    result.addStatus(_checkSelection());
    if (result.hasFatalError) {
      return result;
    }
    // prepare parts
    var status = await _initializeParameters();
    result.addStatus(status);
    _initializeHasAwait();
    await _initializeReturnType();
    // occurrences
    _initializeOccurrences();
    _prepareOffsetsLengths();
    // getter
    canCreateGetter = _computeCanCreateGetter();
    createGetter =
        canCreateGetter && _isExpressionForGetter(_selectionExpression);
    // names
    _prepareExcludedNames();
    _prepareNames();
    // closure cannot have parameters
    if (_selectionFunctionExpression != null && _parameters.isNotEmpty) {
      var message = format(
          'Cannot extract closure as method, it references {0} external variable{1}.',
          _parameters.length,
          _parameters.length == 1 ? '' : 's');
      return RefactoringStatus.fatal(message);
    }
    return result;
  }

  @override
  RefactoringStatus checkName() {
    return validateMethodName(name);
  }

  @override
  Future<SourceChange> createChange() async {
    var change = SourceChange(refactoringName);
    // replace occurrences with method invocation
    for (var occurrence in _occurrences) {
      var range = occurrence.range;
      // may be replacement of duplicates disabled
      if (!extractAll && !occurrence.isSelection) {
        continue;
      }
      // prepare invocation source
      String invocationSource;
      if (_selectionFunctionExpression != null) {
        invocationSource = name;
      } else {
        var sb = StringBuffer();
        // may be returns value
        if (_selectionStatements != null && variableType != null) {
          // single variable assignment / return statement
          if (_returnVariableName != null) {
            var occurrenceName =
                occurrence._parameterOldToOccurrenceName[_returnVariableName];
            // may be declare variable
            if (!_parametersMap.containsKey(_returnVariableName)) {
              if (variableType!.isEmpty) {
                sb.write('var ');
              } else {
                sb.write(variableType);
                sb.write(' ');
              }
            }
            // assign the return value
            sb.write(occurrenceName);
            sb.write(' = ');
          } else {
            sb.write('return ');
          }
        }
        // await
        if (_hasAwait) {
          sb.write('await ');
        }
        // invocation itself
        sb.write(name);
        if (!createGetter) {
          sb.write('(');
          var firstParameter = true;
          for (var parameter in _parameters) {
            // may be comma
            if (firstParameter) {
              firstParameter = false;
            } else {
              sb.write(', ');
            }
            // argument name
            {
              var argumentName =
                  occurrence._parameterOldToOccurrenceName[parameter.id];
              sb.write(argumentName);
            }
          }
          sb.write(')');
        }
        invocationSource = sb.toString();
        // statements as extracted with their ";", so add new after invocation
        if (_selectionStatements != null) {
          invocationSource += ';';
        }
      }
      // add replace edit
      var edit = newSourceEdit_range(range, invocationSource);
      doSourceChange_addElementEdit(
          change, resolveResult.unit.declaredElement!, edit);
    }
    // add method declaration
    {
      // prepare environment
      var prefix = utils.getNodePrefix(_parentMember!);
      var eol = utils.endOfLine;
      // prepare annotations
      var annotations = '';
      {
        // may be "static"
        if (_staticContext) {
          annotations = 'static ';
        }
      }
      // prepare declaration source
      String? declarationSource;
      {
        var returnExpressionSource = _getMethodBodySource();
        // closure
        final selectionFunctionExpression = _selectionFunctionExpression;
        if (selectionFunctionExpression != null) {
          var returnTypeCode = _getExpectedClosureReturnTypeCode();
          declarationSource = '$returnTypeCode$name$returnExpressionSource';
          if (selectionFunctionExpression.body is ExpressionFunctionBody) {
            declarationSource += ';';
          }
        }
        // optional 'async' body modifier
        var asyncKeyword = _hasAwait ? ' async' : '';
        // expression
        if (_selectionExpression != null) {
          var isMultiLine = returnExpressionSource.contains(eol);

          // We generate the method body using the shorthand syntax if it fits
          // into a single line and use the regular method syntax otherwise.
          if (!isMultiLine) {
            // add return type
            if (returnType.isNotEmpty) {
              annotations += '$returnType ';
            }
            // just return expression
            declarationSource = '$annotations$signature$asyncKeyword => ';
            declarationSource += '$returnExpressionSource;';
          } else {
            // Left indent once; returnExpressionSource was indented for method
            // shorthands.
            returnExpressionSource = utils
                .indentSourceLeftRight('${returnExpressionSource.trim()};')
                .trim();

            // add return type
            if (returnType.isNotEmpty) {
              annotations += '$returnType ';
            }
            declarationSource = '$annotations$signature$asyncKeyword {$eol';
            declarationSource += '$prefix  ';
            if (returnType.isNotEmpty) {
              declarationSource += 'return ';
            }
            declarationSource += '$returnExpressionSource$eol$prefix}';
          }
        }
        // statements
        if (_selectionStatements != null) {
          if (returnType.isNotEmpty) {
            annotations += returnType + ' ';
          }
          declarationSource = '$annotations$signature$asyncKeyword {$eol';
          declarationSource += returnExpressionSource;
          if (_returnVariableName != null) {
            declarationSource += '$prefix  return $_returnVariableName;$eol';
          }
          declarationSource += '$prefix}';
        }
      }
      // insert declaration
      if (declarationSource != null) {
        var offset = _parentMember!.end;
        var edit = SourceEdit(offset, 0, '$eol$eol$prefix$declarationSource');
        doSourceChange_addElementEdit(
            change, resolveResult.unit.declaredElement!, edit);
      }
    }
    // done
    await addLibraryImports(resolveResult.session, change,
        resolveResult.libraryElement, librariesToImport);
    return change;
  }

  @override
  bool isAvailable() {
    return !_checkSelection().hasFatalError;
  }

  /// Adds a new reference to the parameter with the given name.
  void _addParameterReference(String name, SourceRange range) {
    var references = _parameterReferencesMap[name];
    if (references == null) {
      references = [];
      _parameterReferencesMap[name] = references;
    }
    references.add(range);
  }

  RefactoringStatus _checkParameterNames() {
    var result = RefactoringStatus();
    for (var parameter in _parameters) {
      result.addStatus(validateParameterName(parameter.name));
      for (var other in _parameters) {
        if (!identical(parameter, other) && other.name == parameter.name) {
          result.addError(
              format("Parameter '{0}' already exists", parameter.name));
          return result;
        }
      }
      if (_isParameterNameConflictWithBody(parameter)) {
        result.addError(format(
            "'{0}' is already used as a name in the selected code",
            parameter.name));
        return result;
      }
    }
    return result;
  }

  /// Checks if created method will shadow or will be shadowed by other
  /// elements.
  Future<RefactoringStatus> _checkPossibleConflicts() async {
    var result = RefactoringStatus();
    var parent = _parentMember!.parent;
    // top-level function
    if (parent is CompilationUnit) {
      var libraryElement = parent.declaredElement!.library;
      return validateCreateFunction(searchEngine, libraryElement, name);
    }
    // method of class
    if (parent is ClassDeclaration) {
      var classElement = parent.declaredElement!;
      return validateCreateMethod(searchEngine,
          AnalysisSessionHelper(resolveResult.session), classElement, name);
    }
    // OK
    return Future<RefactoringStatus>.value(result);
  }

  /// Checks if [selectionRange] selects [Expression] which can be extracted,
  /// and location of this [DartExpression] in AST allows extracting.
  RefactoringStatus _checkSelection() {
    if (selectionOffset <= 0) {
      return RefactoringStatus.fatal(
          'The selection offset must be greater than zero.');
    }
    if (selectionOffset + selectionLength >= resolveResult.content.length) {
      return RefactoringStatus.fatal(
          'The selection end offset must be less then the length of the file.');
    }

    // Check for implicitly selected closure.
    {
      var function = _findFunctionExpression();
      if (function != null) {
        _selectionFunctionExpression = function;
        selectionRange = range.node(function);
        _parentMember = getEnclosingClassOrUnitMember(function);
        return RefactoringStatus();
      }
    }

    var analyzer = _ExtractMethodAnalyzer(resolveResult, selectionRange);
    analyzer.analyze();
    // May be a fatal error.
    {
      if (analyzer.status.hasFatalError) {
        return analyzer.status;
      }
    }

    var selectedNodes = analyzer.selectedNodes;

    // If no selected nodes, extract the smallest covering expression.
    if (selectedNodes.isEmpty) {
      for (var node = analyzer.coveringNode; node != null; node = node.parent) {
        if (node is Statement) {
          break;
        }
        if (node is Expression && _isExtractable(range.node(node))) {
          selectedNodes.add(node);
          selectionRange = range.node(node);
          break;
        }
      }
    }

    // Check selected nodes.
    if (selectedNodes.isNotEmpty) {
      var selectedNode = selectedNodes.first;
      _parentMember = getEnclosingClassOrUnitMember(selectedNode);
      // single expression selected
      if (selectedNodes.length == 1) {
        if (!utils.selectionIncludesNonWhitespaceOutsideNode(
            selectionRange, selectedNode)) {
          if (selectedNode is Expression) {
            _selectionExpression = selectedNode;
            // additional check for closure
            if (_selectionExpression is FunctionExpression) {
              _selectionFunctionExpression =
                  _selectionExpression as FunctionExpression;
              _selectionExpression = null;
            }
            // OK
            return RefactoringStatus();
          }
        }
      }
      // statements selected
      {
        var selectedStatements = <Statement>[];
        for (var selectedNode in selectedNodes) {
          if (selectedNode is Statement) {
            selectedStatements.add(selectedNode);
          }
        }
        if (selectedStatements.length == selectedNodes.length) {
          _selectionStatements = selectedStatements;
          return RefactoringStatus();
        }
      }
    }
    // invalid selection
    return RefactoringStatus.fatal(
        'Can only extract a single expression or a set of statements.');
  }

  /// Initializes [canCreateGetter] flag.
  bool _computeCanCreateGetter() {
    // is a function expression
    if (_selectionFunctionExpression != null) {
      return false;
    }
    // has parameters
    if (parameters.isNotEmpty) {
      return false;
    }
    // is assignment
    if (_selectionExpression != null) {
      if (_selectionExpression is AssignmentExpression) {
        return false;
      }
    }
    // doesn't return a value
    if (_selectionStatements != null) {
      return returnType != 'void';
    }
    // OK
    return true;
  }

  /// If the [selectionRange] is associated with a [FunctionExpression], return
  /// this [FunctionExpression].
  FunctionExpression? _findFunctionExpression() {
    if (selectionRange.length != 0) {
      return null;
    }
    var offset = selectionRange.offset;
    var node = NodeLocator2(offset, offset).searchWithin(resolveResult.unit);

    // Check for the parameter list of a FunctionExpression.
    {
      var function = node?.thisOrAncestorOfType<FunctionExpression>();
      if (function != null) {
        var parameters = function.parameters;
        if (parameters != null && range.node(parameters).contains(offset)) {
          return function;
        }
      }
    }

    // Check for the name of the named argument with the closure expression.
    if (node is SimpleIdentifier) {
      var label = node.parent;
      if (label is Label) {
        var namedExpression = label.parent;
        if (namedExpression is NamedExpression) {
          var expression = namedExpression.expression;
          if (expression is FunctionExpression) {
            return expression;
          }
        }
      }
    }

    return null;
  }

  /// If the selected closure (i.e. [_selectionFunctionExpression]) is an
  /// argument for a function typed parameter (as it should be), and the
  /// function type has the return type specified, return this return type's
  /// code. Otherwise return the empty string.
  String _getExpectedClosureReturnTypeCode() {
    Expression argument = _selectionFunctionExpression!;
    if (argument.parent is NamedExpression) {
      argument = argument.parent as NamedExpression;
    }
    var parameter = argument.staticParameterElement;
    if (parameter != null) {
      var parameterType = parameter.type;
      if (parameterType is FunctionType) {
        var typeCode = _getTypeCode(parameterType.returnType);
        if (typeCode != 'dynamic') {
          return typeCode + ' ';
        }
      }
    }
    return '';
  }

  /// Returns the selected [Expression] source, with applying new parameter
  /// names.
  String _getMethodBodySource() {
    var source = utils.getRangeText(selectionRange);
    // prepare operations to replace variables with parameters
    var replaceEdits = <SourceEdit>[];
    for (var parameter in _parameters) {
      var ranges = _parameterReferencesMap[parameter.id];
      if (ranges != null) {
        for (var range in ranges) {
          replaceEdits.add(SourceEdit(range.offset - selectionRange.offset,
              range.length, parameter.name));
        }
      }
    }
    replaceEdits.sort((a, b) => b.offset - a.offset);
    // apply replacements
    source = SourceEdit.applySequence(source, replaceEdits);
    // change indentation
    final selectionFunctionExpression = _selectionFunctionExpression;
    if (selectionFunctionExpression != null) {
      var baseNode =
          selectionFunctionExpression.thisOrAncestorOfType<Statement>();
      if (baseNode != null) {
        var baseIndent = utils.getNodePrefix(baseNode);
        var targetIndent = utils.getNodePrefix(_parentMember!);
        source = utils.replaceSourceIndent(source, baseIndent, targetIndent);
        source = source.trim();
      }
    }
    final selectionStatements = _selectionStatements;
    if (selectionStatements != null) {
      var selectionIndent = utils.getNodePrefix(selectionStatements[0]);
      var targetIndent = utils.getNodePrefix(_parentMember!) + '  ';
      source = utils.replaceSourceIndent(source, selectionIndent, targetIndent);
    }
    // done
    return source;
  }

  _SourcePattern _getSourcePattern(SourceRange range) {
    var originalSource = utils.getText(range.offset, range.length);
    var pattern = _SourcePattern();
    var replaceEdits = <SourceEdit>[];
    resolveResult.unit
        .accept(_GetSourcePatternVisitor(range, pattern, replaceEdits));
    replaceEdits = replaceEdits.reversed.toList();
    var source = SourceEdit.applySequence(originalSource, replaceEdits);
    pattern.normalizedSource =
        _getNormalizedSource(source, resolveResult.unit.featureSet);
    return pattern;
  }

  String _getTypeCode(DartType type) {
    return utils.getTypeSource(type, librariesToImport)!;
  }

  void _initializeHasAwait() {
    var visitor = _HasAwaitVisitor();
    if (_selectionExpression != null) {
      _selectionExpression!.accept(visitor);
    } else if (_selectionStatements != null) {
      _selectionStatements!.forEach((statement) {
        statement.accept(visitor);
      });
    }
    _hasAwait = visitor.result;
  }

  /// Fills [_occurrences] field.
  void _initializeOccurrences() {
    _occurrences.clear();
    // prepare selection
    var selectionPattern = _getSourcePattern(selectionRange);
    var patternToSelectionName =
        _inverseMap(selectionPattern.originalToPatternNames);
    // prepare an enclosing parent - class or unit
    var enclosingMemberParent = _parentMember!.parent!;
    // visit nodes which will able to access extracted method
    enclosingMemberParent.accept(_InitializeOccurrencesVisitor(
        this, selectionPattern, patternToSelectionName));
  }

  /// Prepares information about used variables, which should be turned into
  /// parameters.
  Future<RefactoringStatus> _initializeParameters() async {
    _parameters.clear();
    _parametersMap.clear();
    _parameterReferencesMap.clear();
    var result = RefactoringStatus();
    var assignedUsedVariables = <VariableElement>[];

    var unit = resolveResult.unit;
    _visibleRangeMap = VisibleRangesComputer.forNode(unit);
    unit.accept(
      _InitializeParametersVisitor(this, assignedUsedVariables),
    );

    // single expression
    final selectionExpression = _selectionExpression;
    if (selectionExpression != null) {
      _returnType = selectionExpression.typeOrThrow;
    }
    // verify that none or all execution flows end with a "return"
    final selectionStatements = _selectionStatements;
    if (selectionStatements != null) {
      var hasReturn = selectionStatements.any(_mayEndWithReturnStatement);
      if (hasReturn && !ExitDetector.exits(selectionStatements.last)) {
        result.addError(ERROR_EXITS);
      }
    }
    // maybe ends with "return" statement
    if (selectionStatements != null) {
      var typeSystem = resolveResult.typeSystem;
      var returnTypeComputer = _ReturnTypeComputer(typeSystem);
      selectionStatements.forEach((statement) {
        statement.accept(returnTypeComputer);
      });
      _returnType = returnTypeComputer.returnType;
    }
    // maybe single variable to return
    if (assignedUsedVariables.length == 1) {
      // we cannot both return variable and have explicit return statement
      if (_returnType != null) {
        result.addFatalError(
            'Ambiguous return value: Selected block contains assignment(s) to '
            'local variables and return statement.');
        return result;
      }
      // prepare to return an assigned variable
      var returnVariable = assignedUsedVariables[0];
      _returnType = returnVariable.type;
      _returnVariableName = returnVariable.displayName;
    }
    // fatal, if multiple variables assigned and used after selection
    if (assignedUsedVariables.length > 1) {
      var sb = StringBuffer();
      for (var variable in assignedUsedVariables) {
        sb.write(variable.displayName);
        sb.write('\n');
      }
      result.addFatalError(format(
          'Ambiguous return value: Selected block contains more than one '
          'assignment to local variables. Affected variables are:\n\n{0}',
          sb.toString().trim()));
    }
    // done
    return result;
  }

  Future<void> _initializeReturnType() async {
    var typeProvider = resolveResult.typeProvider;
    final returnTypeObj = _returnType;
    if (_selectionFunctionExpression != null) {
      variableType = '';
      returnType = '';
    } else if (returnTypeObj == null) {
      variableType = null;
      if (_hasAwait) {
        var futureVoid = typeProvider.futureType(typeProvider.voidType);
        returnType = _getTypeCode(futureVoid);
      } else {
        returnType = 'void';
      }
    } else if (returnTypeObj.isDynamic) {
      variableType = '';
      if (_hasAwait) {
        returnType = _getTypeCode(typeProvider.futureDynamicType);
      } else {
        returnType = '';
      }
    } else {
      variableType = _getTypeCode(returnTypeObj);
      if (_hasAwait) {
        if (returnTypeObj.element != typeProvider.futureElement) {
          returnType = _getTypeCode(typeProvider.futureType(returnTypeObj));
        }
      } else {
        returnType = variableType!;
      }
    }
  }

  /// Checks if the given [element] is declared in [selectionRange].
  bool _isDeclaredInSelection(Element element) {
    return selectionRange.contains(element.nameOffset);
  }

  /// Checks if it is OK to extract the node with the given [SourceRange].
  bool _isExtractable(SourceRange range) {
    var analyzer = _ExtractMethodAnalyzer(resolveResult, range);
    analyzer.analyze();
    return analyzer.status.isOK;
  }

  bool _isParameterNameConflictWithBody(RefactoringMethodParameter parameter) {
    var id = parameter.id;
    var name = parameter.name;
    var parameterRanges = _parameterReferencesMap[id];
    var otherRanges = _localNames[name];
    for (var parameterRange in parameterRanges!) {
      if (otherRanges != null) {
        for (var otherRange in otherRanges) {
          if (parameterRange.intersects(otherRange)) {
            return true;
          }
        }
      }
    }
    if (_unqualifiedNames.contains(name)) {
      return true;
    }
    return false;
  }

  /// Checks if [element] is referenced after [selectionRange].
  bool _isUsedAfterSelection(Element element) {
    var visitor = _IsUsedAfterSelectionVisitor(this, element);
    _parentMember!.accept(visitor);
    return visitor.result;
  }

  /// Prepare names that are used in the enclosing function, so should not be
  /// proposed as names of the extracted method.
  void _prepareExcludedNames() {
    _excludedNames.clear();
    var localElements = getDefinedLocalElements(_parentMember!);
    _excludedNames.addAll(localElements.map((e) => e.name!));
  }

  void _prepareNames() {
    names.clear();
    final selectionExpression = _selectionExpression;
    if (selectionExpression != null) {
      names.addAll(getVariableNameSuggestionsForExpression(
          selectionExpression.typeOrThrow, selectionExpression, _excludedNames,
          isMethod: true));
    }
  }

  void _prepareOffsetsLengths() {
    offsets.clear();
    lengths.clear();
    for (var occurrence in _occurrences) {
      offsets.add(occurrence.range.offset);
      lengths.add(occurrence.range.length);
    }
  }

  /// Checks if the given [expression] is reasonable to extract as a getter.
  static bool _isExpressionForGetter(Expression? expression) {
    if (expression is BinaryExpression) {
      return _isExpressionForGetter(expression.leftOperand) &&
          _isExpressionForGetter(expression.rightOperand);
    }
    if (expression is Literal) {
      return true;
    }
    if (expression is PrefixExpression) {
      return _isExpressionForGetter(expression.operand);
    }
    if (expression is PrefixedIdentifier) {
      return _isExpressionForGetter(expression.prefix);
    }
    if (expression is PropertyAccess) {
      return _isExpressionForGetter(expression.target);
    }
    if (expression is SimpleIdentifier) {
      return true;
    }
    return false;
  }

  /// Returns `true` if the given [statement] may end with a [ReturnStatement].
  static bool _mayEndWithReturnStatement(Statement statement) {
    var visitor = _HasReturnStatementVisitor();
    statement.accept(visitor);
    return visitor.hasReturn;
  }
}

/// [SelectionAnalyzer] for [ExtractMethodRefactoringImpl].
class _ExtractMethodAnalyzer extends StatementAnalyzer {
  _ExtractMethodAnalyzer(
      ResolvedUnitResult resolveResult, SourceRange selection)
      : super(resolveResult, selection);

  @override
  void handleNextSelectedNode(AstNode node) {
    super.handleNextSelectedNode(node);
    _checkParent(node);
  }

  @override
  void handleSelectionEndsIn(AstNode node) {
    super.handleSelectionEndsIn(node);
    invalidSelection(
        'The selection does not cover a set of statements or an expression. '
        'Extend selection to a valid range.');
  }

  @override
  void visitAssignmentExpression(AssignmentExpression node) {
    super.visitAssignmentExpression(node);
    var lhs = node.leftHandSide;
    if (_isFirstSelectedNode(lhs)) {
      invalidSelection('Cannot extract the left-hand side of an assignment.',
          newLocation_fromNode(lhs));
    }
  }

  @override
  void visitConstructorInitializer(ConstructorInitializer node) {
    super.visitConstructorInitializer(node);
    if (_isFirstSelectedNode(node)) {
      invalidSelection(
          'Cannot extract a constructor initializer. '
          'Select expression part of initializer.',
          newLocation_fromNode(node));
    }
  }

  @override
  void visitForParts(ForParts node) {
    node.visitChildren(this);
  }

  @override
  void visitForStatement(ForStatement node) {
    super.visitForStatement(node);
    var forLoopParts = node.forLoopParts;
    if (forLoopParts is ForParts) {
      if (forLoopParts is ForPartsWithDeclarations &&
          identical(forLoopParts.variables, firstSelectedNode)) {
        invalidSelection(
            "Cannot extract initialization part of a 'for' statement.");
      } else if (forLoopParts.updaters.contains(lastSelectedNode)) {
        invalidSelection("Cannot extract increment part of a 'for' statement.");
      }
    }
  }

  @override
  void visitGenericFunctionType(GenericFunctionType node) {
    super.visitGenericFunctionType(node);
    if (_isFirstSelectedNode(node)) {
      invalidSelection('Cannot extract a single type reference.');
    }
  }

  @override
  void visitNamedType(NamedType node) {
    super.visitNamedType(node);
    if (_isFirstSelectedNode(node)) {
      invalidSelection('Cannot extract a single type reference.');
    }
  }

  @override
  void visitSimpleIdentifier(SimpleIdentifier node) {
    super.visitSimpleIdentifier(node);
    if (_isFirstSelectedNode(node)) {
      // name of declaration
      if (node.inDeclarationContext()) {
        invalidSelection('Cannot extract the name part of a declaration.');
      }
      // method name
      var element = node.writeOrReadElement;
      if (element is FunctionElement || element is MethodElement) {
        invalidSelection('Cannot extract a single method name.');
      }
      // name in property access
      if (node.parent is PrefixedIdentifier &&
          (node.parent as PrefixedIdentifier).identifier == node) {
        invalidSelection('Can not extract name part of a property access.');
      }
    }
  }

  @override
  void visitVariableDeclaration(VariableDeclaration node) {
    super.visitVariableDeclaration(node);
    if (_isFirstSelectedNode(node)) {
      invalidSelection(
          'Cannot extract a variable declaration fragment. '
          'Select whole declaration statement.',
          newLocation_fromNode(node));
    }
  }

  void _checkParent(AstNode node) {
    var firstParent = firstSelectedNode!.parent;
    for (var parent in node.withParents) {
      if (identical(parent, firstParent)) {
        return;
      }
    }
    invalidSelection(
        'Not all selected statements are enclosed by the same parent statement.');
  }

  bool _isFirstSelectedNode(AstNode node) => identical(firstSelectedNode, node);
}

class _GetSourcePatternVisitor extends GeneralizingAstVisitor<void> {
  final SourceRange partRange;
  final _SourcePattern pattern;
  final List<SourceEdit> replaceEdits;

  _GetSourcePatternVisitor(this.partRange, this.pattern, this.replaceEdits);

  @override
  void visitSimpleIdentifier(SimpleIdentifier node) {
    var nodeRange = range.node(node);
    if (partRange.covers(nodeRange)) {
      var element = _getLocalElement(node);
      if (element != null) {
        // name of a named expression
        if (isNamedExpressionName(node)) {
          return;
        }
        // continue
        var originalName = element.displayName;
        var patternName = pattern.originalToPatternNames[originalName];
        if (patternName == null) {
          var parameterType = _getElementType(element);
          pattern.parameterTypes.add(parameterType);
          patternName = '__refVar${pattern.originalToPatternNames.length}';
          pattern.originalToPatternNames[originalName] = patternName;
        }
        replaceEdits.add(SourceEdit(nodeRange.offset - partRange.offset,
            nodeRange.length, patternName));
      }
    }
  }

  DartType _getElementType(Element element) {
    if (element is VariableElement) {
      return element.type;
    }
    if (element is FunctionElement) {
      return element.type;
    }
    throw StateError('Unknown element type: ${element.runtimeType}');
  }
}

class _HasAwaitVisitor extends GeneralizingAstVisitor<void> {
  bool result = false;

  @override
  void visitAwaitExpression(AwaitExpression node) {
    result = true;
  }

  @override
  void visitForStatement(ForStatement node) {
    if (node.awaitKeyword != null) {
      result = true;
    }
    super.visitForStatement(node);
  }
}

class _HasReturnStatementVisitor extends RecursiveAstVisitor<void> {
  bool hasReturn = false;

  @override
  void visitBlockFunctionBody(BlockFunctionBody node) {}

  @override
  void visitReturnStatement(ReturnStatement node) {
    hasReturn = true;
  }
}

class _InitializeOccurrencesVisitor extends GeneralizingAstVisitor<void> {
  final ExtractMethodRefactoringImpl ref;
  final _SourcePattern selectionPattern;
  final Map<String, String> patternToSelectionName;

  bool forceStatic = false;

  _InitializeOccurrencesVisitor(
      this.ref, this.selectionPattern, this.patternToSelectionName);

  @override
  void visitBlock(Block node) {
    if (ref._selectionStatements != null) {
      _visitStatements(node.statements);
    }
    super.visitBlock(node);
  }

  @override
  void visitConstructorInitializer(ConstructorInitializer node) {
    forceStatic = true;
    try {
      super.visitConstructorInitializer(node);
    } finally {
      forceStatic = false;
    }
  }

  @override
  void visitExpression(Expression node) {
    if (ref._selectionFunctionExpression != null ||
        ref._selectionExpression != null &&
            node.runtimeType == ref._selectionExpression.runtimeType) {
      var nodeRange = range.node(node);
      _tryToFindOccurrence(nodeRange);
    }
    super.visitExpression(node);
  }

  @override
  void visitMethodDeclaration(MethodDeclaration node) {
    forceStatic = node.isStatic;
    try {
      super.visitMethodDeclaration(node);
    } finally {
      forceStatic = false;
    }
  }

  @override
  void visitSwitchMember(SwitchMember node) {
    if (ref._selectionStatements != null) {
      _visitStatements(node.statements);
    }
    super.visitSwitchMember(node);
  }

  /// Checks if given [SourceRange] matched selection source and adds
  /// [_Occurrence].
  bool _tryToFindOccurrence(SourceRange nodeRange) {
    // check if can be extracted
    if (!ref._isExtractable(nodeRange)) {
      return false;
    }
    // prepare node source
    var nodePattern = ref._getSourcePattern(nodeRange);
    // if matches normalized node source, then add as occurrence
    if (selectionPattern.isCompatible(nodePattern)) {
      var occurrence =
          _Occurrence(nodeRange, ref.selectionRange.intersects(nodeRange));
      ref._occurrences.add(occurrence);
      // prepare mapping of parameter names to the occurrence variables
      nodePattern.originalToPatternNames
          .forEach((String originalName, String patternName) {
        var selectionName = patternToSelectionName[patternName]!;
        occurrence._parameterOldToOccurrenceName[selectionName] = originalName;
      });
      // update static
      if (forceStatic) {
        ref._staticContext = true;
      }
      // we have match
      return true;
    }
    // no match
    return false;
  }

  void _visitStatements(List<Statement> statements) {
    var beginStatementIndex = 0;
    var selectionCount = ref._selectionStatements!.length;
    while (beginStatementIndex + selectionCount <= statements.length) {
      var nodeRange = range.startEnd(statements[beginStatementIndex],
          statements[beginStatementIndex + selectionCount - 1]);
      var found = _tryToFindOccurrence(nodeRange);
      // next statement
      if (found) {
        beginStatementIndex += selectionCount;
      } else {
        beginStatementIndex++;
      }
    }
  }
}

class _InitializeParametersVisitor extends GeneralizingAstVisitor {
  final ExtractMethodRefactoringImpl ref;
  final List<VariableElement> assignedUsedVariables;

  _InitializeParametersVisitor(this.ref, this.assignedUsedVariables);

  @override
  void visitSimpleIdentifier(SimpleIdentifier node) {
    var nodeRange = range.node(node);
    if (!ref.selectionRange.covers(nodeRange)) {
      return;
    }
    var name = node.name;
    // analyze local element
    var element = _getLocalElement(node);
    if (element != null) {
      // name of the named expression
      if (isNamedExpressionName(node)) {
        return;
      }
      // if declared outside, add parameter
      if (!ref._isDeclaredInSelection(element)) {
        // add parameter
        var parameter = ref._parametersMap[name];
        if (parameter == null) {
          var parameterType = node.writeOrReadType!;
          var parametersBuffer = StringBuffer();
          var parameterTypeCode = ref.utils.getTypeSource(
              parameterType, ref.librariesToImport,
              parametersBuffer: parametersBuffer);
          if (parameterTypeCode == null) {
            return;
          }
          var parametersCode =
              parametersBuffer.isNotEmpty ? parametersBuffer.toString() : null;
          parameter = RefactoringMethodParameter(
              RefactoringMethodParameterKind.REQUIRED, parameterTypeCode, name,
              parameters: parametersCode, id: name);
          ref._parameters.add(parameter);
          ref._parametersMap[name] = parameter;
        }
        // add reference to parameter
        ref._addParameterReference(name, nodeRange);
      }
      // remember, if assigned and used after selection
      if (isLeftHandOfAssignment(node) && ref._isUsedAfterSelection(element)) {
        if (element is VariableElement &&
            !assignedUsedVariables.contains(element)) {
          assignedUsedVariables.add(element);
        }
      }
    }
    // remember information for conflicts checking
    if (element is LocalElement) {
      // declared local elements
      if (node.inDeclarationContext()) {
        var range = ref._visibleRangeMap[element];
        if (range != null) {
          var ranges = ref._localNames.putIfAbsent(name, () => <SourceRange>[]);
          ranges.add(range);
        }
      }
    } else {
      // unqualified non-local names
      if (!node.isQualified) {
        ref._unqualifiedNames.add(name);
      }
    }
  }
}

class _IsUsedAfterSelectionVisitor extends GeneralizingAstVisitor<void> {
  final ExtractMethodRefactoringImpl ref;
  final Element element;
  bool result = false;

  _IsUsedAfterSelectionVisitor(this.ref, this.element);

  @override
  void visitSimpleIdentifier(SimpleIdentifier node) {
    var nodeElement = node.writeOrReadElement;
    if (identical(nodeElement, element)) {
      var nodeOffset = node.offset;
      if (nodeOffset > ref.selectionRange.end) {
        result = true;
      }
    }
  }
}

/// Description of a single occurrence of the selected expression or set of
/// statements.
class _Occurrence {
  final SourceRange range;
  final bool isSelection;

  final Map<String, String> _parameterOldToOccurrenceName = <String, String>{};

  _Occurrence(this.range, this.isSelection);
}

class _ReturnTypeComputer extends RecursiveAstVisitor<void> {
  final TypeSystem typeSystem;

  DartType? returnType;

  _ReturnTypeComputer(this.typeSystem);

  @override
  void visitBlockFunctionBody(BlockFunctionBody node) {}

  @override
  void visitReturnStatement(ReturnStatement node) {
    // prepare expression
    var expression = node.expression;
    if (expression == null) {
      return;
    }
    // prepare type
    var type = expression.typeOrThrow;
    if (type.isBottom) {
      return;
    }
    // combine types
    returnType = _combine(returnType, type);
  }

  DartType _combine(DartType? returnType, DartType type) {
    if (returnType == null) {
      return type;
    } else {
      return typeSystem.leastUpperBound(returnType, type);
    }
  }
}

/// Generalized version of some source, in which references to the specific
/// variables are replaced with pattern variables, with back mapping from the
/// pattern to the original variable names.
class _SourcePattern {
  final List<DartType> parameterTypes = <DartType>[];
  late String normalizedSource;
  final Map<String, String> originalToPatternNames = {};

  bool isCompatible(_SourcePattern other) {
    if (other.normalizedSource != normalizedSource) {
      return false;
    }
    if (other.parameterTypes.length != parameterTypes.length) {
      return false;
    }
    for (var i = 0; i < parameterTypes.length; i++) {
      if (other.parameterTypes[i] != parameterTypes[i]) {
        return false;
      }
    }
    return true;
  }
}
