@@ -4,7 +4,6 @@ import * as VAR from "@eslint-react/var";
44import type { Scope } from "@typescript-eslint/scope-manager" ;
55import { AST_NODE_TYPES as T } from "@typescript-eslint/types" ;
66import type { TSESTree } from "@typescript-eslint/utils" ;
7- import { match , P } from "ts-pattern" ;
87
98// type ReactNode =
109// | ReactElement
@@ -22,21 +21,22 @@ import { match, P } from "ts-pattern";
2221/* eslint-disable perfectionist/sort-objects */
2322export const JSXValueHint = {
2423 None : 0n ,
25- SkipNullLiteral : 1n << 0n ,
26- SkipUndefinedLiteral : 1n << 1n ,
24+ SkipUndefined : 1n << 0n ,
25+ SkipNullLiteral : 1n << 1n ,
2726 SkipBooleanLiteral : 1n << 2n ,
2827 SkipStringLiteral : 1n << 3n ,
2928 SkipNumberLiteral : 1n << 4n ,
30- SkipCreateElement : 1n << 5n ,
29+ SkipBigIntLiteral : 1n << 5n ,
3130 SkipEmptyArray : 1n << 6n ,
32- StrictArray : 1n << 7n ,
33- StrictLogical : 1n << 8n ,
34- StrictConditional : 1n << 9n ,
31+ SkipCreateElement : 1n << 7n ,
32+ StrictArray : 1n << 8n ,
33+ StrictLogical : 1n << 9n ,
34+ StrictConditional : 1n << 10n ,
3535} as const ;
3636/* eslint-enable perfectionist/sort-objects */
3737
3838export const DEFAULT_JSX_VALUE_HINT = 0n
39- | JSXValueHint . SkipUndefinedLiteral
39+ | JSXValueHint . SkipUndefined
4040 | JSXValueHint . SkipBooleanLiteral ;
4141
4242/**
@@ -52,30 +52,45 @@ export function isJSXValue(
5252 jsxCtx : { getScope : ( node : TSESTree . Node ) => Scope } ,
5353 hint : bigint = DEFAULT_JSX_VALUE_HINT ,
5454) : boolean {
55- if ( ! node ) {
56- return false ;
57- }
58- return match < typeof node , boolean > ( node )
59- . with ( { type : T . JSXElement } , F . constTrue )
60- . with ( { type : T . JSXFragment } , F . constTrue )
61- . with ( { type : T . JSXMemberExpression } , F . constTrue )
62- . with ( { type : T . JSXNamespacedName } , F . constTrue )
63- . with ( { type : T . Literal } , ( node ) => {
64- return match ( node . value )
65- . with ( null , ( ) => ! ( hint & JSXValueHint . SkipNullLiteral ) )
66- . with ( P . boolean , ( ) => ! ( hint & JSXValueHint . SkipBooleanLiteral ) )
67- . with ( P . string , ( ) => ! ( hint & JSXValueHint . SkipStringLiteral ) )
68- . with ( P . number , ( ) => ! ( hint & JSXValueHint . SkipNumberLiteral ) )
69- . otherwise ( F . constFalse ) ;
70- } )
71- . with ( { type : T . TemplateLiteral } , ( ) => ! ( hint & JSXValueHint . SkipStringLiteral ) )
72- . with ( { type : T . ArrayExpression } , ( node ) => {
55+ switch ( node ?. type ) {
56+ case T . JSXElement :
57+ case T . JSXFragment :
58+ case T . JSXMemberExpression :
59+ case T . JSXNamespacedName : {
60+ return true ;
61+ }
62+ case T . Literal : {
63+ switch ( typeof node . value ) {
64+ case "boolean" :
65+ return ! ( hint & JSXValueHint . SkipBooleanLiteral ) ;
66+ case "string" :
67+ return ! ( hint & JSXValueHint . SkipStringLiteral ) ;
68+ case "number" :
69+ return ! ( hint & JSXValueHint . SkipNumberLiteral ) ;
70+ case "bigint" :
71+ return ! ( hint & JSXValueHint . SkipBigIntLiteral ) ;
72+ }
73+ if ( node . value === null ) {
74+ return ! ( hint & JSXValueHint . SkipNullLiteral ) ;
75+ }
76+ return false ;
77+ }
78+ case T . TemplateLiteral : {
79+ return ! ( hint & JSXValueHint . SkipStringLiteral ) ;
80+ }
81+ case T . ArrayExpression : {
7382 if ( hint & JSXValueHint . StrictArray ) {
7483 return node . elements . every ( ( n ) => isJSXValue ( n , jsxCtx , hint ) ) ;
7584 }
7685 return node . elements . some ( ( n ) => isJSXValue ( n , jsxCtx , hint ) ) ;
77- } )
78- . with ( { type : T . ConditionalExpression } , ( node ) => {
86+ }
87+ case T . LogicalExpression : {
88+ if ( hint & JSXValueHint . StrictLogical ) {
89+ return isJSXValue ( node . left , jsxCtx , hint ) && isJSXValue ( node . right , jsxCtx , hint ) ;
90+ }
91+ return isJSXValue ( node . left , jsxCtx , hint ) || isJSXValue ( node . right , jsxCtx , hint ) ;
92+ }
93+ case T . ConditionalExpression : {
7994 function leftHasJSX ( node : TSESTree . ConditionalExpression ) {
8095 if ( Array . isArray ( node . consequent ) ) {
8196 if ( node . consequent . length === 0 ) {
@@ -95,40 +110,37 @@ export function isJSXValue(
95110 return leftHasJSX ( node ) && rightHasJSX ( node ) ;
96111 }
97112 return leftHasJSX ( node ) || rightHasJSX ( node ) ;
98- } )
99- . with ( { type : T . LogicalExpression } , ( node ) => {
100- if ( hint & JSXValueHint . StrictLogical ) {
101- return isJSXValue ( node . left , jsxCtx , hint ) && isJSXValue ( node . right , jsxCtx , hint ) ;
102- }
103- return isJSXValue ( node . left , jsxCtx , hint ) || isJSXValue ( node . right , jsxCtx , hint ) ;
104- } )
105- . with ( { type : T . SequenceExpression } , ( node ) => {
113+ }
114+ case T . SequenceExpression : {
106115 const exp = node . expressions . at ( - 1 ) ;
107116 return isJSXValue ( exp , jsxCtx , hint ) ;
108- } )
109- . with ( { type : T . CallExpression } , ( node ) => {
117+ }
118+ case T . CallExpression : {
110119 if ( hint & JSXValueHint . SkipCreateElement ) {
111120 return false ;
112121 }
113- return match ( node . callee )
114- . with ( { type : T . Identifier , name : "createElement" } , F . constTrue )
115- . with ( { type : T . MemberExpression , property : { name : "createElement" } } , F . constTrue )
116- . otherwise ( F . constFalse ) ;
117- } )
118- . with ( { type : T . Identifier } , ( node ) => {
122+ switch ( node . callee . type ) {
123+ case T . Identifier :
124+ return node . callee . name === "createElement" ;
125+ case T . MemberExpression :
126+ return node . callee . property . type === T . Identifier && node . callee . property . name === "createElement" ;
127+ }
128+ return false ;
129+ }
130+ case T . Identifier : {
119131 const { name } = node ;
120132 if ( name === "undefined" ) {
121- return ! ( hint & JSXValueHint . SkipUndefinedLiteral ) ;
133+ return ! ( hint & JSXValueHint . SkipUndefined ) ;
122134 }
123135 if ( AST . isJSXTagNameExpression ( node ) ) {
124136 return true ;
125137 }
126- const initialScope = jsxCtx . getScope ( node ) ;
127138 return F . pipe (
128- VAR . findVariable ( name , initialScope ) ,
139+ VAR . findVariable ( name , jsxCtx . getScope ( node ) ) ,
129140 O . flatMap ( VAR . getVariableNode ( 0 ) ) ,
130141 O . exists ( n => isJSXValue ( n , jsxCtx , hint ) ) ,
131142 ) ;
132- } )
133- . otherwise ( F . constFalse ) ;
143+ }
144+ }
145+ return false ;
134146}
0 commit comments