eslint-visitor-keys.cjs 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388
  1. 'use strict';
  2. /* eslint-disable jsdoc/valid-types -- doesn't allow `readonly`.
  3. TODO: remove eslint-disable when https://github.com/jsdoc-type-pratt-parser/jsdoc-type-pratt-parser/issues/164 is fixed
  4. */
  5. /**
  6. * @typedef {{ readonly [type: string]: ReadonlyArray<string> }} VisitorKeys
  7. */
  8. /* eslint-enable jsdoc/valid-types -- doesn't allow `readonly string[]`. TODO: check why */
  9. /**
  10. * @type {VisitorKeys}
  11. */
  12. const KEYS = {
  13. ArrayExpression: [
  14. "elements"
  15. ],
  16. ArrayPattern: [
  17. "elements"
  18. ],
  19. ArrowFunctionExpression: [
  20. "params",
  21. "body"
  22. ],
  23. AssignmentExpression: [
  24. "left",
  25. "right"
  26. ],
  27. AssignmentPattern: [
  28. "left",
  29. "right"
  30. ],
  31. AwaitExpression: [
  32. "argument"
  33. ],
  34. BinaryExpression: [
  35. "left",
  36. "right"
  37. ],
  38. BlockStatement: [
  39. "body"
  40. ],
  41. BreakStatement: [
  42. "label"
  43. ],
  44. CallExpression: [
  45. "callee",
  46. "arguments"
  47. ],
  48. CatchClause: [
  49. "param",
  50. "body"
  51. ],
  52. ChainExpression: [
  53. "expression"
  54. ],
  55. ClassBody: [
  56. "body"
  57. ],
  58. ClassDeclaration: [
  59. "id",
  60. "superClass",
  61. "body"
  62. ],
  63. ClassExpression: [
  64. "id",
  65. "superClass",
  66. "body"
  67. ],
  68. ConditionalExpression: [
  69. "test",
  70. "consequent",
  71. "alternate"
  72. ],
  73. ContinueStatement: [
  74. "label"
  75. ],
  76. DebuggerStatement: [],
  77. DoWhileStatement: [
  78. "body",
  79. "test"
  80. ],
  81. EmptyStatement: [],
  82. ExperimentalRestProperty: [
  83. "argument"
  84. ],
  85. ExperimentalSpreadProperty: [
  86. "argument"
  87. ],
  88. ExportAllDeclaration: [
  89. "exported",
  90. "source"
  91. ],
  92. ExportDefaultDeclaration: [
  93. "declaration"
  94. ],
  95. ExportNamedDeclaration: [
  96. "declaration",
  97. "specifiers",
  98. "source"
  99. ],
  100. ExportSpecifier: [
  101. "exported",
  102. "local"
  103. ],
  104. ExpressionStatement: [
  105. "expression"
  106. ],
  107. ForInStatement: [
  108. "left",
  109. "right",
  110. "body"
  111. ],
  112. ForOfStatement: [
  113. "left",
  114. "right",
  115. "body"
  116. ],
  117. ForStatement: [
  118. "init",
  119. "test",
  120. "update",
  121. "body"
  122. ],
  123. FunctionDeclaration: [
  124. "id",
  125. "params",
  126. "body"
  127. ],
  128. FunctionExpression: [
  129. "id",
  130. "params",
  131. "body"
  132. ],
  133. Identifier: [],
  134. IfStatement: [
  135. "test",
  136. "consequent",
  137. "alternate"
  138. ],
  139. ImportDeclaration: [
  140. "specifiers",
  141. "source"
  142. ],
  143. ImportDefaultSpecifier: [
  144. "local"
  145. ],
  146. ImportExpression: [
  147. "source"
  148. ],
  149. ImportNamespaceSpecifier: [
  150. "local"
  151. ],
  152. ImportSpecifier: [
  153. "imported",
  154. "local"
  155. ],
  156. JSXAttribute: [
  157. "name",
  158. "value"
  159. ],
  160. JSXClosingElement: [
  161. "name"
  162. ],
  163. JSXClosingFragment: [],
  164. JSXElement: [
  165. "openingElement",
  166. "children",
  167. "closingElement"
  168. ],
  169. JSXEmptyExpression: [],
  170. JSXExpressionContainer: [
  171. "expression"
  172. ],
  173. JSXFragment: [
  174. "openingFragment",
  175. "children",
  176. "closingFragment"
  177. ],
  178. JSXIdentifier: [],
  179. JSXMemberExpression: [
  180. "object",
  181. "property"
  182. ],
  183. JSXNamespacedName: [
  184. "namespace",
  185. "name"
  186. ],
  187. JSXOpeningElement: [
  188. "name",
  189. "attributes"
  190. ],
  191. JSXOpeningFragment: [],
  192. JSXSpreadAttribute: [
  193. "argument"
  194. ],
  195. JSXSpreadChild: [
  196. "expression"
  197. ],
  198. JSXText: [],
  199. LabeledStatement: [
  200. "label",
  201. "body"
  202. ],
  203. Literal: [],
  204. LogicalExpression: [
  205. "left",
  206. "right"
  207. ],
  208. MemberExpression: [
  209. "object",
  210. "property"
  211. ],
  212. MetaProperty: [
  213. "meta",
  214. "property"
  215. ],
  216. MethodDefinition: [
  217. "key",
  218. "value"
  219. ],
  220. NewExpression: [
  221. "callee",
  222. "arguments"
  223. ],
  224. ObjectExpression: [
  225. "properties"
  226. ],
  227. ObjectPattern: [
  228. "properties"
  229. ],
  230. PrivateIdentifier: [],
  231. Program: [
  232. "body"
  233. ],
  234. Property: [
  235. "key",
  236. "value"
  237. ],
  238. PropertyDefinition: [
  239. "key",
  240. "value"
  241. ],
  242. RestElement: [
  243. "argument"
  244. ],
  245. ReturnStatement: [
  246. "argument"
  247. ],
  248. SequenceExpression: [
  249. "expressions"
  250. ],
  251. SpreadElement: [
  252. "argument"
  253. ],
  254. StaticBlock: [
  255. "body"
  256. ],
  257. Super: [],
  258. SwitchCase: [
  259. "test",
  260. "consequent"
  261. ],
  262. SwitchStatement: [
  263. "discriminant",
  264. "cases"
  265. ],
  266. TaggedTemplateExpression: [
  267. "tag",
  268. "quasi"
  269. ],
  270. TemplateElement: [],
  271. TemplateLiteral: [
  272. "quasis",
  273. "expressions"
  274. ],
  275. ThisExpression: [],
  276. ThrowStatement: [
  277. "argument"
  278. ],
  279. TryStatement: [
  280. "block",
  281. "handler",
  282. "finalizer"
  283. ],
  284. UnaryExpression: [
  285. "argument"
  286. ],
  287. UpdateExpression: [
  288. "argument"
  289. ],
  290. VariableDeclaration: [
  291. "declarations"
  292. ],
  293. VariableDeclarator: [
  294. "id",
  295. "init"
  296. ],
  297. WhileStatement: [
  298. "test",
  299. "body"
  300. ],
  301. WithStatement: [
  302. "object",
  303. "body"
  304. ],
  305. YieldExpression: [
  306. "argument"
  307. ]
  308. };
  309. // Types.
  310. const NODE_TYPES = Object.keys(KEYS);
  311. // Freeze the keys.
  312. for (const type of NODE_TYPES) {
  313. Object.freeze(KEYS[type]);
  314. }
  315. Object.freeze(KEYS);
  316. /**
  317. * @author Toru Nagashima <https://github.com/mysticatea>
  318. * See LICENSE file in root directory for full license.
  319. */
  320. /**
  321. * @typedef {import('./visitor-keys.js').VisitorKeys} VisitorKeys
  322. */
  323. // List to ignore keys.
  324. const KEY_BLACKLIST = new Set([
  325. "parent",
  326. "leadingComments",
  327. "trailingComments"
  328. ]);
  329. /**
  330. * Check whether a given key should be used or not.
  331. * @param {string} key The key to check.
  332. * @returns {boolean} `true` if the key should be used.
  333. */
  334. function filterKey(key) {
  335. return !KEY_BLACKLIST.has(key) && key[0] !== "_";
  336. }
  337. /* eslint-disable jsdoc/valid-types -- doesn't allow `readonly`.
  338. TODO: remove eslint-disable when https://github.com/jsdoc-type-pratt-parser/jsdoc-type-pratt-parser/issues/164 is fixed
  339. */
  340. /**
  341. * Get visitor keys of a given node.
  342. * @param {Object} node The AST node to get keys.
  343. * @returns {readonly string[]} Visitor keys of the node.
  344. */
  345. function getKeys(node) {
  346. return Object.keys(node).filter(filterKey);
  347. }
  348. /* eslint-enable jsdoc/valid-types -- doesn't allow `readonly` */
  349. /**
  350. * Make the union set with `KEYS` and given keys.
  351. * @param {VisitorKeys} additionalKeys The additional keys.
  352. * @returns {VisitorKeys} The union set.
  353. */
  354. function unionWith(additionalKeys) {
  355. const retv = /** @type {{ [type: string]: ReadonlyArray<string> }} */
  356. (Object.assign({}, KEYS));
  357. for (const type of Object.keys(additionalKeys)) {
  358. if (Object.hasOwn(retv, type)) {
  359. const keys = new Set(additionalKeys[type]);
  360. for (const key of retv[type]) {
  361. keys.add(key);
  362. }
  363. retv[type] = Object.freeze(Array.from(keys));
  364. } else {
  365. retv[type] = Object.freeze(Array.from(additionalKeys[type]));
  366. }
  367. }
  368. return Object.freeze(retv);
  369. }
  370. exports.KEYS = KEYS;
  371. exports.getKeys = getKeys;
  372. exports.unionWith = unionWith;