385 lines
		
	
	
		
			6.9 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			385 lines
		
	
	
		
			6.9 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
'use strict';
 | 
						|
 | 
						|
Object.defineProperty(exports, '__esModule', { value: true });
 | 
						|
 | 
						|
/**
 | 
						|
 * @typedef {{ readonly [type: string]: ReadonlyArray<string> }} VisitorKeys
 | 
						|
 */
 | 
						|
 | 
						|
/**
 | 
						|
 * @type {VisitorKeys}
 | 
						|
 */
 | 
						|
const KEYS = {
 | 
						|
    ArrayExpression: [
 | 
						|
        "elements"
 | 
						|
    ],
 | 
						|
    ArrayPattern: [
 | 
						|
        "elements"
 | 
						|
    ],
 | 
						|
    ArrowFunctionExpression: [
 | 
						|
        "params",
 | 
						|
        "body"
 | 
						|
    ],
 | 
						|
    AssignmentExpression: [
 | 
						|
        "left",
 | 
						|
        "right"
 | 
						|
    ],
 | 
						|
    AssignmentPattern: [
 | 
						|
        "left",
 | 
						|
        "right"
 | 
						|
    ],
 | 
						|
    AwaitExpression: [
 | 
						|
        "argument"
 | 
						|
    ],
 | 
						|
    BinaryExpression: [
 | 
						|
        "left",
 | 
						|
        "right"
 | 
						|
    ],
 | 
						|
    BlockStatement: [
 | 
						|
        "body"
 | 
						|
    ],
 | 
						|
    BreakStatement: [
 | 
						|
        "label"
 | 
						|
    ],
 | 
						|
    CallExpression: [
 | 
						|
        "callee",
 | 
						|
        "arguments"
 | 
						|
    ],
 | 
						|
    CatchClause: [
 | 
						|
        "param",
 | 
						|
        "body"
 | 
						|
    ],
 | 
						|
    ChainExpression: [
 | 
						|
        "expression"
 | 
						|
    ],
 | 
						|
    ClassBody: [
 | 
						|
        "body"
 | 
						|
    ],
 | 
						|
    ClassDeclaration: [
 | 
						|
        "id",
 | 
						|
        "superClass",
 | 
						|
        "body"
 | 
						|
    ],
 | 
						|
    ClassExpression: [
 | 
						|
        "id",
 | 
						|
        "superClass",
 | 
						|
        "body"
 | 
						|
    ],
 | 
						|
    ConditionalExpression: [
 | 
						|
        "test",
 | 
						|
        "consequent",
 | 
						|
        "alternate"
 | 
						|
    ],
 | 
						|
    ContinueStatement: [
 | 
						|
        "label"
 | 
						|
    ],
 | 
						|
    DebuggerStatement: [],
 | 
						|
    DoWhileStatement: [
 | 
						|
        "body",
 | 
						|
        "test"
 | 
						|
    ],
 | 
						|
    EmptyStatement: [],
 | 
						|
    ExperimentalRestProperty: [
 | 
						|
        "argument"
 | 
						|
    ],
 | 
						|
    ExperimentalSpreadProperty: [
 | 
						|
        "argument"
 | 
						|
    ],
 | 
						|
    ExportAllDeclaration: [
 | 
						|
        "exported",
 | 
						|
        "source"
 | 
						|
    ],
 | 
						|
    ExportDefaultDeclaration: [
 | 
						|
        "declaration"
 | 
						|
    ],
 | 
						|
    ExportNamedDeclaration: [
 | 
						|
        "declaration",
 | 
						|
        "specifiers",
 | 
						|
        "source"
 | 
						|
    ],
 | 
						|
    ExportSpecifier: [
 | 
						|
        "exported",
 | 
						|
        "local"
 | 
						|
    ],
 | 
						|
    ExpressionStatement: [
 | 
						|
        "expression"
 | 
						|
    ],
 | 
						|
    ForInStatement: [
 | 
						|
        "left",
 | 
						|
        "right",
 | 
						|
        "body"
 | 
						|
    ],
 | 
						|
    ForOfStatement: [
 | 
						|
        "left",
 | 
						|
        "right",
 | 
						|
        "body"
 | 
						|
    ],
 | 
						|
    ForStatement: [
 | 
						|
        "init",
 | 
						|
        "test",
 | 
						|
        "update",
 | 
						|
        "body"
 | 
						|
    ],
 | 
						|
    FunctionDeclaration: [
 | 
						|
        "id",
 | 
						|
        "params",
 | 
						|
        "body"
 | 
						|
    ],
 | 
						|
    FunctionExpression: [
 | 
						|
        "id",
 | 
						|
        "params",
 | 
						|
        "body"
 | 
						|
    ],
 | 
						|
    Identifier: [],
 | 
						|
    IfStatement: [
 | 
						|
        "test",
 | 
						|
        "consequent",
 | 
						|
        "alternate"
 | 
						|
    ],
 | 
						|
    ImportDeclaration: [
 | 
						|
        "specifiers",
 | 
						|
        "source"
 | 
						|
    ],
 | 
						|
    ImportDefaultSpecifier: [
 | 
						|
        "local"
 | 
						|
    ],
 | 
						|
    ImportExpression: [
 | 
						|
        "source"
 | 
						|
    ],
 | 
						|
    ImportNamespaceSpecifier: [
 | 
						|
        "local"
 | 
						|
    ],
 | 
						|
    ImportSpecifier: [
 | 
						|
        "imported",
 | 
						|
        "local"
 | 
						|
    ],
 | 
						|
    JSXAttribute: [
 | 
						|
        "name",
 | 
						|
        "value"
 | 
						|
    ],
 | 
						|
    JSXClosingElement: [
 | 
						|
        "name"
 | 
						|
    ],
 | 
						|
    JSXClosingFragment: [],
 | 
						|
    JSXElement: [
 | 
						|
        "openingElement",
 | 
						|
        "children",
 | 
						|
        "closingElement"
 | 
						|
    ],
 | 
						|
    JSXEmptyExpression: [],
 | 
						|
    JSXExpressionContainer: [
 | 
						|
        "expression"
 | 
						|
    ],
 | 
						|
    JSXFragment: [
 | 
						|
        "openingFragment",
 | 
						|
        "children",
 | 
						|
        "closingFragment"
 | 
						|
    ],
 | 
						|
    JSXIdentifier: [],
 | 
						|
    JSXMemberExpression: [
 | 
						|
        "object",
 | 
						|
        "property"
 | 
						|
    ],
 | 
						|
    JSXNamespacedName: [
 | 
						|
        "namespace",
 | 
						|
        "name"
 | 
						|
    ],
 | 
						|
    JSXOpeningElement: [
 | 
						|
        "name",
 | 
						|
        "attributes"
 | 
						|
    ],
 | 
						|
    JSXOpeningFragment: [],
 | 
						|
    JSXSpreadAttribute: [
 | 
						|
        "argument"
 | 
						|
    ],
 | 
						|
    JSXSpreadChild: [
 | 
						|
        "expression"
 | 
						|
    ],
 | 
						|
    JSXText: [],
 | 
						|
    LabeledStatement: [
 | 
						|
        "label",
 | 
						|
        "body"
 | 
						|
    ],
 | 
						|
    Literal: [],
 | 
						|
    LogicalExpression: [
 | 
						|
        "left",
 | 
						|
        "right"
 | 
						|
    ],
 | 
						|
    MemberExpression: [
 | 
						|
        "object",
 | 
						|
        "property"
 | 
						|
    ],
 | 
						|
    MetaProperty: [
 | 
						|
        "meta",
 | 
						|
        "property"
 | 
						|
    ],
 | 
						|
    MethodDefinition: [
 | 
						|
        "key",
 | 
						|
        "value"
 | 
						|
    ],
 | 
						|
    NewExpression: [
 | 
						|
        "callee",
 | 
						|
        "arguments"
 | 
						|
    ],
 | 
						|
    ObjectExpression: [
 | 
						|
        "properties"
 | 
						|
    ],
 | 
						|
    ObjectPattern: [
 | 
						|
        "properties"
 | 
						|
    ],
 | 
						|
    PrivateIdentifier: [],
 | 
						|
    Program: [
 | 
						|
        "body"
 | 
						|
    ],
 | 
						|
    Property: [
 | 
						|
        "key",
 | 
						|
        "value"
 | 
						|
    ],
 | 
						|
    PropertyDefinition: [
 | 
						|
        "key",
 | 
						|
        "value"
 | 
						|
    ],
 | 
						|
    RestElement: [
 | 
						|
        "argument"
 | 
						|
    ],
 | 
						|
    ReturnStatement: [
 | 
						|
        "argument"
 | 
						|
    ],
 | 
						|
    SequenceExpression: [
 | 
						|
        "expressions"
 | 
						|
    ],
 | 
						|
    SpreadElement: [
 | 
						|
        "argument"
 | 
						|
    ],
 | 
						|
    StaticBlock: [
 | 
						|
        "body"
 | 
						|
    ],
 | 
						|
    Super: [],
 | 
						|
    SwitchCase: [
 | 
						|
        "test",
 | 
						|
        "consequent"
 | 
						|
    ],
 | 
						|
    SwitchStatement: [
 | 
						|
        "discriminant",
 | 
						|
        "cases"
 | 
						|
    ],
 | 
						|
    TaggedTemplateExpression: [
 | 
						|
        "tag",
 | 
						|
        "quasi"
 | 
						|
    ],
 | 
						|
    TemplateElement: [],
 | 
						|
    TemplateLiteral: [
 | 
						|
        "quasis",
 | 
						|
        "expressions"
 | 
						|
    ],
 | 
						|
    ThisExpression: [],
 | 
						|
    ThrowStatement: [
 | 
						|
        "argument"
 | 
						|
    ],
 | 
						|
    TryStatement: [
 | 
						|
        "block",
 | 
						|
        "handler",
 | 
						|
        "finalizer"
 | 
						|
    ],
 | 
						|
    UnaryExpression: [
 | 
						|
        "argument"
 | 
						|
    ],
 | 
						|
    UpdateExpression: [
 | 
						|
        "argument"
 | 
						|
    ],
 | 
						|
    VariableDeclaration: [
 | 
						|
        "declarations"
 | 
						|
    ],
 | 
						|
    VariableDeclarator: [
 | 
						|
        "id",
 | 
						|
        "init"
 | 
						|
    ],
 | 
						|
    WhileStatement: [
 | 
						|
        "test",
 | 
						|
        "body"
 | 
						|
    ],
 | 
						|
    WithStatement: [
 | 
						|
        "object",
 | 
						|
        "body"
 | 
						|
    ],
 | 
						|
    YieldExpression: [
 | 
						|
        "argument"
 | 
						|
    ]
 | 
						|
};
 | 
						|
 | 
						|
// Types.
 | 
						|
const NODE_TYPES = Object.keys(KEYS);
 | 
						|
 | 
						|
// Freeze the keys.
 | 
						|
for (const type of NODE_TYPES) {
 | 
						|
    Object.freeze(KEYS[type]);
 | 
						|
}
 | 
						|
Object.freeze(KEYS);
 | 
						|
 | 
						|
/**
 | 
						|
 * @author Toru Nagashima <https://github.com/mysticatea>
 | 
						|
 * See LICENSE file in root directory for full license.
 | 
						|
 */
 | 
						|
 | 
						|
/**
 | 
						|
 * @typedef {import('./visitor-keys.js').VisitorKeys} VisitorKeys
 | 
						|
 */
 | 
						|
 | 
						|
// List to ignore keys.
 | 
						|
const KEY_BLACKLIST = new Set([
 | 
						|
    "parent",
 | 
						|
    "leadingComments",
 | 
						|
    "trailingComments"
 | 
						|
]);
 | 
						|
 | 
						|
/**
 | 
						|
 * Check whether a given key should be used or not.
 | 
						|
 * @param {string} key The key to check.
 | 
						|
 * @returns {boolean} `true` if the key should be used.
 | 
						|
 */
 | 
						|
function filterKey(key) {
 | 
						|
    return !KEY_BLACKLIST.has(key) && key[0] !== "_";
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * Get visitor keys of a given node.
 | 
						|
 * @param {object} node The AST node to get keys.
 | 
						|
 * @returns {readonly string[]} Visitor keys of the node.
 | 
						|
 */
 | 
						|
function getKeys(node) {
 | 
						|
    return Object.keys(node).filter(filterKey);
 | 
						|
}
 | 
						|
 | 
						|
// Disable valid-jsdoc rule because it reports syntax error on the type of @returns.
 | 
						|
// eslint-disable-next-line valid-jsdoc
 | 
						|
/**
 | 
						|
 * Make the union set with `KEYS` and given keys.
 | 
						|
 * @param {VisitorKeys} additionalKeys The additional keys.
 | 
						|
 * @returns {VisitorKeys} The union set.
 | 
						|
 */
 | 
						|
function unionWith(additionalKeys) {
 | 
						|
    const retv = /** @type {{
 | 
						|
        [type: string]: ReadonlyArray<string>
 | 
						|
    }} */ (Object.assign({}, KEYS));
 | 
						|
 | 
						|
    for (const type of Object.keys(additionalKeys)) {
 | 
						|
        if (Object.prototype.hasOwnProperty.call(retv, type)) {
 | 
						|
            const keys = new Set(additionalKeys[type]);
 | 
						|
 | 
						|
            for (const key of retv[type]) {
 | 
						|
                keys.add(key);
 | 
						|
            }
 | 
						|
 | 
						|
            retv[type] = Object.freeze(Array.from(keys));
 | 
						|
        } else {
 | 
						|
            retv[type] = Object.freeze(Array.from(additionalKeys[type]));
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    return Object.freeze(retv);
 | 
						|
}
 | 
						|
 | 
						|
exports.KEYS = KEYS;
 | 
						|
exports.getKeys = getKeys;
 | 
						|
exports.unionWith = unionWith;
 |