parent
9527887426
commit
1045590d4b
@ -1,5 +1,6 @@
|
||||
import {
|
||||
isReferenced,
|
||||
// should only use types from @babel/types
|
||||
// do not import runtime methods
|
||||
import type {
|
||||
Identifier,
|
||||
Node,
|
||||
Function,
|
||||
@ -243,3 +244,181 @@ export const isStaticProperty = (node: Node): node is ObjectProperty =>
|
||||
|
||||
export const isStaticPropertyKey = (node: Node, parent: Node) =>
|
||||
isStaticProperty(parent) && parent.key === node
|
||||
|
||||
/**
|
||||
* Copied from https://github.com/babel/babel/blob/main/packages/babel-types/src/validators/isReferenced.ts
|
||||
* To avoid runtime dependency on @babel/types (which includes process references)
|
||||
* This file should not change very often in babel but we may need to keep it
|
||||
* up-to-date from time to time.
|
||||
*
|
||||
* https://github.com/babel/babel/blob/main/LICENSE
|
||||
*
|
||||
*/
|
||||
function isReferenced(node: Node, parent: Node, grandparent?: Node): boolean {
|
||||
switch (parent.type) {
|
||||
// yes: PARENT[NODE]
|
||||
// yes: NODE.child
|
||||
// no: parent.NODE
|
||||
case 'MemberExpression':
|
||||
case 'OptionalMemberExpression':
|
||||
if (parent.property === node) {
|
||||
return !!parent.computed
|
||||
}
|
||||
return parent.object === node
|
||||
|
||||
case 'JSXMemberExpression':
|
||||
return parent.object === node
|
||||
// no: let NODE = init;
|
||||
// yes: let id = NODE;
|
||||
case 'VariableDeclarator':
|
||||
return parent.init === node
|
||||
|
||||
// yes: () => NODE
|
||||
// no: (NODE) => {}
|
||||
case 'ArrowFunctionExpression':
|
||||
return parent.body === node
|
||||
|
||||
// no: class { #NODE; }
|
||||
// no: class { get #NODE() {} }
|
||||
// no: class { #NODE() {} }
|
||||
// no: class { fn() { return this.#NODE; } }
|
||||
case 'PrivateName':
|
||||
return false
|
||||
|
||||
// no: class { NODE() {} }
|
||||
// yes: class { [NODE]() {} }
|
||||
// no: class { foo(NODE) {} }
|
||||
case 'ClassMethod':
|
||||
case 'ClassPrivateMethod':
|
||||
case 'ObjectMethod':
|
||||
if (parent.key === node) {
|
||||
return !!parent.computed
|
||||
}
|
||||
return false
|
||||
|
||||
// yes: { [NODE]: "" }
|
||||
// no: { NODE: "" }
|
||||
// depends: { NODE }
|
||||
// depends: { key: NODE }
|
||||
case 'ObjectProperty':
|
||||
if (parent.key === node) {
|
||||
return !!parent.computed
|
||||
}
|
||||
// parent.value === node
|
||||
return !grandparent || grandparent.type !== 'ObjectPattern'
|
||||
// no: class { NODE = value; }
|
||||
// yes: class { [NODE] = value; }
|
||||
// yes: class { key = NODE; }
|
||||
case 'ClassProperty':
|
||||
if (parent.key === node) {
|
||||
return !!parent.computed
|
||||
}
|
||||
return true
|
||||
case 'ClassPrivateProperty':
|
||||
return parent.key !== node
|
||||
|
||||
// no: class NODE {}
|
||||
// yes: class Foo extends NODE {}
|
||||
case 'ClassDeclaration':
|
||||
case 'ClassExpression':
|
||||
return parent.superClass === node
|
||||
|
||||
// yes: left = NODE;
|
||||
// no: NODE = right;
|
||||
case 'AssignmentExpression':
|
||||
return parent.right === node
|
||||
|
||||
// no: [NODE = foo] = [];
|
||||
// yes: [foo = NODE] = [];
|
||||
case 'AssignmentPattern':
|
||||
return parent.right === node
|
||||
|
||||
// no: NODE: for (;;) {}
|
||||
case 'LabeledStatement':
|
||||
return false
|
||||
|
||||
// no: try {} catch (NODE) {}
|
||||
case 'CatchClause':
|
||||
return false
|
||||
|
||||
// no: function foo(...NODE) {}
|
||||
case 'RestElement':
|
||||
return false
|
||||
|
||||
case 'BreakStatement':
|
||||
case 'ContinueStatement':
|
||||
return false
|
||||
|
||||
// no: function NODE() {}
|
||||
// no: function foo(NODE) {}
|
||||
case 'FunctionDeclaration':
|
||||
case 'FunctionExpression':
|
||||
return false
|
||||
|
||||
// no: export NODE from "foo";
|
||||
// no: export * as NODE from "foo";
|
||||
case 'ExportNamespaceSpecifier':
|
||||
case 'ExportDefaultSpecifier':
|
||||
return false
|
||||
|
||||
// no: export { foo as NODE };
|
||||
// yes: export { NODE as foo };
|
||||
// no: export { NODE as foo } from "foo";
|
||||
case 'ExportSpecifier':
|
||||
// @ts-expect-error
|
||||
if (grandparent?.source) {
|
||||
return false
|
||||
}
|
||||
return parent.local === node
|
||||
|
||||
// no: import NODE from "foo";
|
||||
// no: import * as NODE from "foo";
|
||||
// no: import { NODE as foo } from "foo";
|
||||
// no: import { foo as NODE } from "foo";
|
||||
// no: import NODE from "bar";
|
||||
case 'ImportDefaultSpecifier':
|
||||
case 'ImportNamespaceSpecifier':
|
||||
case 'ImportSpecifier':
|
||||
return false
|
||||
|
||||
// no: import "foo" assert { NODE: "json" }
|
||||
case 'ImportAttribute':
|
||||
return false
|
||||
|
||||
// no: <div NODE="foo" />
|
||||
case 'JSXAttribute':
|
||||
return false
|
||||
|
||||
// no: [NODE] = [];
|
||||
// no: ({ NODE }) = [];
|
||||
case 'ObjectPattern':
|
||||
case 'ArrayPattern':
|
||||
return false
|
||||
|
||||
// no: new.NODE
|
||||
// no: NODE.target
|
||||
case 'MetaProperty':
|
||||
return false
|
||||
|
||||
// yes: type X = { somePropert: NODE }
|
||||
// no: type X = { NODE: OtherType }
|
||||
case 'ObjectTypeProperty':
|
||||
return parent.key !== node
|
||||
|
||||
// yes: enum X { Foo = NODE }
|
||||
// no: enum X { NODE }
|
||||
case 'TSEnumMember':
|
||||
return parent.id !== node
|
||||
|
||||
// yes: { [NODE]: value }
|
||||
// no: { NODE: value }
|
||||
case 'TSPropertySignature':
|
||||
if (parent.key === node) {
|
||||
return !!parent.computed
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user