@@ -19,13 +19,13 @@ type Scope = {
1919 type : string
2020 pragmas : Set < string >
2121}
22- type Pragma = ( typeof pragmas ) [ number ]
22+ type Pragmas = {
23+ react : string
24+ memo : string
25+ forwardRef : string
26+ }
2327
2428const pascal = / ^ [ A - Z ] [ a - z A - Z 0 - 9 ] * $ /
25- const pragmas = [ 'React' , 'memo' , 'forwardRef' ] as const
26- const isPragma = ( name : string ) : name is Pragma => {
27- return pragmas . includes ( name as Pragma )
28- }
2929const isIdentifierName = ( node : Node ) : node is IdentifierName => {
3030 return node . type === 'Identifier' && typeof node . name === 'string'
3131}
@@ -58,44 +58,38 @@ const collectDisplayNames = async (node: Node, code: MagicString) => {
5858 return foundDisplayNames
5959}
6060const detectReactPragmas = async ( node : Node ) => {
61- let isReact = false
62- let isReactMemo = false
63- let isReactForwardRef = false
61+ let react = ''
62+ let memo = ''
63+ let forwardRef = ''
6464
6565 await walk ( node , {
6666 enter ( node ) {
6767 if ( node . type === 'ImportDeclaration' && node . source . value === 'react' ) {
6868 for ( const specifier of node . specifiers ) {
69- if (
70- specifier . type === 'ImportDefaultSpecifier' &&
71- specifier . local . name === 'React'
72- ) {
73- isReact = true
69+ if ( specifier . type === 'ImportDefaultSpecifier' ) {
70+ react = specifier . local . name
7471 }
7572
7673 if (
7774 specifier . type === 'ImportSpecifier' &&
7875 specifier . imported . type === 'Identifier'
7976 ) {
80- if ( specifier . imported . name === 'memo' && specifier . local . name === 'memo' ) {
81- isReactMemo = true
77+ if ( specifier . imported . name === 'memo' ) {
78+ memo = specifier . local . name
8279 }
8380
84- if (
85- specifier . imported . name === 'forwardRef' &&
86- specifier . local . name === 'forwardRef'
87- ) {
88- isReactForwardRef = true
81+ if ( specifier . imported . name === 'forwardRef' ) {
82+ forwardRef = specifier . local . name
8983 }
9084 }
9185 }
9286 }
9387 } ,
9488 } )
9589
96- return { isReact , isReactMemo , isReactForwardRef }
90+ return { react , memo , forwardRef }
9791}
98- const isPragmaShadowed = ( pragma : Pragma , scopes : Scope [ ] ) => {
92+ const isPragmaShadowed = ( pragma : string , scopes : Scope [ ] ) => {
9993 for ( const scope of scopes ) {
10094 if ( scope . pragmas . has ( pragma ) ) {
10195 return true
@@ -104,40 +98,45 @@ const isPragmaShadowed = (pragma: Pragma, scopes: Scope[]) => {
10498
10599 return false
106100}
107- const isReactMember = ( pragma : Pragma , node : CallExpression , scopes : Scope [ ] ) => {
101+ const isReactMember = (
102+ pragma : string ,
103+ node : CallExpression ,
104+ pragmas : Pragmas ,
105+ scopes : Scope [ ] ,
106+ ) => {
108107 const { callee } = node
109108
110109 return (
111110 callee . type === 'MemberExpression' &&
112111 callee . object . type === 'Identifier' &&
113- callee . object . name === 'React' &&
114- ! isPragmaShadowed ( 'React' , scopes ) &&
112+ callee . object . name === pragmas . react &&
115113 callee . property . type === 'Identifier' &&
116- callee . property . name === pragma
114+ callee . property . name === pragma &&
115+ ! isPragmaShadowed ( pragmas . react , scopes )
117116 )
118117}
119- const isMemo = ( node : CallExpression , scopes : Scope [ ] ) => {
118+ const isMemo = ( node : CallExpression , pragmas : Pragmas , scopes : Scope [ ] ) => {
120119 const { callee } = node
121120
122121 return (
123122 ( callee . type === 'Identifier' &&
124- callee . name === ' memo' &&
125- ! isPragmaShadowed ( ' memo' , scopes ) ) ||
126- isReactMember ( 'memo' , node , scopes )
123+ callee . name === pragmas . memo &&
124+ ! isPragmaShadowed ( pragmas . memo , scopes ) ) ||
125+ isReactMember ( 'memo' , node , pragmas , scopes )
127126 )
128127}
129- const isForwardRef = ( node : CallExpression , scopes : Scope [ ] ) => {
128+ const isForwardRef = ( node : CallExpression , pragmas : Pragmas , scopes : Scope [ ] ) => {
130129 const { callee } = node
131130
132131 return (
133132 ( callee . type === 'Identifier' &&
134- callee . name === ' forwardRef' &&
135- ! isPragmaShadowed ( ' forwardRef' , scopes ) ) ||
136- isReactMember ( 'forwardRef' , node , scopes )
133+ callee . name === pragmas . forwardRef &&
134+ ! isPragmaShadowed ( pragmas . forwardRef , scopes ) ) ||
135+ isReactMember ( 'forwardRef' , node , pragmas , scopes )
137136 )
138137}
139- const isMemoWrapped = ( parent : Node , scopes : Scope [ ] ) => {
140- return parent . type === 'CallExpression' && isMemo ( parent , scopes )
138+ const isMemoWrapped = ( parent : Node , pragmas : Pragmas , scopes : Scope [ ] ) => {
139+ return parent . type === 'CallExpression' && isMemo ( parent , pragmas , scopes )
141140}
142141const scopeNodes = [
143142 'FunctionDeclaration' ,
@@ -159,11 +158,13 @@ const defaultOptions = {
159158const modify = async ( source : string , options : Options = defaultOptions ) => {
160159 const ast = parseSync ( 'file.tsx' , source )
161160 const code = new MagicString ( source )
162- const { isReact, isReactMemo, isReactForwardRef } = await detectReactPragmas (
163- ast . program ,
164- )
161+ const { react, memo, forwardRef } = await detectReactPragmas ( ast . program )
162+ const pragmas = { react, memo, forwardRef } satisfies Pragmas
163+ const isPragma = ( name : string ) => {
164+ return name === react || name === memo || name === forwardRef
165+ }
165166
166- if ( isReact || isReactMemo || isReactForwardRef ) {
167+ if ( react || memo || forwardRef ) {
167168 const scopes : Scope [ ] = [ ]
168169 const foundDisplayNames = await collectDisplayNames ( ast . program , code )
169170 const opts = {
@@ -321,13 +322,13 @@ const modify = async (source: string, options: Options = defaultOptions) => {
321322 node . arguments [ 0 ] . type === 'ArrowFunctionExpression' ) &&
322323 ! node . arguments [ 0 ] . id
323324 ) {
324- if ( isMemo ( node , scopes ) ) {
325+ if ( isMemo ( node , pragmas , scopes ) ) {
325326 addDisplayName ( ancestors , node )
326327 }
327328
328- if ( isForwardRef ( node , scopes ) ) {
329+ if ( isForwardRef ( node , pragmas , scopes ) ) {
329330 const parent = ancestors [ ancestors . length - 2 ]
330- const memoWrapped = isMemoWrapped ( parent , scopes )
331+ const memoWrapped = isMemoWrapped ( parent , pragmas , scopes )
331332
332333 if ( ! memoWrapped || ( memoWrapped && opts . modifyNestedForwardRef ) ) {
333334 addDisplayName ( ancestors , node , memoWrapped )
0 commit comments