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