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