// 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.

library services.src.correction.assist;

import 'dart:async';
import 'dart:collection';

import 'package:analysis_server/plugin/edit/assist/assist_core.dart';
import 'package:analysis_server/plugin/edit/assist/assist_dart.dart';
import 'package:analysis_server/src/protocol_server.dart' hide Element;
import 'package:analysis_server/src/services/correction/assist.dart';
import 'package:analysis_server/src/services/correction/name_suggestion.dart';
import 'package:analysis_server/src/services/correction/source_buffer.dart';
import 'package:analysis_server/src/services/correction/source_range.dart';
import 'package:analysis_server/src/services/correction/statement_analyzer.dart';
import 'package:analysis_server/src/services/correction/util.dart';
import 'package:analysis_server/src/services/search/hierarchy.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/standard_resolution_map.dart';
import 'package:analyzer/dart/ast/token.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/src/dart/ast/token.dart';
import 'package:analyzer/src/dart/ast/utilities.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/java_core.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:path/path.dart';

typedef _SimpleIdentifierVisitor(SimpleIdentifier node);

/**
 * The computer for Dart assists.
 */
class AssistProcessor {
  AnalysisContext analysisContext;

  Source source;
  String file;
  int fileStamp;

  CompilationUnit unit;
  CompilationUnitElement unitElement;

  LibraryElement unitLibraryElement;
  String unitLibraryFile;
  String unitLibraryFolder;

  int selectionOffset;
  int selectionLength;
  int selectionEnd;

  final List<Assist> assists = <Assist>[];
  final Map<String, LinkedEditGroup> linkedPositionGroups =
      <String, LinkedEditGroup>{};
  Position exitPosition = null;

  CorrectionUtils utils;
  AstNode node;

  SourceChange change = new SourceChange('<message>');

  AssistProcessor(DartAssistContext dartContext) {
    analysisContext = dartContext.analysisContext;
    // source
    source = dartContext.source;
    file = dartContext.source.fullName;
    fileStamp = analysisContext.getModificationStamp(source);
    // unit
    unit = dartContext.unit;
    unitElement = dartContext.unit.element;
    // library
    unitLibraryElement = resolutionMap
        .elementDeclaredByCompilationUnit(dartContext.unit)
        .library;
    unitLibraryFile = unitLibraryElement.source.fullName;
    unitLibraryFolder = dirname(unitLibraryFile);
    // selection
    selectionOffset = dartContext.selectionOffset;
    selectionLength = dartContext.selectionLength;
    selectionEnd = selectionOffset + selectionLength;
  }

  /**
   * Returns the EOL to use for this [CompilationUnit].
   */
  String get eol => utils.endOfLine;

  Future<List<Assist>> compute() async {
    // If the source was changed between the constructor and running
    // this asynchronous method, it is not safe to use the unit.
    if (analysisContext.getModificationStamp(source) != fileStamp) {
      return const <Assist>[];
    }

    try {
      utils = new CorrectionUtils(unit);
    } catch (e) {
      throw new CancelCorrectionException(exception: e);
    }

    node = new NodeLocator(selectionOffset, selectionEnd).searchWithin(unit);
    if (node == null) {
      return assists;
    }
    // try to add proposals
    _addProposal_addTypeAnnotation_DeclaredIdentifier();
    _addProposal_addTypeAnnotation_SimpleFormalParameter();
    _addProposal_addTypeAnnotation_VariableDeclaration();
    _addProposal_assignToLocalVariable();
    _addProposal_convertIntoFinalField();
    _addProposal_convertIntoGetter();
    _addProposal_convertDocumentationIntoBlock();
    _addProposal_convertDocumentationIntoLine();
    _addProposal_convertToBlockFunctionBody();
    _addProposal_convertToExpressionFunctionBody();
    _addProposal_convertToForIndexLoop();
    _addProposal_convertToIsNot_onIs();
    _addProposal_convertToIsNot_onNot();
    _addProposal_convertToIsNotEmpty();
    _addProposal_convertToFieldParameter();
    _addProposal_convertToNormalParameter();
    _addProposal_encapsulateField();
    _addProposal_exchangeOperands();
    _addProposal_importAddShow();
    _addProposal_introduceLocalTestedType();
    _addProposal_invertIf();
    _addProposal_joinIfStatementInner();
    _addProposal_joinIfStatementOuter();
    _addProposal_joinVariableDeclaration_onAssignment();
    _addProposal_joinVariableDeclaration_onDeclaration();
    _addProposal_removeTypeAnnotation();
    _addProposal_replaceConditionalWithIfElse();
    _addProposal_replaceIfElseWithConditional();
    _addProposal_splitAndCondition();
    _addProposal_splitVariableDeclaration();
    _addProposal_surroundWith();
    // done
    return assists;
  }

  FunctionBody getEnclosingFunctionBody() {
    {
      FunctionExpression function =
          node.getAncestor((node) => node is FunctionExpression);
      if (function != null) {
        return function.body;
      }
    }
    {
      FunctionDeclaration function =
          node.getAncestor((node) => node is FunctionDeclaration);
      if (function != null) {
        return function.functionExpression.body;
      }
    }
    {
      ConstructorDeclaration constructor =
          node.getAncestor((node) => node is ConstructorDeclaration);
      if (constructor != null) {
        return constructor.body;
      }
    }
    {
      MethodDeclaration method =
          node.getAncestor((node) => node is MethodDeclaration);
      if (method != null) {
        return method.body;
      }
    }
    return null;
  }

  void _addAssist(AssistKind kind, List args, {String assistFile}) {
    if (assistFile == null) {
      assistFile = file;
    }
    // check is there are any edits
    if (change.edits.isEmpty) {
      _coverageMarker();
      return;
    }
    // prepare Change
    change.message = formatList(kind.message, args);
    linkedPositionGroups.values
        .forEach((group) => change.addLinkedEditGroup(group));
    change.selection = exitPosition;
    // add Assist
    Assist assist = new Assist(kind, change);
    assists.add(assist);
    // clear
    change = new SourceChange('<message>');
    linkedPositionGroups.clear();
    exitPosition = null;
  }

  void _addIndentEdit(SourceRange range, String oldIndent, String newIndent) {
    SourceEdit edit = utils.createIndentEdit(range, oldIndent, newIndent);
    doSourceChange_addElementEdit(change, unitElement, edit);
  }

  /**
   * Adds a new [Edit] to [edits].
   */
  void _addInsertEdit(int offset, String text) {
    SourceEdit edit = new SourceEdit(offset, 0, text);
    doSourceChange_addElementEdit(change, unitElement, edit);
  }

  void _addProposal_addTypeAnnotation_DeclaredIdentifier() {
    DeclaredIdentifier declaredIdentifier =
        node.getAncestor((n) => n is DeclaredIdentifier);
    if (declaredIdentifier == null) {
      ForEachStatement forEach = node.getAncestor((n) => n is ForEachStatement);
      int offset = node.offset;
      if (forEach != null &&
          forEach.iterable != null &&
          offset < forEach.iterable.offset) {
        declaredIdentifier = forEach.loopVariable;
      }
    }
    if (declaredIdentifier == null) {
      _coverageMarker();
      return;
    }
    // may be has type annotation already
    if (declaredIdentifier.type != null) {
      _coverageMarker();
      return;
    }
    // prepare type source
    String typeSource;
    DartType type = declaredIdentifier.identifier.bestType;
    if (type is InterfaceType || type is FunctionType) {
      _configureTargetLocation(node);
      Set<Source> librariesToImport = new Set<Source>();
      typeSource = utils.getTypeSource(type, librariesToImport);
      addLibraryImports(change, unitLibraryElement, librariesToImport);
    } else {
      _coverageMarker();
      return;
    }
    // type source might be null, if the type is private
    if (typeSource == null) {
      _coverageMarker();
      return;
    }
    // add edit
    Token keyword = declaredIdentifier.keyword;
    if (keyword.keyword == Keyword.VAR) {
      SourceRange range = rangeToken(keyword);
      _addReplaceEdit(range, typeSource);
    } else {
      _addInsertEdit(declaredIdentifier.identifier.offset, '$typeSource ');
    }
    // add proposal
    _addAssist(DartAssistKind.ADD_TYPE_ANNOTATION, []);
  }

  void _addProposal_addTypeAnnotation_SimpleFormalParameter() {
    AstNode node = this.node;
    // should be the name of a simple parameter
    if (node is! SimpleIdentifier || node.parent is! SimpleFormalParameter) {
      _coverageMarker();
      return;
    }
    SimpleIdentifier name = node;
    SimpleFormalParameter parameter = node.parent;
    // the parameter should not have a type
    if (parameter.type != null) {
      _coverageMarker();
      return;
    }
    // prepare propagated type
    DartType type = name.propagatedType;
    // TODO(scheglov) If the parameter is in a method declaration, and if the
    // method overrides a method that has a type for the corresponding
    // parameter, it would be nice to copy down the type from the overridden
    // method.
    if (type is! InterfaceType) {
      _coverageMarker();
      return;
    }
    // prepare type source
    String typeSource;
    {
      _configureTargetLocation(node);
      Set<Source> librariesToImport = new Set<Source>();
      typeSource = utils.getTypeSource(type, librariesToImport);
      addLibraryImports(change, unitLibraryElement, librariesToImport);
    }
    // type source might be null, if the type is private
    if (typeSource == null) {
      _coverageMarker();
      return;
    }
    // add edit
    _addInsertEdit(name.offset, '$typeSource ');
    // add proposal
    _addAssist(DartAssistKind.ADD_TYPE_ANNOTATION, []);
  }

  void _addProposal_addTypeAnnotation_VariableDeclaration() {
    AstNode node = this.node;
    // prepare VariableDeclarationList
    VariableDeclarationList declarationList =
        node.getAncestor((node) => node is VariableDeclarationList);
    if (declarationList == null) {
      _coverageMarker();
      return;
    }
    // may be has type annotation already
    if (declarationList.type != null) {
      _coverageMarker();
      return;
    }
    // prepare single VariableDeclaration
    List<VariableDeclaration> variables = declarationList.variables;
    if (variables.length != 1) {
      _coverageMarker();
      return;
    }
    VariableDeclaration variable = variables[0];
    // must be not after the name of the variable
    if (selectionOffset > variable.name.end) {
      _coverageMarker();
      return;
    }
    // we need an initializer to get the type from
    Expression initializer = variable.initializer;
    if (initializer == null) {
      _coverageMarker();
      return;
    }
    DartType type = initializer.bestType;
    // prepare type source
    String typeSource;
    if (type is InterfaceType || type is FunctionType) {
      _configureTargetLocation(node);
      Set<Source> librariesToImport = new Set<Source>();
      typeSource = utils.getTypeSource(type, librariesToImport);
      addLibraryImports(change, unitLibraryElement, librariesToImport);
    } else {
      _coverageMarker();
      return;
    }
    // type source might be null, if the type is private
    if (typeSource == null) {
      _coverageMarker();
      return;
    }
    // add edit
    Token keyword = declarationList.keyword;
    if (keyword?.keyword == Keyword.VAR) {
      SourceRange range = rangeToken(keyword);
      _addReplaceEdit(range, typeSource);
    } else {
      _addInsertEdit(variable.offset, '$typeSource ');
    }
    // add proposal
    _addAssist(DartAssistKind.ADD_TYPE_ANNOTATION, []);
  }

  void _addProposal_assignToLocalVariable() {
    // prepare enclosing ExpressionStatement
    ExpressionStatement expressionStatement;
    for (AstNode node = this.node; node != null; node = node.parent) {
      if (node is ExpressionStatement) {
        expressionStatement = node;
        break;
      }
      if (node is ArgumentList ||
          node is AssignmentExpression ||
          node is Statement ||
          node is ThrowExpression) {
        _coverageMarker();
        return;
      }
    }
    if (expressionStatement == null) {
      _coverageMarker();
      return;
    }
    // prepare expression
    Expression expression = expressionStatement.expression;
    int offset = expression.offset;
    // prepare expression type
    DartType type = expression.bestType;
    if (type.isVoid) {
      _coverageMarker();
      return;
    }
    // prepare source
    SourceBuilder builder = new SourceBuilder(file, offset);
    builder.append('var ');
    // prepare excluded names
    Set<String> excluded = new Set<String>();
    {
      ScopedNameFinder scopedNameFinder = new ScopedNameFinder(offset);
      expression.accept(scopedNameFinder);
      excluded.addAll(scopedNameFinder.locals.keys.toSet());
    }
    // name(s)
    {
      List<String> suggestions =
          getVariableNameSuggestionsForExpression(type, expression, excluded);
      builder.startPosition('NAME');
      for (int i = 0; i < suggestions.length; i++) {
        String name = suggestions[i];
        if (i == 0) {
          builder.append(name);
        }
        builder.addSuggestion(LinkedEditSuggestionKind.VARIABLE, name);
      }
      builder.endPosition();
    }
    builder.append(' = ');
    // add proposal
    _insertBuilder(builder);
    _addAssist(DartAssistKind.ASSIGN_TO_LOCAL_VARIABLE, []);
  }

  void _addProposal_convertDocumentationIntoBlock() {
    Comment comment = node.getAncestor((n) => n is Comment);
    if (comment != null && comment.isDocumentation) {
      String prefix = utils.getNodePrefix(comment);
      SourceBuilder sb = new SourceBuilder(file, comment.offset);
      sb.append('/**');
      sb.append(eol);
      for (Token token in comment.tokens) {
        if (token is DocumentationCommentToken &&
            token.type == TokenType.SINGLE_LINE_COMMENT) {
          sb.append(prefix);
          sb.append(' *');
          sb.append(token.lexeme.substring('///'.length));
          sb.append(eol);
        } else {
          return;
        }
      }
      sb.append(prefix);
      sb.append(' */');
      _insertBuilder(sb, comment.length);
    }
    // add proposal
    _addAssist(DartAssistKind.CONVERT_DOCUMENTATION_INTO_BLOCK, []);
  }

  void _addProposal_convertDocumentationIntoLine() {
    Comment comment = node.getAncestor((n) => n is Comment);
    if (comment != null && comment.isDocumentation) {
      if (comment.tokens.length == 1) {
        Token token = comment.tokens.first;
        if (token.type == TokenType.MULTI_LINE_COMMENT) {
          String text = token.lexeme;
          List<String> lines = text.split('\n');
          String prefix = utils.getNodePrefix(comment);
          SourceBuilder sb = new SourceBuilder(file, comment.offset);
          bool firstLine = true;
          String linePrefix = '';
          for (String line in lines) {
            if (firstLine) {
              firstLine = false;
              String expectedPrefix = '/**';
              if (!line.startsWith(expectedPrefix)) {
                return;
              }
              line = line.substring(expectedPrefix.length).trim();
              if (line.isNotEmpty) {
                sb.append('/// ');
                sb.append(line);
                linePrefix = eol + prefix;
              }
            } else {
              if (line.startsWith(prefix + ' */')) {
                break;
              }
              String expectedPrefix = prefix + ' * ';
              if (!line.startsWith(expectedPrefix)) {
                return;
              }
              line = line.substring(expectedPrefix.length).trim();
              sb.append(linePrefix);
              sb.append('/// ');
              sb.append(line);
              linePrefix = eol + prefix;
            }
          }
          _insertBuilder(sb, comment.length);
        }
      }
    }
    // add proposal
    _addAssist(DartAssistKind.CONVERT_DOCUMENTATION_INTO_LINE, []);
  }

  void _addProposal_convertIntoFinalField() {
    // Find the enclosing getter.
    MethodDeclaration getter;
    for (AstNode n = node; n != null; n = n.parent) {
      if (n is MethodDeclaration) {
        getter = n;
        break;
      }
      if (n is SimpleIdentifier || n is TypeName || n is TypeArgumentList) {
        continue;
      }
      break;
    }
    if (getter == null || !getter.isGetter) {
      return;
    }
    // Check that there is no corresponding setter.
    {
      ExecutableElement element = getter.element;
      if (element == null) {
        return;
      }
      Element enclosing = element.enclosingElement;
      if (enclosing is ClassElement) {
        if (enclosing.getSetter(element.name) != null) {
          return;
        }
      }
    }
    // Try to find the returned expression.
    Expression expression;
    {
      FunctionBody body = getter.body;
      if (body is ExpressionFunctionBody) {
        expression = body.expression;
      } else if (body is BlockFunctionBody) {
        List<Statement> statements = body.block.statements;
        if (statements.length == 1) {
          Statement statement = statements.first;
          if (statement is ReturnStatement) {
            expression = statement.expression;
          }
        }
      }
    }
    // Use the returned expression as the field initializer.
    if (expression != null) {
      AstNode beginNodeToReplace = getter.name;
      String code = 'final';
      if (getter.returnType != null) {
        beginNodeToReplace = getter.returnType;
        code += ' ' + _getNodeText(getter.returnType);
      }
      code += ' ' + _getNodeText(getter.name);
      if (expression is! NullLiteral) {
        code += ' = ' + _getNodeText(expression);
      }
      code += ';';
      _addReplaceEdit(rangeStartEnd(beginNodeToReplace, getter), code);
      _addAssist(DartAssistKind.CONVERT_INTO_FINAL_FIELD, []);
    }
  }

  void _addProposal_convertIntoGetter() {
    // Find the enclosing field declaration.
    FieldDeclaration fieldDeclaration;
    for (AstNode n = node; n != null; n = n.parent) {
      if (n is FieldDeclaration) {
        fieldDeclaration = n;
        break;
      }
      if (n is SimpleIdentifier ||
          n is VariableDeclaration ||
          n is VariableDeclarationList ||
          n is TypeName ||
          n is TypeArgumentList) {
        continue;
      }
      break;
    }
    if (fieldDeclaration == null) {
      return;
    }
    // The field must be final and has only one variable.
    VariableDeclarationList fieldList = fieldDeclaration.fields;
    if (!fieldList.isFinal || fieldList.variables.length != 1) {
      return;
    }
    VariableDeclaration field = fieldList.variables.first;
    // Prepare the initializer.
    Expression initializer = field.initializer;
    if (initializer == null) {
      return;
    }
    // Add proposal.
    String code = '';
    if (fieldList.type != null) {
      code += _getNodeText(fieldList.type) + ' ';
    }
    code += 'get';
    code += ' ' + _getNodeText(field.name);
    code += ' => ' + _getNodeText(initializer);
    code += ';';
    _addReplaceEdit(rangeStartEnd(fieldList.keyword, fieldDeclaration), code);
    _addAssist(DartAssistKind.CONVERT_INTO_GETTER, []);
  }

  void _addProposal_convertToBlockFunctionBody() {
    FunctionBody body = getEnclosingFunctionBody();
    // prepare expression body
    if (body is! ExpressionFunctionBody || body.isGenerator) {
      _coverageMarker();
      return;
    }
    Expression returnValue = (body as ExpressionFunctionBody).expression;
    DartType returnValueType = returnValue.staticType;
    String returnValueCode = _getNodeText(returnValue);
    // prepare prefix
    String prefix = utils.getNodePrefix(body.parent);
    String indent = utils.getIndent(1);
    // add change
    SourceBuilder sb = new SourceBuilder(file, body.offset);
    if (body.isAsynchronous) {
      sb.append('async ');
    }
    sb.append('{$eol$prefix$indent');
    if (!returnValueType.isVoid) {
      sb.append('return ');
    }
    sb.append(returnValueCode);
    sb.append(';');
    sb.setExitOffset();
    sb.append('$eol$prefix}');
    _insertBuilder(sb, body.length);
    // add proposal
    _addAssist(DartAssistKind.CONVERT_INTO_BLOCK_BODY, []);
  }

  void _addProposal_convertToExpressionFunctionBody() {
    // prepare current body
    FunctionBody body = getEnclosingFunctionBody();
    if (body is! BlockFunctionBody || body.isGenerator) {
      _coverageMarker();
      return;
    }
    // prepare return statement
    List<Statement> statements = (body as BlockFunctionBody).block.statements;
    if (statements.length != 1) {
      _coverageMarker();
      return;
    }
    Statement onlyStatement = statements.first;
    // prepare returned expression
    Expression returnExpression;
    if (onlyStatement is ReturnStatement) {
      returnExpression = onlyStatement.expression;
    } else if (onlyStatement is ExpressionStatement) {
      returnExpression = onlyStatement.expression;
    }
    if (returnExpression == null) {
      _coverageMarker();
      return;
    }
    // add change
    SourceBuilder sb = new SourceBuilder(file, body.offset);
    if (body.isAsynchronous) {
      sb.append('async ');
    }
    sb.append('=> ');
    sb.append(_getNodeText(returnExpression));
    if (body.parent is! FunctionExpression ||
        body.parent.parent is FunctionDeclaration) {
      sb.append(';');
    }
    _insertBuilder(sb, body.length);
    // add proposal
    _addAssist(DartAssistKind.CONVERT_INTO_EXPRESSION_BODY, []);
  }

  void _addProposal_convertToFieldParameter() {
    if (node == null) {
      return;
    }
    // prepare ConstructorDeclaration
    ConstructorDeclaration constructor =
        node.getAncestor((node) => node is ConstructorDeclaration);
    if (constructor == null) {
      return;
    }
    FormalParameterList parameterList = constructor.parameters;
    List<ConstructorInitializer> initializers = constructor.initializers;
    // prepare parameter
    SimpleFormalParameter parameter;
    if (node.parent is SimpleFormalParameter &&
        node.parent.parent is FormalParameterList &&
        node.parent.parent.parent is ConstructorDeclaration) {
      parameter = node.parent;
    }
    if (node is SimpleIdentifier &&
        node.parent is ConstructorFieldInitializer) {
      String name = (node as SimpleIdentifier).name;
      ConstructorFieldInitializer initializer = node.parent;
      if (initializer.expression == node) {
        for (FormalParameter formalParameter in parameterList.parameters) {
          if (formalParameter is SimpleFormalParameter &&
              formalParameter.identifier.name == name) {
            parameter = formalParameter;
          }
        }
      }
    }
    // analyze parameter
    if (parameter != null) {
      String parameterName = parameter.identifier.name;
      ParameterElement parameterElement = parameter.element;
      // check number of references
      {
        int numOfReferences = 0;
        AstVisitor visitor =
            new _SimpleIdentifierRecursiveAstVisitor((SimpleIdentifier node) {
          if (node.staticElement == parameterElement) {
            numOfReferences++;
          }
        });
        for (ConstructorInitializer initializer in initializers) {
          initializer.accept(visitor);
        }
        if (numOfReferences != 1) {
          return;
        }
      }
      // find the field initializer
      ConstructorFieldInitializer parameterInitializer;
      for (ConstructorInitializer initializer in initializers) {
        if (initializer is ConstructorFieldInitializer) {
          Expression expression = initializer.expression;
          if (expression is SimpleIdentifier &&
              expression.name == parameterName) {
            parameterInitializer = initializer;
          }
        }
      }
      if (parameterInitializer == null) {
        return;
      }
      String fieldName = parameterInitializer.fieldName.name;
      // replace parameter
      _addReplaceEdit(rangeNode(parameter), 'this.$fieldName');
      // remove initializer
      int initializerIndex = initializers.indexOf(parameterInitializer);
      if (initializers.length == 1) {
        _addRemoveEdit(rangeEndEnd(parameterList, parameterInitializer));
      } else {
        if (initializerIndex == 0) {
          ConstructorInitializer next = initializers[initializerIndex + 1];
          _addRemoveEdit(rangeStartStart(parameterInitializer, next));
        } else {
          ConstructorInitializer prev = initializers[initializerIndex - 1];
          _addRemoveEdit(rangeEndEnd(prev, parameterInitializer));
        }
      }
      // add proposal
      _addAssist(DartAssistKind.CONVERT_TO_FIELD_PARAMETER, []);
    }
  }

  void _addProposal_convertToForIndexLoop() {
    // find enclosing ForEachStatement
    ForEachStatement forEachStatement =
        node.getAncestor((n) => n is ForEachStatement);
    if (forEachStatement == null) {
      _coverageMarker();
      return;
    }
    if (selectionOffset < forEachStatement.offset ||
        forEachStatement.rightParenthesis.end < selectionOffset) {
      _coverageMarker();
      return;
    }
    // loop should declare variable
    DeclaredIdentifier loopVariable = forEachStatement.loopVariable;
    if (loopVariable == null) {
      _coverageMarker();
      return;
    }
    // iterable should be VariableElement
    String listName;
    Expression iterable = forEachStatement.iterable;
    if (iterable is SimpleIdentifier &&
        iterable.staticElement is VariableElement) {
      listName = iterable.name;
    } else {
      _coverageMarker();
      return;
    }
    // iterable should be List
    {
      DartType iterableType = iterable.bestType;
      InterfaceType listType = analysisContext.typeProvider.listType;
      if (iterableType is! InterfaceType ||
          iterableType.element != listType.element) {
        _coverageMarker();
        return;
      }
    }
    // body should be Block
    if (forEachStatement.body is! Block) {
      _coverageMarker();
      return;
    }
    Block body = forEachStatement.body;
    // prepare a name for the index variable
    String indexName;
    {
      Set<String> conflicts =
          utils.findPossibleLocalVariableConflicts(forEachStatement.offset);
      if (!conflicts.contains('i')) {
        indexName = 'i';
      } else if (!conflicts.contains('j')) {
        indexName = 'j';
      } else if (!conflicts.contains('k')) {
        indexName = 'k';
      } else {
        _coverageMarker();
        return;
      }
    }
    // prepare environment
    String prefix = utils.getNodePrefix(forEachStatement);
    String indent = utils.getIndent(1);
    int firstBlockLine = utils.getLineContentEnd(body.leftBracket.end);
    // add change
    _addReplaceEdit(
        rangeStartEnd(forEachStatement, forEachStatement.rightParenthesis),
        'for (int $indexName = 0; $indexName < $listName.length; $indexName++)');
    _addInsertEdit(firstBlockLine,
        '$prefix$indent$loopVariable = $listName[$indexName];$eol');
    // add proposal
    _addAssist(DartAssistKind.CONVERT_INTO_FOR_INDEX, []);
  }

  void _addProposal_convertToIsNot_onIs() {
    // may be child of "is"
    AstNode node = this.node;
    while (node != null && node is! IsExpression) {
      node = node.parent;
    }
    // prepare "is"
    if (node is! IsExpression) {
      _coverageMarker();
      return;
    }
    IsExpression isExpression = node as IsExpression;
    if (isExpression.notOperator != null) {
      _coverageMarker();
      return;
    }
    // prepare enclosing ()
    AstNode parent = isExpression.parent;
    if (parent is! ParenthesizedExpression) {
      _coverageMarker();
      return;
    }
    ParenthesizedExpression parExpression = parent as ParenthesizedExpression;
    // prepare enclosing !()
    AstNode parent2 = parent.parent;
    if (parent2 is! PrefixExpression) {
      _coverageMarker();
      return;
    }
    PrefixExpression prefExpression = parent2 as PrefixExpression;
    if (prefExpression.operator.type != TokenType.BANG) {
      _coverageMarker();
      return;
    }
    // strip !()
    if (getExpressionParentPrecedence(prefExpression) >=
        TokenType.IS.precedence) {
      _addRemoveEdit(rangeToken(prefExpression.operator));
    } else {
      _addRemoveEdit(
          rangeStartEnd(prefExpression, parExpression.leftParenthesis));
      _addRemoveEdit(
          rangeStartEnd(parExpression.rightParenthesis, prefExpression));
    }
    _addInsertEdit(isExpression.isOperator.end, '!');
    // add proposal
    _addAssist(DartAssistKind.CONVERT_INTO_IS_NOT, []);
  }

  void _addProposal_convertToIsNot_onNot() {
    // may be () in prefix expression
    if (node is ParenthesizedExpression && node.parent is PrefixExpression) {
      node = node.parent;
    }
    // prepare !()
    if (node is! PrefixExpression) {
      _coverageMarker();
      return;
    }
    PrefixExpression prefExpression = node as PrefixExpression;
    // should be ! operator
    if (prefExpression.operator.type != TokenType.BANG) {
      _coverageMarker();
      return;
    }
    // prepare !()
    Expression operand = prefExpression.operand;
    if (operand is! ParenthesizedExpression) {
      _coverageMarker();
      return;
    }
    ParenthesizedExpression parExpression = operand as ParenthesizedExpression;
    operand = parExpression.expression;
    // prepare "is"
    if (operand is! IsExpression) {
      _coverageMarker();
      return;
    }
    IsExpression isExpression = operand as IsExpression;
    if (isExpression.notOperator != null) {
      _coverageMarker();
      return;
    }
    // strip !()
    if (getExpressionParentPrecedence(prefExpression) >=
        TokenType.IS.precedence) {
      _addRemoveEdit(rangeToken(prefExpression.operator));
    } else {
      _addRemoveEdit(
          rangeStartEnd(prefExpression, parExpression.leftParenthesis));
      _addRemoveEdit(
          rangeStartEnd(parExpression.rightParenthesis, prefExpression));
    }
    _addInsertEdit(isExpression.isOperator.end, '!');
    // add proposal
    _addAssist(DartAssistKind.CONVERT_INTO_IS_NOT, []);
  }

  /**
   * Converts "!isEmpty" -> "isNotEmpty" if possible.
   */
  void _addProposal_convertToIsNotEmpty() {
    // prepare "expr.isEmpty"
    AstNode isEmptyAccess = null;
    SimpleIdentifier isEmptyIdentifier = null;
    if (node is SimpleIdentifier) {
      SimpleIdentifier identifier = node as SimpleIdentifier;
      AstNode parent = identifier.parent;
      // normal case (but rare)
      if (parent is PropertyAccess) {
        isEmptyIdentifier = parent.propertyName;
        isEmptyAccess = parent;
      }
      // usual case
      if (parent is PrefixedIdentifier) {
        isEmptyIdentifier = parent.identifier;
        isEmptyAccess = parent;
      }
    }
    if (isEmptyIdentifier == null) {
      _coverageMarker();
      return;
    }
    // should be "isEmpty"
    Element propertyElement = isEmptyIdentifier.bestElement;
    if (propertyElement == null || 'isEmpty' != propertyElement.name) {
      _coverageMarker();
      return;
    }
    // should have "isNotEmpty"
    Element propertyTarget = propertyElement.enclosingElement;
    if (propertyTarget == null ||
        getChildren(propertyTarget, 'isNotEmpty').isEmpty) {
      _coverageMarker();
      return;
    }
    // should be in PrefixExpression
    if (isEmptyAccess.parent is! PrefixExpression) {
      _coverageMarker();
      return;
    }
    PrefixExpression prefixExpression =
        isEmptyAccess.parent as PrefixExpression;
    // should be !
    if (prefixExpression.operator.type != TokenType.BANG) {
      _coverageMarker();
      return;
    }
    // do replace
    _addRemoveEdit(rangeStartStart(prefixExpression, prefixExpression.operand));
    _addReplaceEdit(rangeNode(isEmptyIdentifier), 'isNotEmpty');
    // add proposal
    _addAssist(DartAssistKind.CONVERT_INTO_IS_NOT_EMPTY, []);
  }

  void _addProposal_convertToNormalParameter() {
    if (node is SimpleIdentifier &&
        node.parent is FieldFormalParameter &&
        node.parent.parent is FormalParameterList &&
        node.parent.parent.parent is ConstructorDeclaration) {
      ConstructorDeclaration constructor = node.parent.parent.parent;
      FormalParameterList parameterList = node.parent.parent;
      FieldFormalParameter parameter = node.parent;
      ParameterElement parameterElement = parameter.element;
      String name = (node as SimpleIdentifier).name;
      // prepare type
      DartType type = parameterElement.type;
      Set<Source> librariesToImport = new Set<Source>();
      String typeCode = utils.getTypeSource(type, librariesToImport);
      // replace parameter
      if (type.isDynamic) {
        _addReplaceEdit(rangeNode(parameter), name);
      } else {
        _addReplaceEdit(rangeNode(parameter), '$typeCode $name');
      }
      // add field initializer
      List<ConstructorInitializer> initializers = constructor.initializers;
      if (initializers.isEmpty) {
        _addInsertEdit(parameterList.end, ' : $name = $name');
      } else {
        _addInsertEdit(initializers.last.end, ', $name = $name');
      }
      // add proposal
      _addAssist(DartAssistKind.CONVERT_TO_NORMAL_PARAMETER, []);
    }
  }

  void _addProposal_encapsulateField() {
    // find FieldDeclaration
    FieldDeclaration fieldDeclaration =
        node.getAncestor((x) => x is FieldDeclaration);
    if (fieldDeclaration == null) {
      _coverageMarker();
      return;
    }
    // not interesting for static
    if (fieldDeclaration.isStatic) {
      _coverageMarker();
      return;
    }
    // has a parse error
    VariableDeclarationList variableList = fieldDeclaration.fields;
    if (variableList.keyword == null && variableList.type == null) {
      _coverageMarker();
      return;
    }
    // not interesting for final
    if (variableList.isFinal) {
      _coverageMarker();
      return;
    }
    // should have exactly one field
    List<VariableDeclaration> fields = variableList.variables;
    if (fields.length != 1) {
      _coverageMarker();
      return;
    }
    VariableDeclaration field = fields.first;
    SimpleIdentifier nameNode = field.name;
    FieldElement fieldElement = nameNode.staticElement;
    // should have a public name
    String name = nameNode.name;
    if (Identifier.isPrivateName(name)) {
      _coverageMarker();
      return;
    }
    // should be on the name
    if (nameNode != node) {
      _coverageMarker();
      return;
    }
    // rename field
    _addReplaceEdit(rangeNode(nameNode), '_$name');
    // update references in constructors
    ClassDeclaration classDeclaration = fieldDeclaration.parent;
    for (ClassMember member in classDeclaration.members) {
      if (member is ConstructorDeclaration) {
        for (FormalParameter parameter in member.parameters.parameters) {
          ParameterElement parameterElement = parameter.element;
          if (parameterElement is FieldFormalParameterElement &&
              parameterElement.field == fieldElement) {
            _addReplaceEdit(rangeNode(parameter.identifier), '_$name');
          }
        }
      }
    }
    // add accessors
    String eol2 = eol + eol;
    String typeNameCode =
        variableList.type != null ? _getNodeText(variableList.type) + ' ' : '';
    String getterCode = '$eol2  ${typeNameCode}get $name => _$name;';
    String setterCode = '$eol2'
        '  void set $name($typeNameCode$name) {$eol'
        '    _$name = $name;$eol'
        '  }';
    _addInsertEdit(fieldDeclaration.end, getterCode + setterCode);
    // add proposal
    _addAssist(DartAssistKind.ENCAPSULATE_FIELD, []);
  }

  void _addProposal_exchangeOperands() {
    // check that user invokes quick assist on binary expression
    if (node is! BinaryExpression) {
      _coverageMarker();
      return;
    }
    BinaryExpression binaryExpression = node as BinaryExpression;
    // prepare operator position
    if (!_isOperatorSelected(
        binaryExpression, selectionOffset, selectionLength)) {
      _coverageMarker();
      return;
    }
    // add edits
    {
      Expression leftOperand = binaryExpression.leftOperand;
      Expression rightOperand = binaryExpression.rightOperand;
      // find "wide" enclosing binary expression with same operator
      while (binaryExpression.parent is BinaryExpression) {
        BinaryExpression newBinaryExpression =
            binaryExpression.parent as BinaryExpression;
        if (newBinaryExpression.operator.type !=
            binaryExpression.operator.type) {
          _coverageMarker();
          break;
        }
        binaryExpression = newBinaryExpression;
      }
      // exchange parts of "wide" expression parts
      SourceRange leftRange = rangeStartEnd(binaryExpression, leftOperand);
      SourceRange rightRange = rangeStartEnd(rightOperand, binaryExpression);
      _addReplaceEdit(leftRange, _getRangeText(rightRange));
      _addReplaceEdit(rightRange, _getRangeText(leftRange));
      // maybe replace the operator
      {
        Token operator = binaryExpression.operator;
        // prepare a new operator
        String newOperator = null;
        TokenType operatorType = operator.type;
        if (operatorType == TokenType.LT) {
          newOperator = '>';
        } else if (operatorType == TokenType.LT_EQ) {
          newOperator = '>=';
        } else if (operatorType == TokenType.GT) {
          newOperator = '<';
        } else if (operatorType == TokenType.GT_EQ) {
          newOperator = '<=';
        }
        // replace the operator
        if (newOperator != null) {
          _addReplaceEdit(rangeToken(operator), newOperator);
        }
      }
    }
    // add proposal
    _addAssist(DartAssistKind.EXCHANGE_OPERANDS, []);
  }

  void _addProposal_importAddShow() {
    // prepare ImportDirective
    ImportDirective importDirective =
        node.getAncestor((node) => node is ImportDirective);
    if (importDirective == null) {
      _coverageMarker();
      return;
    }
    // there should be no existing combinators
    if (importDirective.combinators.isNotEmpty) {
      _coverageMarker();
      return;
    }
    // prepare whole import namespace
    ImportElement importElement = importDirective.element;
    if (importElement == null) {
      _coverageMarker();
      return;
    }
    Map<String, Element> namespace = getImportNamespace(importElement);
    // prepare names of referenced elements (from this import)
    SplayTreeSet<String> referencedNames = new SplayTreeSet<String>();
    _SimpleIdentifierRecursiveAstVisitor visitor =
        new _SimpleIdentifierRecursiveAstVisitor((SimpleIdentifier node) {
      Element element = node.staticElement;
      if (element != null && namespace[node.name] == element) {
        referencedNames.add(element.displayName);
      }
    });
    unit.accept(visitor);
    // ignore if unused
    if (referencedNames.isEmpty) {
      _coverageMarker();
      return;
    }
    // prepare change
    String showCombinator = ' show ${referencedNames.join(', ')}';
    _addInsertEdit(importDirective.end - 1, showCombinator);
    // add proposal
    _addAssist(DartAssistKind.IMPORT_ADD_SHOW, []);
  }

  void _addProposal_introduceLocalTestedType() {
    AstNode node = this.node;
    if (node is IfStatement) {
      node = (node as IfStatement).condition;
    } else if (node is WhileStatement) {
      node = (node as WhileStatement).condition;
    }
    // prepare IsExpression
    if (node is! IsExpression) {
      _coverageMarker();
      return;
    }
    IsExpression isExpression = node;
    DartType castType = isExpression.type.type;
    String castTypeCode = _getNodeText(isExpression.type);
    // prepare environment
    String indent = utils.getIndent(1);
    String prefix;
    Block targetBlock;
    {
      Statement statement = node.getAncestor((n) => n is Statement);
      if (statement is IfStatement && statement.thenStatement is Block) {
        targetBlock = statement.thenStatement;
      } else if (statement is WhileStatement && statement.body is Block) {
        targetBlock = statement.body;
      } else {
        _coverageMarker();
        return;
      }
      prefix = utils.getNodePrefix(statement);
    }
    // prepare location
    int offset;
    String statementPrefix;
    if (isExpression.notOperator == null) {
      offset = targetBlock.leftBracket.end;
      statementPrefix = indent;
    } else {
      offset = targetBlock.rightBracket.end;
      statementPrefix = '';
    }
    // prepare source
    SourceBuilder builder = new SourceBuilder(file, offset);
    builder.append(eol + prefix + statementPrefix);
    builder.append(castTypeCode);
    // prepare excluded names
    Set<String> excluded = new Set<String>();
    {
      ScopedNameFinder scopedNameFinder = new ScopedNameFinder(offset);
      isExpression.accept(scopedNameFinder);
      excluded.addAll(scopedNameFinder.locals.keys.toSet());
    }
    // name(s)
    {
      List<String> suggestions =
          getVariableNameSuggestionsForExpression(castType, null, excluded);
      builder.append(' ');
      builder.startPosition('NAME');
      for (int i = 0; i < suggestions.length; i++) {
        String name = suggestions[i];
        if (i == 0) {
          builder.append(name);
        }
        builder.addSuggestion(LinkedEditSuggestionKind.VARIABLE, name);
      }
      builder.endPosition();
    }
    builder.append(' = ');
    builder.append(_getNodeText(isExpression.expression));
    builder.append(';');
    builder.setExitOffset();
    // add proposal
    _insertBuilder(builder);
    _addAssist(DartAssistKind.INTRODUCE_LOCAL_CAST_TYPE, []);
  }

  void _addProposal_invertIf() {
    if (node is! IfStatement) {
      return;
    }
    IfStatement ifStatement = node as IfStatement;
    Expression condition = ifStatement.condition;
    // should have both "then" and "else"
    Statement thenStatement = ifStatement.thenStatement;
    Statement elseStatement = ifStatement.elseStatement;
    if (thenStatement == null || elseStatement == null) {
      return;
    }
    // prepare source
    String invertedCondition = utils.invertCondition(condition);
    String thenSource = _getNodeText(thenStatement);
    String elseSource = _getNodeText(elseStatement);
    // do replacements
    _addReplaceEdit(rangeNode(condition), invertedCondition);
    _addReplaceEdit(rangeNode(thenStatement), elseSource);
    _addReplaceEdit(rangeNode(elseStatement), thenSource);
    // add proposal
    _addAssist(DartAssistKind.INVERT_IF_STATEMENT, []);
  }

  void _addProposal_joinIfStatementInner() {
    // climb up condition to the (supposedly) "if" statement
    AstNode node = this.node;
    while (node is Expression) {
      node = node.parent;
    }
    // prepare target "if" statement
    if (node is! IfStatement) {
      _coverageMarker();
      return;
    }
    IfStatement targetIfStatement = node as IfStatement;
    if (targetIfStatement.elseStatement != null) {
      _coverageMarker();
      return;
    }
    // prepare inner "if" statement
    Statement targetThenStatement = targetIfStatement.thenStatement;
    Statement innerStatement = getSingleStatement(targetThenStatement);
    if (innerStatement is! IfStatement) {
      _coverageMarker();
      return;
    }
    IfStatement innerIfStatement = innerStatement as IfStatement;
    if (innerIfStatement.elseStatement != null) {
      _coverageMarker();
      return;
    }
    // prepare environment
    String prefix = utils.getNodePrefix(targetIfStatement);
    // merge conditions
    String condition;
    {
      Expression targetCondition = targetIfStatement.condition;
      Expression innerCondition = innerIfStatement.condition;
      String targetConditionSource = _getNodeText(targetCondition);
      String innerConditionSource = _getNodeText(innerCondition);
      if (_shouldWrapParenthesisBeforeAnd(targetCondition)) {
        targetConditionSource = '($targetConditionSource)';
      }
      if (_shouldWrapParenthesisBeforeAnd(innerCondition)) {
        innerConditionSource = '($innerConditionSource)';
      }
      condition = '$targetConditionSource && $innerConditionSource';
    }
    // replace target "if" statement
    {
      Statement innerThenStatement = innerIfStatement.thenStatement;
      List<Statement> innerThenStatements = getStatements(innerThenStatement);
      SourceRange lineRanges =
          utils.getLinesRangeStatements(innerThenStatements);
      String oldSource = utils.getRangeText(lineRanges);
      String newSource = utils.indentSourceLeftRight(oldSource, false);
      _addReplaceEdit(rangeNode(targetIfStatement),
          'if ($condition) {$eol$newSource$prefix}');
    }
    // done
    _addAssist(DartAssistKind.JOIN_IF_WITH_INNER, []);
  }

  void _addProposal_joinIfStatementOuter() {
    // climb up condition to the (supposedly) "if" statement
    AstNode node = this.node;
    while (node is Expression) {
      node = node.parent;
    }
    // prepare target "if" statement
    if (node is! IfStatement) {
      _coverageMarker();
      return;
    }
    IfStatement targetIfStatement = node as IfStatement;
    if (targetIfStatement.elseStatement != null) {
      _coverageMarker();
      return;
    }
    // prepare outer "if" statement
    AstNode parent = targetIfStatement.parent;
    if (parent is Block) {
      if ((parent as Block).statements.length != 1) {
        _coverageMarker();
        return;
      }
      parent = parent.parent;
    }
    if (parent is! IfStatement) {
      _coverageMarker();
      return;
    }
    IfStatement outerIfStatement = parent as IfStatement;
    if (outerIfStatement.elseStatement != null) {
      _coverageMarker();
      return;
    }
    // prepare environment
    String prefix = utils.getNodePrefix(outerIfStatement);
    // merge conditions
    String condition;
    {
      Expression targetCondition = targetIfStatement.condition;
      Expression outerCondition = outerIfStatement.condition;
      String targetConditionSource = _getNodeText(targetCondition);
      String outerConditionSource = _getNodeText(outerCondition);
      if (_shouldWrapParenthesisBeforeAnd(targetCondition)) {
        targetConditionSource = '($targetConditionSource)';
      }
      if (_shouldWrapParenthesisBeforeAnd(outerCondition)) {
        outerConditionSource = '($outerConditionSource)';
      }
      condition = '$outerConditionSource && $targetConditionSource';
    }
    // replace outer "if" statement
    {
      Statement targetThenStatement = targetIfStatement.thenStatement;
      List<Statement> targetThenStatements = getStatements(targetThenStatement);
      SourceRange lineRanges =
          utils.getLinesRangeStatements(targetThenStatements);
      String oldSource = utils.getRangeText(lineRanges);
      String newSource = utils.indentSourceLeftRight(oldSource, false);
      _addReplaceEdit(rangeNode(outerIfStatement),
          'if ($condition) {$eol$newSource$prefix}');
    }
    // done
    _addAssist(DartAssistKind.JOIN_IF_WITH_OUTER, []);
  }

  void _addProposal_joinVariableDeclaration_onAssignment() {
    // check that node is LHS in assignment
    if (node is SimpleIdentifier &&
        node.parent is AssignmentExpression &&
        (node.parent as AssignmentExpression).leftHandSide == node &&
        node.parent.parent is ExpressionStatement) {} else {
      _coverageMarker();
      return;
    }
    AssignmentExpression assignExpression = node.parent as AssignmentExpression;
    // check that binary expression is assignment
    if (assignExpression.operator.type != TokenType.EQ) {
      _coverageMarker();
      return;
    }
    // prepare "declaration" statement
    Element element = (node as SimpleIdentifier).staticElement;
    if (element == null) {
      _coverageMarker();
      return;
    }
    int declOffset = element.nameOffset;
    AstNode declNode = new NodeLocator(declOffset).searchWithin(unit);
    if (declNode != null &&
        declNode.parent is VariableDeclaration &&
        (declNode.parent as VariableDeclaration).name == declNode &&
        declNode.parent.parent is VariableDeclarationList &&
        declNode.parent.parent.parent is VariableDeclarationStatement) {} else {
      _coverageMarker();
      return;
    }
    VariableDeclaration decl = declNode.parent as VariableDeclaration;
    VariableDeclarationStatement declStatement =
        decl.parent.parent as VariableDeclarationStatement;
    // may be has initializer
    if (decl.initializer != null) {
      _coverageMarker();
      return;
    }
    // check that "declaration" statement declared only one variable
    if (declStatement.variables.variables.length != 1) {
      _coverageMarker();
      return;
    }
    // check that the "declaration" and "assignment" statements are
    // parts of the same Block
    ExpressionStatement assignStatement =
        node.parent.parent as ExpressionStatement;
    if (assignStatement.parent is Block &&
        assignStatement.parent == declStatement.parent) {} else {
      _coverageMarker();
      return;
    }
    Block block = assignStatement.parent as Block;
    // check that "declaration" and "assignment" statements are adjacent
    List<Statement> statements = block.statements;
    if (statements.indexOf(assignStatement) ==
        statements.indexOf(declStatement) + 1) {} else {
      _coverageMarker();
      return;
    }
    // add edits
    {
      int assignOffset = assignExpression.operator.offset;
      _addReplaceEdit(rangeEndStart(declNode, assignOffset), ' ');
    }
    // add proposal
    _addAssist(DartAssistKind.JOIN_VARIABLE_DECLARATION, []);
  }

  void _addProposal_joinVariableDeclaration_onDeclaration() {
    // prepare enclosing VariableDeclarationList
    VariableDeclarationList declList =
        node.getAncestor((node) => node is VariableDeclarationList);
    if (declList != null && declList.variables.length == 1) {} else {
      _coverageMarker();
      return;
    }
    VariableDeclaration decl = declList.variables[0];
    // already initialized
    if (decl.initializer != null) {
      _coverageMarker();
      return;
    }
    // prepare VariableDeclarationStatement in Block
    if (declList.parent is VariableDeclarationStatement &&
        declList.parent.parent is Block) {} else {
      _coverageMarker();
      return;
    }
    VariableDeclarationStatement declStatement =
        declList.parent as VariableDeclarationStatement;
    Block block = declStatement.parent as Block;
    List<Statement> statements = block.statements;
    // prepare assignment
    AssignmentExpression assignExpression;
    {
      // declaration should not be last Statement
      int declIndex = statements.indexOf(declStatement);
      if (declIndex < statements.length - 1) {} else {
        _coverageMarker();
        return;
      }
      // next Statement should be assignment
      Statement assignStatement = statements[declIndex + 1];
      if (assignStatement is ExpressionStatement) {} else {
        _coverageMarker();
        return;
      }
      ExpressionStatement expressionStatement =
          assignStatement as ExpressionStatement;
      // expression should be assignment
      if (expressionStatement.expression is AssignmentExpression) {} else {
        _coverageMarker();
        return;
      }
      assignExpression = expressionStatement.expression as AssignmentExpression;
    }
    // check that pure assignment
    if (assignExpression.operator.type != TokenType.EQ) {
      _coverageMarker();
      return;
    }
    // add edits
    {
      int assignOffset = assignExpression.operator.offset;
      _addReplaceEdit(rangeEndStart(decl.name, assignOffset), ' ');
    }
    // add proposal
    _addAssist(DartAssistKind.JOIN_VARIABLE_DECLARATION, []);
  }

  void _addProposal_removeTypeAnnotation() {
    VariableDeclarationList declarationList =
        node.getAncestor((n) => n is VariableDeclarationList);
    if (declarationList == null) {
      _coverageMarker();
      return;
    }
    // we need a type
    TypeName typeNode = declarationList.type;
    if (typeNode == null) {
      _coverageMarker();
      return;
    }
    // ignore if an incomplete variable declaration
    if (declarationList.variables.length == 1 &&
        declarationList.variables[0].name.isSynthetic) {
      _coverageMarker();
      return;
    }
    // must be not after the name of the variable
    VariableDeclaration firstVariable = declarationList.variables[0];
    if (selectionOffset > firstVariable.name.end) {
      _coverageMarker();
      return;
    }
    // add edit
    Token keyword = declarationList.keyword;
    SourceRange typeRange = rangeStartStart(typeNode, firstVariable);
    if (keyword != null && keyword.lexeme != 'var') {
      _addReplaceEdit(typeRange, '');
    } else {
      _addReplaceEdit(typeRange, 'var ');
    }
    // add proposal
    _addAssist(DartAssistKind.REMOVE_TYPE_ANNOTATION, []);
  }

  void _addProposal_replaceConditionalWithIfElse() {
    ConditionalExpression conditional = null;
    // may be on Statement with Conditional
    Statement statement = node.getAncestor((node) => node is Statement);
    if (statement == null) {
      _coverageMarker();
      return;
    }
    // variable declaration
    bool inVariable = false;
    if (statement is VariableDeclarationStatement) {
      VariableDeclarationStatement variableStatement = statement;
      for (VariableDeclaration variable
          in variableStatement.variables.variables) {
        if (variable.initializer is ConditionalExpression) {
          conditional = variable.initializer as ConditionalExpression;
          inVariable = true;
          break;
        }
      }
    }
    // assignment
    bool inAssignment = false;
    if (statement is ExpressionStatement) {
      ExpressionStatement exprStmt = statement;
      if (exprStmt.expression is AssignmentExpression) {
        AssignmentExpression assignment =
            exprStmt.expression as AssignmentExpression;
        if (assignment.operator.type == TokenType.EQ &&
            assignment.rightHandSide is ConditionalExpression) {
          conditional = assignment.rightHandSide as ConditionalExpression;
          inAssignment = true;
        }
      }
    }
    // return
    bool inReturn = false;
    if (statement is ReturnStatement) {
      ReturnStatement returnStatement = statement;
      if (returnStatement.expression is ConditionalExpression) {
        conditional = returnStatement.expression as ConditionalExpression;
        inReturn = true;
      }
    }
    // prepare environment
    String indent = utils.getIndent(1);
    String prefix = utils.getNodePrefix(statement);
    // Type v = Conditional;
    if (inVariable) {
      VariableDeclaration variable = conditional.parent as VariableDeclaration;
      _addRemoveEdit(rangeEndEnd(variable.name, conditional));
      String conditionSrc = _getNodeText(conditional.condition);
      String thenSrc = _getNodeText(conditional.thenExpression);
      String elseSrc = _getNodeText(conditional.elseExpression);
      String name = variable.name.name;
      String src = eol;
      src += prefix + 'if ($conditionSrc) {' + eol;
      src += prefix + indent + '$name = $thenSrc;' + eol;
      src += prefix + '} else {' + eol;
      src += prefix + indent + '$name = $elseSrc;' + eol;
      src += prefix + '}';
      _addReplaceEdit(rangeEndLength(statement, 0), src);
    }
    // v = Conditional;
    if (inAssignment) {
      AssignmentExpression assignment =
          conditional.parent as AssignmentExpression;
      Expression leftSide = assignment.leftHandSide;
      String conditionSrc = _getNodeText(conditional.condition);
      String thenSrc = _getNodeText(conditional.thenExpression);
      String elseSrc = _getNodeText(conditional.elseExpression);
      String name = _getNodeText(leftSide);
      String src = '';
      src += 'if ($conditionSrc) {' + eol;
      src += prefix + indent + '$name = $thenSrc;' + eol;
      src += prefix + '} else {' + eol;
      src += prefix + indent + '$name = $elseSrc;' + eol;
      src += prefix + '}';
      _addReplaceEdit(rangeNode(statement), src);
    }
    // return Conditional;
    if (inReturn) {
      String conditionSrc = _getNodeText(conditional.condition);
      String thenSrc = _getNodeText(conditional.thenExpression);
      String elseSrc = _getNodeText(conditional.elseExpression);
      String src = '';
      src += 'if ($conditionSrc) {' + eol;
      src += prefix + indent + 'return $thenSrc;' + eol;
      src += prefix + '} else {' + eol;
      src += prefix + indent + 'return $elseSrc;' + eol;
      src += prefix + '}';
      _addReplaceEdit(rangeNode(statement), src);
    }
    // add proposal
    _addAssist(DartAssistKind.REPLACE_CONDITIONAL_WITH_IF_ELSE, []);
  }

  void _addProposal_replaceIfElseWithConditional() {
    // should be "if"
    if (node is! IfStatement) {
      _coverageMarker();
      return;
    }
    IfStatement ifStatement = node as IfStatement;
    // single then/else statements
    Statement thenStatement = getSingleStatement(ifStatement.thenStatement);
    Statement elseStatement = getSingleStatement(ifStatement.elseStatement);
    if (thenStatement == null || elseStatement == null) {
      _coverageMarker();
      return;
    }
    // returns
    if (thenStatement is ReturnStatement && elseStatement is ReturnStatement) {
      String conditionSrc = _getNodeText(ifStatement.condition);
      String theSrc = _getNodeText(thenStatement.expression);
      String elseSrc = _getNodeText(elseStatement.expression);
      _addReplaceEdit(
          rangeNode(ifStatement), 'return $conditionSrc ? $theSrc : $elseSrc;');
    }
    // assignments -> v = Conditional;
    if (thenStatement is ExpressionStatement &&
        elseStatement is ExpressionStatement) {
      Expression thenExpression = thenStatement.expression;
      Expression elseExpression = elseStatement.expression;
      if (thenExpression is AssignmentExpression &&
          elseExpression is AssignmentExpression) {
        AssignmentExpression thenAssignment = thenExpression;
        AssignmentExpression elseAssignment = elseExpression;
        String thenTarget = _getNodeText(thenAssignment.leftHandSide);
        String elseTarget = _getNodeText(elseAssignment.leftHandSide);
        if (thenAssignment.operator.type == TokenType.EQ &&
            elseAssignment.operator.type == TokenType.EQ &&
            thenTarget == elseTarget) {
          String conditionSrc = _getNodeText(ifStatement.condition);
          String theSrc = _getNodeText(thenAssignment.rightHandSide);
          String elseSrc = _getNodeText(elseAssignment.rightHandSide);
          _addReplaceEdit(rangeNode(ifStatement),
              '$thenTarget = $conditionSrc ? $theSrc : $elseSrc;');
        }
      }
    }
    // add proposal
    _addAssist(DartAssistKind.REPLACE_IF_ELSE_WITH_CONDITIONAL, []);
  }

  void _addProposal_splitAndCondition() {
    // check that user invokes quick assist on binary expression
    if (node is! BinaryExpression) {
      _coverageMarker();
      return;
    }
    BinaryExpression binaryExpression = node as BinaryExpression;
    // prepare operator position
    if (!_isOperatorSelected(
        binaryExpression, selectionOffset, selectionLength)) {
      _coverageMarker();
      return;
    }
    // should be &&
    if (binaryExpression.operator.type != TokenType.AMPERSAND_AMPERSAND) {
      _coverageMarker();
      return;
    }
    // prepare "if"
    Statement statement = node.getAncestor((node) => node is Statement);
    if (statement is! IfStatement) {
      _coverageMarker();
      return;
    }
    IfStatement ifStatement = statement as IfStatement;
    // no support "else"
    if (ifStatement.elseStatement != null) {
      _coverageMarker();
      return;
    }
    // check that binary expression is part of first level && condition of "if"
    BinaryExpression condition = binaryExpression;
    while (condition.parent is BinaryExpression &&
        (condition.parent as BinaryExpression).operator.type ==
            TokenType.AMPERSAND_AMPERSAND) {
      condition = condition.parent as BinaryExpression;
    }
    if (ifStatement.condition != condition) {
      _coverageMarker();
      return;
    }
    // prepare environment
    String prefix = utils.getNodePrefix(ifStatement);
    String indent = utils.getIndent(1);
    // prepare "rightCondition"
    String rightConditionSource;
    {
      SourceRange rightConditionRange =
          rangeStartEnd(binaryExpression.rightOperand, condition);
      rightConditionSource = _getRangeText(rightConditionRange);
    }
    // remove "&& rightCondition"
    _addRemoveEdit(rangeEndEnd(binaryExpression.leftOperand, condition));
    // update "then" statement
    Statement thenStatement = ifStatement.thenStatement;
    if (thenStatement is Block) {
      Block thenBlock = thenStatement;
      SourceRange thenBlockRange = rangeNode(thenBlock);
      // insert inner "if" with right part of "condition"
      {
        String source = '$eol$prefix${indent}if ($rightConditionSource) {';
        int thenBlockInsideOffset = thenBlockRange.offset + 1;
        _addInsertEdit(thenBlockInsideOffset, source);
      }
      // insert closing "}" for inner "if"
      {
        int thenBlockEnd = thenBlockRange.end;
        String source = "$indent}";
        // insert before outer "then" block "}"
        source += '$eol$prefix';
        _addInsertEdit(thenBlockEnd - 1, source);
      }
    } else {
      // insert inner "if" with right part of "condition"
      String source = '$eol$prefix${indent}if ($rightConditionSource)';
      _addInsertEdit(ifStatement.rightParenthesis.offset + 1, source);
    }
    // indent "then" statements to correspond inner "if"
    {
      List<Statement> thenStatements = getStatements(thenStatement);
      SourceRange linesRange = utils.getLinesRangeStatements(thenStatements);
      String thenIndentOld = '$prefix$indent';
      String thenIndentNew = '$thenIndentOld$indent';
      _addIndentEdit(linesRange, thenIndentOld, thenIndentNew);
    }
    // add proposal
    _addAssist(DartAssistKind.SPLIT_AND_CONDITION, []);
  }

  void _addProposal_splitVariableDeclaration() {
    // prepare DartVariableStatement, should be part of Block
    VariableDeclarationStatement statement =
        node.getAncestor((node) => node is VariableDeclarationStatement);
    if (statement != null && statement.parent is Block) {} else {
      _coverageMarker();
      return;
    }
    // check that statement declares single variable
    List<VariableDeclaration> variables = statement.variables.variables;
    if (variables.length != 1) {
      _coverageMarker();
      return;
    }
    VariableDeclaration variable = variables[0];
    // prepare initializer
    Expression initializer = variable.initializer;
    if (initializer == null) {
      _coverageMarker();
      return;
    }
    // remove initializer value
    _addRemoveEdit(rangeEndStart(variable.name, statement.semicolon));
    // add assignment statement
    String indent = utils.getNodePrefix(statement);
    String name = variable.name.name;
    String initSrc = _getNodeText(initializer);
    SourceRange assignRange = rangeEndLength(statement, 0);
    _addReplaceEdit(assignRange, eol + indent + name + ' = ' + initSrc + ';');
    // add proposal
    _addAssist(DartAssistKind.SPLIT_VARIABLE_DECLARATION, []);
  }

  void _addProposal_surroundWith() {
    // prepare selected statements
    List<Statement> selectedStatements;
    {
      SourceRange selection =
          rangeStartLength(selectionOffset, selectionLength);
      StatementAnalyzer selectionAnalyzer =
          new StatementAnalyzer(unit, selection);
      unit.accept(selectionAnalyzer);
      List<AstNode> selectedNodes = selectionAnalyzer.selectedNodes;
      // convert nodes to statements
      selectedStatements = [];
      for (AstNode selectedNode in selectedNodes) {
        if (selectedNode is Statement) {
          selectedStatements.add(selectedNode);
        }
      }
      // we want only statements
      if (selectedStatements.isEmpty ||
          selectedStatements.length != selectedNodes.length) {
        return;
      }
    }
    // prepare statement information
    Statement firstStatement = selectedStatements[0];
    Statement lastStatement = selectedStatements[selectedStatements.length - 1];
    SourceRange statementsRange =
        utils.getLinesRangeStatements(selectedStatements);
    // prepare environment
    String indentOld = utils.getNodePrefix(firstStatement);
    String indentNew = '$indentOld${utils.getIndent(1)}';
    String indentedCode =
        utils.replaceSourceRangeIndent(statementsRange, indentOld, indentNew);
    // "block"
    {
      _addInsertEdit(statementsRange.offset, '$indentOld{$eol');
      _addIndentEdit(statementsRange, indentOld, indentNew);
      _addInsertEdit(statementsRange.end, '$indentOld}$eol');
      exitPosition = _newPosition(lastStatement.end);
      // add proposal
      _addAssist(DartAssistKind.SURROUND_WITH_BLOCK, []);
    }
    // "if"
    {
      int offset = statementsRange.offset;
      SourceBuilder sb = new SourceBuilder(file, offset);
      sb.append(indentOld);
      sb.append('if (');
      {
        sb.startPosition('CONDITION');
        sb.append('condition');
        sb.endPosition();
      }
      sb.append(') {');
      sb.append(eol);
      sb.append(indentedCode);
      sb.append(indentOld);
      sb.append('}');
      exitPosition = _newPosition(sb.offset + sb.length);
      sb.append(eol);
      _insertBuilder(sb, statementsRange.length);
      // add proposal
      _addAssist(DartAssistKind.SURROUND_WITH_IF, []);
    }
    // "while"
    {
      int offset = statementsRange.offset;
      SourceBuilder sb = new SourceBuilder(file, offset);
      sb.append(indentOld);
      sb.append('while (');
      {
        sb.startPosition('CONDITION');
        sb.append('condition');
        sb.endPosition();
      }
      sb.append(') {');
      sb.append(eol);
      sb.append(indentedCode);
      sb.append(indentOld);
      sb.append('}');
      exitPosition = _newPosition(sb.offset + sb.length);
      sb.append(eol);
      _insertBuilder(sb, statementsRange.length);
      // add proposal
      _addAssist(DartAssistKind.SURROUND_WITH_WHILE, []);
    }
    // "for-in"
    {
      int offset = statementsRange.offset;
      SourceBuilder sb = new SourceBuilder(file, offset);
      sb.append(indentOld);
      sb.append('for (var ');
      {
        sb.startPosition('NAME');
        sb.append('item');
        sb.endPosition();
      }
      sb.append(' in ');
      {
        sb.startPosition('ITERABLE');
        sb.append('iterable');
        sb.endPosition();
      }
      sb.append(') {');
      sb.append(eol);
      sb.append(indentedCode);
      sb.append(indentOld);
      sb.append('}');
      exitPosition = _newPosition(sb.offset + sb.length);
      sb.append(eol);
      _insertBuilder(sb, statementsRange.length);
      // add proposal
      _addAssist(DartAssistKind.SURROUND_WITH_FOR_IN, []);
    }
    // "for"
    {
      int offset = statementsRange.offset;
      SourceBuilder sb = new SourceBuilder(file, offset);
      sb.append(indentOld);
      sb.append('for (var ');
      {
        sb.startPosition('VAR');
        sb.append('v');
        sb.endPosition();
      }
      sb.append(' = ');
      {
        sb.startPosition('INIT');
        sb.append('init');
        sb.endPosition();
      }
      sb.append('; ');
      {
        sb.startPosition('CONDITION');
        sb.append('condition');
        sb.endPosition();
      }
      sb.append('; ');
      {
        sb.startPosition('INCREMENT');
        sb.append('increment');
        sb.endPosition();
      }
      sb.append(') {');
      sb.append(eol);
      sb.append(indentedCode);
      sb.append(indentOld);
      sb.append('}');
      exitPosition = _newPosition(sb.offset + sb.length);
      sb.append(eol);
      _insertBuilder(sb, statementsRange.length);
      // add proposal
      _addAssist(DartAssistKind.SURROUND_WITH_FOR, []);
    }
    // "do-while"
    {
      int offset = statementsRange.offset;
      SourceBuilder sb = new SourceBuilder(file, offset);
      sb.append(indentOld);
      sb.append('do {');
      sb.append(eol);
      sb.append(indentedCode);
      sb.append(indentOld);
      sb.append('} while (');
      {
        sb.startPosition('CONDITION');
        sb.append('condition');
        sb.endPosition();
      }
      sb.append(');');
      exitPosition = _newPosition(sb.offset + sb.length);
      sb.append(eol);
      _insertBuilder(sb, statementsRange.length);
      // add proposal
      _addAssist(DartAssistKind.SURROUND_WITH_DO_WHILE, []);
    }
    // "try-catch"
    {
      int offset = statementsRange.offset;
      SourceBuilder sb = new SourceBuilder(file, offset);
      sb.append(indentOld);
      sb.append('try {');
      sb.append(eol);
      sb.append(indentedCode);
      sb.append(indentOld);
      sb.append('} on ');
      {
        sb.startPosition('EXCEPTION_TYPE');
        sb.append('Exception');
        sb.endPosition();
      }
      sb.append(' catch (');
      {
        sb.startPosition('EXCEPTION_VAR');
        sb.append('e');
        sb.endPosition();
      }
      sb.append(') {');
      sb.append(eol);
      //
      sb.append(indentNew);
      {
        sb.startPosition('CATCH');
        sb.append('// TODO');
        sb.endPosition();
        sb.setExitOffset();
      }
      sb.append(eol);
      //
      sb.append(indentOld);
      sb.append('}');
      sb.append(eol);
      _insertBuilder(sb, statementsRange.length);
      // add proposal
      _addAssist(DartAssistKind.SURROUND_WITH_TRY_CATCH, []);
    }
    // "try-finally"
    {
      int offset = statementsRange.offset;
      SourceBuilder sb = new SourceBuilder(file, offset);
      //
      sb.append(indentOld);
      sb.append('try {');
      sb.append(eol);
      //
      sb.append(indentedCode);
      //
      sb.append(indentOld);
      sb.append('} finally {');
      sb.append(eol);
      //
      sb.append(indentNew);
      {
        sb.startPosition('FINALLY');
        sb.append('// TODO');
        sb.endPosition();
        sb.setExitOffset();
      }
      sb.setExitOffset();
      sb.append(eol);
      //
      sb.append(indentOld);
      sb.append('}');
      sb.append(eol);
      //
      _insertBuilder(sb, statementsRange.length);
      // add proposal
      _addAssist(DartAssistKind.SURROUND_WITH_TRY_FINALLY, []);
    }
  }

  /**
   * Adds a new [Edit] to [edits].
   */
  void _addRemoveEdit(SourceRange range) {
    _addReplaceEdit(range, '');
  }

  /**
   * Adds a new [SourceEdit] to [edits].
   */
  void _addReplaceEdit(SourceRange range, String text) {
    SourceEdit edit = new SourceEdit(range.offset, range.length, text);
    doSourceChange_addElementEdit(change, unitElement, edit);
  }

  /**
   * Configures [utils] using given [target].
   */
  void _configureTargetLocation(Object target) {
    utils.targetClassElement = null;
    if (target is AstNode) {
      ClassDeclaration targetClassDeclaration =
          target.getAncestor((node) => node is ClassDeclaration);
      if (targetClassDeclaration != null) {
        utils.targetClassElement = targetClassDeclaration.element;
      }
    }
  }

  /**
   * Returns an existing or just added [LinkedEditGroup] with [groupId].
   */
  LinkedEditGroup _getLinkedPosition(String groupId) {
    LinkedEditGroup group = linkedPositionGroups[groupId];
    if (group == null) {
      group = new LinkedEditGroup.empty();
      linkedPositionGroups[groupId] = group;
    }
    return group;
  }

  /**
   * Returns the text of the given node in the unit.
   */
  String _getNodeText(AstNode node) {
    return utils.getNodeText(node);
  }

  /**
   * Returns the text of the given range in the unit.
   */
  String _getRangeText(SourceRange range) {
    return utils.getRangeText(range);
  }

  /**
   * Inserts the given [SourceBuilder] at its offset.
   */
  void _insertBuilder(SourceBuilder builder, [int length = 0]) {
    {
      SourceRange range = rangeStartLength(builder.offset, length);
      String text = builder.toString();
      _addReplaceEdit(range, text);
    }
    // add linked positions
    builder.linkedPositionGroups.forEach((String id, LinkedEditGroup group) {
      LinkedEditGroup fixGroup = _getLinkedPosition(id);
      group.positions.forEach((Position position) {
        fixGroup.addPosition(position, group.length);
      });
      group.suggestions.forEach((LinkedEditSuggestion suggestion) {
        fixGroup.addSuggestion(suggestion);
      });
    });
    // add exit position
    {
      int exitOffset = builder.exitOffset;
      if (exitOffset != null) {
        exitPosition = _newPosition(exitOffset);
      }
    }
  }

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

  /**
   * This method does nothing, but we invoke it in places where Dart VM
   * coverage agent fails to provide coverage information - such as almost
   * all "return" statements.
   *
   * https://code.google.com/p/dart/issues/detail?id=19912
   */
  static void _coverageMarker() {}

  /**
   * Returns `true` if the selection covers an operator of the given
   * [BinaryExpression].
   */
  static bool _isOperatorSelected(
      BinaryExpression binaryExpression, int offset, int length) {
    AstNode left = binaryExpression.leftOperand;
    AstNode right = binaryExpression.rightOperand;
    // between the nodes
    if (offset >= left.endToken.end && offset + length <= right.offset) {
      _coverageMarker();
      return true;
    }
    // or exactly select the node (but not with infix expressions)
    if (offset == left.offset && offset + length == right.endToken.end) {
      if (left is BinaryExpression || right is BinaryExpression) {
        _coverageMarker();
        return false;
      }
      _coverageMarker();
      return true;
    }
    // invalid selection (part of node, etc)
    _coverageMarker();
    return false;
  }

  /**
   * Checks if the given [Expression] should be wrapped with parenthesis when we
   * want to use it as operand of a logical `and` expression.
   */
  static bool _shouldWrapParenthesisBeforeAnd(Expression expr) {
    if (expr is BinaryExpression) {
      BinaryExpression binary = expr;
      int precedence = binary.operator.type.precedence;
      return precedence < TokenClass.LOGICAL_AND_OPERATOR.precedence;
    }
    return false;
  }
}

/**
 * An [AssistContributor] that provides the default set of assists.
 */
class DefaultAssistContributor extends DartAssistContributor {
  @override
  Future<List<Assist>> internalComputeAssists(DartAssistContext context) async {
    try {
      AssistProcessor processor = new AssistProcessor(context);
      return processor.compute();
    } on CancelCorrectionException {
      return Assist.EMPTY_LIST;
    }
  }
}

class _SimpleIdentifierRecursiveAstVisitor extends RecursiveAstVisitor {
  final _SimpleIdentifierVisitor visitor;

  _SimpleIdentifierRecursiveAstVisitor(this.visitor);

  @override
  visitSimpleIdentifier(SimpleIdentifier node) {
    visitor(node);
  }
}
