@eslint-react/core 2.8.1-next.0 → 2.8.1-next.2

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 CHANGED
@@ -211,6 +211,10 @@ interface FunctionComponentSemanticNode extends SemanticNode {
211
211
  * The display name of the component
212
212
  */
213
213
  displayName: unit | TSESTree.Expression;
214
+ /**
215
+ * The directives used in the function (e.g., "use strict", "use client", etc.)
216
+ */
217
+ directives: TSESTree.StringLiteral[];
214
218
  }
215
219
  /**
216
220
  * Represents a React Class Component
@@ -398,11 +402,13 @@ declare function isComponentName(name: string): boolean;
398
402
  */
399
403
  declare function isComponentNameLoose(name: string): boolean;
400
404
  /**
401
- * Check if the function has no name or a loose component name
405
+ * Check if a function has a loose component name
402
406
  * @param context The rule context
403
- * @param fn The function node
407
+ * @param fn The function to check
408
+ * @param allowNone Whether to allow no name
409
+ * @returns Whether the function has a loose component name
404
410
  */
405
- declare function hasNoneOrLooseComponentName(context: RuleContext, fn: AST.TSESTreeFunction): boolean;
411
+ declare function isFunctionWithLooseComponentName(context: RuleContext, fn: AST.TSESTreeFunction, allowNone?: boolean): boolean;
406
412
  //#endregion
407
413
  //#region src/component/component-render-method.d.ts
408
414
  /**
@@ -532,7 +538,7 @@ type FindEnclosingComponentOrHookFilter = (n: TSESTree.Node, name: string | null
532
538
  * @param test Optional test function to customize component or hook identification
533
539
  * @returns The enclosing component or hook node, or `null` if none is found
534
540
  */
535
- declare function findEnclosingComponentOrHook(node: TSESTree.Node | unit, test?: FindEnclosingComponentOrHookFilter): TSESTree.ArrowFunctionExpression | TSESTree.FunctionExpression | TSESTree.FunctionDeclarationWithName | TSESTree.FunctionDeclarationWithOptionalName | undefined;
541
+ declare function findEnclosingComponentOrHook(node: TSESTree.Node | unit, test?: FindEnclosingComponentOrHookFilter): TSESTree.ArrowFunctionExpression | TSESTree.FunctionDeclarationWithName | TSESTree.FunctionDeclarationWithOptionalName | TSESTree.FunctionExpression | undefined;
536
542
  //#endregion
537
543
  //#region src/hierarchy/is-inside-component-or-hook.d.ts
538
544
  /**
@@ -560,6 +566,10 @@ interface HookSemanticNode extends SemanticNode {
560
566
  node: AST.TSESTreeFunction;
561
567
  name: string;
562
568
  hookCalls: TSESTree.CallExpression[];
569
+ /**
570
+ * The directives used in the function (e.g., "use strict", "use client", etc.)
571
+ */
572
+ directives: TSESTree.StringLiteral[];
563
573
  }
564
574
  //#endregion
565
575
  //#region src/hook/hook-collector.d.ts
@@ -715,7 +725,7 @@ declare function resolveJsxAttributeValue(context: RuleContext, attribute: AST.T
715
725
  readonly toStatic: () => string | number | bigint | boolean | RegExp | null;
716
726
  } | {
717
727
  readonly kind: "expression";
718
- readonly node: TSESTree.Expression | TSESTree.JSXEmptyExpression;
728
+ readonly node: TSESTree.JSXEmptyExpression | TSESTree.Expression;
719
729
  readonly toStatic: () => unknown;
720
730
  } | {
721
731
  readonly kind: "element";
@@ -723,7 +733,7 @@ declare function resolveJsxAttributeValue(context: RuleContext, attribute: AST.T
723
733
  readonly toStatic: () => undefined;
724
734
  } | {
725
735
  readonly kind: "spreadChild";
726
- readonly node: TSESTree.Expression | TSESTree.JSXEmptyExpression;
736
+ readonly node: TSESTree.JSXEmptyExpression | TSESTree.Expression;
727
737
  readonly toStatic: () => undefined;
728
738
  } | {
729
739
  readonly kind: "spreadProps";
@@ -879,4 +889,4 @@ declare function isInitializedFromRef(name: string, initialScope: Scope): boolea
879
889
  */
880
890
  declare function isRefName(name: string): boolean;
881
891
  //#endregion
882
- export { ClassComponentSemanticNode, ClientFunctionSemanticNode, ComponentDetectionHint, ComponentFlag, ComponentKind, ComponentSemanticNode, DEFAULT_COMPONENT_DETECTION_HINT, DEFAULT_JSX_DETECTION_HINT, FindEnclosingComponentOrHookFilter, FunctionComponentSemanticNode, FunctionSemanticNode, HookSemanticNode, JsxAttributeValue, JsxConfig, JsxDetectionHint, JsxEmit, REACT_BUILTIN_HOOK_NAMES, SemanticFunc, SemanticNode, ServerFunctionSemanticNode, findEnclosingComponentOrHook, findParentJsxAttribute, getComponentFlagFromInitPath, getFunctionComponentId, getJsxAttribute, getJsxAttributeName, getJsxConfigFromAnnotation, getJsxConfigFromContext, getJsxElementType, hasNoneOrLooseComponentName, isAssignmentToThisState, isCaptureOwnerStack, isCaptureOwnerStackCall, isChildrenCount, isChildrenCountCall, isChildrenForEach, isChildrenForEachCall, isChildrenMap, isChildrenMapCall, isChildrenOnly, isChildrenOnlyCall, isChildrenToArray, isChildrenToArrayCall, isClassComponent, isCloneElement, isCloneElementCall, isComponentDefinition, isComponentDidCatch, isComponentDidMount, isComponentDidMountCallback, isComponentDidUpdate, isComponentName, isComponentNameLoose, isComponentWillMount, isComponentWillReceiveProps, isComponentWillUnmount, isComponentWillUnmountCallback, isComponentWillUpdate, isComponentWrapperCall, isComponentWrapperCallLoose, isComponentWrapperCallback, isComponentWrapperCallbackLoose, isCreateContext, isCreateContextCall, isCreateElement, isCreateElementCall, isCreateRef, isCreateRefCall, isDeclaredInRenderPropLoose, isDirectValueOfRenderPropertyLoose, isForwardRef, isForwardRefCall, isGetChildContext, isGetDefaultProps, isGetDerivedStateFromError, isGetDerivedStateFromProps, isGetInitialState, isGetSnapshotBeforeUpdate, isHook, isHookCall, isHookCallWithName, isHookId, isHookName, isInitializedFromReact, isInitializedFromReactNative, isInitializedFromRef, isInsideComponentOrHook, isJsxFragmentElement, isJsxHostElement, isJsxLike, isJsxText, isLazy, isLazyCall, isMemo, isMemoCall, isPureComponent, isReactAPI, isReactAPICall, isRefName, isRender, isRenderFunctionLoose, isRenderMethodLike, isRenderPropLoose, isShouldComponentUpdate, isThisSetState, isUnsafeComponentWillMount, isUnsafeComponentWillReceiveProps, isUnsafeComponentWillUpdate, isUseActionStateCall, isUseCall, isUseCallbackCall, isUseContextCall, isUseDebugValueCall, isUseDeferredValueCall, isUseEffectCall, isUseEffectCleanupCallback, isUseEffectLikeCall, isUseEffectSetupCallback, isUseFormStatusCall, isUseIdCall, isUseImperativeHandleCall, isUseInsertionEffectCall, isUseLayoutEffectCall, isUseMemoCall, isUseOptimisticCall, isUseReducerCall, isUseRefCall, isUseStateCall, isUseStateLikeCall, isUseSyncExternalStoreCall, isUseTransitionCall, resolveJsxAttributeValue, stringifyJsx, useComponentCollector, useComponentCollectorLegacy, useHookCollector };
892
+ export { ClassComponentSemanticNode, ClientFunctionSemanticNode, ComponentDetectionHint, ComponentFlag, ComponentKind, ComponentSemanticNode, DEFAULT_COMPONENT_DETECTION_HINT, DEFAULT_JSX_DETECTION_HINT, FindEnclosingComponentOrHookFilter, FunctionComponentSemanticNode, FunctionSemanticNode, HookSemanticNode, JsxAttributeValue, JsxConfig, JsxDetectionHint, JsxEmit, REACT_BUILTIN_HOOK_NAMES, SemanticFunc, SemanticNode, ServerFunctionSemanticNode, findEnclosingComponentOrHook, findParentJsxAttribute, getComponentFlagFromInitPath, getFunctionComponentId, getJsxAttribute, getJsxAttributeName, getJsxConfigFromAnnotation, getJsxConfigFromContext, getJsxElementType, isAssignmentToThisState, isCaptureOwnerStack, isCaptureOwnerStackCall, isChildrenCount, isChildrenCountCall, isChildrenForEach, isChildrenForEachCall, isChildrenMap, isChildrenMapCall, isChildrenOnly, isChildrenOnlyCall, isChildrenToArray, isChildrenToArrayCall, isClassComponent, isCloneElement, isCloneElementCall, isComponentDefinition, isComponentDidCatch, isComponentDidMount, isComponentDidMountCallback, isComponentDidUpdate, isComponentName, isComponentNameLoose, isComponentWillMount, isComponentWillReceiveProps, isComponentWillUnmount, isComponentWillUnmountCallback, isComponentWillUpdate, isComponentWrapperCall, isComponentWrapperCallLoose, isComponentWrapperCallback, isComponentWrapperCallbackLoose, isCreateContext, isCreateContextCall, isCreateElement, isCreateElementCall, isCreateRef, isCreateRefCall, isDeclaredInRenderPropLoose, isDirectValueOfRenderPropertyLoose, isForwardRef, isForwardRefCall, isFunctionWithLooseComponentName, isGetChildContext, isGetDefaultProps, isGetDerivedStateFromError, isGetDerivedStateFromProps, isGetInitialState, isGetSnapshotBeforeUpdate, isHook, isHookCall, isHookCallWithName, isHookId, isHookName, isInitializedFromReact, isInitializedFromReactNative, isInitializedFromRef, isInsideComponentOrHook, isJsxFragmentElement, isJsxHostElement, isJsxLike, isJsxText, isLazy, isLazyCall, isMemo, isMemoCall, isPureComponent, isReactAPI, isReactAPICall, isRefName, isRender, isRenderFunctionLoose, isRenderMethodLike, isRenderPropLoose, isShouldComponentUpdate, isThisSetState, isUnsafeComponentWillMount, isUnsafeComponentWillReceiveProps, isUnsafeComponentWillUpdate, isUseActionStateCall, isUseCall, isUseCallbackCall, isUseContextCall, isUseDebugValueCall, isUseDeferredValueCall, isUseEffectCall, isUseEffectCleanupCallback, isUseEffectLikeCall, isUseEffectSetupCallback, isUseFormStatusCall, isUseIdCall, isUseImperativeHandleCall, isUseInsertionEffectCall, isUseLayoutEffectCall, isUseMemoCall, isUseOptimisticCall, isUseReducerCall, isUseRefCall, isUseStateCall, isUseStateLikeCall, isUseSyncExternalStoreCall, isUseTransitionCall, resolveJsxAttributeValue, stringifyJsx, useComponentCollector, useComponentCollectorLegacy, useHookCollector };
package/dist/index.js CHANGED
@@ -280,6 +280,7 @@ function useHookCollector(context) {
280
280
  kind: "function",
281
281
  name: AST.toStringFormat(id, getText),
282
282
  node,
283
+ directives: [],
283
284
  flag: 0n,
284
285
  hint: 0n,
285
286
  hookCalls: []
@@ -792,13 +793,15 @@ function isComponentNameLoose(name) {
792
793
  return RE_COMPONENT_NAME_LOOSE.test(name);
793
794
  }
794
795
  /**
795
- * Check if the function has no name or a loose component name
796
+ * Check if a function has a loose component name
796
797
  * @param context The rule context
797
- * @param fn The function node
798
+ * @param fn The function to check
799
+ * @param allowNone Whether to allow no name
800
+ * @returns Whether the function has a loose component name
798
801
  */
799
- function hasNoneOrLooseComponentName(context, fn) {
802
+ function isFunctionWithLooseComponentName(context, fn, allowNone = false) {
800
803
  const id = getFunctionComponentId(context, fn);
801
- if (id == null) return true;
804
+ if (id == null) return allowNone;
802
805
  if (id.type === AST_NODE_TYPES.Identifier) return isComponentNameLoose(id.name);
803
806
  if (id.type === AST_NODE_TYPES.MemberExpression && id.property.type === AST_NODE_TYPES.Identifier) return isComponentNameLoose(id.property.name);
804
807
  return false;
@@ -882,7 +885,7 @@ function isChildrenOfCreateElement(context, node) {
882
885
  * @returns `true` if the node is considered a component definition
883
886
  */
884
887
  function isComponentDefinition(context, node, hint) {
885
- if (!hasNoneOrLooseComponentName(context, node)) return false;
888
+ if (!isFunctionWithLooseComponentName(context, node, true)) return false;
886
889
  if (isChildrenOfCreateElement(context, node) || isRenderMethodCallback(node)) return false;
887
890
  if (shouldExcludeBasedOnHint(node, hint)) return false;
888
891
  const significantParent = AST.findParentNode(node, AST.isOneOf([
@@ -947,12 +950,14 @@ function useComponentCollector(context, options = {}) {
947
950
  const id = getFunctionComponentId(context, node);
948
951
  const name = id == null ? unit : AST.toStringFormat(id, getText);
949
952
  const initPath = AST.getFunctionInitPath(node);
950
- functionEntries.push({
953
+ const directives = AST.getFunctionDirectives(node);
954
+ const entry = {
951
955
  id: getFunctionComponentId(context, node),
952
956
  key,
953
957
  kind: "function",
954
958
  name,
955
959
  node,
960
+ directives,
956
961
  displayName: unit,
957
962
  flag: getComponentFlagFromInitPath(initPath),
958
963
  hint,
@@ -962,7 +967,10 @@ function useComponentCollector(context, options = {}) {
962
967
  isExportDefault,
963
968
  isExportDefaultDeclaration,
964
969
  rets: []
965
- });
970
+ };
971
+ functionEntries.push(entry);
972
+ if (!entry.isComponentDefinition || !isFunctionWithLooseComponentName(context, node, false)) return;
973
+ if (directives.some((d) => d.value === "use memo" || d.value === "use no memo")) components.set(entry.key, entry);
966
974
  };
967
975
  const onFunctionExit = () => {
968
976
  return functionEntries.pop();
@@ -1266,4 +1274,4 @@ function isInitializedFromRef(name, initialScope) {
1266
1274
  }
1267
1275
 
1268
1276
  //#endregion
1269
- export { ComponentDetectionHint, ComponentFlag, DEFAULT_COMPONENT_DETECTION_HINT, DEFAULT_JSX_DETECTION_HINT, JsxDetectionHint, JsxEmit, REACT_BUILTIN_HOOK_NAMES, findEnclosingComponentOrHook, findParentJsxAttribute, getComponentFlagFromInitPath, getFunctionComponentId, getJsxAttribute, getJsxAttributeName, getJsxConfigFromAnnotation, getJsxConfigFromContext, getJsxElementType, hasNoneOrLooseComponentName, isAssignmentToThisState, isCaptureOwnerStack, isCaptureOwnerStackCall, isChildrenCount, isChildrenCountCall, isChildrenForEach, isChildrenForEachCall, isChildrenMap, isChildrenMapCall, isChildrenOnly, isChildrenOnlyCall, isChildrenToArray, isChildrenToArrayCall, isClassComponent, isCloneElement, isCloneElementCall, isComponentDefinition, isComponentDidCatch, isComponentDidMount, isComponentDidMountCallback, isComponentDidUpdate, isComponentName, isComponentNameLoose, isComponentWillMount, isComponentWillReceiveProps, isComponentWillUnmount, isComponentWillUnmountCallback, isComponentWillUpdate, isComponentWrapperCall, isComponentWrapperCallLoose, isComponentWrapperCallback, isComponentWrapperCallbackLoose, isCreateContext, isCreateContextCall, isCreateElement, isCreateElementCall, isCreateRef, isCreateRefCall, isDeclaredInRenderPropLoose, isDirectValueOfRenderPropertyLoose, isForwardRef, isForwardRefCall, isGetChildContext, isGetDefaultProps, isGetDerivedStateFromError, isGetDerivedStateFromProps, isGetInitialState, isGetSnapshotBeforeUpdate, isHook, isHookCall, isHookCallWithName, isHookId, isHookName, isInitializedFromReact, isInitializedFromReactNative, isInitializedFromRef, isInsideComponentOrHook, isJsxFragmentElement, isJsxHostElement, isJsxLike, isJsxText, isLazy, isLazyCall, isMemo, isMemoCall, isPureComponent, isReactAPI, isReactAPICall, isRefName, isRender, isRenderFunctionLoose, isRenderMethodLike, isRenderPropLoose, isShouldComponentUpdate, isThisSetState, isUnsafeComponentWillMount, isUnsafeComponentWillReceiveProps, isUnsafeComponentWillUpdate, isUseActionStateCall, isUseCall, isUseCallbackCall, isUseContextCall, isUseDebugValueCall, isUseDeferredValueCall, isUseEffectCall, isUseEffectCleanupCallback, isUseEffectLikeCall, isUseEffectSetupCallback, isUseFormStatusCall, isUseIdCall, isUseImperativeHandleCall, isUseInsertionEffectCall, isUseLayoutEffectCall, isUseMemoCall, isUseOptimisticCall, isUseReducerCall, isUseRefCall, isUseStateCall, isUseStateLikeCall, isUseSyncExternalStoreCall, isUseTransitionCall, resolveJsxAttributeValue, stringifyJsx, useComponentCollector, useComponentCollectorLegacy, useHookCollector };
1277
+ export { ComponentDetectionHint, ComponentFlag, DEFAULT_COMPONENT_DETECTION_HINT, DEFAULT_JSX_DETECTION_HINT, JsxDetectionHint, JsxEmit, REACT_BUILTIN_HOOK_NAMES, findEnclosingComponentOrHook, findParentJsxAttribute, getComponentFlagFromInitPath, getFunctionComponentId, getJsxAttribute, getJsxAttributeName, getJsxConfigFromAnnotation, getJsxConfigFromContext, getJsxElementType, isAssignmentToThisState, isCaptureOwnerStack, isCaptureOwnerStackCall, isChildrenCount, isChildrenCountCall, isChildrenForEach, isChildrenForEachCall, isChildrenMap, isChildrenMapCall, isChildrenOnly, isChildrenOnlyCall, isChildrenToArray, isChildrenToArrayCall, isClassComponent, isCloneElement, isCloneElementCall, isComponentDefinition, isComponentDidCatch, isComponentDidMount, isComponentDidMountCallback, isComponentDidUpdate, isComponentName, isComponentNameLoose, isComponentWillMount, isComponentWillReceiveProps, isComponentWillUnmount, isComponentWillUnmountCallback, isComponentWillUpdate, isComponentWrapperCall, isComponentWrapperCallLoose, isComponentWrapperCallback, isComponentWrapperCallbackLoose, isCreateContext, isCreateContextCall, isCreateElement, isCreateElementCall, isCreateRef, isCreateRefCall, isDeclaredInRenderPropLoose, isDirectValueOfRenderPropertyLoose, isForwardRef, isForwardRefCall, isFunctionWithLooseComponentName, isGetChildContext, isGetDefaultProps, isGetDerivedStateFromError, isGetDerivedStateFromProps, isGetInitialState, isGetSnapshotBeforeUpdate, isHook, isHookCall, isHookCallWithName, isHookId, isHookName, isInitializedFromReact, isInitializedFromReactNative, isInitializedFromRef, isInsideComponentOrHook, isJsxFragmentElement, isJsxHostElement, isJsxLike, isJsxText, isLazy, isLazyCall, isMemo, isMemoCall, isPureComponent, isReactAPI, isReactAPICall, isRefName, isRender, isRenderFunctionLoose, isRenderMethodLike, isRenderPropLoose, isShouldComponentUpdate, isThisSetState, isUnsafeComponentWillMount, isUnsafeComponentWillReceiveProps, isUnsafeComponentWillUpdate, isUseActionStateCall, isUseCall, isUseCallbackCall, isUseContextCall, isUseDebugValueCall, isUseDeferredValueCall, isUseEffectCall, isUseEffectCleanupCallback, isUseEffectLikeCall, isUseEffectSetupCallback, isUseFormStatusCall, isUseIdCall, isUseImperativeHandleCall, isUseInsertionEffectCall, isUseLayoutEffectCall, isUseMemoCall, isUseOptimisticCall, isUseReducerCall, isUseRefCall, isUseStateCall, isUseStateLikeCall, 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.8.1-next.0",
3
+ "version": "2.8.1-next.2",
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,10 +34,10 @@
34
34
  "@typescript-eslint/types": "^8.54.0",
35
35
  "@typescript-eslint/utils": "^8.54.0",
36
36
  "ts-pattern": "^5.9.0",
37
- "@eslint-react/ast": "2.8.1-next.0",
38
- "@eslint-react/eff": "2.8.1-next.0",
39
- "@eslint-react/shared": "2.8.1-next.0",
40
- "@eslint-react/var": "2.8.1-next.0"
37
+ "@eslint-react/ast": "2.8.1-next.2",
38
+ "@eslint-react/eff": "2.8.1-next.2",
39
+ "@eslint-react/shared": "2.8.1-next.2",
40
+ "@eslint-react/var": "2.8.1-next.2"
41
41
  },
42
42
  "devDependencies": {
43
43
  "tsdown": "^0.20.1",