@eslint-react/core 2.0.4 → 2.0.5-beta.0
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 +25 -47
- package/dist/index.js +40 -67
- package/package.json +7 -7
package/dist/index.d.ts
CHANGED
|
@@ -431,7 +431,17 @@ declare function isFunctionOfUseEffectSetup(node: TSESTree.Node | unit): boolean
|
|
|
431
431
|
declare function isFunctionOfUseEffectCleanup(node: TSESTree.Node | unit): boolean;
|
|
432
432
|
//#endregion
|
|
433
433
|
//#region src/jsx/jsx-attribute.d.ts
|
|
434
|
-
declare function
|
|
434
|
+
declare function getJsxAttribute(context: RuleContext, attributes: AST.TSESTreeJSXAttributeLike[], initialScope?: Scope): (name: string) => AST.TSESTreeJSXAttributeLike | undefined;
|
|
435
|
+
/**
|
|
436
|
+
* Checks if a JSX element has a specific attribute
|
|
437
|
+
*
|
|
438
|
+
* @param context - ESLint rule context
|
|
439
|
+
* @param name - Name of the attribute to check for
|
|
440
|
+
* @param attributes - List of JSX attributes from opening element
|
|
441
|
+
* @param initialScope - Optional scope for resolving variables in spread attributes
|
|
442
|
+
* @returns boolean indicating whether the attribute exists
|
|
443
|
+
*/
|
|
444
|
+
declare function hasJsxAttribute(context: RuleContext, name: string, attributes: TSESTree.JSXOpeningElement["attributes"], initialScope?: Scope): boolean;
|
|
435
445
|
//#endregion
|
|
436
446
|
//#region src/jsx/jsx-attribute-name.d.ts
|
|
437
447
|
/**
|
|
@@ -440,13 +450,13 @@ declare function getAttribute(context: RuleContext, attributes: AST.TSESTreeJSXA
|
|
|
440
450
|
* @param node The JSX attribute node
|
|
441
451
|
* @returns The name of the attribute
|
|
442
452
|
*/
|
|
443
|
-
declare function
|
|
453
|
+
declare function getJsxAttributeName(context: RuleContext, node: TSESTree$1.JSXAttribute): string;
|
|
444
454
|
//#endregion
|
|
445
455
|
//#region src/jsx/jsx-attribute-value.d.ts
|
|
446
456
|
/**
|
|
447
457
|
* Represents possible JSX attribute value types that can be resolved
|
|
448
458
|
*/
|
|
449
|
-
type
|
|
459
|
+
type JsxAttributeValue = {
|
|
450
460
|
kind: "boolean";
|
|
451
461
|
toStatic(): true;
|
|
452
462
|
} | {
|
|
@@ -470,7 +480,7 @@ type AttributeValue = {
|
|
|
470
480
|
node: TSESTree.JSXSpreadChild["expression"];
|
|
471
481
|
toStatic(): unknown;
|
|
472
482
|
};
|
|
473
|
-
declare function
|
|
483
|
+
declare function resolveJsxAttributeValue(context: RuleContext, attribute: AST.TSESTreeJSXAttributeLike): {
|
|
474
484
|
readonly kind: "boolean";
|
|
475
485
|
readonly toStatic: () => true;
|
|
476
486
|
readonly node?: never;
|
|
@@ -480,7 +490,7 @@ declare function resolveAttributeValue(context: RuleContext, attribute: AST.TSES
|
|
|
480
490
|
readonly toStatic: () => string | number | bigint | boolean | RegExp | null;
|
|
481
491
|
} | {
|
|
482
492
|
readonly kind: "expression";
|
|
483
|
-
readonly node: TSESTree.
|
|
493
|
+
readonly node: TSESTree.JSXEmptyExpression | TSESTree.Expression;
|
|
484
494
|
readonly toStatic: () => unknown;
|
|
485
495
|
} | {
|
|
486
496
|
readonly kind: "element";
|
|
@@ -488,7 +498,7 @@ declare function resolveAttributeValue(context: RuleContext, attribute: AST.TSES
|
|
|
488
498
|
readonly toStatic: () => undefined;
|
|
489
499
|
} | {
|
|
490
500
|
readonly kind: "spreadChild";
|
|
491
|
-
readonly node: TSESTree.
|
|
501
|
+
readonly node: TSESTree.JSXEmptyExpression | TSESTree.Expression;
|
|
492
502
|
readonly toStatic: () => undefined;
|
|
493
503
|
} | {
|
|
494
504
|
readonly kind: "spreadProps";
|
|
@@ -534,13 +544,13 @@ declare function getJsxConfigFromAnnotation(context: RuleContext): JsxConfig;
|
|
|
534
544
|
* BitFlags for configuring JSX detection behavior
|
|
535
545
|
* Uses BigInt for bit operations to support many flags
|
|
536
546
|
*/
|
|
537
|
-
type
|
|
547
|
+
type JsxDetectionHint = bigint;
|
|
538
548
|
/**
|
|
539
549
|
* Flags to control JSX detection behavior:
|
|
540
550
|
* - Skip* flags: Ignore specific node types when detecting JSX
|
|
541
551
|
* - Strict* flags: Enforce stricter rules for container types
|
|
542
552
|
*/
|
|
543
|
-
declare const
|
|
553
|
+
declare const JsxDetectionHint: {
|
|
544
554
|
readonly None: 0n;
|
|
545
555
|
readonly SkipUndefined: bigint;
|
|
546
556
|
readonly SkipNullLiteral: bigint;
|
|
@@ -577,7 +587,7 @@ declare function isJsxText(node: TSESTree$1.Node | null | unit): node is TSESTre
|
|
|
577
587
|
*/
|
|
578
588
|
declare function isJsxLike(code: {
|
|
579
589
|
getScope: (node: TSESTree$1.Node) => Scope;
|
|
580
|
-
}, node: TSESTree$1.Node | unit | null, hint?:
|
|
590
|
+
}, node: TSESTree$1.Node | unit | null, hint?: JsxDetectionHint): boolean;
|
|
581
591
|
//#endregion
|
|
582
592
|
//#region src/jsx/jsx-element-is.d.ts
|
|
583
593
|
/**
|
|
@@ -588,7 +598,7 @@ declare function isJsxLike(code: {
|
|
|
588
598
|
* @param node - AST node to check
|
|
589
599
|
* @returns boolean indicating if the element is a host element
|
|
590
600
|
*/
|
|
591
|
-
declare function
|
|
601
|
+
declare function isJsxHostElement(context: RuleContext, node: TSESTree.Node): boolean;
|
|
592
602
|
/**
|
|
593
603
|
* Determines if a JSX element is a React Fragment
|
|
594
604
|
* Fragments can be imported from React and used like <Fragment> or <React.Fragment>
|
|
@@ -597,7 +607,7 @@ declare function isHostElement(context: RuleContext, node: TSESTree.Node): boole
|
|
|
597
607
|
* @param node - AST node to check
|
|
598
608
|
* @returns boolean indicating if the element is a Fragment with type narrowing
|
|
599
609
|
*/
|
|
600
|
-
declare function
|
|
610
|
+
declare function isJsxFragmentElement(context: RuleContext, node: TSESTree.Node): node is TSESTree.JSXElement;
|
|
601
611
|
//#endregion
|
|
602
612
|
//#region src/jsx/jsx-element-type.d.ts
|
|
603
613
|
/**
|
|
@@ -609,39 +619,7 @@ declare function isFragmentElement(context: RuleContext, node: TSESTree.Node): n
|
|
|
609
619
|
* @param node - JSX element or fragment node
|
|
610
620
|
* @returns String representation of the element type
|
|
611
621
|
*/
|
|
612
|
-
declare function
|
|
613
|
-
//#endregion
|
|
614
|
-
//#region src/jsx/jsx-has.d.ts
|
|
615
|
-
/**
|
|
616
|
-
* Checks if a JSX element has a specific attribute
|
|
617
|
-
*
|
|
618
|
-
* @param context - ESLint rule context
|
|
619
|
-
* @param name - Name of the attribute to check for
|
|
620
|
-
* @param attributes - List of JSX attributes from opening element
|
|
621
|
-
* @param initialScope - Optional scope for resolving variables in spread attributes
|
|
622
|
-
* @returns boolean indicating whether the attribute exists
|
|
623
|
-
*/
|
|
624
|
-
declare function hasAttribute(context: RuleContext, name: string, attributes: TSESTree.JSXOpeningElement["attributes"], initialScope?: Scope): boolean;
|
|
625
|
-
/**
|
|
626
|
-
* Checks if a JSX element has at least one of the specified attributes
|
|
627
|
-
*
|
|
628
|
-
* @param context - ESLint rule context
|
|
629
|
-
* @param names - Array of attribute names to check for
|
|
630
|
-
* @param attributes - List of JSX attributes from opening element
|
|
631
|
-
* @param initialScope - Optional scope for resolving variables in spread attributes
|
|
632
|
-
* @returns boolean indicating whether any of the attributes exist
|
|
633
|
-
*/
|
|
634
|
-
declare function hasAnyAttribute(context: RuleContext, names: string[], attributes: TSESTree.JSXOpeningElement["attributes"], initialScope?: Scope): boolean;
|
|
635
|
-
/**
|
|
636
|
-
* Checks if a JSX element has all of the specified attributes
|
|
637
|
-
*
|
|
638
|
-
* @param context - ESLint rule context
|
|
639
|
-
* @param names - Array of attribute names to check for
|
|
640
|
-
* @param attributes - List of JSX attributes from opening element
|
|
641
|
-
* @param initialScope - Optional scope for resolving variables in spread attributes
|
|
642
|
-
* @returns boolean indicating whether all of the attributes exist
|
|
643
|
-
*/
|
|
644
|
-
declare function hasEveryAttribute(context: RuleContext, names: string[], attributes: TSESTree.JSXOpeningElement["attributes"], initialScope?: Scope): boolean;
|
|
622
|
+
declare function getJsxElementType(context: RuleContext, node: TSESTree.JSXElement | TSESTree.JSXFragment): string;
|
|
645
623
|
//#endregion
|
|
646
624
|
//#region src/jsx/jsx-hierarchy.d.ts
|
|
647
625
|
/**
|
|
@@ -652,7 +630,7 @@ declare function hasEveryAttribute(context: RuleContext, names: string[], attrib
|
|
|
652
630
|
* Defaults to always returning true (matches any attribute)
|
|
653
631
|
* @returns The first matching JSX attribute node found when traversing upwards, or undefined
|
|
654
632
|
*/
|
|
655
|
-
declare function
|
|
633
|
+
declare function findParentJsxAttribute(node: TSESTree.Node, test?: (node: TSESTree.JSXAttribute) => boolean): TSESTree.JSXAttribute | unit;
|
|
656
634
|
//#endregion
|
|
657
635
|
//#region src/jsx/jsx-stringify.d.ts
|
|
658
636
|
/**
|
|
@@ -671,7 +649,7 @@ declare function stringifyJsx(node: TSESTree$1.JSXIdentifier | TSESTree$1.JSXNam
|
|
|
671
649
|
* @param prev The previous AST node in the traversal (used for context)
|
|
672
650
|
* @internal
|
|
673
651
|
*/
|
|
674
|
-
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.
|
|
652
|
+
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;
|
|
675
653
|
//#endregion
|
|
676
654
|
//#region src/utils/is-from-react.d.ts
|
|
677
655
|
/**
|
|
@@ -730,4 +708,4 @@ declare const isForwardRefCall: isReactAPICall.ReturnType;
|
|
|
730
708
|
declare const isMemoCall: isReactAPICall.ReturnType;
|
|
731
709
|
declare const isLazyCall: isReactAPICall.ReturnType;
|
|
732
710
|
//#endregion
|
|
733
|
-
export {
|
|
711
|
+
export { ClassComponent, Component, ComponentDetectionHint, ComponentEffectPhaseKind, ComponentFlag, ComponentKind, ComponentLifecyclePhaseKind, ComponentPhaseKind, ComponentPhaseRelevance, ComponentStateKind, DEFAULT_COMPONENT_DETECTION_HINT, DEFAULT_JSX_DETECTION_HINT, EffectKind, FunctionComponent, Hook, JsxAttributeValue, JsxConfig, JsxDetectionHint, JsxEmit, REACT_BUILTIN_HOOK_NAMES, SemanticEntry, SemanticNode, findParentJsxAttribute, getComponentFlagFromInitPath, getComponentNameFromId, getFunctionComponentId, getInstanceId, getJsxAttribute, getJsxAttributeName, getJsxConfigFromAnnotation, getJsxConfigFromContext, getJsxElementType, getPhaseKindOfFunction, hasJsxAttribute, hasNoneOrLooseComponentName, isAssignmentToThisState, 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, isForwardRef, isForwardRefCall, isFunctionOfComponentDidMount, isFunctionOfComponentWillUnmount, isFunctionOfRenderMethod, isFunctionOfUseEffectCleanup, isFunctionOfUseEffectSetup, isGetChildContext, isGetDefaultProps, isGetDerivedStateFromError, isGetDerivedStateFromProps, isGetInitialState, isGetSnapshotBeforeUpdate, isInitializedFromReact, isInstanceIdEqual, isInversePhase, isJsxFragmentElement, isJsxHostElement, isJsxLike, isJsxText, isLazy, isLazyCall, isMemo, isMemoCall, isPureComponent, isReactAPI, isReactAPICall, isReactHook, isReactHookCall, isReactHookCallWithName, isReactHookCallWithNameAlias, isReactHookId, isReactHookName, isRender, isRenderFunctionLoose, isRenderMethodLike, isRenderPropLoose, isShouldComponentUpdate, isThisSetState, isUnsafeComponentWillMount, isUnsafeComponentWillReceiveProps, isUnsafeComponentWillUpdate, isUseActionStateCall, isUseCall, isUseCallbackCall, isUseContextCall, isUseDebugValueCall, isUseDeferredValueCall, isUseEffectCall, isUseEffectLikeCall, isUseFormStatusCall, isUseIdCall, isUseImperativeHandleCall, isUseInsertionEffectCall, isUseLayoutEffectCall, isUseMemoCall, isUseOptimisticCall, isUseReducerCall, isUseRefCall, isUseStateCall, isUseSyncExternalStoreCall, isUseTransitionCall, resolveJsxAttributeValue, stringifyJsx, useComponentCollector, useComponentCollectorLegacy, useHookCollector };
|
package/dist/index.js
CHANGED
|
@@ -301,16 +301,16 @@ function stringifyJsx(node) {
|
|
|
301
301
|
* @param node The JSX attribute node
|
|
302
302
|
* @returns The name of the attribute
|
|
303
303
|
*/
|
|
304
|
-
function
|
|
304
|
+
function getJsxAttributeName(context, node) {
|
|
305
305
|
return stringifyJsx(node.name);
|
|
306
306
|
}
|
|
307
307
|
|
|
308
308
|
//#endregion
|
|
309
309
|
//#region src/jsx/jsx-attribute.ts
|
|
310
|
-
function
|
|
310
|
+
function getJsxAttribute(context, attributes, initialScope) {
|
|
311
311
|
return (name) => {
|
|
312
312
|
return attributes.findLast((attr) => {
|
|
313
|
-
if (attr.type === AST_NODE_TYPES.JSXAttribute) return
|
|
313
|
+
if (attr.type === AST_NODE_TYPES.JSXAttribute) return getJsxAttributeName(context, attr) === name;
|
|
314
314
|
if (initialScope == null) return false;
|
|
315
315
|
switch (attr.argument.type) {
|
|
316
316
|
case AST_NODE_TYPES.Identifier: {
|
|
@@ -325,10 +325,22 @@ function getAttribute(context, attributes, initialScope) {
|
|
|
325
325
|
});
|
|
326
326
|
};
|
|
327
327
|
}
|
|
328
|
+
/**
|
|
329
|
+
* Checks if a JSX element has a specific attribute
|
|
330
|
+
*
|
|
331
|
+
* @param context - ESLint rule context
|
|
332
|
+
* @param name - Name of the attribute to check for
|
|
333
|
+
* @param attributes - List of JSX attributes from opening element
|
|
334
|
+
* @param initialScope - Optional scope for resolving variables in spread attributes
|
|
335
|
+
* @returns boolean indicating whether the attribute exists
|
|
336
|
+
*/
|
|
337
|
+
function hasJsxAttribute(context, name, attributes, initialScope) {
|
|
338
|
+
return getJsxAttribute(context, attributes, initialScope)(name) != null;
|
|
339
|
+
}
|
|
328
340
|
|
|
329
341
|
//#endregion
|
|
330
342
|
//#region src/jsx/jsx-attribute-value.ts
|
|
331
|
-
function
|
|
343
|
+
function resolveJsxAttributeValue(context, attribute) {
|
|
332
344
|
const initialScope = context.sourceCode.getScope(attribute);
|
|
333
345
|
function handleJsxAttribute(node) {
|
|
334
346
|
if (node.value == null) return {
|
|
@@ -447,7 +459,7 @@ function getJsxConfigFromAnnotation(context) {
|
|
|
447
459
|
* - Skip* flags: Ignore specific node types when detecting JSX
|
|
448
460
|
* - Strict* flags: Enforce stricter rules for container types
|
|
449
461
|
*/
|
|
450
|
-
const
|
|
462
|
+
const JsxDetectionHint = {
|
|
451
463
|
None: 0n,
|
|
452
464
|
SkipUndefined: 1n << 0n,
|
|
453
465
|
SkipNullLiteral: 1n << 1n,
|
|
@@ -465,7 +477,7 @@ const JSXDetectionHint = {
|
|
|
465
477
|
* Default JSX detection configuration
|
|
466
478
|
* Skips undefined and boolean literals (common in React)
|
|
467
479
|
*/
|
|
468
|
-
const DEFAULT_JSX_DETECTION_HINT = 0n |
|
|
480
|
+
const DEFAULT_JSX_DETECTION_HINT = 0n | JsxDetectionHint.SkipUndefined | JsxDetectionHint.SkipBooleanLiteral;
|
|
469
481
|
/**
|
|
470
482
|
* Checks if a node is a `JSXText` or a `Literal` node
|
|
471
483
|
* @param node The AST node to check
|
|
@@ -491,26 +503,26 @@ function isJsxLike(code, node, hint = DEFAULT_JSX_DETECTION_HINT) {
|
|
|
491
503
|
switch (node.type) {
|
|
492
504
|
case AST_NODE_TYPES.Literal:
|
|
493
505
|
switch (typeof node.value) {
|
|
494
|
-
case "boolean": return !(hint &
|
|
495
|
-
case "string": return !(hint &
|
|
496
|
-
case "number": return !(hint &
|
|
497
|
-
case "bigint": return !(hint &
|
|
506
|
+
case "boolean": return !(hint & JsxDetectionHint.SkipBooleanLiteral);
|
|
507
|
+
case "string": return !(hint & JsxDetectionHint.SkipStringLiteral);
|
|
508
|
+
case "number": return !(hint & JsxDetectionHint.SkipNumberLiteral);
|
|
509
|
+
case "bigint": return !(hint & JsxDetectionHint.SkipBigIntLiteral);
|
|
498
510
|
}
|
|
499
|
-
if (node.value == null) return !(hint &
|
|
511
|
+
if (node.value == null) return !(hint & JsxDetectionHint.SkipNullLiteral);
|
|
500
512
|
return false;
|
|
501
|
-
case AST_NODE_TYPES.TemplateLiteral: return !(hint &
|
|
513
|
+
case AST_NODE_TYPES.TemplateLiteral: return !(hint & JsxDetectionHint.SkipStringLiteral);
|
|
502
514
|
case AST_NODE_TYPES.ArrayExpression:
|
|
503
|
-
if (node.elements.length === 0) return !(hint &
|
|
504
|
-
if (hint &
|
|
515
|
+
if (node.elements.length === 0) return !(hint & JsxDetectionHint.SkipEmptyArray);
|
|
516
|
+
if (hint & JsxDetectionHint.StrictArray) return node.elements.every((n) => isJsxLike(code, n, hint));
|
|
505
517
|
return node.elements.some((n) => isJsxLike(code, n, hint));
|
|
506
518
|
case AST_NODE_TYPES.LogicalExpression:
|
|
507
|
-
if (hint &
|
|
519
|
+
if (hint & JsxDetectionHint.StrictLogical) return isJsxLike(code, node.left, hint) && isJsxLike(code, node.right, hint);
|
|
508
520
|
return isJsxLike(code, node.left, hint) || isJsxLike(code, node.right, hint);
|
|
509
521
|
case AST_NODE_TYPES.ConditionalExpression: {
|
|
510
522
|
function leftHasJSX(node$1) {
|
|
511
523
|
if (Array.isArray(node$1.consequent)) {
|
|
512
|
-
if (node$1.consequent.length === 0) return !(hint &
|
|
513
|
-
if (hint &
|
|
524
|
+
if (node$1.consequent.length === 0) return !(hint & JsxDetectionHint.SkipEmptyArray);
|
|
525
|
+
if (hint & JsxDetectionHint.StrictArray) return node$1.consequent.every((n) => isJsxLike(code, n, hint));
|
|
514
526
|
return node$1.consequent.some((n) => isJsxLike(code, n, hint));
|
|
515
527
|
}
|
|
516
528
|
return isJsxLike(code, node$1.consequent, hint);
|
|
@@ -518,7 +530,7 @@ function isJsxLike(code, node, hint = DEFAULT_JSX_DETECTION_HINT) {
|
|
|
518
530
|
function rightHasJSX(node$1) {
|
|
519
531
|
return isJsxLike(code, node$1.alternate, hint);
|
|
520
532
|
}
|
|
521
|
-
if (hint &
|
|
533
|
+
if (hint & JsxDetectionHint.StrictConditional) return leftHasJSX(node) && rightHasJSX(node);
|
|
522
534
|
return leftHasJSX(node) || rightHasJSX(node);
|
|
523
535
|
}
|
|
524
536
|
case AST_NODE_TYPES.SequenceExpression: {
|
|
@@ -526,7 +538,7 @@ function isJsxLike(code, node, hint = DEFAULT_JSX_DETECTION_HINT) {
|
|
|
526
538
|
return isJsxLike(code, exp, hint);
|
|
527
539
|
}
|
|
528
540
|
case AST_NODE_TYPES.CallExpression:
|
|
529
|
-
if (hint &
|
|
541
|
+
if (hint & JsxDetectionHint.SkipCreateElement) return false;
|
|
530
542
|
switch (node.callee.type) {
|
|
531
543
|
case AST_NODE_TYPES.Identifier: return node.callee.name === "createElement";
|
|
532
544
|
case AST_NODE_TYPES.MemberExpression: return node.callee.property.type === AST_NODE_TYPES.Identifier && node.callee.property.name === "createElement";
|
|
@@ -534,7 +546,7 @@ function isJsxLike(code, node, hint = DEFAULT_JSX_DETECTION_HINT) {
|
|
|
534
546
|
return false;
|
|
535
547
|
case AST_NODE_TYPES.Identifier: {
|
|
536
548
|
const { name } = node;
|
|
537
|
-
if (name === "undefined") return !(hint &
|
|
549
|
+
if (name === "undefined") return !(hint & JsxDetectionHint.SkipUndefined);
|
|
538
550
|
if (AST.isJSXTagNameExpression(node)) return true;
|
|
539
551
|
const variable = findVariable(name, code.getScope(node));
|
|
540
552
|
const variableNode = variable && getVariableDefinitionNode(variable, 0);
|
|
@@ -555,7 +567,7 @@ function isJsxLike(code, node, hint = DEFAULT_JSX_DETECTION_HINT) {
|
|
|
555
567
|
* @param node - JSX element or fragment node
|
|
556
568
|
* @returns String representation of the element type
|
|
557
569
|
*/
|
|
558
|
-
function
|
|
570
|
+
function getJsxElementType(context, node) {
|
|
559
571
|
if (node.type === AST_NODE_TYPES.JSXFragment) return "";
|
|
560
572
|
return stringifyJsx(node.openingElement.name);
|
|
561
573
|
}
|
|
@@ -570,7 +582,7 @@ function getElementType(context, node) {
|
|
|
570
582
|
* @param node - AST node to check
|
|
571
583
|
* @returns boolean indicating if the element is a host element
|
|
572
584
|
*/
|
|
573
|
-
function
|
|
585
|
+
function isJsxHostElement(context, node) {
|
|
574
586
|
return node.type === AST_NODE_TYPES.JSXElement && node.openingElement.name.type === AST_NODE_TYPES.JSXIdentifier && /^[a-z]/u.test(node.openingElement.name.name);
|
|
575
587
|
}
|
|
576
588
|
/**
|
|
@@ -581,48 +593,9 @@ function isHostElement(context, node) {
|
|
|
581
593
|
* @param node - AST node to check
|
|
582
594
|
* @returns boolean indicating if the element is a Fragment with type narrowing
|
|
583
595
|
*/
|
|
584
|
-
function
|
|
596
|
+
function isJsxFragmentElement(context, node) {
|
|
585
597
|
if (node.type !== AST_NODE_TYPES.JSXElement) return false;
|
|
586
|
-
return
|
|
587
|
-
}
|
|
588
|
-
|
|
589
|
-
//#endregion
|
|
590
|
-
//#region src/jsx/jsx-has.ts
|
|
591
|
-
/**
|
|
592
|
-
* Checks if a JSX element has a specific attribute
|
|
593
|
-
*
|
|
594
|
-
* @param context - ESLint rule context
|
|
595
|
-
* @param name - Name of the attribute to check for
|
|
596
|
-
* @param attributes - List of JSX attributes from opening element
|
|
597
|
-
* @param initialScope - Optional scope for resolving variables in spread attributes
|
|
598
|
-
* @returns boolean indicating whether the attribute exists
|
|
599
|
-
*/
|
|
600
|
-
function hasAttribute(context, name, attributes, initialScope) {
|
|
601
|
-
return getAttribute(context, attributes, initialScope)(name) != null;
|
|
602
|
-
}
|
|
603
|
-
/**
|
|
604
|
-
* Checks if a JSX element has at least one of the specified attributes
|
|
605
|
-
*
|
|
606
|
-
* @param context - ESLint rule context
|
|
607
|
-
* @param names - Array of attribute names to check for
|
|
608
|
-
* @param attributes - List of JSX attributes from opening element
|
|
609
|
-
* @param initialScope - Optional scope for resolving variables in spread attributes
|
|
610
|
-
* @returns boolean indicating whether any of the attributes exist
|
|
611
|
-
*/
|
|
612
|
-
function hasAnyAttribute(context, names, attributes, initialScope) {
|
|
613
|
-
return names.some((n) => hasAttribute(context, n, attributes, initialScope));
|
|
614
|
-
}
|
|
615
|
-
/**
|
|
616
|
-
* Checks if a JSX element has all of the specified attributes
|
|
617
|
-
*
|
|
618
|
-
* @param context - ESLint rule context
|
|
619
|
-
* @param names - Array of attribute names to check for
|
|
620
|
-
* @param attributes - List of JSX attributes from opening element
|
|
621
|
-
* @param initialScope - Optional scope for resolving variables in spread attributes
|
|
622
|
-
* @returns boolean indicating whether all of the attributes exist
|
|
623
|
-
*/
|
|
624
|
-
function hasEveryAttribute(context, names, attributes, initialScope) {
|
|
625
|
-
return names.every((n) => hasAttribute(context, n, attributes, initialScope));
|
|
598
|
+
return getJsxElementType(context, node).split(".").at(-1) === "Fragment";
|
|
626
599
|
}
|
|
627
600
|
|
|
628
601
|
//#endregion
|
|
@@ -635,7 +608,7 @@ function hasEveryAttribute(context, names, attributes, initialScope) {
|
|
|
635
608
|
* Defaults to always returning true (matches any attribute)
|
|
636
609
|
* @returns The first matching JSX attribute node found when traversing upwards, or undefined
|
|
637
610
|
*/
|
|
638
|
-
function
|
|
611
|
+
function findParentJsxAttribute(node, test = constTrue) {
|
|
639
612
|
const guard = (node$1) => {
|
|
640
613
|
return node$1.type === AST_NODE_TYPES.JSXAttribute && test(node$1);
|
|
641
614
|
};
|
|
@@ -648,7 +621,7 @@ function findParentAttribute(node, test = constTrue) {
|
|
|
648
621
|
* Hints for component collector
|
|
649
622
|
*/
|
|
650
623
|
const ComponentDetectionHint = {
|
|
651
|
-
...
|
|
624
|
+
...JsxDetectionHint,
|
|
652
625
|
SkipMemo: 1n << 64n,
|
|
653
626
|
SkipForwardRef: 1n << 65n,
|
|
654
627
|
SkipArrayMapArgument: 1n << 66n,
|
|
@@ -1146,7 +1119,7 @@ function getPhaseKindOfFunction(node) {
|
|
|
1146
1119
|
function isRenderFunctionLoose(context, node) {
|
|
1147
1120
|
const { body, parent } = node;
|
|
1148
1121
|
if (AST.getFunctionId(node)?.name.startsWith("render")) return parent.type === AST_NODE_TYPES.JSXExpressionContainer && parent.parent.type === AST_NODE_TYPES.JSXAttribute && parent.parent.name.type === AST_NODE_TYPES.JSXIdentifier && parent.parent.name.name.startsWith("render");
|
|
1149
|
-
return isJsxLike(context.sourceCode, body,
|
|
1122
|
+
return isJsxLike(context.sourceCode, body, JsxDetectionHint.SkipNullLiteral | JsxDetectionHint.SkipUndefined | JsxDetectionHint.StrictLogical | JsxDetectionHint.StrictConditional);
|
|
1150
1123
|
}
|
|
1151
1124
|
/**
|
|
1152
1125
|
* Unsafe check whether given JSXAttribute is a render prop
|
|
@@ -1210,4 +1183,4 @@ function isAssignmentToThisState(node) {
|
|
|
1210
1183
|
}
|
|
1211
1184
|
|
|
1212
1185
|
//#endregion
|
|
1213
|
-
export { ComponentDetectionHint, ComponentFlag, ComponentPhaseRelevance, DEFAULT_COMPONENT_DETECTION_HINT, DEFAULT_JSX_DETECTION_HINT,
|
|
1186
|
+
export { ComponentDetectionHint, ComponentFlag, ComponentPhaseRelevance, DEFAULT_COMPONENT_DETECTION_HINT, DEFAULT_JSX_DETECTION_HINT, JsxDetectionHint, JsxEmit, REACT_BUILTIN_HOOK_NAMES, findParentJsxAttribute, getComponentFlagFromInitPath, getComponentNameFromId, getFunctionComponentId, getInstanceId, getJsxAttribute, getJsxAttributeName, getJsxConfigFromAnnotation, getJsxConfigFromContext, getJsxElementType, getPhaseKindOfFunction, hasJsxAttribute, hasNoneOrLooseComponentName, isAssignmentToThisState, 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, isForwardRef, isForwardRefCall, isFunctionOfComponentDidMount, isFunctionOfComponentWillUnmount, isFunctionOfRenderMethod, isFunctionOfUseEffectCleanup, isFunctionOfUseEffectSetup, isGetChildContext, isGetDefaultProps, isGetDerivedStateFromError, isGetDerivedStateFromProps, isGetInitialState, isGetSnapshotBeforeUpdate, isInitializedFromReact, isInstanceIdEqual, isInversePhase, isJsxFragmentElement, isJsxHostElement, isJsxLike, isJsxText, isLazy, isLazyCall, isMemo, isMemoCall, isPureComponent, isReactAPI, isReactAPICall, isReactHook, isReactHookCall, isReactHookCallWithName, isReactHookCallWithNameAlias, isReactHookId, isReactHookName, isRender, isRenderFunctionLoose, isRenderMethodLike, isRenderPropLoose, isShouldComponentUpdate, isThisSetState, isUnsafeComponentWillMount, isUnsafeComponentWillReceiveProps, isUnsafeComponentWillUpdate, isUseActionStateCall, isUseCall, isUseCallbackCall, isUseContextCall, isUseDebugValueCall, isUseDeferredValueCall, isUseEffectCall, isUseEffectLikeCall, isUseFormStatusCall, isUseIdCall, isUseImperativeHandleCall, isUseInsertionEffectCall, isUseLayoutEffectCall, isUseMemoCall, isUseOptimisticCall, isUseReducerCall, isUseRefCall, isUseStateCall, isUseSyncExternalStoreCall, isUseTransitionCall, resolveJsxAttributeValue, stringifyJsx, useComponentCollector, useComponentCollectorLegacy, useHookCollector };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eslint-react/core",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.5-beta.0",
|
|
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": {
|
|
@@ -32,14 +32,14 @@
|
|
|
32
32
|
"@typescript-eslint/utils": "^8.45.0",
|
|
33
33
|
"birecord": "^0.1.1",
|
|
34
34
|
"ts-pattern": "^5.8.0",
|
|
35
|
-
"@eslint-react/ast": "2.0.
|
|
36
|
-
"@eslint-react/
|
|
37
|
-
"@eslint-react/
|
|
38
|
-
"@eslint-react/shared": "2.0.
|
|
39
|
-
"@eslint-react/var": "2.0.
|
|
35
|
+
"@eslint-react/ast": "2.0.5-beta.0",
|
|
36
|
+
"@eslint-react/eff": "2.0.5-beta.0",
|
|
37
|
+
"@eslint-react/kit": "2.0.5-beta.0",
|
|
38
|
+
"@eslint-react/shared": "2.0.5-beta.0",
|
|
39
|
+
"@eslint-react/var": "2.0.5-beta.0"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
|
-
"tsdown": "^0.15.
|
|
42
|
+
"tsdown": "^0.15.6",
|
|
43
43
|
"@local/configs": "0.0.0"
|
|
44
44
|
},
|
|
45
45
|
"engines": {
|