@eslint-react/core 2.0.0-next.150 → 2.0.0-next.152
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +158 -75
- package/dist/index.js +199 -136
- package/package.json +6 -6
package/dist/index.d.ts
CHANGED
|
@@ -188,7 +188,14 @@ declare function useComponentCollectorLegacy(): useComponentCollectorLegacy.Retu
|
|
|
188
188
|
* @returns `true` if node is a render function, `false` if not
|
|
189
189
|
*/
|
|
190
190
|
declare function isFunctionOfRenderMethod(node: AST.TSESTreeFunction): boolean;
|
|
191
|
-
|
|
191
|
+
/**
|
|
192
|
+
* Determines if a function node represents a valid React component definition
|
|
193
|
+
* @param context The rule context
|
|
194
|
+
* @param node The function node to check
|
|
195
|
+
* @param hint Component detection hints as bit flags
|
|
196
|
+
* @returns `true` if the node is a valid component definition, `false` otherwise
|
|
197
|
+
*/
|
|
198
|
+
declare function isComponentDefinition(context: RuleContext, node: AST.TSESTreeFunction, hint: bigint): boolean;
|
|
192
199
|
//#endregion
|
|
193
200
|
//#region src/component/component-id.d.ts
|
|
194
201
|
declare function getFunctionComponentId(context: RuleContext, node: AST.TSESTreeFunction): TSESTree.Identifier | TSESTree.Identifier[] | unit;
|
|
@@ -214,23 +221,24 @@ declare function isPureComponent(node: TSESTree.Node): boolean;
|
|
|
214
221
|
type ComponentKind = "classComponent" | "functionComponent";
|
|
215
222
|
//#endregion
|
|
216
223
|
//#region src/component/component-method.d.ts
|
|
217
|
-
declare
|
|
218
|
-
declare
|
|
219
|
-
declare
|
|
220
|
-
declare
|
|
221
|
-
declare
|
|
222
|
-
declare
|
|
223
|
-
declare
|
|
224
|
-
declare
|
|
225
|
-
declare
|
|
226
|
-
declare
|
|
227
|
-
declare
|
|
228
|
-
declare
|
|
229
|
-
declare
|
|
230
|
-
declare
|
|
231
|
-
declare
|
|
232
|
-
declare
|
|
233
|
-
declare
|
|
224
|
+
declare const isRender: (node: TSESTree.Node) => node is AST.TSESTreeMethodOrProperty;
|
|
225
|
+
declare const isComponentDidCatch: (node: TSESTree.Node) => node is AST.TSESTreeMethodOrProperty;
|
|
226
|
+
declare const isComponentDidMount: (node: TSESTree.Node) => node is AST.TSESTreeMethodOrProperty;
|
|
227
|
+
declare const isComponentDidUpdate: (node: TSESTree.Node) => node is AST.TSESTreeMethodOrProperty;
|
|
228
|
+
declare const isComponentWillMount: (node: TSESTree.Node) => node is AST.TSESTreeMethodOrProperty;
|
|
229
|
+
declare const isComponentWillReceiveProps: (node: TSESTree.Node) => node is AST.TSESTreeMethodOrProperty;
|
|
230
|
+
declare const isComponentWillUnmount: (node: TSESTree.Node) => node is AST.TSESTreeMethodOrProperty;
|
|
231
|
+
declare const isComponentWillUpdate: (node: TSESTree.Node) => node is AST.TSESTreeMethodOrProperty;
|
|
232
|
+
declare const isGetChildContext: (node: TSESTree.Node) => node is AST.TSESTreeMethodOrProperty;
|
|
233
|
+
declare const isGetInitialState: (node: TSESTree.Node) => node is AST.TSESTreeMethodOrProperty;
|
|
234
|
+
declare const isGetSnapshotBeforeUpdate: (node: TSESTree.Node) => node is AST.TSESTreeMethodOrProperty;
|
|
235
|
+
declare const isShouldComponentUpdate: (node: TSESTree.Node) => node is AST.TSESTreeMethodOrProperty;
|
|
236
|
+
declare const isUnsafeComponentWillMount: (node: TSESTree.Node) => node is AST.TSESTreeMethodOrProperty;
|
|
237
|
+
declare const isUnsafeComponentWillReceiveProps: (node: TSESTree.Node) => node is AST.TSESTreeMethodOrProperty;
|
|
238
|
+
declare const isUnsafeComponentWillUpdate: (node: TSESTree.Node) => node is AST.TSESTreeMethodOrProperty;
|
|
239
|
+
declare const isGetDefaultProps: (node: TSESTree.Node) => node is AST.TSESTreeMethodOrProperty;
|
|
240
|
+
declare const isGetDerivedStateFromProps: (node: TSESTree.Node) => node is AST.TSESTreeMethodOrProperty;
|
|
241
|
+
declare const isGetDerivedStateFromError: (node: TSESTree.Node) => node is AST.TSESTreeMethodOrProperty;
|
|
234
242
|
//#endregion
|
|
235
243
|
//#region src/component/component-name.d.ts
|
|
236
244
|
declare function isComponentName(name: string): boolean;
|
|
@@ -238,33 +246,6 @@ declare function isComponentNameLoose(name: string): boolean;
|
|
|
238
246
|
declare function getComponentNameFromId(id: TSESTree.Identifier | TSESTree.Identifier[] | unit): string | undefined;
|
|
239
247
|
declare function hasNoneOrLooseComponentName(context: RuleContext, fn: AST.TSESTreeFunction): boolean;
|
|
240
248
|
//#endregion
|
|
241
|
-
//#region src/component/component-render.d.ts
|
|
242
|
-
/**
|
|
243
|
-
* Check whether given node is a render function of a class component
|
|
244
|
-
* @example
|
|
245
|
-
* ```tsx
|
|
246
|
-
* class Component extends React.Component {
|
|
247
|
-
* render() {
|
|
248
|
-
* return <div />;
|
|
249
|
-
* }
|
|
250
|
-
* }
|
|
251
|
-
* ```
|
|
252
|
-
* @param node The AST node to check
|
|
253
|
-
* @returns `true` if node is a render function, `false` if not
|
|
254
|
-
*/
|
|
255
|
-
declare function isRenderLike(node: TSESTree.Node): node is AST.TSESTreeMethodOrProperty;
|
|
256
|
-
/**
|
|
257
|
-
* Check whether given node is a function of a render function of a class component
|
|
258
|
-
* @example
|
|
259
|
-
* ```tsx
|
|
260
|
-
* class Component extends React.Component {
|
|
261
|
-
* render = () => <div />;
|
|
262
|
-
* ```
|
|
263
|
-
* @param node The AST node to check
|
|
264
|
-
* @returns `true` if node is a render function, `false` if not
|
|
265
|
-
*/
|
|
266
|
-
declare function isFunctionOfRender(node: AST.TSESTreeFunction): boolean;
|
|
267
|
-
//#endregion
|
|
268
249
|
//#region src/component/component-render-method.d.ts
|
|
269
250
|
/**
|
|
270
251
|
* Check whether given node is a render method of a class component
|
|
@@ -378,6 +359,11 @@ declare function useHookCollector(): useHookCollector.ReturnType;
|
|
|
378
359
|
declare function isReactHookId(id: TSESTree.Identifier | TSESTree.MemberExpression): boolean;
|
|
379
360
|
//#endregion
|
|
380
361
|
//#region src/hook/hook-is.d.ts
|
|
362
|
+
/**
|
|
363
|
+
* Determines if a function node is a React Hook based on its name.
|
|
364
|
+
* @param node The function node to check
|
|
365
|
+
* @returns True if the function is a React Hook, false otherwise
|
|
366
|
+
*/
|
|
381
367
|
declare function isReactHook(node: AST.TSESTreeFunction | unit): boolean;
|
|
382
368
|
/**
|
|
383
369
|
* Check if the given node is a React Hook call by its name.
|
|
@@ -385,9 +371,33 @@ declare function isReactHook(node: AST.TSESTreeFunction | unit): boolean;
|
|
|
385
371
|
* @returns `true` if the node is a React Hook call, `false` otherwise.
|
|
386
372
|
*/
|
|
387
373
|
declare function isReactHookCall(node: TSESTree.Node | unit): boolean;
|
|
374
|
+
/**
|
|
375
|
+
* Checks if a node is a call to a specific React hook, with React import validation.
|
|
376
|
+
* Returns a function that accepts a hook name to check against.
|
|
377
|
+
* @param context The rule context
|
|
378
|
+
* @param node The AST node to check
|
|
379
|
+
* @returns A function that takes a hook name and returns boolean
|
|
380
|
+
*/
|
|
388
381
|
declare function isReactHookCallWithName(context: RuleContext, node: TSESTree.Node | unit): (name: string) => boolean;
|
|
382
|
+
/**
|
|
383
|
+
* Lightweight version of isReactHookCallWithName that doesn't check imports.
|
|
384
|
+
* @param node The AST node to check
|
|
385
|
+
* @returns A function that takes a hook name and returns boolean
|
|
386
|
+
*/
|
|
389
387
|
declare function isReactHookCallWithNameLoose(node: TSESTree.Node | unit): (name: string) => boolean;
|
|
388
|
+
/**
|
|
389
|
+
* Checks if a node is a call to a specific React hook or one of its aliases.
|
|
390
|
+
* @param context The rule context
|
|
391
|
+
* @param name The primary hook name to check
|
|
392
|
+
* @param alias Optional array of alias names to also accept
|
|
393
|
+
* @returns Function that checks if a node matches the hook name or aliases
|
|
394
|
+
*/
|
|
390
395
|
declare function isReactHookCallWithNameAlias(context: RuleContext, name: string, alias?: unit | string[]): (node: TSESTree.CallExpression) => boolean;
|
|
396
|
+
/**
|
|
397
|
+
* Detects useEffect calls and variations (useLayoutEffect, etc.) using regex pattern.
|
|
398
|
+
* @param node The AST node to check
|
|
399
|
+
* @returns True if the node is a useEffect-like call
|
|
400
|
+
*/
|
|
391
401
|
declare function isUseEffectCallLoose(node: TSESTree.Node | unit): boolean;
|
|
392
402
|
declare const isUseCall: (context: RuleContext, node: TSESTree.Node | undefined) => boolean;
|
|
393
403
|
declare const isUseActionStateCall: (context: RuleContext, node: TSESTree.Node | undefined) => boolean;
|
|
@@ -421,12 +431,14 @@ declare function isReactHookName(name: string): boolean;
|
|
|
421
431
|
//#endregion
|
|
422
432
|
//#region src/jsx/jsx-attribute.d.ts
|
|
423
433
|
/**
|
|
424
|
-
*
|
|
425
|
-
*
|
|
426
|
-
*
|
|
427
|
-
* @param
|
|
428
|
-
* @param
|
|
429
|
-
* @
|
|
434
|
+
* Searches for a specific JSX attribute by name in a list of attributes
|
|
435
|
+
* Returns the last matching attribute (rightmost in JSX)
|
|
436
|
+
*
|
|
437
|
+
* @param context - ESLint rule context
|
|
438
|
+
* @param name - The name of the attribute to find
|
|
439
|
+
* @param attributes - Array of JSX attributes to search through
|
|
440
|
+
* @param initialScope - Optional scope for resolving variables
|
|
441
|
+
* @returns The found attribute or undefined
|
|
430
442
|
*/
|
|
431
443
|
declare function getAttribute(context: RuleContext, name: string, attributes: (TSESTree$1.JSXAttribute | TSESTree$1.JSXSpreadAttribute)[], initialScope?: Scope): TSESTree$1.JSXAttribute | TSESTree$1.JSXSpreadAttribute | unit;
|
|
432
444
|
//#endregion
|
|
@@ -441,18 +453,27 @@ declare function getAttributeName(context: RuleContext, node: TSESTree$1.JSXAttr
|
|
|
441
453
|
//#endregion
|
|
442
454
|
//#region src/jsx/jsx-attribute-value.d.ts
|
|
443
455
|
/**
|
|
444
|
-
*
|
|
445
|
-
* @param context
|
|
446
|
-
* @param node
|
|
447
|
-
* @param name
|
|
448
|
-
* @returns The
|
|
456
|
+
* Extracts the value of a JSX attribute by name
|
|
457
|
+
* @param context - ESLint rule context
|
|
458
|
+
* @param node - JSX attribute or spread attribute node
|
|
459
|
+
* @param name - Name of the attribute to extract
|
|
460
|
+
* @returns The extracted attribute value in a structured format
|
|
449
461
|
*/
|
|
450
462
|
declare function getAttributeValue(context: RuleContext, node: TSESTree$1.JSXAttribute | TSESTree$1.JSXSpreadAttribute, name: string): Exclude<VAR.LazyValue, {
|
|
451
463
|
kind: "lazy";
|
|
452
464
|
}>;
|
|
453
465
|
//#endregion
|
|
454
466
|
//#region src/jsx/jsx-detection-hint.d.ts
|
|
467
|
+
/**
|
|
468
|
+
* BitFlags for configuring JSX detection behavior
|
|
469
|
+
* Uses BigInt for bit operations to support many flags
|
|
470
|
+
*/
|
|
455
471
|
type JSXDetectionHint = bigint;
|
|
472
|
+
/**
|
|
473
|
+
* Flags to control JSX detection behavior:
|
|
474
|
+
* - Skip* flags: Ignore specific node types when detecting JSX
|
|
475
|
+
* - Strict* flags: Enforce stricter rules for container types
|
|
476
|
+
*/
|
|
456
477
|
declare const JSXDetectionHint: {
|
|
457
478
|
readonly None: 0n;
|
|
458
479
|
readonly SkipUndefined: bigint;
|
|
@@ -467,59 +488,115 @@ declare const JSXDetectionHint: {
|
|
|
467
488
|
readonly StrictLogical: bigint;
|
|
468
489
|
readonly StrictConditional: bigint;
|
|
469
490
|
};
|
|
491
|
+
/**
|
|
492
|
+
* Default JSX detection configuration
|
|
493
|
+
* Skips undefined and boolean literals (common in React)
|
|
494
|
+
*/
|
|
470
495
|
declare const DEFAULT_JSX_DETECTION_HINT: bigint;
|
|
471
496
|
//#endregion
|
|
472
497
|
//#region src/jsx/jsx-detection.d.ts
|
|
473
498
|
/**
|
|
474
|
-
*
|
|
499
|
+
* Checks if a node is a `JSXText` or a `Literal` node
|
|
475
500
|
* @param node The AST node to check
|
|
476
501
|
* @returns `true` if the node is a `JSXText` or a `Literal` node
|
|
477
502
|
*/
|
|
478
503
|
declare function isJsxText(node: TSESTree$1.Node | null | unit): node is TSESTree$1.JSXText | TSESTree$1.Literal;
|
|
479
504
|
/**
|
|
480
|
-
*
|
|
481
|
-
*
|
|
505
|
+
* Determines if a node represents JSX-like content based on heuristics
|
|
506
|
+
* Supports configuration through hint flags to customize detection behavior
|
|
507
|
+
*
|
|
508
|
+
* @param code The source code with scope lookup capability
|
|
482
509
|
* @param code.getScope The function to get the scope of a node
|
|
483
|
-
* @param node The AST node to
|
|
484
|
-
* @param hint The
|
|
485
|
-
* @returns boolean
|
|
510
|
+
* @param node The AST node to analyze
|
|
511
|
+
* @param hint The configuration flags to adjust detection behavior
|
|
512
|
+
* @returns boolean Whether the node is considered JSX-like
|
|
486
513
|
*/
|
|
487
514
|
declare function isJsxLike(code: {
|
|
488
515
|
getScope: (node: TSESTree$1.Node) => Scope;
|
|
489
516
|
}, node: TSESTree$1.Node | unit | null, hint?: JSXDetectionHint): boolean;
|
|
490
517
|
//#endregion
|
|
491
518
|
//#region src/jsx/jsx-element-is.d.ts
|
|
519
|
+
/**
|
|
520
|
+
* Determines if a JSX element is a host element
|
|
521
|
+
* Host elements in React start with lowercase letters (e.g., div, span)
|
|
522
|
+
*
|
|
523
|
+
* @param context - ESLint rule context
|
|
524
|
+
* @param node - AST node to check
|
|
525
|
+
* @returns boolean indicating if the element is a host element
|
|
526
|
+
*/
|
|
492
527
|
declare function isHostElement(context: RuleContext, node: TSESTree.Node): boolean;
|
|
528
|
+
/**
|
|
529
|
+
* Determines if a JSX element is a React Fragment
|
|
530
|
+
* Fragments can be imported from React and used like <Fragment> or <React.Fragment>
|
|
531
|
+
*
|
|
532
|
+
* @param context - ESLint rule context
|
|
533
|
+
* @param node - AST node to check
|
|
534
|
+
* @returns boolean indicating if the element is a Fragment with type narrowing
|
|
535
|
+
*/
|
|
493
536
|
declare function isFragmentElement(context: RuleContext, node: TSESTree.Node): node is TSESTree.JSXElement;
|
|
494
537
|
//#endregion
|
|
495
538
|
//#region src/jsx/jsx-element-type.d.ts
|
|
496
539
|
/**
|
|
497
|
-
*
|
|
498
|
-
*
|
|
499
|
-
*
|
|
500
|
-
*
|
|
540
|
+
* Extracts the element type name from a JSX element or fragment
|
|
541
|
+
* For JSX elements, returns the stringified name (e.g., "div", "Button", "React.Fragment")
|
|
542
|
+
* For JSX fragments, returns an empty string
|
|
543
|
+
*
|
|
544
|
+
* @param context - ESLint rule context
|
|
545
|
+
* @param node - JSX element or fragment node
|
|
546
|
+
* @returns String representation of the element type
|
|
501
547
|
*/
|
|
502
548
|
declare function getElementType(context: RuleContext, node: TSESTree.JSXElement | TSESTree.JSXFragment): string;
|
|
503
549
|
//#endregion
|
|
504
550
|
//#region src/jsx/jsx-has.d.ts
|
|
551
|
+
/**
|
|
552
|
+
* Checks if a JSX element has a specific attribute
|
|
553
|
+
*
|
|
554
|
+
* @param context - ESLint rule context
|
|
555
|
+
* @param name - Name of the attribute to check for
|
|
556
|
+
* @param attributes - List of JSX attributes from opening element
|
|
557
|
+
* @param initialScope - Optional scope for resolving variables in spread attributes
|
|
558
|
+
* @returns boolean indicating whether the attribute exists
|
|
559
|
+
*/
|
|
505
560
|
declare function hasAttribute(context: RuleContext, name: string, attributes: TSESTree.JSXOpeningElement["attributes"], initialScope?: Scope): boolean;
|
|
561
|
+
/**
|
|
562
|
+
* Checks if a JSX element has at least one of the specified attributes
|
|
563
|
+
*
|
|
564
|
+
* @param context - ESLint rule context
|
|
565
|
+
* @param names - Array of attribute names to check for
|
|
566
|
+
* @param attributes - List of JSX attributes from opening element
|
|
567
|
+
* @param initialScope - Optional scope for resolving variables in spread attributes
|
|
568
|
+
* @returns boolean indicating whether any of the attributes exist
|
|
569
|
+
*/
|
|
506
570
|
declare function hasAnyAttribute(context: RuleContext, names: string[], attributes: TSESTree.JSXOpeningElement["attributes"], initialScope?: Scope): boolean;
|
|
571
|
+
/**
|
|
572
|
+
* Checks if a JSX element has all of the specified attributes
|
|
573
|
+
*
|
|
574
|
+
* @param context - ESLint rule context
|
|
575
|
+
* @param names - Array of attribute names to check for
|
|
576
|
+
* @param attributes - List of JSX attributes from opening element
|
|
577
|
+
* @param initialScope - Optional scope for resolving variables in spread attributes
|
|
578
|
+
* @returns boolean indicating whether all of the attributes exist
|
|
579
|
+
*/
|
|
507
580
|
declare function hasEveryAttribute(context: RuleContext, names: string[], attributes: TSESTree.JSXOpeningElement["attributes"], initialScope?: Scope): boolean;
|
|
508
581
|
//#endregion
|
|
509
582
|
//#region src/jsx/jsx-hierarchy.d.ts
|
|
510
583
|
/**
|
|
511
|
-
*
|
|
512
|
-
*
|
|
513
|
-
* @param
|
|
514
|
-
* @
|
|
584
|
+
* Traverses up the AST to find a parent JSX attribute node that matches a given test
|
|
585
|
+
*
|
|
586
|
+
* @param node - The starting AST node
|
|
587
|
+
* @param test - Optional predicate function to test if the attribute meets criteria
|
|
588
|
+
* Defaults to always returning true (matches any attribute)
|
|
589
|
+
* @returns The first matching JSX attribute node found when traversing upwards, or undefined
|
|
515
590
|
*/
|
|
516
591
|
declare function findParentAttribute(node: TSESTree.Node, test?: (node: TSESTree.JSXAttribute) => boolean): TSESTree.JSXAttribute | unit;
|
|
517
592
|
//#endregion
|
|
518
593
|
//#region src/jsx/jsx-stringify.d.ts
|
|
519
594
|
/**
|
|
520
|
-
*
|
|
521
|
-
*
|
|
522
|
-
*
|
|
595
|
+
* Converts a JSX AST node to its string representation
|
|
596
|
+
* Handles different JSX node types and returns their textual form
|
|
597
|
+
*
|
|
598
|
+
* @param node - JSX node from TypeScript ESTree
|
|
599
|
+
* @returns String representation of the JSX node
|
|
523
600
|
*/
|
|
524
601
|
declare function stringifyJsx(node: TSESTree$1.JSXIdentifier | TSESTree$1.JSXMemberExpression | TSESTree$1.JSXNamespacedName | TSESTree$1.JSXOpeningElement | TSESTree$1.JSXClosingElement | TSESTree$1.JSXOpeningFragment | TSESTree$1.JSXClosingFragment | TSESTree$1.JSXText): string;
|
|
525
602
|
//#endregion
|
|
@@ -636,7 +713,13 @@ type TypeVariant = "any" | "bigint" | "boolean" | "enum" | "never" | "nullish" |
|
|
|
636
713
|
declare function getTypeVariants(types: ts.Type[]): Set<TypeVariant>;
|
|
637
714
|
//#endregion
|
|
638
715
|
//#region src/utils/get-instance-id.d.ts
|
|
639
|
-
/**
|
|
716
|
+
/**
|
|
717
|
+
* Gets the identifier node of an instance based on AST node relationships.
|
|
718
|
+
* Used for tracking where hooks or components are being assigned in the code.
|
|
719
|
+
* @param node The current AST node to evaluate
|
|
720
|
+
* @param prev The previous AST node in the traversal (used for context)
|
|
721
|
+
* @internal
|
|
722
|
+
*/
|
|
640
723
|
declare function getInstanceId(node: TSESTree.Node, prev?: TSESTree.Node): TSESTree.ArrayExpression | TSESTree.ArrayPattern | TSESTree.ArrowFunctionExpression | TSESTree.AssignmentExpression | TSESTree.AwaitExpression | TSESTree.BinaryExpression | TSESTree.CallExpression | TSESTree.ChainExpression | TSESTree.ClassExpression | TSESTree.ConditionalExpression | TSESTree.FunctionExpression | TSESTree.Identifier | TSESTree.ImportExpression | TSESTree.JSXElement | TSESTree.JSXFragment | TSESTree.BigIntLiteral | TSESTree.BooleanLiteral | TSESTree.NullLiteral | TSESTree.NumberLiteral | TSESTree.RegExpLiteral | TSESTree.StringLiteral | TSESTree.LogicalExpression | TSESTree.MemberExpressionComputedName | TSESTree.MemberExpressionNonComputedName | TSESTree.MetaProperty | TSESTree.NewExpression | TSESTree.ObjectExpression | TSESTree.ObjectPattern | TSESTree.PrivateIdentifier | TSESTree.SequenceExpression | TSESTree.Super | TSESTree.TaggedTemplateExpression | TSESTree.TemplateLiteral | TSESTree.ThisExpression | TSESTree.TSAsExpression | TSESTree.TSInstantiationExpression | TSESTree.TSNonNullExpression | TSESTree.TSSatisfiesExpression | TSESTree.TSTypeAssertion | TSESTree.UnaryExpression | TSESTree.UpdateExpression | TSESTree.YieldExpression | undefined;
|
|
641
724
|
//#endregion
|
|
642
725
|
//#region src/utils/is-from-react.d.ts
|
|
@@ -696,4 +779,4 @@ declare const isForwardRefCall: isReactAPICall.ReturnType;
|
|
|
696
779
|
declare const isMemoCall: isReactAPICall.ReturnType;
|
|
697
780
|
declare const isLazyCall: isReactAPICall.ReturnType;
|
|
698
781
|
//#endregion
|
|
699
|
-
export { ClassComponent, Component, ComponentDetectionHint, ComponentEffectPhaseKind, ComponentFlag, ComponentKind, ComponentLifecyclePhaseKind, ComponentPhaseKind, ComponentPhaseRelevance, ComponentStateKind, DEFAULT_COMPONENT_DETECTION_HINT, DEFAULT_JSX_DETECTION_HINT, EffectKind, FunctionComponent, Hook, JSXDetectionHint, REACT_BUILTIN_HOOK_NAMES, SemanticEntry, SemanticNode, TypeVariant, findParentAttribute, getAttribute, getAttributeName, getAttributeValue, getComponentFlagFromInitPath, getComponentNameFromId, getElementType, getFunctionComponentId, getInstanceId, getTypeVariants, hasAnyAttribute, hasAttribute, hasEveryAttribute, hasNoneOrLooseComponentName, isAnyType, isAssignmentToThisState, isBigIntType, isBooleanType, isCaptureOwnerStack, isCaptureOwnerStackCall, isChildrenCount, isChildrenCountCall, isChildrenForEach, isChildrenForEachCall, isChildrenMap, isChildrenMapCall, isChildrenOfCreateElement, isChildrenOnly, isChildrenOnlyCall, isChildrenToArray, isChildrenToArrayCall, isClassComponent, isCloneElement, isCloneElementCall, isComponentDidCatch, isComponentDidMount, isComponentDidUpdate, isComponentName, isComponentNameLoose, isComponentWillMount, isComponentWillReceiveProps, isComponentWillUnmount, isComponentWillUpdate, isComponentWrapperCall, isComponentWrapperCallLoose, isCreateContext, isCreateContextCall, isCreateElement, isCreateElementCall, isCreateRef, isCreateRefCall, isDeclaredInRenderPropLoose, isDirectValueOfRenderPropertyLoose, isEnumType, isFalseLiteralType, isFalsyBigIntType, isFalsyNumberType, isFalsyStringType, isForwardRef, isForwardRefCall, isFragmentElement,
|
|
782
|
+
export { ClassComponent, Component, ComponentDetectionHint, ComponentEffectPhaseKind, ComponentFlag, ComponentKind, ComponentLifecyclePhaseKind, ComponentPhaseKind, ComponentPhaseRelevance, ComponentStateKind, DEFAULT_COMPONENT_DETECTION_HINT, DEFAULT_JSX_DETECTION_HINT, EffectKind, FunctionComponent, Hook, JSXDetectionHint, REACT_BUILTIN_HOOK_NAMES, SemanticEntry, SemanticNode, TypeVariant, findParentAttribute, getAttribute, getAttributeName, getAttributeValue, getComponentFlagFromInitPath, getComponentNameFromId, getElementType, getFunctionComponentId, getInstanceId, getTypeVariants, hasAnyAttribute, hasAttribute, hasEveryAttribute, hasNoneOrLooseComponentName, isAnyType, isAssignmentToThisState, isBigIntType, isBooleanType, isCaptureOwnerStack, isCaptureOwnerStackCall, isChildrenCount, isChildrenCountCall, isChildrenForEach, isChildrenForEachCall, isChildrenMap, isChildrenMapCall, isChildrenOfCreateElement, isChildrenOnly, isChildrenOnlyCall, isChildrenToArray, isChildrenToArrayCall, isClassComponent, isCloneElement, isCloneElementCall, isComponentDefinition, isComponentDidCatch, isComponentDidMount, isComponentDidUpdate, isComponentName, isComponentNameLoose, isComponentWillMount, isComponentWillReceiveProps, isComponentWillUnmount, isComponentWillUpdate, isComponentWrapperCall, isComponentWrapperCallLoose, isCreateContext, isCreateContextCall, isCreateElement, isCreateElementCall, isCreateRef, isCreateRefCall, isDeclaredInRenderPropLoose, isDirectValueOfRenderPropertyLoose, isEnumType, isFalseLiteralType, isFalsyBigIntType, isFalsyNumberType, isFalsyStringType, isForwardRef, isForwardRefCall, isFragmentElement, isFunctionOfRenderMethod, isGetChildContext, isGetDefaultProps, isGetDerivedStateFromError, isGetDerivedStateFromProps, isGetInitialState, isGetSnapshotBeforeUpdate, isHostElement, isInitializedFromReact, isInstanceIdEqual, isInversePhase, isJsxLike, isJsxText, isLazy, isLazyCall, isMemo, isMemoCall, isNeverType, isNullishType, isNumberType, isObjectType, isPureComponent, isReactAPI, isReactAPICall, isReactHook, isReactHookCall, isReactHookCallWithName, isReactHookCallWithNameAlias, isReactHookCallWithNameLoose, isReactHookId, isReactHookName, isRender, isRenderFunctionLoose, isRenderMethodLike, isRenderPropLoose, isShouldComponentUpdate, isStringType, isThisSetState, isTrueLiteralType, isTruthyBigIntType, isTruthyNumberType, isTruthyStringType, isUnknownType, isUnsafeComponentWillMount, isUnsafeComponentWillReceiveProps, isUnsafeComponentWillUpdate, isUseActionStateCall, isUseCall, isUseCallbackCall, isUseContextCall, isUseDebugValueCall, isUseDeferredValueCall, isUseEffectCall, isUseEffectCallLoose, isUseFormStatusCall, isUseIdCall, isUseImperativeHandleCall, isUseInsertionEffectCall, isUseLayoutEffectCall, isUseMemoCall, isUseOptimisticCall, isUseReducerCall, isUseRefCall, isUseStateCall, isUseSyncExternalStoreCall, isUseTransitionCall, stringifyJsx, useComponentCollector, useComponentCollectorLegacy, useHookCollector };
|
package/dist/index.js
CHANGED
|
@@ -73,7 +73,13 @@ function isChildrenOfCreateElement(context, node) {
|
|
|
73
73
|
|
|
74
74
|
//#endregion
|
|
75
75
|
//#region src/utils/get-instance-id.ts
|
|
76
|
-
/**
|
|
76
|
+
/**
|
|
77
|
+
* Gets the identifier node of an instance based on AST node relationships.
|
|
78
|
+
* Used for tracking where hooks or components are being assigned in the code.
|
|
79
|
+
* @param node The current AST node to evaluate
|
|
80
|
+
* @param prev The previous AST node in the traversal (used for context)
|
|
81
|
+
* @internal
|
|
82
|
+
*/
|
|
77
83
|
function getInstanceId(node, prev) {
|
|
78
84
|
switch (true) {
|
|
79
85
|
case node.type === AST_NODE_TYPES.VariableDeclarator && node.init === prev: return node.id;
|
|
@@ -171,6 +177,11 @@ function isReactHookName(name) {
|
|
|
171
177
|
|
|
172
178
|
//#endregion
|
|
173
179
|
//#region src/hook/hook-is.ts
|
|
180
|
+
/**
|
|
181
|
+
* Determines if a function node is a React Hook based on its name.
|
|
182
|
+
* @param node The function node to check
|
|
183
|
+
* @returns True if the function is a React Hook, false otherwise
|
|
184
|
+
*/
|
|
174
185
|
function isReactHook(node) {
|
|
175
186
|
if (node == null) return false;
|
|
176
187
|
const id = AST.getFunctionId(node);
|
|
@@ -188,6 +199,13 @@ function isReactHookCall(node) {
|
|
|
188
199
|
if (node.callee.type === AST_NODE_TYPES.MemberExpression) return node.callee.property.type === AST_NODE_TYPES.Identifier && isReactHookName(node.callee.property.name);
|
|
189
200
|
return false;
|
|
190
201
|
}
|
|
202
|
+
/**
|
|
203
|
+
* Checks if a node is a call to a specific React hook, with React import validation.
|
|
204
|
+
* Returns a function that accepts a hook name to check against.
|
|
205
|
+
* @param context The rule context
|
|
206
|
+
* @param node The AST node to check
|
|
207
|
+
* @returns A function that takes a hook name and returns boolean
|
|
208
|
+
*/
|
|
191
209
|
function isReactHookCallWithName(context, node) {
|
|
192
210
|
if (node == null || node.type !== AST_NODE_TYPES.CallExpression) return constFalse;
|
|
193
211
|
const { importSource = DEFAULT_ESLINT_REACT_SETTINGS.importSource, skipImportCheck = true } = coerceSettings(context.settings);
|
|
@@ -200,6 +218,11 @@ function isReactHookCallWithName(context, node) {
|
|
|
200
218
|
}
|
|
201
219
|
};
|
|
202
220
|
}
|
|
221
|
+
/**
|
|
222
|
+
* Lightweight version of isReactHookCallWithName that doesn't check imports.
|
|
223
|
+
* @param node The AST node to check
|
|
224
|
+
* @returns A function that takes a hook name and returns boolean
|
|
225
|
+
*/
|
|
203
226
|
function isReactHookCallWithNameLoose(node) {
|
|
204
227
|
if (node == null || node.type !== AST_NODE_TYPES.CallExpression) return constFalse;
|
|
205
228
|
return (name) => {
|
|
@@ -210,6 +233,13 @@ function isReactHookCallWithNameLoose(node) {
|
|
|
210
233
|
}
|
|
211
234
|
};
|
|
212
235
|
}
|
|
236
|
+
/**
|
|
237
|
+
* Checks if a node is a call to a specific React hook or one of its aliases.
|
|
238
|
+
* @param context The rule context
|
|
239
|
+
* @param name The primary hook name to check
|
|
240
|
+
* @param alias Optional array of alias names to also accept
|
|
241
|
+
* @returns Function that checks if a node matches the hook name or aliases
|
|
242
|
+
*/
|
|
213
243
|
function isReactHookCallWithNameAlias(context, name, alias = []) {
|
|
214
244
|
const { importSource = DEFAULT_ESLINT_REACT_SETTINGS.importSource, skipImportCheck = true } = coerceSettings(context.settings);
|
|
215
245
|
return (node) => {
|
|
@@ -221,6 +251,11 @@ function isReactHookCallWithNameAlias(context, name, alias = []) {
|
|
|
221
251
|
}
|
|
222
252
|
};
|
|
223
253
|
}
|
|
254
|
+
/**
|
|
255
|
+
* Detects useEffect calls and variations (useLayoutEffect, etc.) using regex pattern.
|
|
256
|
+
* @param node The AST node to check
|
|
257
|
+
* @returns True if the node is a useEffect-like call
|
|
258
|
+
*/
|
|
224
259
|
function isUseEffectCallLoose(node) {
|
|
225
260
|
if (node == null) return false;
|
|
226
261
|
if (node.type !== AST_NODE_TYPES.CallExpression) return false;
|
|
@@ -320,9 +355,11 @@ function isReactHookId(id) {
|
|
|
320
355
|
//#endregion
|
|
321
356
|
//#region src/jsx/jsx-stringify.ts
|
|
322
357
|
/**
|
|
323
|
-
*
|
|
324
|
-
*
|
|
325
|
-
*
|
|
358
|
+
* Converts a JSX AST node to its string representation
|
|
359
|
+
* Handles different JSX node types and returns their textual form
|
|
360
|
+
*
|
|
361
|
+
* @param node - JSX node from TypeScript ESTree
|
|
362
|
+
* @returns String representation of the JSX node
|
|
326
363
|
*/
|
|
327
364
|
function stringifyJsx(node) {
|
|
328
365
|
switch (node.type) {
|
|
@@ -352,12 +389,14 @@ function getAttributeName(context, node) {
|
|
|
352
389
|
//#endregion
|
|
353
390
|
//#region src/jsx/jsx-attribute.ts
|
|
354
391
|
/**
|
|
355
|
-
*
|
|
356
|
-
*
|
|
357
|
-
*
|
|
358
|
-
* @param
|
|
359
|
-
* @param
|
|
360
|
-
* @
|
|
392
|
+
* Searches for a specific JSX attribute by name in a list of attributes
|
|
393
|
+
* Returns the last matching attribute (rightmost in JSX)
|
|
394
|
+
*
|
|
395
|
+
* @param context - ESLint rule context
|
|
396
|
+
* @param name - The name of the attribute to find
|
|
397
|
+
* @param attributes - Array of JSX attributes to search through
|
|
398
|
+
* @param initialScope - Optional scope for resolving variables
|
|
399
|
+
* @returns The found attribute or undefined
|
|
361
400
|
*/
|
|
362
401
|
function getAttribute(context, name, attributes, initialScope) {
|
|
363
402
|
return attributes.findLast((attr) => {
|
|
@@ -379,11 +418,11 @@ function getAttribute(context, name, attributes, initialScope) {
|
|
|
379
418
|
//#endregion
|
|
380
419
|
//#region src/jsx/jsx-attribute-value.ts
|
|
381
420
|
/**
|
|
382
|
-
*
|
|
383
|
-
* @param context
|
|
384
|
-
* @param node
|
|
385
|
-
* @param name
|
|
386
|
-
* @returns The
|
|
421
|
+
* Extracts the value of a JSX attribute by name
|
|
422
|
+
* @param context - ESLint rule context
|
|
423
|
+
* @param node - JSX attribute or spread attribute node
|
|
424
|
+
* @param name - Name of the attribute to extract
|
|
425
|
+
* @returns The extracted attribute value in a structured format
|
|
387
426
|
*/
|
|
388
427
|
function getAttributeValue(context, node, name) {
|
|
389
428
|
const initialScope = context.sourceCode.getScope(node);
|
|
@@ -433,6 +472,11 @@ function getAttributeValue(context, node, name) {
|
|
|
433
472
|
|
|
434
473
|
//#endregion
|
|
435
474
|
//#region src/jsx/jsx-detection-hint.ts
|
|
475
|
+
/**
|
|
476
|
+
* Flags to control JSX detection behavior:
|
|
477
|
+
* - Skip* flags: Ignore specific node types when detecting JSX
|
|
478
|
+
* - Strict* flags: Enforce stricter rules for container types
|
|
479
|
+
*/
|
|
436
480
|
const JSXDetectionHint = {
|
|
437
481
|
None: 0n,
|
|
438
482
|
SkipUndefined: 1n << 0n,
|
|
@@ -447,12 +491,16 @@ const JSXDetectionHint = {
|
|
|
447
491
|
StrictLogical: 1n << 9n,
|
|
448
492
|
StrictConditional: 1n << 10n
|
|
449
493
|
};
|
|
494
|
+
/**
|
|
495
|
+
* Default JSX detection configuration
|
|
496
|
+
* Skips undefined and boolean literals (common in React)
|
|
497
|
+
*/
|
|
450
498
|
const DEFAULT_JSX_DETECTION_HINT = 0n | JSXDetectionHint.SkipUndefined | JSXDetectionHint.SkipBooleanLiteral;
|
|
451
499
|
|
|
452
500
|
//#endregion
|
|
453
501
|
//#region src/jsx/jsx-detection.ts
|
|
454
502
|
/**
|
|
455
|
-
*
|
|
503
|
+
* Checks if a node is a `JSXText` or a `Literal` node
|
|
456
504
|
* @param node The AST node to check
|
|
457
505
|
* @returns `true` if the node is a `JSXText` or a `Literal` node
|
|
458
506
|
*/
|
|
@@ -461,12 +509,14 @@ function isJsxText(node) {
|
|
|
461
509
|
return node.type === AST_NODE_TYPES.JSXText || node.type === AST_NODE_TYPES.Literal;
|
|
462
510
|
}
|
|
463
511
|
/**
|
|
464
|
-
*
|
|
465
|
-
*
|
|
512
|
+
* Determines if a node represents JSX-like content based on heuristics
|
|
513
|
+
* Supports configuration through hint flags to customize detection behavior
|
|
514
|
+
*
|
|
515
|
+
* @param code The source code with scope lookup capability
|
|
466
516
|
* @param code.getScope The function to get the scope of a node
|
|
467
|
-
* @param node The AST node to
|
|
468
|
-
* @param hint The
|
|
469
|
-
* @returns boolean
|
|
517
|
+
* @param node The AST node to analyze
|
|
518
|
+
* @param hint The configuration flags to adjust detection behavior
|
|
519
|
+
* @returns boolean Whether the node is considered JSX-like
|
|
470
520
|
*/
|
|
471
521
|
function isJsxLike(code, node, hint = DEFAULT_JSX_DETECTION_HINT) {
|
|
472
522
|
if (node == null) return false;
|
|
@@ -530,10 +580,13 @@ function isJsxLike(code, node, hint = DEFAULT_JSX_DETECTION_HINT) {
|
|
|
530
580
|
//#endregion
|
|
531
581
|
//#region src/jsx/jsx-element-type.ts
|
|
532
582
|
/**
|
|
533
|
-
*
|
|
534
|
-
*
|
|
535
|
-
*
|
|
536
|
-
*
|
|
583
|
+
* Extracts the element type name from a JSX element or fragment
|
|
584
|
+
* For JSX elements, returns the stringified name (e.g., "div", "Button", "React.Fragment")
|
|
585
|
+
* For JSX fragments, returns an empty string
|
|
586
|
+
*
|
|
587
|
+
* @param context - ESLint rule context
|
|
588
|
+
* @param node - JSX element or fragment node
|
|
589
|
+
* @returns String representation of the element type
|
|
537
590
|
*/
|
|
538
591
|
function getElementType(context, node) {
|
|
539
592
|
if (node.type === AST_NODE_TYPES.JSXFragment) return "";
|
|
@@ -542,9 +595,25 @@ function getElementType(context, node) {
|
|
|
542
595
|
|
|
543
596
|
//#endregion
|
|
544
597
|
//#region src/jsx/jsx-element-is.ts
|
|
598
|
+
/**
|
|
599
|
+
* Determines if a JSX element is a host element
|
|
600
|
+
* Host elements in React start with lowercase letters (e.g., div, span)
|
|
601
|
+
*
|
|
602
|
+
* @param context - ESLint rule context
|
|
603
|
+
* @param node - AST node to check
|
|
604
|
+
* @returns boolean indicating if the element is a host element
|
|
605
|
+
*/
|
|
545
606
|
function isHostElement(context, node) {
|
|
546
607
|
return node.type === AST_NODE_TYPES.JSXElement && node.openingElement.name.type === AST_NODE_TYPES.JSXIdentifier && /^[a-z]/u.test(node.openingElement.name.name);
|
|
547
608
|
}
|
|
609
|
+
/**
|
|
610
|
+
* Determines if a JSX element is a React Fragment
|
|
611
|
+
* Fragments can be imported from React and used like <Fragment> or <React.Fragment>
|
|
612
|
+
*
|
|
613
|
+
* @param context - ESLint rule context
|
|
614
|
+
* @param node - AST node to check
|
|
615
|
+
* @returns boolean indicating if the element is a Fragment with type narrowing
|
|
616
|
+
*/
|
|
548
617
|
function isFragmentElement(context, node) {
|
|
549
618
|
if (node.type !== AST_NODE_TYPES.JSXElement) return false;
|
|
550
619
|
return getElementType(context, node).split(".").at(-1) === "Fragment";
|
|
@@ -552,12 +621,39 @@ function isFragmentElement(context, node) {
|
|
|
552
621
|
|
|
553
622
|
//#endregion
|
|
554
623
|
//#region src/jsx/jsx-has.ts
|
|
624
|
+
/**
|
|
625
|
+
* Checks if a JSX element has a specific attribute
|
|
626
|
+
*
|
|
627
|
+
* @param context - ESLint rule context
|
|
628
|
+
* @param name - Name of the attribute to check for
|
|
629
|
+
* @param attributes - List of JSX attributes from opening element
|
|
630
|
+
* @param initialScope - Optional scope for resolving variables in spread attributes
|
|
631
|
+
* @returns boolean indicating whether the attribute exists
|
|
632
|
+
*/
|
|
555
633
|
function hasAttribute(context, name, attributes, initialScope) {
|
|
556
634
|
return getAttribute(context, name, attributes, initialScope) != null;
|
|
557
635
|
}
|
|
636
|
+
/**
|
|
637
|
+
* Checks if a JSX element has at least one of the specified attributes
|
|
638
|
+
*
|
|
639
|
+
* @param context - ESLint rule context
|
|
640
|
+
* @param names - Array of attribute names to check for
|
|
641
|
+
* @param attributes - List of JSX attributes from opening element
|
|
642
|
+
* @param initialScope - Optional scope for resolving variables in spread attributes
|
|
643
|
+
* @returns boolean indicating whether any of the attributes exist
|
|
644
|
+
*/
|
|
558
645
|
function hasAnyAttribute(context, names, attributes, initialScope) {
|
|
559
646
|
return names.some((n) => hasAttribute(context, n, attributes, initialScope));
|
|
560
647
|
}
|
|
648
|
+
/**
|
|
649
|
+
* Checks if a JSX element has all of the specified attributes
|
|
650
|
+
*
|
|
651
|
+
* @param context - ESLint rule context
|
|
652
|
+
* @param names - Array of attribute names to check for
|
|
653
|
+
* @param attributes - List of JSX attributes from opening element
|
|
654
|
+
* @param initialScope - Optional scope for resolving variables in spread attributes
|
|
655
|
+
* @returns boolean indicating whether all of the attributes exist
|
|
656
|
+
*/
|
|
561
657
|
function hasEveryAttribute(context, names, attributes, initialScope) {
|
|
562
658
|
return names.every((n) => hasAttribute(context, n, attributes, initialScope));
|
|
563
659
|
}
|
|
@@ -565,10 +661,12 @@ function hasEveryAttribute(context, names, attributes, initialScope) {
|
|
|
565
661
|
//#endregion
|
|
566
662
|
//#region src/jsx/jsx-hierarchy.ts
|
|
567
663
|
/**
|
|
568
|
-
*
|
|
569
|
-
*
|
|
570
|
-
* @param
|
|
571
|
-
* @
|
|
664
|
+
* Traverses up the AST to find a parent JSX attribute node that matches a given test
|
|
665
|
+
*
|
|
666
|
+
* @param node - The starting AST node
|
|
667
|
+
* @param test - Optional predicate function to test if the attribute meets criteria
|
|
668
|
+
* Defaults to always returning true (matches any attribute)
|
|
669
|
+
* @returns The first matching JSX attribute node found when traversing upwards, or undefined
|
|
572
670
|
*/
|
|
573
671
|
function findParentAttribute(node, test = constTrue) {
|
|
574
672
|
const guard = (node$1) => {
|
|
@@ -649,21 +747,26 @@ function isRenderMethodLike(node) {
|
|
|
649
747
|
|
|
650
748
|
//#endregion
|
|
651
749
|
//#region src/component/component-definition.ts
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
}
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
750
|
+
/**
|
|
751
|
+
* Function pattern matchers for different contexts
|
|
752
|
+
*/
|
|
753
|
+
const functionPatterns = {
|
|
754
|
+
classMethod: {
|
|
755
|
+
type: P.union(AST_NODE_TYPES.ArrowFunctionExpression, AST_NODE_TYPES.FunctionExpression),
|
|
756
|
+
parent: AST_NODE_TYPES.MethodDefinition
|
|
757
|
+
},
|
|
758
|
+
classProperty: {
|
|
759
|
+
type: P.union(AST_NODE_TYPES.ArrowFunctionExpression, AST_NODE_TYPES.FunctionExpression),
|
|
760
|
+
parent: AST_NODE_TYPES.Property
|
|
761
|
+
},
|
|
762
|
+
objectMethod: {
|
|
763
|
+
type: P.union(AST_NODE_TYPES.ArrowFunctionExpression, AST_NODE_TYPES.FunctionExpression),
|
|
764
|
+
parent: {
|
|
765
|
+
type: AST_NODE_TYPES.Property,
|
|
766
|
+
parent: { type: AST_NODE_TYPES.ObjectExpression }
|
|
767
|
+
}
|
|
665
768
|
}
|
|
666
|
-
}
|
|
769
|
+
};
|
|
667
770
|
/**
|
|
668
771
|
* Check whether given node is a function of a render method of a class component
|
|
669
772
|
* @example
|
|
@@ -677,15 +780,31 @@ const isFunctionOfObjectMethod = isMatching({
|
|
|
677
780
|
* @returns `true` if node is a render function, `false` if not
|
|
678
781
|
*/
|
|
679
782
|
function isFunctionOfRenderMethod(node) {
|
|
680
|
-
|
|
681
|
-
|
|
783
|
+
return isRenderMethodLike(node.parent) && isClassComponent(node.parent.parent.parent);
|
|
784
|
+
}
|
|
785
|
+
/**
|
|
786
|
+
* Checks if a function node should be excluded based on detection hints
|
|
787
|
+
* @param node The function node to check
|
|
788
|
+
* @param hint Component detection hints as bit flags
|
|
789
|
+
* @returns `true` if the function should be excluded, `false` otherwise
|
|
790
|
+
*/
|
|
791
|
+
function shouldExcludeBasedOnHint(node, hint) {
|
|
792
|
+
if (hint & ComponentDetectionHint.SkipObjectMethod && isMatching(functionPatterns.objectMethod)(node)) return true;
|
|
793
|
+
if (hint & ComponentDetectionHint.SkipClassMethod && isMatching(functionPatterns.classMethod)(node)) return true;
|
|
794
|
+
if (hint & ComponentDetectionHint.SkipClassProperty && isMatching(functionPatterns.classProperty)(node)) return true;
|
|
795
|
+
if (hint & ComponentDetectionHint.SkipArrayMapArgument && AST.isArrayMapCall(node.parent)) return true;
|
|
796
|
+
return false;
|
|
682
797
|
}
|
|
683
|
-
|
|
798
|
+
/**
|
|
799
|
+
* Determines if a function node represents a valid React component definition
|
|
800
|
+
* @param context The rule context
|
|
801
|
+
* @param node The function node to check
|
|
802
|
+
* @param hint Component detection hints as bit flags
|
|
803
|
+
* @returns `true` if the node is a valid component definition, `false` otherwise
|
|
804
|
+
*/
|
|
805
|
+
function isComponentDefinition(context, node, hint) {
|
|
684
806
|
if (isChildrenOfCreateElement(context, node) || isFunctionOfRenderMethod(node)) return false;
|
|
685
|
-
if (
|
|
686
|
-
if (hint & ComponentDetectionHint.SkipClassMethod && isFunctionOfClassMethod(node.parent)) return false;
|
|
687
|
-
if (hint & ComponentDetectionHint.SkipClassProperty && isFunctionOfClassProperty(node.parent)) return false;
|
|
688
|
-
if (hint & ComponentDetectionHint.SkipArrayMapArgument && AST.isArrayMapCall(node.parent)) return false;
|
|
807
|
+
if (shouldExcludeBasedOnHint(node, hint)) return false;
|
|
689
808
|
const significantParent = AST.findParentNode(node, AST.isOneOf([
|
|
690
809
|
AST_NODE_TYPES.JSXExpressionContainer,
|
|
691
810
|
AST_NODE_TYPES.ArrowFunctionExpression,
|
|
@@ -823,7 +942,7 @@ function useComponentCollector(context, options = {}) {
|
|
|
823
942
|
const entry = getCurrentEntry();
|
|
824
943
|
if (entry == null) return;
|
|
825
944
|
const { body } = entry.node;
|
|
826
|
-
const isComponent = hasNoneOrLooseComponentName(context, entry.node) && isJsxLike(context.sourceCode, body, hint) &&
|
|
945
|
+
const isComponent = hasNoneOrLooseComponentName(context, entry.node) && isJsxLike(context.sourceCode, body, hint) && isComponentDefinition(context, entry.node, hint);
|
|
827
946
|
if (!isComponent) return;
|
|
828
947
|
const initPath = AST.getFunctionInitPath(entry.node);
|
|
829
948
|
const id = getFunctionComponentId(context, entry.node);
|
|
@@ -859,7 +978,7 @@ function useComponentCollector(context, options = {}) {
|
|
|
859
978
|
"ReturnStatement[type]"(node) {
|
|
860
979
|
const entry = getCurrentEntry();
|
|
861
980
|
if (entry == null) return;
|
|
862
|
-
const isComponent = hasNoneOrLooseComponentName(context, entry.node) && isJsxLike(context.sourceCode, node.argument, hint) &&
|
|
981
|
+
const isComponent = hasNoneOrLooseComponentName(context, entry.node) && isJsxLike(context.sourceCode, node.argument, hint) && isComponentDefinition(context, entry.node, hint);
|
|
863
982
|
if (!isComponent) return;
|
|
864
983
|
entry.isComponent = true;
|
|
865
984
|
const initPath = AST.getFunctionInitPath(entry.node);
|
|
@@ -925,57 +1044,34 @@ function useComponentCollectorLegacy() {
|
|
|
925
1044
|
|
|
926
1045
|
//#endregion
|
|
927
1046
|
//#region src/component/component-method.ts
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
function
|
|
935
|
-
|
|
936
|
-
}
|
|
937
|
-
function isComponentWillMount(node) {
|
|
938
|
-
return AST.isMethodOrProperty(node) && !node.static && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "componentWillMount";
|
|
939
|
-
}
|
|
940
|
-
function isComponentWillReceiveProps(node) {
|
|
941
|
-
return AST.isMethodOrProperty(node) && !node.static && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "componentWillReceiveProps";
|
|
942
|
-
}
|
|
943
|
-
function isComponentWillUnmount(node) {
|
|
944
|
-
return AST.isMethodOrProperty(node) && !node.static && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "componentWillUnmount";
|
|
945
|
-
}
|
|
946
|
-
function isComponentWillUpdate(node) {
|
|
947
|
-
return AST.isMethodOrProperty(node) && !node.static && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "componentWillUpdate";
|
|
948
|
-
}
|
|
949
|
-
function isGetChildContext(node) {
|
|
950
|
-
return AST.isMethodOrProperty(node) && !node.static && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "getChildContext";
|
|
951
|
-
}
|
|
952
|
-
function isGetDefaultProps(node) {
|
|
953
|
-
return AST.isMethodOrProperty(node) && node.static && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "getDefaultProps";
|
|
954
|
-
}
|
|
955
|
-
function isGetInitialState(node) {
|
|
956
|
-
return AST.isMethodOrProperty(node) && !node.static && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "getInitialState";
|
|
957
|
-
}
|
|
958
|
-
function isGetSnapshotBeforeUpdate(node) {
|
|
959
|
-
return AST.isMethodOrProperty(node) && !node.static && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "getSnapshotBeforeUpdate";
|
|
960
|
-
}
|
|
961
|
-
function isShouldComponentUpdate(node) {
|
|
962
|
-
return AST.isMethodOrProperty(node) && !node.static && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "shouldComponentUpdate";
|
|
963
|
-
}
|
|
964
|
-
function isUnsafeComponentWillMount(node) {
|
|
965
|
-
return AST.isMethodOrProperty(node) && !node.static && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "UNSAFE_componentWillMount";
|
|
966
|
-
}
|
|
967
|
-
function isUnsafeComponentWillReceiveProps(node) {
|
|
968
|
-
return AST.isMethodOrProperty(node) && !node.static && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "UNSAFE_componentWillReceiveProps";
|
|
969
|
-
}
|
|
970
|
-
function isUnsafeComponentWillUpdate(node) {
|
|
971
|
-
return AST.isMethodOrProperty(node) && !node.static && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "UNSAFE_componentWillUpdate";
|
|
972
|
-
}
|
|
973
|
-
function isGetDerivedStateFromProps(node) {
|
|
974
|
-
return AST.isMethodOrProperty(node) && node.static && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "getDerivedStateFromProps";
|
|
975
|
-
}
|
|
976
|
-
function isGetDerivedStateFromError(node) {
|
|
977
|
-
return AST.isMethodOrProperty(node) && node.static && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "getDerivedStateFromError";
|
|
1047
|
+
/**
|
|
1048
|
+
* Create a lifecycle method checker function
|
|
1049
|
+
* @param methodName The lifecycle method name
|
|
1050
|
+
* @param isStatic Whether the method is static
|
|
1051
|
+
*/
|
|
1052
|
+
function createLifecycleChecker(methodName, isStatic) {
|
|
1053
|
+
return function(node) {
|
|
1054
|
+
return AST.isMethodOrProperty(node) && node.static === isStatic && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === methodName;
|
|
1055
|
+
};
|
|
978
1056
|
}
|
|
1057
|
+
const isRender = createLifecycleChecker("render", false);
|
|
1058
|
+
const isComponentDidCatch = createLifecycleChecker("componentDidCatch", false);
|
|
1059
|
+
const isComponentDidMount = createLifecycleChecker("componentDidMount", false);
|
|
1060
|
+
const isComponentDidUpdate = createLifecycleChecker("componentDidUpdate", false);
|
|
1061
|
+
const isComponentWillMount = createLifecycleChecker("componentWillMount", false);
|
|
1062
|
+
const isComponentWillReceiveProps = createLifecycleChecker("componentWillReceiveProps", false);
|
|
1063
|
+
const isComponentWillUnmount = createLifecycleChecker("componentWillUnmount", false);
|
|
1064
|
+
const isComponentWillUpdate = createLifecycleChecker("componentWillUpdate", false);
|
|
1065
|
+
const isGetChildContext = createLifecycleChecker("getChildContext", false);
|
|
1066
|
+
const isGetInitialState = createLifecycleChecker("getInitialState", false);
|
|
1067
|
+
const isGetSnapshotBeforeUpdate = createLifecycleChecker("getSnapshotBeforeUpdate", false);
|
|
1068
|
+
const isShouldComponentUpdate = createLifecycleChecker("shouldComponentUpdate", false);
|
|
1069
|
+
const isUnsafeComponentWillMount = createLifecycleChecker("UNSAFE_componentWillMount", false);
|
|
1070
|
+
const isUnsafeComponentWillReceiveProps = createLifecycleChecker("UNSAFE_componentWillReceiveProps", false);
|
|
1071
|
+
const isUnsafeComponentWillUpdate = createLifecycleChecker("UNSAFE_componentWillUpdate", false);
|
|
1072
|
+
const isGetDefaultProps = createLifecycleChecker("getDefaultProps", true);
|
|
1073
|
+
const isGetDerivedStateFromProps = createLifecycleChecker("getDerivedStateFromProps", true);
|
|
1074
|
+
const isGetDerivedStateFromError = createLifecycleChecker("getDerivedStateFromError", true);
|
|
979
1075
|
|
|
980
1076
|
//#endregion
|
|
981
1077
|
//#region src/component/component-phase.ts
|
|
@@ -985,39 +1081,6 @@ const ComponentPhaseRelevance = birecord({
|
|
|
985
1081
|
});
|
|
986
1082
|
const isInversePhase = dual(2, (a, b) => ComponentPhaseRelevance.get(a) === b);
|
|
987
1083
|
|
|
988
|
-
//#endregion
|
|
989
|
-
//#region src/component/component-render.ts
|
|
990
|
-
/**
|
|
991
|
-
* Check whether given node is a render function of a class component
|
|
992
|
-
* @example
|
|
993
|
-
* ```tsx
|
|
994
|
-
* class Component extends React.Component {
|
|
995
|
-
* render() {
|
|
996
|
-
* return <div />;
|
|
997
|
-
* }
|
|
998
|
-
* }
|
|
999
|
-
* ```
|
|
1000
|
-
* @param node The AST node to check
|
|
1001
|
-
* @returns `true` if node is a render function, `false` if not
|
|
1002
|
-
*/
|
|
1003
|
-
function isRenderLike(node) {
|
|
1004
|
-
return AST.isMethodOrProperty(node) && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "render" && node.parent.parent.type === AST_NODE_TYPES.ClassDeclaration;
|
|
1005
|
-
}
|
|
1006
|
-
/**
|
|
1007
|
-
* Check whether given node is a function of a render function of a class component
|
|
1008
|
-
* @example
|
|
1009
|
-
* ```tsx
|
|
1010
|
-
* class Component extends React.Component {
|
|
1011
|
-
* render = () => <div />;
|
|
1012
|
-
* ```
|
|
1013
|
-
* @param node The AST node to check
|
|
1014
|
-
* @returns `true` if node is a render function, `false` if not
|
|
1015
|
-
*/
|
|
1016
|
-
function isFunctionOfRender(node) {
|
|
1017
|
-
if (!isRenderLike(node.parent)) return false;
|
|
1018
|
-
return isClassComponent(node.parent.parent.parent);
|
|
1019
|
-
}
|
|
1020
|
-
|
|
1021
1084
|
//#endregion
|
|
1022
1085
|
//#region src/component/component-render-prop.ts
|
|
1023
1086
|
/**
|
|
@@ -1178,4 +1241,4 @@ function getTypeVariants(types) {
|
|
|
1178
1241
|
}
|
|
1179
1242
|
|
|
1180
1243
|
//#endregion
|
|
1181
|
-
export { ComponentDetectionHint, ComponentFlag, ComponentPhaseRelevance, DEFAULT_COMPONENT_DETECTION_HINT, DEFAULT_JSX_DETECTION_HINT, JSXDetectionHint, REACT_BUILTIN_HOOK_NAMES, findParentAttribute, getAttribute, getAttributeName, getAttributeValue, getComponentFlagFromInitPath, getComponentNameFromId, getElementType, getFunctionComponentId, getInstanceId, getTypeVariants, hasAnyAttribute, hasAttribute, hasEveryAttribute, hasNoneOrLooseComponentName, isAnyType, isAssignmentToThisState, isBigIntType, isBooleanType, isCaptureOwnerStack, isCaptureOwnerStackCall, isChildrenCount, isChildrenCountCall, isChildrenForEach, isChildrenForEachCall, isChildrenMap, isChildrenMapCall, isChildrenOfCreateElement, isChildrenOnly, isChildrenOnlyCall, isChildrenToArray, isChildrenToArrayCall, isClassComponent, isCloneElement, isCloneElementCall, isComponentDidCatch, isComponentDidMount, isComponentDidUpdate, isComponentName, isComponentNameLoose, isComponentWillMount, isComponentWillReceiveProps, isComponentWillUnmount, isComponentWillUpdate, isComponentWrapperCall, isComponentWrapperCallLoose, isCreateContext, isCreateContextCall, isCreateElement, isCreateElementCall, isCreateRef, isCreateRefCall, isDeclaredInRenderPropLoose, isDirectValueOfRenderPropertyLoose, isEnumType, isFalseLiteralType, isFalsyBigIntType, isFalsyNumberType, isFalsyStringType, isForwardRef, isForwardRefCall, isFragmentElement,
|
|
1244
|
+
export { ComponentDetectionHint, ComponentFlag, ComponentPhaseRelevance, DEFAULT_COMPONENT_DETECTION_HINT, DEFAULT_JSX_DETECTION_HINT, JSXDetectionHint, REACT_BUILTIN_HOOK_NAMES, findParentAttribute, getAttribute, getAttributeName, getAttributeValue, getComponentFlagFromInitPath, getComponentNameFromId, getElementType, getFunctionComponentId, getInstanceId, getTypeVariants, hasAnyAttribute, hasAttribute, hasEveryAttribute, hasNoneOrLooseComponentName, isAnyType, isAssignmentToThisState, isBigIntType, isBooleanType, isCaptureOwnerStack, isCaptureOwnerStackCall, isChildrenCount, isChildrenCountCall, isChildrenForEach, isChildrenForEachCall, isChildrenMap, isChildrenMapCall, isChildrenOfCreateElement, isChildrenOnly, isChildrenOnlyCall, isChildrenToArray, isChildrenToArrayCall, isClassComponent, isCloneElement, isCloneElementCall, isComponentDefinition, isComponentDidCatch, isComponentDidMount, isComponentDidUpdate, isComponentName, isComponentNameLoose, isComponentWillMount, isComponentWillReceiveProps, isComponentWillUnmount, isComponentWillUpdate, isComponentWrapperCall, isComponentWrapperCallLoose, isCreateContext, isCreateContextCall, isCreateElement, isCreateElementCall, isCreateRef, isCreateRefCall, isDeclaredInRenderPropLoose, isDirectValueOfRenderPropertyLoose, isEnumType, isFalseLiteralType, isFalsyBigIntType, isFalsyNumberType, isFalsyStringType, isForwardRef, isForwardRefCall, isFragmentElement, isFunctionOfRenderMethod, isGetChildContext, isGetDefaultProps, isGetDerivedStateFromError, isGetDerivedStateFromProps, isGetInitialState, isGetSnapshotBeforeUpdate, isHostElement, isInitializedFromReact, isInstanceIdEqual, isInversePhase, isJsxLike, isJsxText, isLazy, isLazyCall, isMemo, isMemoCall, isNeverType, isNullishType, isNumberType, isObjectType, isPureComponent, isReactAPI, isReactAPICall, isReactHook, isReactHookCall, isReactHookCallWithName, isReactHookCallWithNameAlias, isReactHookCallWithNameLoose, isReactHookId, isReactHookName, isRender, isRenderFunctionLoose, isRenderMethodLike, isRenderPropLoose, isShouldComponentUpdate, isStringType, isThisSetState, isTrueLiteralType, isTruthyBigIntType, isTruthyNumberType, isTruthyStringType, isUnknownType, isUnsafeComponentWillMount, isUnsafeComponentWillReceiveProps, isUnsafeComponentWillUpdate, isUseActionStateCall, isUseCall, isUseCallbackCall, isUseContextCall, isUseDebugValueCall, isUseDeferredValueCall, isUseEffectCall, isUseEffectCallLoose, isUseFormStatusCall, isUseIdCall, isUseImperativeHandleCall, isUseInsertionEffectCall, isUseLayoutEffectCall, isUseMemoCall, isUseOptimisticCall, isUseReducerCall, isUseRefCall, isUseStateCall, isUseSyncExternalStoreCall, isUseTransitionCall, stringifyJsx, useComponentCollector, useComponentCollectorLegacy, useHookCollector };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eslint-react/core",
|
|
3
|
-
"version": "2.0.0-next.
|
|
3
|
+
"version": "2.0.0-next.152",
|
|
4
4
|
"description": "ESLint React's ESLint utility module for static analysis of React core APIs and patterns.",
|
|
5
5
|
"homepage": "https://github.com/Rel1cx/eslint-react",
|
|
6
6
|
"bugs": {
|
|
@@ -34,11 +34,11 @@
|
|
|
34
34
|
"birecord": "^0.1.1",
|
|
35
35
|
"ts-api-utils": "^2.1.0",
|
|
36
36
|
"ts-pattern": "^5.8.0",
|
|
37
|
-
"@eslint-react/ast": "2.0.0-next.
|
|
38
|
-
"@eslint-react/eff": "2.0.0-next.
|
|
39
|
-
"@eslint-react/
|
|
40
|
-
"@eslint-react/
|
|
41
|
-
"@eslint-react/var": "2.0.0-next.
|
|
37
|
+
"@eslint-react/ast": "2.0.0-next.152",
|
|
38
|
+
"@eslint-react/eff": "2.0.0-next.152",
|
|
39
|
+
"@eslint-react/shared": "2.0.0-next.152",
|
|
40
|
+
"@eslint-react/kit": "2.0.0-next.152",
|
|
41
|
+
"@eslint-react/var": "2.0.0-next.152"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
44
|
"tsdown": "^0.14.2",
|