location.js 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. 'use strict';
  2. var syntax = require('estraverse').Syntax;
  3. function locationOf(currentNode, tokens) {
  4. switch(currentNode.type) {
  5. case syntax.MemberExpression:
  6. return propertyLocationOf(currentNode, tokens);
  7. case syntax.CallExpression:
  8. if (currentNode.callee.type === syntax.MemberExpression) {
  9. return propertyLocationOf(currentNode.callee, tokens);
  10. }
  11. break;
  12. case syntax.BinaryExpression:
  13. case syntax.LogicalExpression:
  14. case syntax.AssignmentExpression:
  15. return infixOperatorLocationOf(currentNode, tokens);
  16. default:
  17. break;
  18. }
  19. return currentNode.range;
  20. }
  21. function propertyLocationOf(memberExpression, tokens) {
  22. var prop = memberExpression.property;
  23. var token;
  24. if (!memberExpression.computed) {
  25. return prop.range;
  26. }
  27. token = findLeftBracketTokenOf(memberExpression, tokens);
  28. return token ? token.range : prop.range;
  29. }
  30. // calculate location of infix operator for BinaryExpression, AssignmentExpression and LogicalExpression.
  31. function infixOperatorLocationOf (expression, tokens) {
  32. var token = findOperatorTokenOf(expression, tokens);
  33. return token ? token.range : expression.left.range;
  34. }
  35. function findLeftBracketTokenOf(expression, tokens) {
  36. var fromColumn = expression.property.range[0];
  37. return searchToken(tokens, function (token, index) {
  38. var prevToken;
  39. if (token.range[0] === fromColumn) {
  40. prevToken = tokens[index - 1];
  41. // if (prevToken.type === 'Punctuator' && prevToken.value === '[') { // esprima
  42. if (prevToken.type.label === '[') { // acorn
  43. return prevToken;
  44. }
  45. }
  46. return undefined;
  47. });
  48. }
  49. function findOperatorTokenOf(expression, tokens) {
  50. var fromColumn = expression.left.range[1];
  51. var toColumn = expression.right.range[0];
  52. return searchToken(tokens, function (token, index) {
  53. if (fromColumn < token.range[0] &&
  54. token.range[1] < toColumn &&
  55. token.value === expression.operator) {
  56. return token;
  57. }
  58. return undefined;
  59. });
  60. }
  61. function searchToken(tokens, predicate) {
  62. var i, token, found;
  63. for(i = 0; i < tokens.length; i += 1) {
  64. token = tokens[i];
  65. found = predicate(token, i);
  66. if (found) {
  67. return found;
  68. }
  69. }
  70. return undefined;
  71. }
  72. module.exports = locationOf;