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

// This code was auto-generated, is not intended to be edited, and is subject to
// significant change. Please see the README file for more information.

library services.util;

import 'dart:collection';
import "dart:math" as math;

import 'package:analyzer/src/generated/java_core.dart' hide StringUtils;
import 'package:analyzer/src/generated/ast.dart';
import 'package:analyzer/src/generated/element.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/error.dart';
import 'package:analyzer/src/generated/resolver.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/generated/scanner.dart';

import 'stubs.dart';

/**
 * Context for which assistance should be provided.
 */
class AssistContext {
  final SearchEngine searchEngine;

  final AnalysisContext analysisContext;

  final String analysisContextId;

  final Source source;

  final CompilationUnit compilationUnit;

  final int selectionOffset;

  final int selectionLength;

  AstNode _coveredNode;

  AstNode _coveringNode;

  Element _coveredElement;

  bool _coveredElementFound = false;

  AssistContext.con1(this.searchEngine, this.analysisContext,
      this.analysisContextId, this.source, this.compilationUnit,
      this.selectionOffset, this.selectionLength);

  AssistContext.con2(SearchEngine searchEngine, AnalysisContext analysisContext,
      String analysisContextId, Source source, CompilationUnit compilationUnit,
      SourceRange selectionRange)
      : this.con1(searchEngine, analysisContext, analysisContextId, source,
          compilationUnit, selectionRange.offset, selectionRange.length);

  /**
   * @return the resolved [CompilationUnitElement] of the [Source].
   */
  CompilationUnitElement get compilationUnitElement => compilationUnit.element;

  /**
   * @return the [Element] of the [coveredNode], may be <code>null</code>.
   */
  Element get coveredElement {
    if (!_coveredElementFound) {
      _coveredElementFound = true;
      AstNode coveredNode = this.coveredNode;
      if (coveredNode == null) {
        return null;
      }
      _coveredElement =
          ElementLocator.locateWithOffset(coveredNode, selectionOffset);
    }
    return _coveredElement;
  }

  /**
   * @return the [AstNode] that is covered by the selection.
   */
  AstNode get coveredNode {
    if (_coveredNode == null) {
      NodeLocator locator = new NodeLocator(selectionOffset, selectionOffset);
      _coveredNode = locator.searchWithin(compilationUnit);
    }
    return _coveredNode;
  }

  /**
   * @return the ASTNode that covers the selection.
   */
  AstNode get coveringNode {
    if (_coveringNode == null) {
      NodeLocator locator =
          new NodeLocator(selectionOffset, selectionOffset + selectionLength);
      _coveringNode = locator.searchWithin(compilationUnit);
    }
    return _coveringNode;
  }

  /**
   * @return the errors associated with the [Source].
   */
  List<AnalysisError> get errors {
    Source source = this.source;
    if (analysisContext == null || source == null) {
      return AnalysisError.NO_ERRORS;
    }
    return analysisContext.getErrors(source).errors;
  }

  /**
   * @return the [SourceRange] of the selection.
   */
  SourceRange get selectionRange =>
      new SourceRange(selectionOffset, selectionLength);
}

/**
 * Utilities for analyzing [CompilationUnit], its parts and source.
 */
class CorrectionUtils {
  static List<String> _KNOWN_METHOD_NAME_PREFIXES = ["get", "is", "to"];

  /**
   * @return <code>true</code> if given [List]s are equals at given position.
   */
  static bool allListsEqual(List<List> lists, int position) {
    Object element = lists[0][position];
    for (List list in lists) {
      if (!identical(list[position], element)) {
        return false;
      }
    }
    return true;
  }

  /**
   * @return <code>true</code> if given [SourceRange] covers given [AstNode].
   */
  static bool covers(SourceRange r, AstNode node) {
    SourceRange nodeRange = SourceRangeFactory.rangeNode(node);
    return r.covers(nodeRange);
  }

  /**
   * @return all direct children of the given [Element].
   */
  static List<Element> getChildren(Element parent) =>
      getChildren2(parent, null);

  /**
   * @param name the required name of children; may be <code>null</code> to get children with any
   *          name.
   * @return all direct children of the given [Element], with given name.
   */
  static List<Element> getChildren2(Element parent, String name) {
    List<Element> children = [];
    parent.accept(new GeneralizingElementVisitor_CorrectionUtils_getChildren(
        parent, name, children));
    return children;
  }

  static String getDefaultValueCode(DartType type) {
    if (type != null) {
      String typeName = type.displayName;
      if (typeName == "bool") {
        return "false";
      }
      if (typeName == "int") {
        return "0";
      }
      if (typeName == "double") {
        return "0.0";
      }
      if (typeName == "String") {
        return "''";
      }
    }
    // no better guess
    return "null";
  }

  /**
   * @return the name of the [Element] kind.
   */
  static String getElementKindName(Element element) {
    ElementKind kind = element.kind;
    return getElementKindName2(kind);
  }

  /**
   * @return the display name of the [ElementKind].
   */
  static String getElementKindName2(ElementKind kind) => kind.displayName;

  /**
   * @return the human name of the [Element].
   */
  static String getElementQualifiedName(Element element) {
    ElementKind kind = element.kind;
    while (true) {
      if (kind == ElementKind.FIELD || kind == ElementKind.METHOD) {
        return "${element.enclosingElement.displayName}.${element.displayName}";
      } else {
        return element.displayName;
      }
      break;
    }
  }

  /**
   * @return the [ExecutableElement] of the enclosing executable [AstNode].
   */
  static ExecutableElement getEnclosingExecutableElement(AstNode node) {
    while (node != null) {
      if (node is FunctionDeclaration) {
        return node.element;
      }
      if (node is ConstructorDeclaration) {
        return node.element;
      }
      if (node is MethodDeclaration) {
        return node.element;
      }
      node = node.parent;
    }
    return null;
  }

  /**
   * @return the enclosing executable [AstNode].
   */
  static AstNode getEnclosingExecutableNode(AstNode node) {
    while (node != null) {
      if (node is FunctionDeclaration) {
        return node;
      }
      if (node is ConstructorDeclaration) {
        return node;
      }
      if (node is MethodDeclaration) {
        return node;
      }
      node = node.parent;
    }
    return null;
  }

  /**
   * @return [Element] exported from the given [LibraryElement].
   */
  static Element getExportedElement(LibraryElement library, String name) {
    if (library == null) {
      return null;
    }
    return getExportNamespace2(library)[name];
  }

  /**
   * TODO(scheglov) may be replace with some API for this
   *
   * @return the namespace of the given [ExportElement].
   */
  static Map<String, Element> getExportNamespace(ExportElement exp) {
    Namespace namespace =
        new NamespaceBuilder().createExportNamespaceForDirective(exp);
    return namespace.definedNames;
  }

  /**
   * TODO(scheglov) may be replace with some API for this
   *
   * @return the export namespace of the given [LibraryElement].
   */
  static Map<String, Element> getExportNamespace2(LibraryElement library) {
    Namespace namespace =
        new NamespaceBuilder().createExportNamespaceForLibrary(library);
    return namespace.definedNames;
  }

  /**
   * @return [getExpressionPrecedence] for parent node, or `0` if parent node
   *         is [ParenthesizedExpression]. The reason is that `(expr)` is always
   *         executed after `expr`.
   */
  static int getExpressionParentPrecedence(AstNode node) {
    AstNode parent = node.parent;
    if (parent is ParenthesizedExpression) {
      return 0;
    }
    return getExpressionPrecedence(parent);
  }

  /**
   * Return the precedence of the given [node]: the result of invoking
   * [Expression.precedence] if the node is an [Expression], or a negative value
   * otherwise.
   */
  static int getExpressionPrecedence(AstNode node) {
    if (node is Expression) {
      return node.precedence;
    }
    return -1000;
  }

  /**
   * TODO(scheglov) may be replace with some API for this
   *
   * @return the namespace of the given [ImportElement].
   */
  static Map<String, Element> getImportNamespace(ImportElement imp) {
    Namespace namespace =
        new NamespaceBuilder().createImportNamespaceForDirective(imp);
    return namespace.definedNames;
  }

  /**
   * @return all [CompilationUnitElement] the given [LibraryElement] consists of.
   */
  static List<CompilationUnitElement> getLibraryUnits(LibraryElement library) {
    List<CompilationUnitElement> units = [];
    units.add(library.definingCompilationUnit);
    units.addAll(library.parts);
    return units;
  }

  /**
   * @return the line prefix from the given source, i.e. basically just whitespace prefix of the
   *         given [String].
   */
  static String getLinesPrefix(String lines) {
    int index = 0;
    while (index < lines.length) {
      int c = lines.codeUnitAt(index);
      if (!Character.isWhitespace(c)) {
        break;
      }
      index++;
    }
    return lines.substring(0, index);
  }

  /**
   * @return the [LocalVariableElement] or [ParameterElement] if given
   *         [SimpleIdentifier] is the reference to local variable or parameter, or
   *         <code>null</code> in the other case.
   */
  static VariableElement getLocalOrParameterVariableElement(
      SimpleIdentifier node) {
    Element element = node.staticElement;
    if (element is LocalVariableElement) {
      return element;
    }
    if (element is ParameterElement) {
      return element;
    }
    return null;
  }

  /**
   * @return the [LocalVariableElement] if given [SimpleIdentifier] is the reference to
   *         local variable, or <code>null</code> in the other case.
   */
  static LocalVariableElement getLocalVariableElement(SimpleIdentifier node) {
    Element element = node.staticElement;
    if (element is LocalVariableElement) {
      return element;
    }
    return null;
  }

  /**
   * @return the nearest common ancestor [AstNode] of the given [AstNode]s.
   */
  static AstNode getNearestCommonAncestor(List<AstNode> nodes) {
    // may be no nodes
    if (nodes.isEmpty) {
      return null;
    }
    // prepare parents
    List<List<AstNode>> parents = [];
    for (AstNode node in nodes) {
      parents.add(getParents(node));
    }
    // find min length
    int minLength = 2147483647;
    for (List<AstNode> parentList in parents) {
      minLength = math.min(minLength, parentList.length);
    }
    // find deepest parent
    int i = 0;
    for (; i < minLength; i++) {
      if (!allListsEqual(parents, i)) {
        break;
      }
    }
    return parents[0][i - 1];
  }

  /**
   * @return the [Expression] qualified if given node is name part of a [PropertyAccess]
   *         or [PrefixedIdentifier]. May be <code>null</code>.
   */
  static Expression getNodeQualifier(SimpleIdentifier node) {
    AstNode parent = node.parent;
    if (parent is PropertyAccess) {
      PropertyAccess propertyAccess = parent;
      if (identical(propertyAccess.propertyName, node)) {
        return propertyAccess.target;
      }
    }
    if (parent is PrefixedIdentifier) {
      PrefixedIdentifier prefixed = parent;
      if (identical(prefixed.identifier, node)) {
        return prefixed.prefix;
      }
    }
    return null;
  }

  /**
   * @return the [ParameterElement] if given [SimpleIdentifier] is the reference to
   *         parameter, or <code>null</code> in the other case.
   */
  static ParameterElement getParameterElement(SimpleIdentifier node) {
    Element element = node.staticElement;
    if (element is ParameterElement) {
      return element;
    }
    return null;
  }

  /**
   * Return the precedence of the given [expression]'s parent. May be `-1` no
   * operator.
   *
   * See [getPrecedence].
   */
  static int getParentPrecedence(Expression expression) {
    AstNode parent = expression.parent;
    if (parent is Expression) {
      return getPrecedence(parent);
    }
    return -1;
  }

  /**
   * @return parent [AstNode]s from [CompilationUnit] (at index "0") to the given one.
   */
  static List<AstNode> getParents(AstNode node) {
    // prepare number of parents
    int numParents = 0;
    {
      AstNode current = node.parent;
      while (current != null) {
        numParents++;
        current = current.parent;
      }
    }
    // fill array of parents
    List<AstNode> parents = new List<AstNode>(numParents);
    AstNode current = node.parent;
    int index = numParents;
    while (current != null) {
      parents[--index] = current;
      current = current.parent;
    }
    return parents;
  }

  /**
   * @return the precedence of the given [Expression] operator. May be
   *         `Integer#MAX_VALUE` if not an operator.
   */
  static int getPrecedence(Expression expression) {
    if (expression is BinaryExpression) {
      BinaryExpression binaryExpression = expression;
      return binaryExpression.operator.type.precedence;
    }
    if (expression is PrefixExpression) {
      PrefixExpression prefixExpression = expression;
      return prefixExpression.operator.type.precedence;
    }
    if (expression is PostfixExpression) {
      PostfixExpression postfixExpression = expression;
      return postfixExpression.operator.type.precedence;
    }
    return 2147483647;
  }

  /**
   * @return the [PropertyAccessorElement] if given [SimpleIdentifier] is the reference
   *         to property, or <code>null</code> in the other case.
   */
  static PropertyAccessorElement getPropertyAccessorElement(
      SimpleIdentifier node) {
    Element element = node.staticElement;
    if (element is PropertyAccessorElement) {
      return element;
    }
    return null;
  }

  /**
   * If given [AstNode] is name of qualified property extraction, returns target from which
   * this property is extracted. Otherwise `null`.
   */
  static Expression getQualifiedPropertyTarget(AstNode node) {
    AstNode parent = node.parent;
    if (parent is PrefixedIdentifier) {
      PrefixedIdentifier prefixed = parent;
      if (identical(prefixed.identifier, node)) {
        return parent.prefix;
      }
    }
    if (parent is PropertyAccess) {
      PropertyAccess access = parent;
      if (identical(access.propertyName, node)) {
        return access.realTarget;
      }
    }
    return null;
  }

  /**
   * Returns the name of the file which corresponds to the name of the class according to the style
   * guide. However class does not have to be in this file.
   */
  static String getRecommentedFileNameForClass(String className) {
    int len = className.length;
    StringBuffer buffer = new StringBuffer();
    bool prevWasUpper = false;
    for (int i = 0; i < len; i++) {
      int c = className.codeUnitAt(i);
      if (Character.isUpperCase(c)) {
        bool nextIsUpper =
            i < len - 1 && Character.isUpperCase(className.codeUnitAt(i + 1));
        if (i == 0) {} else if (prevWasUpper) {
          // HTTPServer
          //     ^
          if (!nextIsUpper) {
            buffer.writeCharCode(0x5F);
          }
        } else {
          // HttpServer
          //     ^
          buffer.writeCharCode(0x5F);
        }
        prevWasUpper = true;
        c = Character.toLowerCase(c);
      } else {
        prevWasUpper = false;
      }
      buffer.writeCharCode(c);
    }
    buffer.write(".dart");
    String fileName = buffer.toString();
    return fileName;
  }

  /**
   * @return given [Statement] if not [Block], first child [Statement] if
   *         [Block], or <code>null</code> if more than one child.
   */
  static Statement getSingleStatement(Statement statement) {
    if (statement is Block) {
      List<Statement> blockStatements = statement.statements;
      if (blockStatements.length != 1) {
        return null;
      }
      return blockStatements[0];
    }
    return statement;
  }

  /**
   * @return the [String] content of the given [Source].
   */
  static String getSourceContent(AnalysisContext context, Source source) =>
      context.getContents(source).data.toString();

  /**
   * @return given [Statement] if not [Block], all children [Statement]s if
   *         [Block].
   */
  static List<Statement> getStatements(Statement statement) {
    if (statement is Block) {
      return statement.statements;
    }
    return [];
  }

  /**
   * @return all top-level elements declared in the given [LibraryElement].
   */
  static List<Element> getTopLevelElements(LibraryElement library) {
    List<Element> elements = [];
    List<CompilationUnitElement> units = getLibraryUnits(library);
    for (CompilationUnitElement unit in units) {
      elements.addAll(unit.functions);
      elements.addAll(unit.functionTypeAliases);
      elements.addAll(unit.types);
      elements.addAll(unit.topLevelVariables);
    }
    return elements;
  }

  /**
   * @return the possible names for variable with initializer of the given [StringLiteral].
   */
  static List<String> getVariableNameSuggestions(
      String text, Set<String> excluded) {
    // filter out everything except of letters and white spaces
    {
      StringBuffer buffer = new StringBuffer();
      for (int i = 0; i < text.length; i++) {
        int c = text.codeUnitAt(i);
        if (Character.isLetter(c) || Character.isWhitespace(c)) {
          buffer.writeCharCode(c);
        }
      }
      text = buffer.toString();
    }
    // make single camel-case text
    {
      List<String> words = StringUtils.split(text);
      StringBuffer buffer = new StringBuffer();
      for (int i = 0; i < words.length; i++) {
        String word = words[i];
        if (i > 0) {
          word = StringUtils.capitalize(word);
        }
        buffer.write(word);
      }
      text = buffer.toString();
    }
    // split camel-case into separate suggested names
    Set<String> res = new LinkedHashSet();
    _addAll(excluded, res, _getVariableNameSuggestions(text));
    return new List.from(res);
  }

  /**
   * @return the possible names for variable with given expected type and expression.
   */
  static List<String> getVariableNameSuggestions2(DartType expectedType,
      Expression assignedExpression, Set<String> excluded) {
    Set<String> res = new LinkedHashSet();
    // use expression
    if (assignedExpression != null) {
      String nameFromExpression =
          _getBaseNameFromExpression(assignedExpression);
      if (nameFromExpression != null) {
        nameFromExpression = StringUtils.removeStart(nameFromExpression, "_");
        _addAll(excluded, res, _getVariableNameSuggestions(nameFromExpression));
      }
      String nameFromParent =
          _getBaseNameFromLocationInParent(assignedExpression);
      if (nameFromParent != null) {
        _addAll(excluded, res, _getVariableNameSuggestions(nameFromParent));
      }
    }
    // use type
    if (expectedType != null && !expectedType.isDynamic) {
      String typeName = expectedType.name;
      if ("int" == typeName) {
        _addSingleCharacterName(excluded, res, 0x69);
      } else if ("double" == typeName) {
        _addSingleCharacterName(excluded, res, 0x64);
      } else if ("String" == typeName) {
        _addSingleCharacterName(excluded, res, 0x73);
      } else {
        _addAll(excluded, res, _getVariableNameSuggestions(typeName));
      }
      res.remove(typeName);
    }
    // done
    return new List.from(res);
  }

  /**
   * Return `true` if the given [element]'s display name ([Element.displayName])
   * is equal to the given [name].
   */
  static bool hasDisplayName(Element element, String name) {
    if (element == null) {
      return false;
    }
    String elementDisplayName = element.displayName;
    return StringUtils.equals(elementDisplayName, name);
  }

  /**
   * Return `true` if the given [element]'s name ([Element.name]) is equal to
   * the given [name].
   */
  static bool hasName(Element element, String name) {
    if (element == null) {
      return false;
    }
    String elementName = element.name;
    return StringUtils.equals(elementName, name);
  }

  /**
   * @return `true` if the given [SimpleIdentifier] is the name of the
   *         [NamedExpression].
   */
  static bool isNamedExpressionName(SimpleIdentifier node) {
    AstNode parent = node.parent;
    if (parent is Label) {
      Label label = parent;
      if (identical(label.label, node)) {
        AstNode parent2 = label.parent;
        if (parent2 is NamedExpression) {
          return identical(parent2.name, label);
        }
      }
    }
    return false;
  }

  /**
   * Adds "toAdd" items which are not excluded.
   */
  static void _addAll(
      Set<String> excluded, Set<String> result, Iterable<String> toAdd) {
    for (String item in toAdd) {
      // add name based on "item", but not "excluded"
      for (int suffix = 1;; suffix++) {
        // prepare name, just "item" or "item2", "item3", etc
        String name = item;
        if (suffix > 1) {
          name += suffix.toString();
        }
        // add once found not excluded
        if (!excluded.contains(name)) {
          result.add(name);
          break;
        }
      }
    }
  }

  /**
   * Add to "result" then given "c" or the first ASCII character after it.
   */
  static void _addSingleCharacterName(
      Set<String> excluded, Set<String> result, int c) {
    while (c < 0x7A) {
      String name = new String.fromCharCode(c);
      // may be done
      if (!excluded.contains(name)) {
        result.add(name);
        break;
      }
      // next character
      c = (c + 1);
    }
  }

  static String _getBaseNameFromExpression(Expression expression) {
    String name = null;
    // e as Type
    if (expression is AsExpression) {
      AsExpression asExpression = expression as AsExpression;
      expression = asExpression.expression;
    }
    // analyze expressions
    if (expression is SimpleIdentifier) {
      SimpleIdentifier node = expression;
      return node.name;
    } else if (expression is PrefixedIdentifier) {
      PrefixedIdentifier node = expression;
      return node.identifier.name;
    } else if (expression is MethodInvocation) {
      name = expression.methodName.name;
    } else if (expression is InstanceCreationExpression) {
      InstanceCreationExpression creation = expression;
      ConstructorName constructorName = creation.constructorName;
      TypeName typeName = constructorName.type;
      if (typeName != null) {
        Identifier typeNameIdentifier = typeName.name;
        // new ClassName()
        if (typeNameIdentifier is SimpleIdentifier) {
          return typeNameIdentifier.name;
        }
        // new prefix.name();
        if (typeNameIdentifier is PrefixedIdentifier) {
          PrefixedIdentifier prefixed = typeNameIdentifier;
          // new prefix.ClassName()
          if (prefixed.prefix.staticElement is PrefixElement) {
            return prefixed.identifier.name;
          }
          // new ClassName.constructorName()
          return prefixed.prefix.name;
        }
      }
    }
    // strip known prefixes
    if (name != null) {
      for (int i = 0; i < _KNOWN_METHOD_NAME_PREFIXES.length; i++) {
        String curr = _KNOWN_METHOD_NAME_PREFIXES[i];
        if (name.startsWith(curr)) {
          if (name == curr) {
            return null;
          } else if (Character.isUpperCase(name.codeUnitAt(curr.length))) {
            return name.substring(curr.length);
          }
        }
      }
    }
    // done
    return name;
  }

  static String _getBaseNameFromLocationInParent(Expression expression) {
    // value in named expression
    if (expression.parent is NamedExpression) {
      NamedExpression namedExpression = expression.parent as NamedExpression;
      if (identical(namedExpression.expression, expression)) {
        return namedExpression.name.label.name;
      }
    }
    // positional argument
    {
      ParameterElement parameter = expression.propagatedParameterElement;
      if (parameter == null) {
        parameter = expression.staticParameterElement;
      }
      if (parameter != null) {
        return parameter.displayName;
      }
    }
    // unknown
    return null;
  }

  /**
   * @return [Expression]s from <code>operands</code> which are completely covered by given
   *         [SourceRange]. Range should start and end between given [Expression]s.
   */
  static List<Expression> _getOperandsForSourceRange(
      List<Expression> operands, SourceRange range) {
    assert(!operands.isEmpty);
    List<Expression> subOperands = [];
    // track range enter/exit
    bool entered = false;
    bool exited = false;
    // may be range starts before or on first operand
    if (range.offset <= operands[0].offset) {
      entered = true;
    }
    // iterate over gaps between operands
    for (int i = 0; i < operands.length - 1; i++) {
      Expression operand = operands[i];
      Expression nextOperand = operands[i + 1];
      SourceRange inclusiveGap =
          SourceRangeFactory.rangeEndStart(operand, nextOperand).getMoveEnd(1);
      // add operand, if already entered range
      if (entered) {
        subOperands.add(operand);
        // may be last operand in range
        if (range.endsIn(inclusiveGap)) {
          exited = true;
        }
      } else {
        // may be first operand in range
        if (range.startsIn(inclusiveGap)) {
          entered = true;
        }
      }
    }
    // check if last operand is in range
    Expression lastGroupMember = operands[operands.length - 1];
    if (range.end == lastGroupMember.end) {
      subOperands.add(lastGroupMember);
      exited = true;
    }
    // we expect that range covers only given operands
    if (!exited) {
      return [];
    }
    // done
    return subOperands;
  }

  /**
   * @return all operands of the given [BinaryExpression] and its children with the same
   *         operator.
   */
  static List<Expression> _getOperandsInOrderFor(BinaryExpression groupRoot) {
    List<Expression> operands = [];
    TokenType groupOperatorType = groupRoot.operator.type;
    groupRoot.accept(
        new GeneralizingAstVisitor_CorrectionUtils_getOperandsInOrderFor(
            groupOperatorType, operands));
    return operands;
  }

  /**
   * @return all variants of names by removing leading words by one.
   */
  static List<String> _getVariableNameSuggestions(String name) {
    List<String> result = [];
    List<String> parts =
        name.split("(?<!(^|[A-Z]))(?=[A-Z])|(?<!^)(?=[A-Z][a-z])");
    for (int i = 0; i < parts.length; i++) {
      String suggestion =
          "${parts[i].toLowerCase()}${StringUtils.join(parts, "", i + 1, parts.length)}";
      result.add(suggestion);
    }
    return result;
  }

  final CompilationUnit unit;

  LibraryElement _library;

  String _buffer;

  String _endOfLine;

  CorrectionUtils(this.unit) {
    CompilationUnitElement element = unit.element;
    this._library = element.library;
    this._buffer = getSourceContent(element.context, element.source);
  }

  /**
   * @return the [AstNode] that encloses the given offset.
   */
  AstNode findNode(int offset) => new NodeLocator(offset).searchWithin(unit);

  /**
   * TODO(scheglov) replace with nodes once there will be [CompilationUnit.comments].
   *
   * @return the [SourceRange]s of all comments in [CompilationUnit].
   */
  List<SourceRange> get commentRanges {
    List<SourceRange> ranges = [];
    Token token = unit.beginToken;
    while (token != null && token.type != TokenType.EOF) {
      Token commentToken = token.precedingComments;
      while (commentToken != null) {
        ranges.add(SourceRangeFactory.rangeToken(commentToken));
        commentToken = commentToken.next;
      }
      token = token.next;
    }
    return ranges;
  }

  /**
   * @return the EOL to use for this [CompilationUnit].
   */
  String get endOfLine {
    if (_endOfLine == null) {
      if (_buffer.contains("\r\n")) {
        _endOfLine = "\r\n";
      } else {
        _endOfLine = "\n";
      }
    }
    return _endOfLine;
  }

  /**
   * @return the default indentation with given level.
   */
  String getIndent(int level) => StringUtils.repeat("  ", level);

  /**
   * @return the source of the given [SourceRange] with indentation changed from "oldIndent"
   *         to "newIndent", keeping indentation of the lines relative to each other.
   */
  String getIndentSource(
      SourceRange range, String oldIndent, String newIndent) {
    String oldSource = getText3(range);
    return getIndentSource3(oldSource, oldIndent, newIndent);
  }

  /**
   * Indents given source left or right.
   *
   * @return the source with changed indentation.
   */
  String getIndentSource2(String source, bool right) {
    StringBuffer buffer = new StringBuffer();
    String indent = getIndent(1);
    String eol = endOfLine;
    List<String> lines =
        StringUtils.splitByWholeSeparatorPreserveAllTokens(source, eol);
    for (int i = 0; i < lines.length; i++) {
      String line = lines[i];
      // last line, stop if empty
      if (i == lines.length - 1 && StringUtils.isEmpty(line)) {
        break;
      }
      // update line
      if (right) {
        line = "${indent}${line}";
      } else {
        line = StringUtils.removeStart(line, indent);
      }
      // append line
      buffer.write(line);
      buffer.write(eol);
    }
    return buffer.toString();
  }

  /**
   * @return the source with indentation changed from "oldIndent" to "newIndent", keeping
   *         indentation of the lines relative to each other.
   */
  String getIndentSource3(String source, String oldIndent, String newIndent) {
    // prepare STRING token ranges
    List<SourceRange> lineRanges = [];
    for (Token token in TokenUtils.getTokens(source)) {
      if (token.type == TokenType.STRING) {
        lineRanges.add(SourceRangeFactory.rangeToken(token));
      }
    }
    // re-indent lines
    StringBuffer buffer = new StringBuffer();
    String eol = endOfLine;
    List<String> lines =
        StringUtils.splitByWholeSeparatorPreserveAllTokens(source, eol);
    int lineOffset = 0;
    for (int i = 0; i < lines.length; i++) {
      String line = lines[i];
      // last line, stop if empty
      if (i == lines.length - 1 && StringUtils.isEmpty(line)) {
        break;
      }
      // check if "offset" is in one of the String ranges
      bool inString = false;
      for (SourceRange lineRange in lineRanges) {
        if (lineOffset > lineRange.offset && lineOffset < lineRange.end) {
          inString = true;
        }
        if (lineOffset > lineRange.end) {
          break;
        }
      }
      lineOffset += line.length + eol.length;
      // update line indent
      if (!inString) {
        line = "${newIndent}${StringUtils.removeStart(line, oldIndent)}";
      }
      // append line
      buffer.write(line);
      buffer.write(eol);
    }
    return buffer.toString();
  }

  /**
   * @return [InsertDesc], description where to insert new library-related directive.
   */
  CorrectionUtils_InsertDesc get insertDescImport {
    // analyze directives
    Directive prevDirective = null;
    for (Directive directive in unit.directives) {
      if (directive is LibraryDirective ||
          directive is ImportDirective ||
          directive is ExportDirective) {
        prevDirective = directive;
      }
    }
    // insert after last library-related directive
    if (prevDirective != null) {
      CorrectionUtils_InsertDesc result = new CorrectionUtils_InsertDesc();
      result.offset = prevDirective.end;
      String eol = endOfLine;
      if (prevDirective is LibraryDirective) {
        result.prefix = "${eol}${eol}";
      } else {
        result.prefix = eol;
      }
      return result;
    }
    // no directives, use "top" location
    return insertDescTop;
  }

  /**
   * @return [InsertDesc], description where to insert new 'part 'directive.
   */
  CorrectionUtils_InsertDesc get insertDescPart {
    // analyze directives
    Directive prevDirective = null;
    for (Directive directive in unit.directives) {
      prevDirective = directive;
    }
    // insert after last directive
    if (prevDirective != null) {
      CorrectionUtils_InsertDesc result = new CorrectionUtils_InsertDesc();
      result.offset = prevDirective.end;
      String eol = endOfLine;
      if (prevDirective is PartDirective) {
        result.prefix = eol;
      } else {
        result.prefix = "${eol}${eol}";
      }
      return result;
    }
    // no directives, use "top" location
    return insertDescTop;
  }

  /**
   * @return [InsertDesc], description where to insert new directive or top-level declaration
   *         at the top of file.
   */
  CorrectionUtils_InsertDesc get insertDescTop {
    // skip leading line comments
    int offset = 0;
    bool insertEmptyLineBefore = false;
    bool insertEmptyLineAfter = false;
    String source = text;
    // skip hash-bang
    if (offset < source.length - 2) {
      String linePrefix = getText2(offset, 2);
      if (linePrefix == "#!") {
        insertEmptyLineBefore = true;
        offset = getLineNext(offset);
        // skip empty lines to first line comment
        int emptyOffset = offset;
        while (emptyOffset < source.length - 2) {
          int nextLineOffset = getLineNext(emptyOffset);
          String line = source.substring(emptyOffset, nextLineOffset);
          if (line.trim().isEmpty) {
            emptyOffset = nextLineOffset;
            continue;
          } else if (line.startsWith("//")) {
            offset = emptyOffset;
            break;
          } else {
            break;
          }
        }
      }
    }
    // skip line comments
    while (offset < source.length - 2) {
      String linePrefix = getText2(offset, 2);
      if (linePrefix == "//") {
        insertEmptyLineBefore = true;
        offset = getLineNext(offset);
      } else {
        break;
      }
    }
    // determine if empty line is required after
    int nextLineOffset = getLineNext(offset);
    String insertLine = source.substring(offset, nextLineOffset);
    if (!insertLine.trim().isEmpty) {
      insertEmptyLineAfter = true;
    }
    // fill InsertDesc
    CorrectionUtils_InsertDesc desc = new CorrectionUtils_InsertDesc();
    desc.offset = offset;
    if (insertEmptyLineBefore) {
      desc.prefix = endOfLine;
    }
    if (insertEmptyLineAfter) {
      desc.suffix = endOfLine;
    }
    return desc;
  }

  /**
   * Skips whitespace characters and single EOL on the right from the given position. If from
   * statement or method end, then this is in the most cases start of the next line.
   */
  int getLineContentEnd(int index) {
    int length = _buffer.length;
    // skip whitespace characters
    while (index < length) {
      int c = _buffer.codeUnitAt(index);
      if (!Character.isWhitespace(c) || c == 0xD || c == 0xA) {
        break;
      }
      index++;
    }
    // skip single \r
    if (index < length && _buffer.codeUnitAt(index) == 0xD) {
      index++;
    }
    // skip single \n
    if (index < length && _buffer.codeUnitAt(index) == 0xA) {
      index++;
    }
    // done
    return index;
  }

  /**
   * @return the index of the last space or tab on the left from the given one, if from statement or
   *         method start, then this is in most cases start of the line.
   */
  int getLineContentStart(int index) {
    while (index > 0) {
      int c = _buffer.codeUnitAt(index - 1);
      if (c != 0x20 && c != 0x9) {
        break;
      }
      index--;
    }
    return index;
  }

  /**
   * @return the start index of the next line after the line which contains given index.
   */
  int getLineNext(int index) {
    int length = _buffer.length;
    // skip to the end of the line
    while (index < length) {
      int c = _buffer.codeUnitAt(index);
      if (c == 0xD || c == 0xA) {
        break;
      }
      index++;
    }
    // skip single \r
    if (index < length && _buffer.codeUnitAt(index) == 0xD) {
      index++;
    }
    // skip single \n
    if (index < length && _buffer.codeUnitAt(index) == 0xA) {
      index++;
    }
    // done
    return index;
  }

  /**
   * @return the whitespace prefix of the line which contains given offset.
   */
  String getLinePrefix(int index) {
    int lineStart = getLineThis(index);
    int length = _buffer.length;
    int lineNonWhitespace = lineStart;
    while (lineNonWhitespace < length) {
      int c = _buffer.codeUnitAt(lineNonWhitespace);
      if (c == 0xD || c == 0xA) {
        break;
      }
      if (!Character.isWhitespace(c)) {
        break;
      }
      lineNonWhitespace++;
    }
    return getText2(lineStart, lineNonWhitespace - lineStart);
  }

  /**
   * @return the [getLinesRange] for given [Statement]s.
   */
  SourceRange getLinesRange(List<Statement> statements) {
    SourceRange range = SourceRangeFactory.rangeNodes(statements);
    return getLinesRange2(range);
  }

  /**
   * @return the [SourceRange] which starts at the start of the line of "offset" and ends at
   *         the start of the next line after "end" of the given [SourceRange], i.e. basically
   *         complete lines of the source for given [SourceRange].
   */
  SourceRange getLinesRange2(SourceRange range) {
    // start
    int startOffset = range.offset;
    int startLineOffset = getLineContentStart(startOffset);
    // end
    int endOffset = range.end;
    int afterEndLineOffset = getLineContentEnd(endOffset);
    // range
    return SourceRangeFactory.rangeStartEnd(
        startLineOffset, afterEndLineOffset);
  }

  /**
   * @return the [getLinesRange] for given [Statement]s.
   */
  SourceRange getLinesRange3(List<Statement> statements) => getLinesRange([]);

  /**
   * @return the start index of the line which contains given index.
   */
  int getLineThis(int index) {
    while (index > 0) {
      int c = _buffer.codeUnitAt(index - 1);
      if (c == 0xD || c == 0xA) {
        break;
      }
      index--;
    }
    return index;
  }

  /**
   * @return the line prefix consisting of spaces and tabs on the left from the given
   *         [AstNode].
   */
  String getNodePrefix(AstNode node) {
    int offset = node.offset;
    // function literal is special, it uses offset of enclosing line
    if (node is FunctionExpression) {
      return getLinePrefix(offset);
    }
    // use just prefix directly before node
    return getPrefix(offset);
  }

  /**
   * @return the index of the first non-whitespace character after given index.
   */
  int getNonWhitespaceForward(int index) {
    int length = _buffer.length;
    // skip whitespace characters
    while (index < length) {
      int c = _buffer.codeUnitAt(index);
      if (!Character.isWhitespace(c)) {
        break;
      }
      index++;
    }
    // done
    return index;
  }

  /**
   * @return the source for the parameter with the given type and name.
   */
  String getParameterSource(DartType type, String name) {
    // no type
    if (type == null || type.isDynamic) {
      return name;
    }
    // function type
    if (type is FunctionType) {
      FunctionType functionType = type;
      StringBuffer buffer = new StringBuffer();
      // return type
      DartType returnType = functionType.returnType;
      if (returnType != null && !returnType.isDynamic) {
        buffer.write(getTypeSource2(returnType));
        buffer.writeCharCode(0x20);
      }
      // parameter name
      buffer.write(name);
      // parameters
      buffer.writeCharCode(0x28);
      List<ParameterElement> fParameters = functionType.parameters;
      for (int i = 0; i < fParameters.length; i++) {
        ParameterElement fParameter = fParameters[i];
        if (i != 0) {
          buffer.write(", ");
        }
        buffer.write(getParameterSource(fParameter.type, fParameter.name));
      }
      buffer.writeCharCode(0x29);
      // done
      return buffer.toString();
    }
    // simple type
    return "${getTypeSource2(type)} ${name}";
  }

  /**
   * @return the line prefix consisting of spaces and tabs on the left from the given offset.
   */
  String getPrefix(int endIndex) {
    int startIndex = getLineContentStart(endIndex);
    return _buffer.substring(startIndex, endIndex);
  }

  /**
   * @return the full text of unit.
   */
  String get text => _buffer;

  /**
   * @return the given range of text from unit.
   */
  String getText(AstNode node) => getText2(node.offset, node.length);

  /**
   * @return the given range of text from unit.
   */
  String getText2(int offset, int length) =>
      _buffer.substring(offset, offset + length);

  /**
   * @return the given range of text from unit.
   */
  String getText3(SourceRange range) => getText2(range.offset, range.length);

  /**
   * @return the actual type source of the given [Expression], may be `null` if can not
   *         be resolved, should be treated as <code>Dynamic</code>.
   */
  String getTypeSource(Expression expression) {
    if (expression == null) {
      return null;
    }
    DartType type = expression.bestType;
    String typeSource = getTypeSource2(type);
    if ("dynamic" == typeSource) {
      return null;
    }
    return typeSource;
  }

  /**
   * @return the source to reference the given [Type] in this [CompilationUnit].
   */
  String getTypeSource2(DartType type) {
    StringBuffer buffer = new StringBuffer();
    // prepare element
    Element element = type.element;
    if (element == null) {
      String source = type.toString();
      source = StringUtils.remove(source, "<dynamic>");
      source = StringUtils.remove(source, "<dynamic, dynamic>");
      return source;
    }
    // append prefix
    {
      ImportElement imp = _getImportElement(element);
      if (imp != null && imp.prefix != null) {
        buffer.write(imp.prefix.displayName);
        buffer.write(".");
      }
    }
    // append simple name
    String name = element.displayName;
    buffer.write(name);
    // may be type arguments
    if (type is InterfaceType) {
      InterfaceType interfaceType = type;
      List<DartType> arguments = interfaceType.typeArguments;
      // check if has arguments
      bool hasArguments = false;
      for (DartType argument in arguments) {
        if (!argument.isDynamic) {
          hasArguments = true;
          break;
        }
      }
      // append type arguments
      if (hasArguments) {
        buffer.write("<");
        for (int i = 0; i < arguments.length; i++) {
          DartType argument = arguments[i];
          if (i != 0) {
            buffer.write(", ");
          }
          buffer.write(getTypeSource2(argument));
        }
        buffer.write(">");
      }
    }
    // done
    return buffer.toString();
  }

  /**
   * @return <code>true</code> if selection range contains only whitespace.
   */
  bool isJustWhitespace(SourceRange range) =>
      getText3(range).trim().length == 0;

  /**
   * @return <code>true</code> if selection range contains only whitespace or comments
   */
  bool isJustWhitespaceOrComment(SourceRange range) {
    String trimmedText = getText3(range).trim();
    // may be whitespace
    if (trimmedText.isEmpty) {
      return true;
    }
    // may be comment
    return TokenUtils.getTokens(trimmedText).isEmpty;
  }

  /**
   * @return <code>true</code> if "selection" covers "node" and there are any non-whitespace tokens
   *         between "selection" and "node" start/end.
   */
  bool selectionIncludesNonWhitespaceOutsideNode(
          SourceRange selection, AstNode node) =>
      _selectionIncludesNonWhitespaceOutsideRange(
          selection, SourceRangeFactory.rangeNode(node));

  /**
   * @return <code>true</code> if given range of [BinaryExpression] can be extracted.
   */
  bool validateBinaryExpressionRange(
      BinaryExpression binaryExpression, SourceRange range) {
    // only parts of associative expression are safe to extract
    if (!binaryExpression.operator.type.isAssociativeOperator) {
      return false;
    }
    // prepare selected operands
    List<Expression> operands = _getOperandsInOrderFor(binaryExpression);
    List<Expression> subOperands = _getOperandsForSourceRange(operands, range);
    // if empty, then something wrong with selection
    if (subOperands.isEmpty) {
      return false;
    }
    // may be some punctuation included into selection - operators, braces, etc
    if (_selectionIncludesNonWhitespaceOutsideOperands(range, subOperands)) {
      return false;
    }
    // OK
    return true;
  }

  /**
   * @return the [ImportElement] used to import given [Element] into [library].
   *         May be `null` if was not imported, i.e. declared in the same library.
   */
  ImportElement _getImportElement(Element element) {
    for (ImportElement imp in _library.imports) {
      Map<String, Element> definedNames = getImportNamespace(imp);
      if (definedNames.containsValue(element)) {
        return imp;
      }
    }
    return null;
  }

  bool _selectionIncludesNonWhitespaceOutsideOperands(
          SourceRange selection, List<Expression> operands) =>
      _selectionIncludesNonWhitespaceOutsideRange(
          selection, SourceRangeFactory.rangeNodes(operands));

  /**
   * @return <code>true</code> if "selection" covers "range" and there are any non-whitespace tokens
   *         between "selection" and "range" start/end.
   */
  bool _selectionIncludesNonWhitespaceOutsideRange(
      SourceRange selection, SourceRange range) {
    // selection should cover range
    if (!selection.covers(range)) {
      return false;
    }
    // non-whitespace between selection start and range start
    if (!isJustWhitespaceOrComment(
        SourceRangeFactory.rangeStartStart(selection, range))) {
      return true;
    }
    // non-whitespace after range
    if (!isJustWhitespaceOrComment(
        SourceRangeFactory.rangeEndEnd(range, selection))) {
      return true;
    }
    // only whitespace in selection around range
    return false;
  }
}

/**
 * Describes where to insert new directive or top-level declaration.
 */
class CorrectionUtils_InsertDesc {
  int offset = 0;

  String prefix = "";

  String suffix = "";
}

class GeneralizingAstVisitor_CorrectionUtils_getOperandsInOrderFor
    extends GeneralizingAstVisitor<Object> {
  TokenType groupOperatorType;

  List<Expression> operands;

  GeneralizingAstVisitor_CorrectionUtils_getOperandsInOrderFor(
      this.groupOperatorType, this.operands)
      : super();

  @override
  Object visitExpression(Expression node) {
    if (node is BinaryExpression && node.operator.type == groupOperatorType) {
      return super.visitNode(node);
    }
    operands.add(node);
    return null;
  }
}

class GeneralizingElementVisitor_CorrectionUtils_getChildren
    extends GeneralizingElementVisitor<Object> {
  Element parent;

  String name;

  List<Element> children;

  GeneralizingElementVisitor_CorrectionUtils_getChildren(
      this.parent, this.name, this.children)
      : super();

  @override
  Object visitElement(Element element) {
    if (identical(element, parent)) {
      super.visitElement(element);
    } else if (name == null || CorrectionUtils.hasDisplayName(element, name)) {
      children.add(element);
    }
    return null;
  }
}

class GeneralizingElementVisitor_HierarchyUtils_getDirectMembers
    extends GeneralizingElementVisitor<Object> {
  ClassElement clazz;

  bool includeSynthetic = false;

  List<Element> members;

  GeneralizingElementVisitor_HierarchyUtils_getDirectMembers(
      this.clazz, this.includeSynthetic, this.members)
      : super();

  @override
  Object visitElement(Element element) {
    if (identical(element, clazz)) {
      return super.visitElement(element);
    }
    if (!includeSynthetic && element.isSynthetic) {
      return null;
    }
    if (element is ConstructorElement) {
      return null;
    }
    if (element is ExecutableElement) {
      members.add(element);
    }
    if (element is FieldElement) {
      members.add(element);
    }
    return null;
  }
}

class NameOccurrencesFinder extends RecursiveAstVisitor<Object> {
  static Iterable<AstNode> findIn(SimpleIdentifier ident, AstNode root) {
    if (ident == null || ident.bestElement == null) {
      return new Set<AstNode>();
    }
    NameOccurrencesFinder finder = new NameOccurrencesFinder(ident.bestElement);
    root.accept(finder);
    return finder.matches;
  }

  Element _target;

  Element _target2;

  Element _target3;

  Element _target4;

  Set<AstNode> _matches;

  NameOccurrencesFinder(Element source) {
    this._target = source;
    while (true) {
      if (source.kind == ElementKind.GETTER ||
          source.kind == ElementKind.SETTER) {
        PropertyAccessorElement accessorElem =
            source as PropertyAccessorElement;
        this._target2 = accessorElem.variable;
        if (source is Member) {
          Member member = source;
          this._target4 = member.baseElement;
        }
        if (this._target2 is Member) {
          Member member = source as Member;
          this._target3 = member.baseElement;
        }
      } else if (source.kind == ElementKind.FIELD ||
          source.kind == ElementKind.TOP_LEVEL_VARIABLE) {
        PropertyInducingElement propertyElem =
            source as PropertyInducingElement;
        this._target2 = propertyElem.getter;
        this._target3 = propertyElem.setter;
      } else if (source.kind == ElementKind.METHOD) {
        if (source is Member) {
          Member member = source;
          this._target4 = member.baseElement;
        }
      } else if (source.kind == ElementKind.PARAMETER) {
        ParameterElement param = source as ParameterElement;
        if (param.isInitializingFormal) {
          FieldFormalParameterElement fieldInit =
              param as FieldFormalParameterElement;
          this._target2 = fieldInit.field;
        }
      } else {}
      break;
    }
    if (_target2 == null) {
      _target2 = _target;
    }
    if (_target3 == null) {
      _target3 = _target;
    }
    if (_target4 == null) {
      _target4 = _target;
    }
    this._matches = new Set<AstNode>();
  }

  Iterable<AstNode> get matches => _matches;

  @override
  Object visitSimpleIdentifier(SimpleIdentifier node) {
    Element element = node.bestElement;
    if (element == null) {
      return null;
    }
    _match(element, node);
    if (element is Member) {
      Member member = element;
      _match(member.baseElement, node);
    }
    while (true) {
      if (element.kind == ElementKind.GETTER ||
          element.kind == ElementKind.SETTER) {
        PropertyAccessorElement accessorElem =
            element as PropertyAccessorElement;
        _match(accessorElem.variable, node);
      } else if (element.kind == ElementKind.FIELD ||
          element.kind == ElementKind.TOP_LEVEL_VARIABLE) {
        PropertyInducingElement propertyElem =
            element as PropertyInducingElement;
        _match(propertyElem.getter, node);
        _match(propertyElem.setter, node);
      } else if (element.kind == ElementKind.PARAMETER) {
        ParameterElement param = element as ParameterElement;
        if (param.isInitializingFormal) {
          FieldFormalParameterElement fieldInit =
              param as FieldFormalParameterElement;
          _match(fieldInit.field, node);
        }
      } else {}
      break;
    }
    return null;
  }

  void _match(Element element, AstNode node) {
    if (identical(_target, element) ||
        identical(_target2, element) ||
        identical(_target3, element) ||
        identical(_target4, element)) {
      _matches.add(node);
    }
  }
}

/**
 * Utilities to work with [Token]s.
 */
class TokenUtils {
  /**
   * @return the first [KeywordToken] with given [Keyword], may be <code>null</code> if
   *         not found.
   */
  static KeywordToken findKeywordToken(List<Token> tokens, Keyword keyword) {
    for (Token token in tokens) {
      if (token is KeywordToken) {
        KeywordToken keywordToken = token;
        if (keywordToken.keyword == keyword) {
          return keywordToken;
        }
      }
    }
    return null;
  }

  /**
   * @return the first [Token] with given [TokenType], may be <code>null</code> if not
   *         found.
   */
  static Token findToken(List<Token> tokens, TokenType type) {
    for (Token token in tokens) {
      if (token.type == type) {
        return token;
      }
    }
    return null;
  }

  /**
   * @return [Token]s of the given Dart source, not <code>null</code>, may be empty if no
   *         tokens or some exception happens.
   */
  static List<Token> getTokens(String s) {
    try {
      List<Token> tokens = [];
      Scanner scanner = new Scanner(null, new CharSequenceReader(s), null);
      Token token = scanner.tokenize();
      while (token.type != TokenType.EOF) {
        tokens.add(token);
        token = token.next;
      }
      return tokens;
    } catch (e) {
      return [];
    }
  }

  /**
   * @return <code>true</code> if given [Token]s contain only single [Token] with given
   *         [TokenType].
   */
  static bool hasOnly(List<Token> tokens, TokenType type) =>
      tokens.length == 1 && tokens[0].type == type;
}
