// 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.refactoring.inline_method;

import 'dart:async';

import 'package:analysis_server/src/protocol_server.dart' hide Element;
import 'package:analysis_server/src/services/correction/source_range.dart';
import 'package:analysis_server/src/services/correction/status.dart';
import 'package:analysis_server/src/services/correction/strings.dart';
import 'package:analysis_server/src/services/correction/util.dart';
import 'package:analysis_server/src/services/refactoring/refactoring.dart';
import 'package:analysis_server/src/services/refactoring/refactoring_internal.dart';
import 'package:analysis_server/src/services/search/element_visitors.dart';
import 'package:analysis_server/src/services/search/hierarchy.dart';
import 'package:analysis_server/src/services/search/search_engine.dart';
import 'package:analyzer/src/generated/ast.dart';
import 'package:analyzer/src/generated/element.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/generated/utilities_dart.dart';


/**
 * Returns the [SourceRange] to find conflicting locals in.
 */
SourceRange _getLocalsConflictingRange(AstNode node) {
  // maybe Block
  Block block = node.getAncestor((node) => node is Block);
  if (block != null) {
    int offset = node.offset;
    int endOffset = block.end;
    return rangeStartEnd(offset, endOffset);
  }
  // maybe whole executable
  AstNode executableNode = getEnclosingExecutableNode(node);
  if (executableNode != null) {
    return rangeNode(executableNode);
  }
  // not a part of a declaration with locals
  return SourceRange.EMPTY;
}


/**
 * Returns the source which should replace given invocation with given
 * arguments.
 */
String _getMethodSourceForInvocation(RefactoringStatus status, _SourcePart part,
    CorrectionUtils utils, AstNode contextNode, Expression targetExpression,
    List<Expression> arguments) {
  // prepare edits to replace parameters with arguments
  List<SourceEdit> edits = <SourceEdit>[];
  part._parameters.forEach(
      (ParameterElement parameter, List<_ParameterOccurrence> occurrences) {
    // prepare argument
    Expression argument = null;
    for (Expression arg in arguments) {
      if (arg.bestParameterElement == parameter) {
        argument = arg;
        break;
      }
    }
    if (argument is NamedExpression) {
      argument = (argument as NamedExpression).expression;
    }
    // prepare argument properties
    int argumentPrecedence;
    String argumentSource;
    if (argument != null) {
      argumentPrecedence = getExpressionPrecedence(argument);
      argumentSource = utils.getNodeText(argument);
    } else {
      // report about a missing required parameter
      if (parameter.parameterKind == ParameterKind.REQUIRED) {
        status.addError(
            'No argument for the parameter "${parameter.name}".',
            newLocation_fromNode(contextNode));
        return;
      }
      // an optional parameter
      argumentPrecedence = -1000;
      argumentSource = parameter.defaultValueCode;
      if (argumentSource == null) {
        argumentSource = 'null';
      }
    }
    // replace all occurrences of this parameter
    for (_ParameterOccurrence occurrence in occurrences) {
      SourceRange range = occurrence.range;
      // prepare argument source to apply at this occurrence
      String occurrenceArgumentSource;
      if (argumentPrecedence < occurrence.parentPrecedence) {
        occurrenceArgumentSource = "($argumentSource)";
      } else {
        occurrenceArgumentSource = argumentSource;
      }
      // do replace
      edits.add(newSourceEdit_range(range, occurrenceArgumentSource));
    }
  });
  // replace static field "qualifier" with invocation target
  part._staticFieldQualifiers.forEach(
      (String className, List<SourceRange> ranges) {
    for (SourceRange range in ranges) {
      edits.add(newSourceEdit_range(range, className + '.'));
    }
  });
  // replace instance field "qualifier" with invocation target
  if (targetExpression != null) {
    String targetSource = utils.getNodeText(targetExpression) + '.';
    for (SourceRange qualifierRange in part._instanceFieldQualifiers) {
      edits.add(newSourceEdit_range(qualifierRange, targetSource));
    }
  }
  // prepare edits to replace conflicting variables
  Set<String> conflictingNames = _getNamesConflictingAt(contextNode);
  part._variables.forEach((VariableElement variable, List<SourceRange> ranges) {
    String originalName = variable.displayName;
    // prepare unique name
    String uniqueName;
    {
      uniqueName = originalName;
      int uniqueIndex = 2;
      while (conflictingNames.contains(uniqueName)) {
        uniqueName = originalName + uniqueIndex.toString();
        uniqueIndex++;
      }
    }
    // update references, if name was change
    if (uniqueName != originalName) {
      for (SourceRange range in ranges) {
        edits.add(newSourceEdit_range(range, uniqueName));
      }
    }
  });
  // prepare source with applied arguments
  edits.sort((SourceEdit a, SourceEdit b) => b.offset - a.offset);
  return SourceEdit.applySequence(part._source, edits);
}


/**
 * Returns the names which will shadow or will be shadowed by any declaration
 * at [node].
 */
Set<String> _getNamesConflictingAt(AstNode node) {
  Set<String> result = new Set<String>();
  // local variables and functions
  {
    SourceRange localsRange = _getLocalsConflictingRange(node);
    ExecutableElement enclosingExecutable = getEnclosingExecutableElement(node);
    if (enclosingExecutable != null) {
      visitChildren(enclosingExecutable, (element) {
        if (element is LocalElement) {
          SourceRange elementRange = element.visibleRange;
          if (elementRange != null && elementRange.intersects(localsRange)) {
            result.add(element.displayName);
          }
        }
        return true;
      });
    }
  }
  // fields
  {
    ClassElement enclosingClassElement = getEnclosingClassElement(node);
    if (enclosingClassElement != null) {
      Set<ClassElement> elements = new Set<ClassElement>();
      elements.add(enclosingClassElement);
      elements.addAll(getSuperClasses(enclosingClassElement));
      for (ClassElement classElement in elements) {
        List<Element> classMembers = getChildren(classElement);
        for (Element classMemberElement in classMembers) {
          result.add(classMemberElement.displayName);
        }
      }
    }
  }
  // done
  return result;
}


/**
 * [InlineMethodRefactoring] implementation.
 */
class InlineMethodRefactoringImpl extends RefactoringImpl implements
    InlineMethodRefactoring {
  final SearchEngine searchEngine;
  final CompilationUnit unit;
  final int offset;
  CorrectionUtils utils;
  SourceChange change;

  bool isDeclaration = false;
  bool deleteSource = false;
  bool inlineAll = true;

  ExecutableElement _methodElement;
  bool _isAccessor;
  String _methodFile;
  CompilationUnit _methodUnit;
  CorrectionUtils _methodUtils;
  AstNode _methodNode;
  FormalParameterList _methodParameters;
  FunctionBody _methodBody;
  Expression _methodExpression;
  _SourcePart _methodExpressionPart;
  _SourcePart _methodStatementsPart;
  List<_ReferenceProcessor> _referenceProcessors = [];

  InlineMethodRefactoringImpl(this.searchEngine, this.unit, this.offset) {
    utils = new CorrectionUtils(unit);
  }

  @override
  String get className {
    if (_methodElement == null) {
      return null;
    }
    Element classElement = _methodElement.enclosingElement;
    if (classElement is ClassElement) {
      return classElement.displayName;
    }
    return null;
  }

  @override
  String get methodName {
    if (_methodElement == null) {
      return null;
    }
    return _methodElement.displayName;
  }

  @override
  String get refactoringName {
    if (_methodElement is MethodElement) {
      return "Inline Method";
    } else {
      return "Inline Function";
    }
  }

  @override
  Future<RefactoringStatus> checkFinalConditions() {
    change = new SourceChange(refactoringName);
    RefactoringStatus result = new RefactoringStatus();
    // check for compatibility of "deleteSource" and "inlineAll"
    if (deleteSource && !inlineAll) {
      result.addError('All references must be inlined to remove the source.');
    }
    // prepare changes
    for (_ReferenceProcessor processor in _referenceProcessors) {
      processor._process(result);
    }
    // delete method
    if (deleteSource && inlineAll) {
      SourceRange methodRange = rangeNode(_methodNode);
      SourceRange linesRange = _methodUtils.getLinesRange(methodRange);
      doSourceChange_addElementEdit(
          change,
          _methodElement,
          newSourceEdit_range(linesRange, ''));
    }
    // done
    return new Future.value(result);
  }

  @override
  Future<RefactoringStatus> checkInitialConditions() {
    RefactoringStatus result = new RefactoringStatus();
    // prepare method information
    result.addStatus(_prepareMethod());
    if (result.hasFatalError) {
      return new Future.value(result);
    }
    // maybe operator
    if (_methodElement.isOperator) {
      result = new RefactoringStatus.fatal('Cannot inline operator.');
      return new Future.value(result);
    }
    // analyze method body
    result.addStatus(_prepareMethodParts());
    // process references
    return searchEngine.searchReferences(_methodElement).then((references) {
      _referenceProcessors.clear();
      for (SearchMatch reference in references) {
        _ReferenceProcessor processor =
            new _ReferenceProcessor(this, reference);
        _referenceProcessors.add(processor);
      }
    }).then((_) {
      return result;
    });
  }

  @override
  Future<SourceChange> createChange() {
    return new Future.value(change);
  }

  @override
  bool requiresPreview() => false;

  _SourcePart _createSourcePart(SourceRange range) {
    String source = _methodUtils.getRangeText(range);
    String prefix = getLinePrefix(source);
    _SourcePart result = new _SourcePart(range.offset, source, prefix);
    // remember parameters and variables occurrences
    _methodUnit.accept(new _VariablesVisitor(_methodElement, range, result));
    // done
    return result;
  }

  /**
   * Initializes [_methodElement] and related fields.
   */
  RefactoringStatus _prepareMethod() {
    _methodElement = null;
    _methodParameters = null;
    _methodBody = null;
    deleteSource = false;
    inlineAll = false;
    // prepare for failure
    RefactoringStatus fatalStatus = new RefactoringStatus.fatal(
        'Method declaration or reference must be selected to activate this refactoring.');
    // prepare selected SimpleIdentifier
    AstNode node = new NodeLocator.con1(offset).searchWithin(unit);
    if (node is! SimpleIdentifier) {
      return fatalStatus;
    }
    SimpleIdentifier identifier = node as SimpleIdentifier;
    // prepare selected ExecutableElement
    Element element = identifier.bestElement;
    if (element is! ExecutableElement) {
      return fatalStatus;
    }
    _methodElement = element as ExecutableElement;
    _isAccessor = element is PropertyAccessorElement;
    _methodFile = _methodElement.source.fullName;
    _methodUnit = element.unit;
    _methodUtils = new CorrectionUtils(_methodUnit);
    // class member
    bool isClassMember = element.enclosingElement is ClassElement;
    if (element is MethodElement || _isAccessor && isClassMember) {
      MethodDeclaration methodDeclaration = element.node;
      _methodNode = methodDeclaration;
      _methodParameters = methodDeclaration.parameters;
      _methodBody = methodDeclaration.body;
      // prepare mode
      isDeclaration = node == methodDeclaration.name;
      deleteSource = isDeclaration;
      inlineAll = deleteSource;
      return new RefactoringStatus();
    }
    // unit member
    bool isUnitMember = element.enclosingElement is CompilationUnitElement;
    if (element is FunctionElement || _isAccessor && isUnitMember) {
      FunctionDeclaration functionDeclaration = element.node;
      _methodNode = functionDeclaration;
      _methodParameters = functionDeclaration.functionExpression.parameters;
      _methodBody = functionDeclaration.functionExpression.body;
      // prepare mode
      isDeclaration = node == functionDeclaration.name;
      deleteSource = isDeclaration;
      inlineAll = deleteSource;
      return new RefactoringStatus();
    }
    // OK
    return fatalStatus;
  }

  /**
   * Analyze [_methodBody] to fill [_methodExpressionPart] and
   * [_methodStatementsPart].
   */
  RefactoringStatus _prepareMethodParts() {
    RefactoringStatus result = new RefactoringStatus();
    if (_methodBody is ExpressionFunctionBody) {
      ExpressionFunctionBody body = _methodBody as ExpressionFunctionBody;
      _methodExpression = body.expression;
      SourceRange methodExpressionRange = rangeNode(_methodExpression);
      _methodExpressionPart = _createSourcePart(methodExpressionRange);
    } else if (_methodBody is BlockFunctionBody) {
      Block body = (_methodBody as BlockFunctionBody).block;
      List<Statement> statements = body.statements;
      if (statements.length >= 1) {
        Statement lastStatement = statements[statements.length - 1];
        // "return" statement requires special handling
        if (lastStatement is ReturnStatement) {
          _methodExpression = lastStatement.expression;
          SourceRange methodExpressionRange = rangeNode(_methodExpression);
          _methodExpressionPart = _createSourcePart(methodExpressionRange);
          // exclude "return" statement from statements
          statements = statements.sublist(0, statements.length - 1);
        }
        // if there are statements, process them
        if (!statements.isEmpty) {
          SourceRange statementsRange =
              _methodUtils.getLinesRangeStatements(statements);
          _methodStatementsPart = _createSourcePart(statementsRange);
        }
      }
      // check if more than one return
      body.accept(new _ReturnsValidatorVisitor(result));
    } else {
      return new RefactoringStatus.fatal('Cannot inline method without body.');
    }
    return result;
  }
}


class _ParameterOccurrence {
  final int parentPrecedence;
  final SourceRange range;
  _ParameterOccurrence(this.parentPrecedence, this.range);
}


/**
 * Processor for single [SearchMatch] reference to [methodElement].
 */
class _ReferenceProcessor {
  final InlineMethodRefactoringImpl ref;

  Element refElement;
  CorrectionUtils _refUtils;
  SimpleIdentifier _node;
  SourceRange _refLineRange;
  String _refPrefix;

  _ReferenceProcessor(this.ref, SearchMatch reference) {
    refElement = reference.element;
    // prepare CorrectionUtils
    CompilationUnit refUnit = refElement.unit;
    _refUtils = new CorrectionUtils(refUnit);
    // prepare node and environment
    _node = _refUtils.findNode(reference.sourceRange.offset);
    Statement refStatement = _node.getAncestor((node) => node is Statement);
    if (refStatement != null) {
      _refLineRange = _refUtils.getLinesRangeStatements([refStatement]);
      _refPrefix = _refUtils.getNodePrefix(refStatement);
    } else {
      _refLineRange = null;
      _refPrefix = _refUtils.getLinePrefix(_node.offset);
    }
  }

  void _addRefEdit(SourceEdit edit) {
    doSourceChange_addElementEdit(ref.change, refElement, edit);
  }

  bool _canInlineBody(AstNode usage) {
    // no statements, usually just expression
    if (ref._methodStatementsPart == null) {
      // empty method, inline as closure
      if (ref._methodExpressionPart == null) {
        return false;
      }
      // OK, just expression
      return true;
    }
    // analyze point of invocation
    AstNode parent = usage.parent;
    AstNode parent2 = parent.parent;
    // OK, if statement in block
    if (parent is Statement) {
      return parent2 is Block;
    }
    // maybe assignment, in block
    if (parent is AssignmentExpression) {
      AssignmentExpression assignment = parent;
      // inlining setter
      if (assignment.leftHandSide == usage) {
        return parent2 is Statement && parent2.parent is Block;
      }
      // inlining initializer
      return ref._methodExpressionPart != null;
    }
    // maybe value for variable initializer, in block
    if (ref._methodExpressionPart != null) {
      if (parent is VariableDeclaration) {
        if (parent2 is VariableDeclarationList) {
          AstNode parent3 = parent2.parent;
          return parent3 is VariableDeclarationStatement &&
              parent3.parent is Block;
        }
      }
    }
    // not in block, cannot inline body
    return false;
  }

  void _inlineMethodInvocation(RefactoringStatus status, Expression usage,
      bool cascaded, Expression target, List<Expression> arguments) {
    // we don't support cascade
    if (cascaded) {
      status.addError(
          'Cannot inline cascade invocation.',
          newLocation_fromNode(usage));
    }
    // can we inline method body into "methodUsage" block?
    if (_canInlineBody(usage)) {
      // insert non-return statements
      if (ref._methodStatementsPart != null) {
        // prepare statements source for invocation
        String source = _getMethodSourceForInvocation(
            status,
            ref._methodStatementsPart,
            _refUtils,
            usage,
            target,
            arguments);
        source = _refUtils.replaceSourceIndent(
            source,
            ref._methodStatementsPart._prefix,
            _refPrefix);
        // do insert
        SourceRange range = rangeStartLength(_refLineRange, 0);
        SourceEdit edit = newSourceEdit_range(range, source);
        _addRefEdit(edit);
      }
      // replace invocation with return expression
      if (ref._methodExpressionPart != null) {
        // prepare expression source for invocation
        String source = _getMethodSourceForInvocation(
            status,
            ref._methodExpressionPart,
            _refUtils,
            usage,
            target,
            arguments);
        if (getExpressionPrecedence(ref._methodExpression) <
            getExpressionParentPrecedence(usage)) {
          source = "(${source})";
        }
        // do replace
        SourceRange methodUsageRange = rangeNode(usage);
        SourceEdit edit = newSourceEdit_range(methodUsageRange, source);
        _addRefEdit(edit);
      } else {
        SourceEdit edit = newSourceEdit_range(_refLineRange, "");
        _addRefEdit(edit);
      }
      return;
    }
    // inline as closure invocation
    String source;
    {
      source = ref._methodUtils.getRangeText(
          rangeStartEnd(ref._methodParameters.leftParenthesis, ref._methodNode));
      String methodPrefix =
          ref._methodUtils.getLinePrefix(ref._methodNode.offset);
      source = _refUtils.replaceSourceIndent(source, methodPrefix, _refPrefix);
      source = source.trim();
    }
    // do insert
    SourceRange range = rangeNode(_node);
    SourceEdit edit = newSourceEdit_range(range, source);
    _addRefEdit(edit);
  }

  void _process(RefactoringStatus status) {
    AstNode nodeParent = _node.parent;
    // may be only single place should be inlined
    if (!_shouldProcess()) {
      return;
    }
    // may be invocation of inline method
    if (nodeParent is MethodInvocation) {
      MethodInvocation invocation = nodeParent;
      Expression target = invocation.target;
      List<Expression> arguments = invocation.argumentList.arguments;
      _inlineMethodInvocation(
          status,
          invocation,
          invocation.isCascaded,
          target,
          arguments);
    } else {
      // cannot inline reference to method: var v = new A().method;
      if (ref._methodElement is MethodElement) {
        status.addFatalError(
            'Cannot inline class method reference.',
            newLocation_fromNode(_node));
        return;
      }
      // PropertyAccessorElement
      if (ref._methodElement is PropertyAccessorElement) {
        Expression usage = _node;
        Expression target = null;
        bool cascade = false;
        if (nodeParent is PrefixedIdentifier) {
          PrefixedIdentifier propertyAccess = nodeParent;
          usage = propertyAccess;
          target = propertyAccess.prefix;
          cascade = false;
        }
        if (nodeParent is PropertyAccess) {
          PropertyAccess propertyAccess = nodeParent;
          usage = propertyAccess;
          target = propertyAccess.realTarget;
          cascade = propertyAccess.isCascaded;
        }
        // prepare arguments
        List<Expression> arguments = [];
        if (_node.inSetterContext()) {
          AssignmentExpression assignment =
              _node.getAncestor((node) => node is AssignmentExpression);
          arguments.add(assignment.rightHandSide);
        }
        // inline body
        _inlineMethodInvocation(status, usage, cascade, target, arguments);
        return;
      }
      // not invocation, just reference to function
      String source;
      {
        source = ref._methodUtils.getRangeText(
            rangeStartEnd(ref._methodParameters.leftParenthesis, ref._methodNode));
        String methodPrefix =
            ref._methodUtils.getLinePrefix(ref._methodNode.offset);
        source =
            _refUtils.replaceSourceIndent(source, methodPrefix, _refPrefix);
        source = source.trim();
        source = removeEnd(source, ';');
      }
      // do insert
      SourceRange range = rangeNode(_node);
      SourceEdit edit = newSourceEdit_range(range, source);
      _addRefEdit(edit);
    }
  }

  bool _shouldProcess() {
    if (!ref.inlineAll) {
      SourceRange parentRange = rangeNode(_node);
      return parentRange.contains(ref.offset);
    }
    return true;
  }
}

class _ReturnsValidatorVisitor extends RecursiveAstVisitor {
  final RefactoringStatus result;
  int _numReturns = 0;

  _ReturnsValidatorVisitor(this.result);

  @override
  visitReturnStatement(ReturnStatement node) {
    _numReturns++;
    if (_numReturns == 2) {
      result.addError('Ambiguous return value.', newLocation_fromNode(node));
    }
  }
}

/**
 * Information about the source of a method being inlined.
 */
class _SourcePart {
  /**
   * The base for all [SourceRange]s.
   */
  final int _base;

  /**
   * The source of the method.
   */
  final String _source;

  /**
   * The original prefix of the method.
   */
  final String _prefix;

  /**
   * The occurrences of the method parameters.
   */
  Map<ParameterElement, List<_ParameterOccurrence>> _parameters = {};

  /**
   * The occurrences of the method local variables.
   */
  Map<VariableElement, List<SourceRange>> _variables = {};

  /**
   * The source ranges of the qualifiers in instance field references.
   * Some of them have length `0`.
   */
  List<SourceRange> _instanceFieldQualifiers = [];

  /**
   * The source ranges of the qualifiers in instance field references.
   * Some of them have length `0`.
   */
  Map<String, List<SourceRange>> _staticFieldQualifiers = {};

  _SourcePart(this._base, this._source, this._prefix);

  void addInstanceFieldQualifier(SourceRange range) {
    range = rangeFromBase(range, _base);
    _instanceFieldQualifiers.add(range);
  }

  void addParameterOccurrence(ParameterElement parameter, SourceRange range,
      int precedence) {
    if (parameter != null) {
      List<_ParameterOccurrence> occurrences = _parameters[parameter];
      if (occurrences == null) {
        occurrences = [];
        _parameters[parameter] = occurrences;
      }
      range = rangeFromBase(range, _base);
      occurrences.add(new _ParameterOccurrence(precedence, range));
    }
  }

  void addStaticFieldQualifier(String className, SourceRange range) {
    List<SourceRange> ranges = _staticFieldQualifiers[className];
    if (ranges == null) {
      ranges = [];
      _staticFieldQualifiers[className] = ranges;
    }
    range = rangeFromBase(range, _base);
    ranges.add(range);
  }

  void addVariable(VariableElement element, SourceRange range) {
    List<SourceRange> ranges = _variables[element];
    if (ranges == null) {
      ranges = [];
      _variables[element] = ranges;
    }
    range = rangeFromBase(range, _base);
    ranges.add(range);
  }
}

/**
 * A visitor that fills [_SourcePart] with fields, parameters and variables.
 */
class _VariablesVisitor extends GeneralizingAstVisitor {
  /**
   * The [ExecutableElement] being inlined.
   */
  final ExecutableElement methodElement;

  /**
   * The [SourceRange] of the element body.
   */
  SourceRange bodyRange;

  /**
   * The [_SourcePart] to record reference into.
   */
  _SourcePart result;

  _VariablesVisitor(this.methodElement, this.bodyRange, this.result);

  @override
  visitNode(AstNode node) {
    SourceRange nodeRange = rangeNode(node);
    if (!bodyRange.intersects(nodeRange)) {
      return null;
    }
    super.visitNode(node);
  }

  @override
  visitSimpleIdentifier(SimpleIdentifier node) {
    SourceRange nodeRange = rangeNode(node);
    if (bodyRange.covers(nodeRange)) {
      _addInstanceFieldQualifier(node);
      _addParameter(node);
      _addVariable(node);
    }
  }

  void _addInstanceFieldQualifier(SimpleIdentifier node) {
    PropertyAccessorElement accessor = getPropertyAccessorElement(node);
    if (isFieldAccessorElement(accessor)) {
      AstNode qualifier = getNodeQualifier(node);
      if (qualifier == null || qualifier is ThisExpression) {
        if (accessor.isStatic) {
          String className = accessor.enclosingElement.displayName;
          if (qualifier == null) {
            SourceRange qualifierRange = rangeStartLength(node, 0);
            result.addStaticFieldQualifier(className, qualifierRange);
          }
        } else {
          SourceRange qualifierRange;
          if (qualifier != null) {
            qualifierRange = rangeStartStart(qualifier, node);
          } else {
            qualifierRange = rangeStartLength(node, 0);
          }
          result.addInstanceFieldQualifier(qualifierRange);
        }
      }
    }
  }

  void _addParameter(SimpleIdentifier node) {
    ParameterElement parameterElement = getParameterElement(node);
    // not a parameter
    if (parameterElement == null) {
      return;
    }
    // not a parameter of the function being inlined
    if (!methodElement.parameters.contains(parameterElement)) {
      return;
    }
    // OK, add occurrence
    SourceRange nodeRange = rangeNode(node);
    int parentPrecedence = getExpressionParentPrecedence(node);
    result.addParameterOccurrence(
        parameterElement,
        nodeRange,
        parentPrecedence);
  }

  void _addVariable(SimpleIdentifier node) {
    VariableElement variableElement = getLocalVariableElement(node);
    if (variableElement != null) {
      SourceRange nodeRange = rangeNode(node);
      result.addVariable(variableElement, nodeRange);
    }
  }
}
