Spaces:
Running
Running
; | |
/* eslint-disable jsdoc/valid-types -- doesn't allow `readonly`. | |
TODO: remove eslint-disable when https://github.com/jsdoc-type-pratt-parser/jsdoc-type-pratt-parser/issues/164 is fixed | |
*/ | |
/** | |
* @typedef {{ readonly [type: string]: ReadonlyArray<string> }} VisitorKeys | |
*/ | |
/* eslint-enable jsdoc/valid-types -- doesn't allow `readonly string[]`. TODO: check why */ | |
/** | |
* @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", | |
"attributes" | |
], | |
ExportDefaultDeclaration: [ | |
"declaration" | |
], | |
ExportNamedDeclaration: [ | |
"declaration", | |
"specifiers", | |
"source", | |
"attributes" | |
], | |
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" | |
], | |
ImportAttribute: [ | |
"key", | |
"value" | |
], | |
ImportDeclaration: [ | |
"specifiers", | |
"source", | |
"attributes" | |
], | |
ImportDefaultSpecifier: [ | |
"local" | |
], | |
ImportExpression: [ | |
"source", | |
"options" | |
], | |
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] !== "_"; | |
} | |
/* eslint-disable jsdoc/valid-types -- doesn't allow `readonly`. | |
TODO: remove eslint-disable when https://github.com/jsdoc-type-pratt-parser/jsdoc-type-pratt-parser/issues/164 is fixed | |
*/ | |
/** | |
* 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); | |
} | |
/* eslint-enable jsdoc/valid-types -- doesn't allow `readonly` */ | |
/** | |
* 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.hasOwn(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; | |