|
1 |
| -import { |
2 |
| - isReferenced, |
| 1 | +// should only use types from @babel/types |
| 2 | +// do not import runtime methods |
| 3 | +import type { |
3 | 4 | Identifier,
|
4 | 5 | Node,
|
5 | 6 | Function,
|
@@ -243,3 +244,181 @@ export const isStaticProperty = (node: Node): node is ObjectProperty =>
|
243 | 244 |
|
244 | 245 | export const isStaticPropertyKey = (node: Node, parent: Node) =>
|
245 | 246 | isStaticProperty(parent) && parent.key === node
|
| 247 | + |
| 248 | +/** |
| 249 | + * Copied from https://github.com/babel/babel/blob/main/packages/babel-types/src/validators/isReferenced.ts |
| 250 | + * To avoid runtime dependency on @babel/types (which includes process references) |
| 251 | + * This file should not change very often in babel but we may need to keep it |
| 252 | + * up-to-date from time to time. |
| 253 | + * |
| 254 | + * https://github.com/babel/babel/blob/main/LICENSE |
| 255 | + * |
| 256 | + */ |
| 257 | +function isReferenced(node: Node, parent: Node, grandparent?: Node): boolean { |
| 258 | + switch (parent.type) { |
| 259 | + // yes: PARENT[NODE] |
| 260 | + // yes: NODE.child |
| 261 | + // no: parent.NODE |
| 262 | + case 'MemberExpression': |
| 263 | + case 'OptionalMemberExpression': |
| 264 | + if (parent.property === node) { |
| 265 | + return !!parent.computed |
| 266 | + } |
| 267 | + return parent.object === node |
| 268 | + |
| 269 | + case 'JSXMemberExpression': |
| 270 | + return parent.object === node |
| 271 | + // no: let NODE = init; |
| 272 | + // yes: let id = NODE; |
| 273 | + case 'VariableDeclarator': |
| 274 | + return parent.init === node |
| 275 | + |
| 276 | + // yes: () => NODE |
| 277 | + // no: (NODE) => {} |
| 278 | + case 'ArrowFunctionExpression': |
| 279 | + return parent.body === node |
| 280 | + |
| 281 | + // no: class { #NODE; } |
| 282 | + // no: class { get #NODE() {} } |
| 283 | + // no: class { #NODE() {} } |
| 284 | + // no: class { fn() { return this.#NODE; } } |
| 285 | + case 'PrivateName': |
| 286 | + return false |
| 287 | + |
| 288 | + // no: class { NODE() {} } |
| 289 | + // yes: class { [NODE]() {} } |
| 290 | + // no: class { foo(NODE) {} } |
| 291 | + case 'ClassMethod': |
| 292 | + case 'ClassPrivateMethod': |
| 293 | + case 'ObjectMethod': |
| 294 | + if (parent.key === node) { |
| 295 | + return !!parent.computed |
| 296 | + } |
| 297 | + return false |
| 298 | + |
| 299 | + // yes: { [NODE]: "" } |
| 300 | + // no: { NODE: "" } |
| 301 | + // depends: { NODE } |
| 302 | + // depends: { key: NODE } |
| 303 | + case 'ObjectProperty': |
| 304 | + if (parent.key === node) { |
| 305 | + return !!parent.computed |
| 306 | + } |
| 307 | + // parent.value === node |
| 308 | + return !grandparent || grandparent.type !== 'ObjectPattern' |
| 309 | + // no: class { NODE = value; } |
| 310 | + // yes: class { [NODE] = value; } |
| 311 | + // yes: class { key = NODE; } |
| 312 | + case 'ClassProperty': |
| 313 | + if (parent.key === node) { |
| 314 | + return !!parent.computed |
| 315 | + } |
| 316 | + return true |
| 317 | + case 'ClassPrivateProperty': |
| 318 | + return parent.key !== node |
| 319 | + |
| 320 | + // no: class NODE {} |
| 321 | + // yes: class Foo extends NODE {} |
| 322 | + case 'ClassDeclaration': |
| 323 | + case 'ClassExpression': |
| 324 | + return parent.superClass === node |
| 325 | + |
| 326 | + // yes: left = NODE; |
| 327 | + // no: NODE = right; |
| 328 | + case 'AssignmentExpression': |
| 329 | + return parent.right === node |
| 330 | + |
| 331 | + // no: [NODE = foo] = []; |
| 332 | + // yes: [foo = NODE] = []; |
| 333 | + case 'AssignmentPattern': |
| 334 | + return parent.right === node |
| 335 | + |
| 336 | + // no: NODE: for (;;) {} |
| 337 | + case 'LabeledStatement': |
| 338 | + return false |
| 339 | + |
| 340 | + // no: try {} catch (NODE) {} |
| 341 | + case 'CatchClause': |
| 342 | + return false |
| 343 | + |
| 344 | + // no: function foo(...NODE) {} |
| 345 | + case 'RestElement': |
| 346 | + return false |
| 347 | + |
| 348 | + case 'BreakStatement': |
| 349 | + case 'ContinueStatement': |
| 350 | + return false |
| 351 | + |
| 352 | + // no: function NODE() {} |
| 353 | + // no: function foo(NODE) {} |
| 354 | + case 'FunctionDeclaration': |
| 355 | + case 'FunctionExpression': |
| 356 | + return false |
| 357 | + |
| 358 | + // no: export NODE from "foo"; |
| 359 | + // no: export * as NODE from "foo"; |
| 360 | + case 'ExportNamespaceSpecifier': |
| 361 | + case 'ExportDefaultSpecifier': |
| 362 | + return false |
| 363 | + |
| 364 | + // no: export { foo as NODE }; |
| 365 | + // yes: export { NODE as foo }; |
| 366 | + // no: export { NODE as foo } from "foo"; |
| 367 | + case 'ExportSpecifier': |
| 368 | + // @ts-expect-error |
| 369 | + if (grandparent?.source) { |
| 370 | + return false |
| 371 | + } |
| 372 | + return parent.local === node |
| 373 | + |
| 374 | + // no: import NODE from "foo"; |
| 375 | + // no: import * as NODE from "foo"; |
| 376 | + // no: import { NODE as foo } from "foo"; |
| 377 | + // no: import { foo as NODE } from "foo"; |
| 378 | + // no: import NODE from "bar"; |
| 379 | + case 'ImportDefaultSpecifier': |
| 380 | + case 'ImportNamespaceSpecifier': |
| 381 | + case 'ImportSpecifier': |
| 382 | + return false |
| 383 | + |
| 384 | + // no: import "foo" assert { NODE: "json" } |
| 385 | + case 'ImportAttribute': |
| 386 | + return false |
| 387 | + |
| 388 | + // no: <div NODE="foo" /> |
| 389 | + case 'JSXAttribute': |
| 390 | + return false |
| 391 | + |
| 392 | + // no: [NODE] = []; |
| 393 | + // no: ({ NODE }) = []; |
| 394 | + case 'ObjectPattern': |
| 395 | + case 'ArrayPattern': |
| 396 | + return false |
| 397 | + |
| 398 | + // no: new.NODE |
| 399 | + // no: NODE.target |
| 400 | + case 'MetaProperty': |
| 401 | + return false |
| 402 | + |
| 403 | + // yes: type X = { somePropert: NODE } |
| 404 | + // no: type X = { NODE: OtherType } |
| 405 | + case 'ObjectTypeProperty': |
| 406 | + return parent.key !== node |
| 407 | + |
| 408 | + // yes: enum X { Foo = NODE } |
| 409 | + // no: enum X { NODE } |
| 410 | + case 'TSEnumMember': |
| 411 | + return parent.id !== node |
| 412 | + |
| 413 | + // yes: { [NODE]: value } |
| 414 | + // no: { NODE: value } |
| 415 | + case 'TSPropertySignature': |
| 416 | + if (parent.key === node) { |
| 417 | + return !!parent.computed |
| 418 | + } |
| 419 | + |
| 420 | + return true |
| 421 | + } |
| 422 | + |
| 423 | + return true |
| 424 | +} |
0 commit comments