File: ast.js

package info (click to toggle)
node-eslint-plugin-requirejs 4.0.0-7
  • links: PTS, VCS
  • area: main
  • in suites: bullseye, sid
  • size: 916 kB
  • sloc: javascript: 4,677; perl: 48; makefile: 31; sh: 6
file content (172 lines) | stat: -rw-r--r-- 4,763 bytes parent folder | download
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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
/**
 * @file    Helper functions for working with AST Nodes
 * @author  Casey Visco <cvisco@gmail.com>
 */

"use strict";

const isArray = Array.isArray;

/**
 * Test if supplied `value` is an object.
 * @private
 * @param   {*} value - value to test
 * @returns {boolean} true if value is an object
 */
function isObject(value) {
    const type = typeof value;

    return type === "object" || type === "function";
}

/**
 * Test if supplied `node` represents an identifier.
 * @param   {ASTNode} node - node to test
 * @returns {boolean} true if node represents an identifier
 */
function isIdentifier(node) {
    return isObject(node) && node.type === "Identifier";
}

/**
 * Test if supplied `node` represents a literal of any kind.
 * @param   {ASTNode} node - node to test
 * @returns {boolean} true if node represents a literal
 */
function isLiteral(node) {
    return isObject(node) && node.type === "Literal";
}

/**
 * Test if supplied `node` represents a string literal.
 * @param   {ASTNode} node - node to test
 * @returns {boolean} true if node represents a string literal
 */
function isStringLiteral(node) {
    return isLiteral(node) && typeof node.value === "string";
}

/**
 * Test if supplied `node` represents an array expression.
 * @param   {ASTNode} node - node to test
 * @returns {boolean} true if node represents an array expression
 */
function isArrayExpr(node) {
    return isObject(node) && node.type === "ArrayExpression";
}

/**
 * Test if supplied `node` represents an object expression.
 * @param   {ASTNode} node - node to test
 * @returns {boolean} true if node represents an object expression
 */
function isObjectExpr(node) {
    return isObject(node) && node.type === "ObjectExpression";
}

/**
 * Test if supplied `node` represents a function expression.
 * @param   {ASTNode} node - node to test
 * @returns {boolean} true if node represents a function expression
 */
function isFunctionExpr(node) {
    return isObject(node) &&
           (node.type === "FunctionExpression" ||
            node.type === "ArrowFunctionExpression");
}

/**
 * Test if supplied `node` represents a member expression.
 * @param   {ASTNode} node - node to test
 * @returns {boolean} true if node represents a member expression
 */
function isMemberExpr(node) {
    return isObject(node) && node.type === "MemberExpression";
}

/**
 * Test if supplied `node` represents an expression of any kind.
 * @param   {ASTNode} node - node to test
 * @returns {boolean} true if node represents an expression statement
 */
function isExprStatement(node) {
    return isObject(node) && node.type === "ExpressionStatement";
}

/**
 * Test if supplied `node` represents an array of string literals. Empty
 * arrays are also valid here.
 * @param   {ASTNode} node - ArrayExpression node to test
 * @returns {boolean} true if node represents an array of string literals
 */
function isStringLiteralArray(node) {
    return isArrayExpr(node) &&
           isArray(node.elements) &&
           node.elements.every(isStringLiteral);
}

/**
 * Test if supplied `node` has parameters.
 * @param   {ASTNode} node - FunctionExpression node to test
 * @returns {boolean} true if node has at least one parameter
 */
function hasParams(node) {
    return isObject(node) &&
           isArray(node.params) &&
           node.params.length > 0;
}

/**
 * Test if supplied `node` has at least one callback argument
 * @param   {ASTNode} node - CallExpression node to test
 * @returns {boolean} true if node has at least one callback
 */
function hasCallback(node) {
    return isObject(node) &&
           isArray(node.arguments) &&
           node.arguments.some(isFunctionExpr);
}

/**
 * Determine if `node` has an ancestor satisfying `predicate`.
 * @param   {Function} predicate - predicate to test each ancestor against
 * @param   {ASTNode} node - child node to begin search at
 * @returns {boolean} true if an ancestor satisfies `predicate`
 */
function ancestor(predicate, node) {
    while ((node = node.parent)) {
        if (predicate(node)) return true;
    }

    return false;
}

/**
 * Find the nearest ancestor satisfying `predicate`.
 * @param   {Function} predicate - predicate to test each ancestor against
 * @param   {ASTNode} node - child node to begin search at
 * @returns {ASTNode|undefined} nearest ancestor satisfying `predicate`, if any
 */
function nearest(predicate, node) {
    while ((node = node.parent)) {
        if (predicate(node)) return node;
    }

    return undefined;
}

module.exports = {
    isIdentifier,
    isLiteral,
    isStringLiteral,
    isArrayExpr,
    isObjectExpr,
    isMemberExpr,
    isFunctionExpr,
    isExprStatement,
    isStringLiteralArray,
    hasParams,
    hasCallback,
    ancestor,
    nearest
};