// 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:math';

import 'package:analysis_server/src/protocol_server.dart' hide Element;
import 'package:analysis_server/src/services/correction/source_buffer.dart';
import 'package:analysis_server/src/services/correction/util.dart';
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/error/error.dart';
import 'package:analyzer/error/error.dart' as engine;
import 'package:analyzer/src/dart/ast/utilities.dart';
import 'package:analyzer/src/dart/error/syntactic_errors.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/generated/java_core.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer_plugin/utilities/range_factory.dart';
import 'package:collection/collection.dart';

/// An enumeration of possible statement completion kinds.
class DartStatementCompletion {
  static const NO_COMPLETION =
      StatementCompletionKind('No_COMPLETION', 'No completion available');
  static const SIMPLE_ENTER = StatementCompletionKind(
      'SIMPLE_ENTER', 'Insert a newline at the end of the current line');
  static const SIMPLE_SEMICOLON = StatementCompletionKind(
      'SIMPLE_SEMICOLON', 'Add a semicolon and newline');
  static const COMPLETE_CLASS_DECLARATION = StatementCompletionKind(
      'COMPLETE_CLASS_DECLARATION', 'Complete class declaration');
  static const COMPLETE_CONTROL_FLOW_BLOCK = StatementCompletionKind(
      'COMPLETE_CONTROL_FLOW_BLOCK', 'Complete control flow block');
  static const COMPLETE_DO_STMT =
      StatementCompletionKind('COMPLETE_DO_STMT', 'Complete do-statement');
  static const COMPLETE_IF_STMT =
      StatementCompletionKind('COMPLETE_IF_STMT', 'Complete if-statement');
  static const COMPLETE_FOR_STMT =
      StatementCompletionKind('COMPLETE_FOR_STMT', 'Complete for-statement');
  static const COMPLETE_FOR_EACH_STMT = StatementCompletionKind(
      'COMPLETE_FOR_EACH_STMT', 'Complete for-each-statement');
  static const COMPLETE_FUNCTION_DECLARATION = StatementCompletionKind(
      'COMPLETE_FUNCTION_DECLARATION', 'Complete function declaration');
  static const COMPLETE_SWITCH_STMT = StatementCompletionKind(
      'COMPLETE_SWITCH_STMT', 'Complete switch-statement');
  static const COMPLETE_TRY_STMT =
      StatementCompletionKind('COMPLETE_TRY_STMT', 'Complete try-statement');
  static const COMPLETE_VARIABLE_DECLARATION = StatementCompletionKind(
      'COMPLETE_VARIABLE_DECLARATION', 'Complete variable declaration');
  static const COMPLETE_WHILE_STMT = StatementCompletionKind(
      'COMPLETE_WHILE_STMT', 'Complete while-statement');
}

/// A description of a statement completion.
///
/// Clients may not extend, implement or mix-in this class.
class StatementCompletion {
  /// A description of the assist being proposed.
  final StatementCompletionKind kind;

  /// The change to be made in order to apply the assist.
  final SourceChange change;

  /// Initialize a newly created completion to have the given [kind] and
  /// [change].
  StatementCompletion(this.kind, this.change);
}

/// The context for computing a statement completion.
class StatementCompletionContext {
  final ResolvedUnitResult resolveResult;
  final int selectionOffset;

  StatementCompletionContext(this.resolveResult, this.selectionOffset);
}

/// A description of a class of statement completions. Instances are intended to
/// hold the information that is common across a number of completions and to be
/// shared by those completions.
///
/// Clients may not extend, implement or mix-in this class.
class StatementCompletionKind {
  /// The name of this kind of statement completion, used for debugging.
  final String name;

  /// A human-readable description of the changes that will be applied by this
  /// kind of statement completion.
  final String message;

  /// Initialize a newly created kind of statement completion to have the given
  /// [name] and [message].
  const StatementCompletionKind(this.name, this.message);

  @override
  String toString() => name;
}

/// The computer for Dart statement completions.
class StatementCompletionProcessor {
  static final NO_COMPLETION = StatementCompletion(
      DartStatementCompletion.NO_COMPLETION, SourceChange('', edits: []));

  final StatementCompletionContext statementContext;
  final CorrectionUtils utils;

  /// TODO(brianwilkerson) Refactor the code so that the completion is returned
  ///  from the methods in which it's computed rather than being a field that we
  ///  have to test.
  StatementCompletion? completion;
  SourceChange change = SourceChange('statement-completion');
  List<engine.AnalysisError> errors = [];
  final Map<String, LinkedEditGroup> linkedPositionGroups =
      <String, LinkedEditGroup>{};
  Position? exitPosition;

  StatementCompletionProcessor(this.statementContext)
      : utils = CorrectionUtils(statementContext.resolveResult);

  String get eol => utils.endOfLine;

  String get file => statementContext.resolveResult.path;

  LineInfo get lineInfo => statementContext.resolveResult.lineInfo;

  int get selectionOffset => statementContext.selectionOffset;

  Source get source => unitElement.source;

  CompilationUnit get unit => statementContext.resolveResult.unit!;

  CompilationUnitElement get unitElement => unit.declaredElement!;

  Future<StatementCompletion> compute() async {
    var node = _selectedNode();
    if (node == null) {
      return NO_COMPLETION;
    }
    node = node.thisOrAncestorMatching(
        (n) => n is Statement || _isNonStatementDeclaration(n));
    if (node == null) {
      return _complete_simpleEnter() ? completion! : NO_COMPLETION;
    }
    if (node is Block) {
      if (node.statements.isNotEmpty) {
        node = node.statements.last;
      }
    }
    if (_isEmptyStatementOrEmptyBlock(node)) {
      node = node.parent!;
    }
    for (var error in statementContext.resolveResult.errors) {
      if (error.offset >= node.offset && error.offset <= node.end) {
        if (error.errorCode is! HintCode) {
          errors.add(error);
        }
      }
    }

    _checkExpressions(node);
    if (node is Statement) {
      if (errors.isEmpty) {
        if (_complete_ifStatement(node) ||
            _complete_forStatement2(node) ||
            _complete_whileStatement(node) ||
            _complete_controlFlowBlock(node)) {
          return completion!;
        }
      } else {
        if (_complete_ifStatement(node) ||
            _complete_doStatement(node) ||
            _complete_forStatement2(node) ||
            _complete_functionDeclarationStatement(node) ||
            _complete_switchStatement(node) ||
            _complete_tryStatement(node) ||
            _complete_whileStatement(node) ||
            _complete_controlFlowBlock(node) ||
            _complete_simpleSemicolon(node) ||
            _complete_methodCall(node)) {
          return completion!;
        }
      }
    } else if (node is Declaration) {
      if (errors.isNotEmpty) {
        if (_complete_classDeclaration(node) ||
            _complete_variableDeclaration(node) ||
            _complete_simpleSemicolon(node) ||
            _complete_functionDeclaration(node)) {
          return completion!;
        }
      }
    }
    if (_complete_simpleEnter()) {
      return completion!;
    }
    return NO_COMPLETION;
  }

  void _addInsertEdit(int offset, String text) {
    var edit = SourceEdit(offset, 0, text);
    doSourceChange_addElementEdit(change, unitElement, edit);
  }

  void _addReplaceEdit(SourceRange range, String text) {
    var edit = SourceEdit(range.offset, range.length, text);
    // TODO(brianwilkerson) The commented out function call has been inlined in
    //  order to work around a situation in which _complete_doStatement creates
    //  a conflicting edit that happens to work because of the order in which
    //  the edits are applied. The implementation needs to be cleaned up in
    //  order to prevent the conflicting edit from being generated.
    // doSourceChange_addElementEdit(change, unitElement, edit);
    var fileEdit = change.getFileEdit(unitElement.source.fullName);
    if (fileEdit == null) {
      fileEdit = SourceFileEdit(file, 0);
      change.addFileEdit(fileEdit);
    }
    var edits = fileEdit.edits;
    var length = edits.length;
    var index = 0;
    while (index < length && edits[index].offset > edit.offset) {
      index++;
    }
    edits.insert(index, edit);
  }

  void _appendEmptyBraces(SourceBuilder sb, [bool needsExitMark = false]) {
    sb.append('{');
    sb.append(eol);
    var indent = utils.getLinePrefix(selectionOffset);
    sb.append(indent);
    sb.append(utils.getIndent(1));
    if (needsExitMark && sb.exitOffset == null) {
      sb.setExitOffset();
    }
    sb.append(eol);
    sb.append(indent);
    sb.append('}');
  }

  int _appendNewlinePlusIndent() {
    return _appendNewlinePlusIndentAt(selectionOffset);
  }

  int _appendNewlinePlusIndentAt(int offset) {
    // Append a newline plus proper indent and another newline.
    // Return the position before the second newline.
    var indent = utils.getLinePrefix(offset);
    var loc = utils.getLineNext(offset);
    _addInsertEdit(loc, indent + eol);
    return loc + indent.length;
  }

  String _baseNodeText(AstNode astNode) {
    var text = utils.getNodeText(astNode);
    if (text.endsWith(eol)) {
      text = text.substring(0, text.length - eol.length);
    }
    return text;
  }

  void _checkExpressions(AstNode node) {
    // Note: This may queue edits that have to be accounted for later.
    // See _lengthOfInsertions().
    AstNode? errorMatching(errorCode, {partialMatch}) {
      var error = _findError(errorCode, partialMatch: partialMatch);
      if (error == null) {
        return null;
      }
      var expr = _selectedNode();
      return (expr?.thisOrAncestorOfType<StringInterpolation>() == null)
          ? expr
          : null;
    }

    var expr = errorMatching(ScannerErrorCode.UNTERMINATED_STRING_LITERAL);
    if (expr != null) {
      var source = utils.getNodeText(expr);
      var content = source;
      var char = content.codeUnitAt(0);
      if (char == 'r'.codeUnitAt(0)) {
        content = source.substring(1);
        char = content.codeUnitAt(0);
      }
      String delimiter;
      int loc;
      if (content.length >= 3 &&
          char == content.codeUnitAt(1) &&
          char == content.codeUnitAt(2)) {
        // multi-line string
        delimiter = content.substring(0, 3);
        var newlineLoc = source.indexOf(eol, selectionOffset - expr.offset);
        if (newlineLoc < 0) {
          newlineLoc = source.length;
        }
        loc = newlineLoc + expr.offset;
      } else {
        // add first char of src
        delimiter = content.substring(0, 1);
        loc = expr.offset + source.length;
      }
      _removeError(ScannerErrorCode.UNTERMINATED_STRING_LITERAL);
      _addInsertEdit(loc, delimiter);
    }
    expr = errorMatching(ParserErrorCode.EXPECTED_TOKEN, partialMatch: "']'") ??
        errorMatching(ScannerErrorCode.EXPECTED_TOKEN, partialMatch: "']'");
    if (expr != null) {
      expr = expr.thisOrAncestorOfType<ListLiteral>();
      if (expr is ListLiteral) {
        if (expr.rightBracket.isSynthetic) {
          var src = utils.getNodeText(expr).trim();
          var loc = expr.offset + src.length;
          if (src.contains(eol)) {
            var indent = utils.getNodePrefix(node);
            _addInsertEdit(loc, ',' + eol + indent + ']');
          } else {
            _addInsertEdit(loc, ']');
          }
          _removeError(ParserErrorCode.EXPECTED_TOKEN, partialMatch: "']'");
          _removeError(ScannerErrorCode.EXPECTED_TOKEN, partialMatch: "']'");
        }
      }
    }
    // The following code is similar to the code for ']' but does not work well.
    // A closing brace is recognized as belong to the map even if it is intended
    // to close a block of code.
    /*
    expr = errorMatching(ParserErrorCode.EXPECTED_TOKEN, partialMatch: "'}'");
    if (expr != null) {
      expr = expr.getAncestor((n) => n is MapLiteral);
      if (expr != null) {
        MapLiteral lit = expr;
        String src = utils.getNodeText(expr).trim();
        int loc = expr.offset + src.length;
        if (lit.entries.last.separator.isSynthetic) {
          _addInsertEdit(loc, ': ');
        }
        if (!src.endsWith('}')/*lit.rightBracket.isSynthetic*/) {
          _addInsertEdit(loc, '}');
        }
        _removeError(ParserErrorCode.EXPECTED_TOKEN, partialMatch: "'}'");
        var ms =
          _findError(ParserErrorCode.EXPECTED_TOKEN, partialMatch: "';'");
        if (ms != null) {
          // Ensure the semicolon gets inserted in the correct location.
          ms.offset = loc - 1;
        }
      }
    }
    */
  }

  bool _complete_classDeclaration(AstNode node) {
    if (node is! ClassDeclaration) {
      return false;
    }
    if (node.leftBracket.isSynthetic && errors.length == 1) {
      // The space before the left brace is assumed to exist, even if it does not.
      var sb = SourceBuilder(file, node.end - 1);
      sb.append(' ');
      _appendEmptyBraces(sb, true);
      _insertBuilder(sb);
      _setCompletion(DartStatementCompletion.COMPLETE_CLASS_DECLARATION);
      return true;
    }
    return false;
  }

  bool _complete_controlFlowBlock(AstNode node) {
    var expr = (node is ExpressionStatement)
        ? node.expression
        : (node is ReturnStatement ? node.expression : null);
    if (!(node is ReturnStatement || expr is ThrowExpression)) {
      return false;
    }
    var parent = node.parent;
    if (parent is! Block) {
      return false;
    }
    var outer = parent.parent;
    if (!(outer is DoStatement ||
        outer is ForStatement ||
        outer is IfStatement ||
        outer is WhileStatement)) {
      return false;
    }
    var previousInsertions = _lengthOfInsertions();
    var delta = 0;
    if (errors.isNotEmpty) {
      var error =
          _findError(ParserErrorCode.EXPECTED_TOKEN, partialMatch: "';'");
      if (error != null) {
        int insertOffset;
        // Fasta scanner reports unterminated string literal errors
        // and generates a synthetic string token with non-zero length.
        // Because of this, check for length == 0 rather than isSynthetic.
        if (expr == null || expr.length == 0) {
          if (node is ReturnStatement) {
            insertOffset = node.returnKeyword.end;
          } else if (node is ExpressionStatement) {
            insertOffset =
                (node.expression as ThrowExpression).throwKeyword.end;
          } else {
            insertOffset = node.end; // Not reached.
          }
        } else {
          insertOffset = expr.end;
        }
        //TODO(messick) Uncomment the following line when error location is fixed.
        //insertOffset = error.offset + error.length;
        _addInsertEdit(insertOffset, ';');
        delta = 1;
      }
    }
    var offset = _appendNewlinePlusIndentAt(parent.end);
    exitPosition = Position(file, offset + delta + previousInsertions);
    _setCompletion(DartStatementCompletion.COMPLETE_CONTROL_FLOW_BLOCK);
    return true;
  }

  bool _complete_doStatement(AstNode node) {
    if (node is! DoStatement) {
      return false;
    }
    var sb = _sourceBuilderAfterKeyword(node, node.doKeyword);
    var hasWhileKeyword = !node.whileKeyword.isSynthetic;
    var exitDelta = 0;
    if (!_statementHasValidBody(node.doKeyword, node.body)) {
      var text = utils.getNodeText(node.body);
      var delta = 0;
      if (text.startsWith(';')) {
        delta = 1;
        _addReplaceEdit(range.startLength(node.body, delta), '');
        if (hasWhileKeyword) {
          text = utils.getNodeText(node);
          if (text.indexOf(RegExp(r'do\s*;\s*while')) == 0) {
            var end = text.indexOf('while');
            var start = text.indexOf(';') + 1;
            delta += end - start - 1;
            _addReplaceEdit(SourceRange(start + node.offset, end - start), ' ');
          }
        }
        sb = SourceBuilder(file, sb.offset + delta);
        sb.append(' ');
      }
      _appendEmptyBraces(
          sb, !(hasWhileKeyword && _isSyntheticExpression(node.condition)));
      if (delta != 0) {
        exitDelta = sb.length - delta;
      }
    } else if (_isEmptyBlock(node.body)) {
      sb = SourceBuilder(sb.file, node.body.end);
    }
    SourceBuilder? sb2;
    if (hasWhileKeyword) {
      var stmt = _KeywordConditionBlockStructure(node.whileKeyword,
          node.leftParenthesis, node.condition, node.rightParenthesis, null);
      sb2 = _complete_keywordCondition(node, stmt);
      if (sb2 == null) {
        return false;
      }
      if (sb2.length == 0) {
        // true if condition is '()'
        final exitPosition = this.exitPosition;
        if (exitPosition != null) {
          if (node.semicolon.isSynthetic) {
            _insertBuilder(sb);
            sb = SourceBuilder(file, exitPosition.offset + 1);
            sb.append(';');
          }
        }
      } else {
        if (sb.exitOffset == null && sb2.exitOffset != null) {
          _insertBuilder(sb);
          sb = sb2;
          sb.append(';');
        } else {
          sb.append(sb2.toString());
        }
      }
    } else {
      sb.append(' while (');
      sb.setExitOffset();
      sb.append(');');
    }
    _insertBuilder(sb);
    if (exitDelta != 0) {
      exitPosition =
          Position(exitPosition!.file, exitPosition!.offset + exitDelta);
    }
    _setCompletion(DartStatementCompletion.COMPLETE_DO_STMT);
    return true;
  }

  bool _complete_forEachStatement(
      ForStatement forNode, ForEachParts forEachParts) {
    AstNode name;
    if (forEachParts is ForEachPartsWithIdentifier) {
      name = forEachParts.identifier;
    } else if (forEachParts is ForEachPartsWithDeclaration) {
      name = forEachParts.loopVariable;
    } else {
      throw StateError('Unrecognized for loop parts');
    }
    return _complete_forEachStatementRest(
        forNode,
        forNode.forKeyword,
        forNode.leftParenthesis,
        name,
        forEachParts.inKeyword,
        forEachParts.iterable,
        forNode.rightParenthesis,
        forNode.body);
  }

  bool _complete_forEachStatementRest(
      AstNode node,
      Token forKeyword,
      Token leftParenthesis,
      AstNode? name,
      Token inKeyword,
      Expression? iterable,
      Token rightParenthesis,
      Statement body) {
    if (inKeyword.isSynthetic) {
      return false; // Can't happen -- would be parsed as a for-statement.
    }
    var sb = SourceBuilder(file, rightParenthesis.offset + 1);
    var src = utils.getNodeText(node);
    if (name == null) {
      exitPosition = Position(file, leftParenthesis.offset + 1);
      src = src.substring(leftParenthesis.offset - node.offset);
      if (src.startsWith(RegExp(r'\(\s*in\s*\)'))) {
        _addReplaceEdit(
            range.startOffsetEndOffset(
                leftParenthesis.offset + 1, rightParenthesis.offset),
            ' in ');
      } else if (src.startsWith(RegExp(r'\(\s*in'))) {
        _addReplaceEdit(
            range.startOffsetEndOffset(
                leftParenthesis.offset + 1, inKeyword.offset),
            ' ');
      }
    } else if (iterable != null && _isSyntheticExpression(iterable)) {
      exitPosition = Position(file, rightParenthesis.offset + 1);
      src = src.substring(inKeyword.offset - node.offset);
      if (src.startsWith(RegExp(r'in\s*\)'))) {
        _addReplaceEdit(
            range.startOffsetEndOffset(
                inKeyword.offset + inKeyword.length, rightParenthesis.offset),
            ' ');
      }
    }
    if (!_statementHasValidBody(forKeyword, body)) {
      sb.append(' ');
      _appendEmptyBraces(sb, exitPosition == null);
    }
    _insertBuilder(sb);
    _setCompletion(DartStatementCompletion.COMPLETE_FOR_EACH_STMT);
    return true;
  }

  bool _complete_forStatement(ForStatement forNode, ForParts forParts) {
    SourceBuilder sb;
    var replacementLength = 0;
    if (forNode.leftParenthesis.isSynthetic) {
      if (!forNode.rightParenthesis.isSynthetic) {
        return false;
      }
      // keywordOnly (unit test name suffix that exercises this branch)
      sb = _sourceBuilderAfterKeyword(forNode, forNode.forKeyword);
      sb.append('(');
      sb.setExitOffset();
      sb.append(')');
    } else {
      if (!forParts.rightSeparator.isSynthetic) {
        // Fully-defined init, cond, updaters so nothing more needed here.
        // emptyParts, noError
        sb = SourceBuilder(file, forNode.rightParenthesis.offset + 1);
      } else if (!forParts.leftSeparator.isSynthetic) {
        if (_isSyntheticExpression(forParts.condition)) {
          var text = utils
              .getNodeText(forNode)
              .substring(forParts.leftSeparator.offset - forNode.offset);
          var match = RegExp(r';\s*(/\*.*\*/\s*)?\)[ \t]*').matchAsPrefix(text);
          if (match != null) {
            // emptyCondition, emptyInitializersEmptyCondition
            replacementLength = match.end - match.start;
            sb = SourceBuilder(file, forParts.leftSeparator.offset);
            sb.append('; ${match.group(1) ?? ''}; )');
            var suffix = text.substring(match.end);
            if (suffix.trim().isNotEmpty) {
              sb.append(' ');
              sb.append(suffix.trim());
              replacementLength += suffix.length;
              if (suffix.endsWith(eol)) {
                // emptyCondition
                replacementLength -= eol.length;
              }
            }
            exitPosition = _newPosition(forParts.leftSeparator.offset + 2);
          } else {
            return false; // Line comment in condition
          }
        } else {
          // emptyUpdaters
          sb = SourceBuilder(file, forNode.rightParenthesis.offset);
          replacementLength = 1;
          sb.append('; )');
          exitPosition = _newPosition(forParts.rightSeparator.offset + 2);
        }
      } else if (forParts is ForPartsWithExpression &&
          _isSyntheticExpression(forParts.initialization)) {
        // emptyInitializers
        exitPosition = _newPosition(forNode.rightParenthesis.offset);
        sb = SourceBuilder(file, forNode.rightParenthesis.offset);
      } else if (forParts is ForPartsWithExpression &&
          forParts.initialization is SimpleIdentifier &&
          forParts.initialization!.beginToken.lexeme == 'in') {
        // looks like a for/each statement missing the loop variable
        return _complete_forEachStatementRest(
            forNode,
            forNode.forKeyword,
            forNode.leftParenthesis,
            null,
            forParts.initialization!.beginToken,
            null,
            forNode.rightParenthesis,
            forNode.body);
      } else {
        var start = forParts.condition!.offset + forParts.condition!.length;
        var text = utils.getNodeText(forNode).substring(start - forNode.offset);
        if (text.startsWith(RegExp(r'\s*\)'))) {
          // missingLeftSeparator
          var end = text.indexOf(')');
          sb = SourceBuilder(file, start);
          _addReplaceEdit(SourceRange(start, end), '; ; ');
          exitPosition = Position(file, start - (end - '; '.length));
        } else {
          // Not possible; any comment following init is attached to init.
          exitPosition = _newPosition(forNode.rightParenthesis.offset);
          sb = SourceBuilder(file, forNode.rightParenthesis.offset);
        }
      }
    }
    var body = forNode.body;
    if (!_statementHasValidBody(forNode.forKeyword, body)) {
      // keywordOnly, noError
      sb.append(' ');
      _appendEmptyBraces(sb, true /*exitPosition == null*/);
    } else if (body is Block) {
      if (body.rightBracket.end <= selectionOffset) {
        // emptyInitializersAfterBody
        errors = []; // Ignore errors; they are for previous statement.
        return false; // If cursor is after closing brace just add newline.
      }
    }
    _insertBuilder(sb, replacementLength);
    _setCompletion(DartStatementCompletion.COMPLETE_FOR_STMT);
    return true;
  }

  bool _complete_forStatement2(AstNode node) {
    if (node is ForStatement) {
      var forLoopParts = node.forLoopParts;
      if (forLoopParts is ForParts) {
        return _complete_forStatement(node, forLoopParts);
      } else if (forLoopParts is ForEachParts) {
        return _complete_forEachStatement(node, forLoopParts);
      }
    }
    return false;
  }

  bool _complete_functionDeclaration(AstNode node) {
    if (node is! MethodDeclaration && node is! FunctionDeclaration) {
      return false;
    }
    var needsParen = false;
    int computeExitPos(FormalParameterList parameters) {
      if (needsParen = parameters.rightParenthesis.isSynthetic) {
        var error = _findError(ParserErrorCode.MISSING_CLOSING_PARENTHESIS);
        if (error != null) {
          return error.offset - 1;
        }
      }
      return node.end - 1;
    }

    int paramListEnd;
    if (node is FunctionDeclaration) {
      var parameters = node.functionExpression.parameters;
      if (parameters == null) {
        return false;
      }
      paramListEnd = computeExitPos(parameters);
    } else if (node is MethodDeclaration) {
      var parameters = node.parameters;
      if (parameters == null) {
        return false;
      }
      paramListEnd = computeExitPos(parameters);
    } else {
      return false;
    }
    var sb = SourceBuilder(file, paramListEnd);
    if (needsParen) {
      sb.append(')');
    }
    sb.append(' ');
    _appendEmptyBraces(sb, true);
    _insertBuilder(sb);
    _setCompletion(DartStatementCompletion.COMPLETE_FUNCTION_DECLARATION);
    return true;
  }

  bool _complete_functionDeclarationStatement(AstNode node) {
    if (node is! FunctionDeclarationStatement) {
      return false;
    }
    var error = _findError(ParserErrorCode.EXPECTED_TOKEN, partialMatch: "';'");
    if (error != null) {
      var src = utils.getNodeText(node);
      var insertOffset = node.functionDeclaration.end - 1;
      var body = node.functionDeclaration.functionExpression.body;
      if (body is ExpressionFunctionBody) {
        var fnbOffset = body.functionDefinition.offset;
        var fnSrc = src.substring(fnbOffset - node.offset);
        if (!fnSrc.startsWith('=>')) {
          return false;
        }
        var delta = 0;
        if (body.expression.isSynthetic) {
          if (!fnSrc.startsWith('=> ')) {
            _addInsertEdit(insertOffset, ' ');
            delta = 1;
          }
          _addInsertEdit(insertOffset, ';');
          _appendNewlinePlusIndentAt(insertOffset);
        } else {
          delta = 1;
          _addInsertEdit(insertOffset, ';');
          insertOffset = _appendNewlinePlusIndent();
        }
        _setCompletionAt(
            DartStatementCompletion.SIMPLE_SEMICOLON, insertOffset + delta);
        return true;
      }
    }
    return false;
  }

  bool _complete_ifOrWhileStatement(AstNode node,
      _KeywordConditionBlockStructure statement, StatementCompletionKind kind) {
    if (_statementHasValidBody(statement.keyword, statement.block!)) {
      return false;
    }
    var sb = _complete_keywordCondition(node, statement);
    if (sb == null) {
      return false;
    }
    var overshoot = _lengthOfDeletions();
    sb.append(' ');
    _appendEmptyBraces(sb, exitPosition == null);
    _insertBuilder(sb);
    if (overshoot != 0) {
      exitPosition = _newPosition(exitPosition!.offset - overshoot);
    }
    _setCompletion(kind);
    return true;
  }

  bool _complete_ifStatement(AstNode node) {
    if (node is! IfStatement) {
      return false;
    }
    var elseKeyword = node.elseKeyword;
    if (elseKeyword != null) {
      if (selectionOffset >= elseKeyword.end &&
          _isEmptyStatement(node.elseStatement)) {
        var sb = SourceBuilder(file, selectionOffset);
        var src = utils.getNodeText(node);
        if (!src
            .substring(elseKeyword.end - node.offset)
            .startsWith(RegExp(r'[ \t]'))) {
          sb.append(' ');
        }
        _appendEmptyBraces(sb, true);
        _insertBuilder(sb);
        _setCompletion(DartStatementCompletion.COMPLETE_IF_STMT);
        return true;
      }
      return false;
    }
    var stmt = _KeywordConditionBlockStructure(
        node.ifKeyword,
        node.leftParenthesis,
        node.condition,
        node.rightParenthesis,
        node.thenStatement);
    return _complete_ifOrWhileStatement(
        node, stmt, DartStatementCompletion.COMPLETE_IF_STMT);
  }

  SourceBuilder? _complete_keywordCondition(
      AstNode node, _KeywordConditionBlockStructure statement) {
    SourceBuilder sb;
    if (statement.leftParenthesis.isSynthetic) {
      if (!statement.rightParenthesis.isSynthetic) {
        // Quite unlikely to see this so don't try to fix it.
        return null;
      }
      sb = _sourceBuilderAfterKeyword(node, statement.keyword);
      sb.append('(');
      sb.setExitOffset();
      sb.append(')');
    } else {
      if (_isSyntheticExpression(statement.condition)) {
        exitPosition = _newPosition(statement.leftParenthesis.offset + 1);
        sb = SourceBuilder(file, statement.rightParenthesis.offset + 1);
      } else if (statement.rightParenthesis.isSynthetic) {
        sb = SourceBuilder(file, statement.condition.end);
        sb.append(')');
      } else {
        var afterParen = statement.rightParenthesis.offset + 1;
        if (utils
            .getNodeText(node)
            .substring(afterParen - node.offset)
            .startsWith(RegExp(r'[ \t]'))) {
          _addReplaceEdit(SourceRange(afterParen, 1), '');
          sb = SourceBuilder(file, afterParen + 1);
        } else {
          sb = SourceBuilder(file, afterParen);
        }
      }
    }
    return sb;
  }

  bool _complete_methodCall(AstNode node) {
    var parenError =
        _findError(ParserErrorCode.EXPECTED_TOKEN, partialMatch: "')'") ??
            _findError(ScannerErrorCode.EXPECTED_TOKEN, partialMatch: "')'");
    if (parenError == null) {
      return false;
    }
    var argList = _selectedNode(at: selectionOffset)
        ?.thisOrAncestorOfType<ArgumentList>();
    argList ??= _selectedNode(at: parenError.offset)
        ?.thisOrAncestorOfType<ArgumentList>();
    if (argList == null ||
        argList.thisOrAncestorMatching((n) => n == node) == null) {
      return false;
    }
    var previousInsertions = _lengthOfInsertions();
    var loc = min(selectionOffset, argList.end - 1);
    var delta = 1;
    var semicolonError =
        _findError(ParserErrorCode.EXPECTED_TOKEN, partialMatch: "';'");
    if (semicolonError == null) {
      loc += 1;
      delta = 0;
    }
    _addInsertEdit(loc, ')');
    if (semicolonError != null) {
      _addInsertEdit(loc, ';');
    }
    var indent = utils.getLinePrefix(selectionOffset);
    var exit = utils.getLineNext(selectionOffset);
    _addInsertEdit(exit, indent + eol);
    exit += indent.length + eol.length + previousInsertions;

    _setCompletionAt(DartStatementCompletion.SIMPLE_ENTER, exit + delta);
    return true;
  }

  bool _complete_simpleEnter() {
    int offset;
    if (errors.isNotEmpty) {
      offset = selectionOffset;
    } else {
      var indent = utils.getLinePrefix(selectionOffset);
      var loc = utils.getLineNext(selectionOffset);
      _addInsertEdit(loc, indent + eol);
      offset = loc + indent.length;
    }
    _setCompletionAt(DartStatementCompletion.SIMPLE_ENTER, offset);
    return true;
  }

  bool _complete_simpleSemicolon(AstNode node) {
    if (errors.length != 1) {
      return false;
    }
    var error = _findError(ParserErrorCode.EXPECTED_TOKEN, partialMatch: "';'");
    if (error != null) {
      var previousInsertions = _lengthOfInsertions();
      // TODO(messick) Fix this to find the correct place in all cases.
      var insertOffset = error.offset + error.length;
      _addInsertEdit(insertOffset, ';');
      var offset = _appendNewlinePlusIndent() + 1 /*';'*/ + previousInsertions;
      _setCompletionAt(DartStatementCompletion.SIMPLE_SEMICOLON, offset);
      return true;
    }
    return false;
  }

  bool _complete_switchStatement(AstNode node) {
    if (node is! SwitchStatement) {
      return false;
    }
    SourceBuilder sb;
    if (node.leftParenthesis.isSynthetic && node.rightParenthesis.isSynthetic) {
      exitPosition = Position(file, node.switchKeyword.end + 2);
      var src = utils.getNodeText(node);
      if (src
          .substring(node.switchKeyword.end - node.offset)
          .startsWith(RegExp(r'[ \t]+'))) {
        sb = SourceBuilder(file, node.switchKeyword.end + 1);
      } else {
        sb = SourceBuilder(file, node.switchKeyword.end);
        sb.append(' ');
      }
      sb.append('()');
    } else if (node.leftParenthesis.isSynthetic ||
        node.rightParenthesis.isSynthetic) {
      return false;
    } else {
      sb = SourceBuilder(file, node.rightParenthesis.offset + 1);
      if (_isSyntheticExpression(node.expression)) {
        exitPosition = Position(file, node.leftParenthesis.offset + 1);
      }
    }
    if (node
        .leftBracket.isSynthetic /*&& switchNode.rightBracket.isSynthetic*/) {
      // See https://github.com/dart-lang/sdk/issues/29391
      sb.append(' ');
      _appendEmptyBraces(sb, exitPosition == null);
    } else {
      var member = _findInvalidElement(node.members);
      if (member != null) {
        if (member.colon.isSynthetic) {
          var loc =
              member is SwitchCase ? member.expression.end : member.keyword.end;
          sb = SourceBuilder(file, loc);
          sb.append(': ');
          exitPosition = Position(file, loc + 2);
        }
      }
    }
    _insertBuilder(sb);
    _setCompletion(DartStatementCompletion.COMPLETE_SWITCH_STMT);
    return true;
  }

  bool _complete_tryStatement(AstNode node) {
    if (node is! TryStatement) {
      return false;
    }
    var addSpace = true;
    if (node.body.leftBracket.isSynthetic) {
      var src = utils.getNodeText(node);
      SourceBuilder sb;
      if (src
          .substring(node.tryKeyword.end - node.offset)
          .startsWith(RegExp(r'[ \t]+'))) {
        // keywordSpace
        sb = SourceBuilder(file, node.tryKeyword.end + 1);
      } else {
        // keywordOnly
        sb = SourceBuilder(file, node.tryKeyword.end);
        sb.append(' ');
      }
      _appendEmptyBraces(sb, true);
      _insertBuilder(sb);
    } else {
      SourceBuilder? sb;
      var catchNode = _findInvalidElement(node.catchClauses);
      if (catchNode != null) {
        var onKeyword = catchNode.onKeyword;
        var exceptionType = catchNode.exceptionType;
        if (onKeyword != null && exceptionType != null) {
          if (exceptionType.length == 0 ||
              _findError(CompileTimeErrorCode.NON_TYPE_IN_CATCH_CLAUSE,
                      partialMatch: "name 'catch") !=
                  null) {
            var src = utils.getNodeText(catchNode);
            if (src.startsWith(RegExp(r'on[ \t]+'))) {
              if (src.startsWith(RegExp(r'on[ \t][ \t]+'))) {
                // onSpaces
                exitPosition = Position(file, onKeyword.end + 1);
                sb = SourceBuilder(file, onKeyword.end + 2);
                addSpace = false;
              } else {
                // onSpace
                sb = SourceBuilder(file, onKeyword.end + 1);
                sb.setExitOffset();
              }
            } else {
              // onOnly
              sb = SourceBuilder(file, onKeyword.end);
              sb.append(' ');
              sb.setExitOffset();
            }
          } else {
            // onType
            sb = SourceBuilder(file, exceptionType.end);
          }
        }
        var catchKeyword = catchNode.catchKeyword;
        if (catchKeyword != null) {
          // catchOnly
          var struct = _KeywordConditionBlockStructure(
              catchKeyword,
              catchNode.leftParenthesis!,
              catchNode.exceptionParameter!,
              catchNode.rightParenthesis!,
              catchNode.body);
          if (sb != null) {
            // onCatch
            _insertBuilder(sb);
          }
          sb = _complete_keywordCondition(node, struct);
          if (sb == null) {
            return false;
          }
        }
        if (sb != null) {
          if (catchNode.body.leftBracket.isSynthetic) {
            // onOnly and others
            if (addSpace) {
              sb.append(' ');
            }
            _appendEmptyBraces(sb, exitPosition == null);
          }
          _insertBuilder(sb);
        }
      } else if (node.finallyKeyword != null) {
        if (node.finallyBlock!.leftBracket.isSynthetic) {
          // finallyOnly
          sb = SourceBuilder(file, node.finallyKeyword!.end);
          sb.append(' ');
          _appendEmptyBraces(sb, true);
          _insertBuilder(sb);
        }
      }
    }
    _setCompletion(DartStatementCompletion.COMPLETE_TRY_STMT);
    return true;
  }

  bool _complete_variableDeclaration(AstNode node) {
    if (node is! VariableDeclaration) {
      return false;
    }
    _addInsertEdit(node.end, ';');
    exitPosition = Position(file, _appendNewlinePlusIndentAt(node.end) + 1);
    _setCompletion(DartStatementCompletion.COMPLETE_VARIABLE_DECLARATION);
    return true;
  }

  bool _complete_whileStatement(AstNode node) {
    if (node is! WhileStatement) {
      return false;
    }
    var stmt = _KeywordConditionBlockStructure(node.whileKeyword,
        node.leftParenthesis, node.condition, node.rightParenthesis, node.body);
    return _complete_ifOrWhileStatement(
        node, stmt, DartStatementCompletion.COMPLETE_WHILE_STMT);
  }

  engine.AnalysisError? _findError(ErrorCode code, {partialMatch}) {
    return errors.firstWhereOrNull((err) =>
        err.errorCode == code &&
        (partialMatch == null ? true : err.message.contains(partialMatch)));
  }

  T? _findInvalidElement<T extends AstNode>(NodeList<T> list) {
    return list.firstWhereOrNull((item) =>
        selectionOffset >= item.offset && selectionOffset <= item.end);
  }

  void _insertBuilder(SourceBuilder builder, [int length = 0]) {
    {
      var range = SourceRange(builder.offset, length);
      var text = builder.toString();
      _addReplaceEdit(range, text);
    }
    // add exit position
    {
      var exitOffset = builder.exitOffset;
      if (exitOffset != null) {
        exitPosition = _newPosition(exitOffset);
      }
    }
  }

  bool _isEmptyBlock(AstNode stmt) {
    return stmt is Block && stmt.statements.isEmpty;
  }

  bool _isEmptyStatement(AstNode? stmt) {
    if (stmt is ExpressionStatement) {
      var expression = stmt.expression;
      if (expression is SimpleIdentifier) {
        return expression.token.isSynthetic;
      }
    }
    return stmt is EmptyStatement;
  }

  bool _isEmptyStatementOrEmptyBlock(AstNode stmt) {
    return _isEmptyStatement(stmt) || _isEmptyBlock(stmt);
  }

  bool _isNonStatementDeclaration(AstNode n) {
    if (n is! Declaration) {
      return false;
    }
    if (n is! VariableDeclaration && n is! FunctionDeclaration) {
      return true;
    }
    var p = n.parent;
    return p is! Statement &&
        p?.parent is! Statement &&
        p?.parent?.parent is! Statement;
  }

  bool _isSyntheticExpression(Expression? expr) {
    return expr is SimpleIdentifier && expr.isSynthetic;
  }

  int _lengthOfDeletions() {
    if (change.edits.isEmpty) {
      return 0;
    }
    var length = 0;
    for (var edit in change.edits) {
      for (var srcEdit in edit.edits) {
        if (srcEdit.length > 0) {
          length += srcEdit.length - srcEdit.replacement.length;
        }
      }
    }
    return length;
  }

  int _lengthOfInsertions() {
    // Any _complete_*() that may follow changes made by _checkExpressions()
    // must cache the result of this method and add that value to its
    // exit position. That's assuming all edits are done in increasing position.
    // There are currently no editing sequences that produce both insertions and
    // deletions, but if there were this approach would have to be generalized.
    if (change.edits.isEmpty) {
      return 0;
    }
    var length = 0;
    for (var edit in change.edits) {
      for (var srcEdit in edit.edits) {
        if (srcEdit.length == 0) {
          length += srcEdit.replacement.length;
        }
      }
    }
    return length;
  }

  Position _newPosition(int offset) {
    return Position(file, offset);
  }

  void _removeError(errorCode, {partialMatch}) {
    var error = _findError(errorCode, partialMatch: partialMatch);
    if (error != null) {
      errors.remove(error);
    }
  }

  AstNode? _selectedNode({int? at}) =>
      NodeLocator(at ?? selectionOffset).searchWithin(unit);

  void _setCompletion(StatementCompletionKind kind, [List? args]) {
    assert(exitPosition != null);
    change.selection = exitPosition;
    change.message = formatList(kind.message, args);
    linkedPositionGroups.values
        .forEach((group) => change.addLinkedEditGroup(group));
    completion = StatementCompletion(kind, change);
  }

  void _setCompletionAt(StatementCompletionKind kind, int offset,
      [List? args]) {
    exitPosition = _newPosition(offset);
    _setCompletion(kind, args);
  }

  SourceBuilder _sourceBuilderAfterKeyword(AstNode node, Token keyword) {
    SourceBuilder sb;
    var text = _baseNodeText(node);
    text = text.substring(keyword.offset - node.offset);
    var len = keyword.length;
    if (text.length == len || // onCatchComment
        !text.substring(len, len + 1).contains(RegExp(r'[ \t]'))) {
      sb = SourceBuilder(file, keyword.offset + len);
      sb.append(' ');
    } else {
      sb = SourceBuilder(file, keyword.offset + len + 1);
    }
    return sb;
  }

  bool _statementHasValidBody(Token keyword, Statement body) {
    // A "valid" body is either a non-synthetic block or a single statement
    // on the same line as the parent statement, similar to dart_style.
    if (body.isSynthetic) {
      return false;
    }
    if (body is Block) {
      var block = body;
      return !block.leftBracket.isSynthetic;
    }
    return lineInfo.getLocation(keyword.offset) ==
        lineInfo.getLocation(body.offset);
  }
}

// Encapsulate common structure of if-statement and while-statement.
class _KeywordConditionBlockStructure {
  final Token keyword;
  final Token leftParenthesis, rightParenthesis;
  final Expression condition;
  final Statement? block;

  _KeywordConditionBlockStructure(this.keyword, this.leftParenthesis,
      this.condition, this.rightParenthesis, this.block);

  int get offset => keyword.offset;
}
