1 | 'use strict';
|
2 |
|
3 | var syntax = require('estraverse').Syntax;
|
4 |
|
5 | function locationOf(currentNode, tokens) {
|
6 | switch(currentNode.type) {
|
7 | case syntax.MemberExpression:
|
8 | return propertyLocationOf(currentNode, tokens);
|
9 | case syntax.CallExpression:
|
10 | if (currentNode.callee.type === syntax.MemberExpression) {
|
11 | return propertyLocationOf(currentNode.callee, tokens);
|
12 | }
|
13 | break;
|
14 | case syntax.BinaryExpression:
|
15 | case syntax.LogicalExpression:
|
16 | case syntax.AssignmentExpression:
|
17 | return infixOperatorLocationOf(currentNode, tokens);
|
18 | default:
|
19 | break;
|
20 | }
|
21 | return currentNode.loc;
|
22 | }
|
23 |
|
24 | function propertyLocationOf(memberExpression, tokens) {
|
25 | var prop = memberExpression.property;
|
26 | var token;
|
27 | if (!memberExpression.computed) {
|
28 | return prop.loc;
|
29 | }
|
30 | token = findLeftBracketTokenOf(memberExpression, tokens);
|
31 | return token ? token.loc : prop.loc;
|
32 | }
|
33 |
|
34 |
|
35 | function infixOperatorLocationOf (expression, tokens) {
|
36 | var token = findOperatorTokenOf(expression, tokens);
|
37 | return token ? token.loc : expression.left.loc;
|
38 | }
|
39 |
|
40 | function findLeftBracketTokenOf(expression, tokens) {
|
41 | var fromLine = expression.loc.start.line;
|
42 | var toLine = expression.property.loc.start.line;
|
43 | var fromColumn = expression.property.loc.start.column;
|
44 | return searchToken(tokens, fromLine, toLine, function (token, index) {
|
45 | var prevToken;
|
46 | if (token.loc.start.column === fromColumn) {
|
47 | prevToken = tokens[index - 1];
|
48 | if (prevToken.type === 'Punctuator' && prevToken.value === '[') {
|
49 |
|
50 | return prevToken;
|
51 | }
|
52 | }
|
53 | return undefined;
|
54 | });
|
55 | }
|
56 |
|
57 | function findOperatorTokenOf(expression, tokens) {
|
58 | var fromLine = expression.left.loc.end.line;
|
59 | var toLine = expression.right.loc.start.line;
|
60 | var fromColumn = expression.left.loc.end.column;
|
61 | var toColumn = expression.right.loc.start.column;
|
62 | return searchToken(tokens, fromLine, toLine, function (token, index) {
|
63 | if (fromColumn < token.loc.start.column &&
|
64 | token.loc.end.column < toColumn &&
|
65 | token.value === expression.operator) {
|
66 | return token;
|
67 | }
|
68 | return undefined;
|
69 | });
|
70 | }
|
71 |
|
72 | function searchToken(tokens, fromLine, toLine, predicate) {
|
73 | var i, token, found;
|
74 | for(i = 0; i < tokens.length; i += 1) {
|
75 | token = tokens[i];
|
76 | if (token.loc.start.line < fromLine) {
|
77 | continue;
|
78 | }
|
79 | if (toLine < token.loc.end.line) {
|
80 | break;
|
81 | }
|
82 | found = predicate(token, i);
|
83 | if (found) {
|
84 | return found;
|
85 | }
|
86 | }
|
87 | return undefined;
|
88 | }
|
89 |
|
90 | module.exports = locationOf;
|