eslint-config-typed 3.8.1 → 3.10.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.
Files changed (66) hide show
  1. package/README.md +1 -1
  2. package/dist/plugins/react-coding-style/rules/ban-use-imperative-handle-hook.mjs +4 -4
  3. package/dist/plugins/react-coding-style/rules/ban-use-imperative-handle-hook.mjs.map +1 -1
  4. package/dist/plugins/react-coding-style/rules/component-name.d.mts.map +1 -1
  5. package/dist/plugins/react-coding-style/rules/component-name.mjs +5 -3
  6. package/dist/plugins/react-coding-style/rules/component-name.mjs.map +1 -1
  7. package/dist/plugins/react-coding-style/rules/display-name.d.mts +14 -0
  8. package/dist/plugins/react-coding-style/rules/display-name.d.mts.map +1 -0
  9. package/dist/plugins/react-coding-style/rules/display-name.mjs +86 -0
  10. package/dist/plugins/react-coding-style/rules/display-name.mjs.map +1 -0
  11. package/dist/plugins/react-coding-style/rules/import-style.d.mts +8 -2
  12. package/dist/plugins/react-coding-style/rules/import-style.d.mts.map +1 -1
  13. package/dist/plugins/react-coding-style/rules/import-style.mjs +63 -26
  14. package/dist/plugins/react-coding-style/rules/import-style.mjs.map +1 -1
  15. package/dist/plugins/react-coding-style/rules/props-type-annotation-style.mjs +2 -2
  16. package/dist/plugins/react-coding-style/rules/props-type-annotation-style.mjs.map +1 -1
  17. package/dist/plugins/react-coding-style/rules/react-memo-props-argument-name.mjs +2 -2
  18. package/dist/plugins/react-coding-style/rules/react-memo-props-argument-name.mjs.map +1 -1
  19. package/dist/plugins/react-coding-style/rules/react-memo-type-parameter.mjs +2 -2
  20. package/dist/plugins/react-coding-style/rules/react-memo-type-parameter.mjs.map +1 -1
  21. package/dist/plugins/react-coding-style/rules/rules.d.mts +6 -1
  22. package/dist/plugins/react-coding-style/rules/rules.d.mts.map +1 -1
  23. package/dist/plugins/react-coding-style/rules/rules.mjs +2 -0
  24. package/dist/plugins/react-coding-style/rules/rules.mjs.map +1 -1
  25. package/dist/plugins/react-coding-style/rules/shared.d.mts +7 -3
  26. package/dist/plugins/react-coding-style/rules/shared.d.mts.map +1 -1
  27. package/dist/plugins/react-coding-style/rules/shared.mjs +61 -3
  28. package/dist/plugins/react-coding-style/rules/shared.mjs.map +1 -1
  29. package/dist/plugins/react-coding-style/rules/use-memo-hooks-style.d.mts.map +1 -1
  30. package/dist/plugins/react-coding-style/rules/use-memo-hooks-style.mjs +45 -3
  31. package/dist/plugins/react-coding-style/rules/use-memo-hooks-style.mjs.map +1 -1
  32. package/dist/plugins/ts-restrictions/rules/check-destructuring-completeness.d.mts.map +1 -1
  33. package/dist/plugins/ts-restrictions/rules/check-destructuring-completeness.mjs +46 -46
  34. package/dist/plugins/ts-restrictions/rules/check-destructuring-completeness.mjs.map +1 -1
  35. package/dist/rules/eslint-import-rules.d.mts +1 -3
  36. package/dist/rules/eslint-import-rules.d.mts.map +1 -1
  37. package/dist/rules/eslint-import-rules.mjs +3 -1
  38. package/dist/rules/eslint-import-rules.mjs.map +1 -1
  39. package/dist/rules/eslint-react-coding-style-rules.d.mts +6 -1
  40. package/dist/rules/eslint-react-coding-style-rules.d.mts.map +1 -1
  41. package/dist/rules/eslint-react-coding-style-rules.mjs +3 -2
  42. package/dist/rules/eslint-react-coding-style-rules.mjs.map +1 -1
  43. package/dist/types/rules/eslint-react-coding-style-rules.d.mts +69 -2
  44. package/dist/types/rules/eslint-react-coding-style-rules.d.mts.map +1 -1
  45. package/package.json +1 -1
  46. package/src/plugins/react-coding-style/README.md +22 -0
  47. package/src/plugins/react-coding-style/rules/ban-use-imperative-handle-hook.mts +4 -4
  48. package/src/plugins/react-coding-style/rules/ban-use-imperative-handle-hook.test.mts +50 -18
  49. package/src/plugins/react-coding-style/rules/component-name.mts +6 -3
  50. package/src/plugins/react-coding-style/rules/display-name.mts +117 -0
  51. package/src/plugins/react-coding-style/rules/display-name.test.mts +87 -0
  52. package/src/plugins/react-coding-style/rules/import-style.mts +92 -34
  53. package/src/plugins/react-coding-style/rules/import-style.test.mts +81 -34
  54. package/src/plugins/react-coding-style/rules/props-type-annotation-style.mts +2 -2
  55. package/src/plugins/react-coding-style/rules/react-memo-props-argument-name.mts +2 -2
  56. package/src/plugins/react-coding-style/rules/react-memo-type-parameter.mts +2 -2
  57. package/src/plugins/react-coding-style/rules/rules.mts +2 -0
  58. package/src/plugins/react-coding-style/rules/shared.mts +92 -7
  59. package/src/plugins/react-coding-style/rules/use-memo-hooks-style-named.test.mts +162 -0
  60. package/src/plugins/react-coding-style/rules/use-memo-hooks-style-namespace.test.mts +162 -0
  61. package/src/plugins/react-coding-style/rules/use-memo-hooks-style.mts +68 -3
  62. package/src/plugins/ts-restrictions/rules/check-destructuring-completeness.mts +59 -59
  63. package/src/rules/eslint-import-rules.mts +4 -1
  64. package/src/rules/eslint-react-coding-style-rules.mts +3 -2
  65. package/src/types/rules/eslint-react-coding-style-rules.mts +78 -2
  66. package/src/plugins/react-coding-style/rules/use-memo-hooks-style.test.mts +0 -72
package/README.md CHANGED
@@ -560,7 +560,7 @@ export default [
560
560
  'warn',
561
561
  ...eslintRules['no-restricted-syntax'].slice(1),
562
562
  ],
563
- 'custom/no-restricted-syntax': [
563
+ 'ts-restrictions/no-restricted-syntax': [
564
564
  'error',
565
565
  {
566
566
  // Restrict import style of React
@@ -1,5 +1,5 @@
1
1
  import { castDeepMutable } from 'ts-data-forge';
2
- import { isReactMemberExpression } from './shared.mjs';
2
+ import { isReactApiCall } from './shared.mjs';
3
3
 
4
4
  const banUseImperativeHandleHook = {
5
5
  meta: {
@@ -13,10 +13,10 @@ const banUseImperativeHandleHook = {
13
13
  },
14
14
  },
15
15
  create: (context) => ({
16
- MemberExpression: (node) => {
17
- if (isReactMemberExpression(node, 'useImperativeHandle')) {
16
+ CallExpression: (node) => {
17
+ if (isReactApiCall(context, node, 'useImperativeHandle')) {
18
18
  context.report({
19
- node: castDeepMutable(node),
19
+ node: castDeepMutable(node.callee),
20
20
  messageId: 'disallowUseImperativeHandle',
21
21
  });
22
22
  }
@@ -1 +1 @@
1
- {"version":3,"file":"ban-use-imperative-handle-hook.mjs","sources":["../../../../src/plugins/react-coding-style/rules/ban-use-imperative-handle-hook.mts"],"sourcesContent":[null],"names":[],"mappings":";;;AAMO,MAAM,0BAA0B,GAAoC;AACzE,IAAA,IAAI,EAAE;AACJ,QAAA,IAAI,EAAE,YAAY;AAClB,QAAA,IAAI,EAAE;AACJ,YAAA,WAAW,EACT,+EAA+E;AAClF,SAAA;AACD,QAAA,MAAM,EAAE,EAAE;AACV,QAAA,QAAQ,EAAE;AACR,YAAA,2BAA2B,EACzB,4EAA4E;AAC/E,SAAA;AACF,KAAA;AACD,IAAA,MAAM,EAAE,CAAC,OAAO,MAAM;AACpB,QAAA,gBAAgB,EAAE,CAAC,IAA6C,KAAI;AAClE,YAAA,IAAI,uBAAuB,CAAC,IAAI,EAAE,qBAAqB,CAAC,EAAE;gBACxD,OAAO,CAAC,MAAM,CAAC;AACb,oBAAA,IAAI,EAAE,eAAe,CAAC,IAAI,CAAC;AAC3B,oBAAA,SAAS,EAAE,6BAA6B;AACzC,iBAAA,CAAC;YACJ;QACF,CAAC;KACF,CAAC;AACF,IAAA,cAAc,EAAE,EAAE;;;;;"}
1
+ {"version":3,"file":"ban-use-imperative-handle-hook.mjs","sources":["../../../../src/plugins/react-coding-style/rules/ban-use-imperative-handle-hook.mts"],"sourcesContent":[null],"names":[],"mappings":";;;AAMO,MAAM,0BAA0B,GAAoC;AACzE,IAAA,IAAI,EAAE;AACJ,QAAA,IAAI,EAAE,YAAY;AAClB,QAAA,IAAI,EAAE;AACJ,YAAA,WAAW,EACT,+EAA+E;AAClF,SAAA;AACD,QAAA,MAAM,EAAE,EAAE;AACV,QAAA,QAAQ,EAAE;AACR,YAAA,2BAA2B,EACzB,4EAA4E;AAC/E,SAAA;AACF,KAAA;AACD,IAAA,MAAM,EAAE,CAAC,OAAO,MAAM;AACpB,QAAA,cAAc,EAAE,CAAC,IAA2C,KAAI;YAC9D,IAAI,cAAc,CAAC,OAAO,EAAE,IAAI,EAAE,qBAAqB,CAAC,EAAE;gBACxD,OAAO,CAAC,MAAM,CAAC;AACb,oBAAA,IAAI,EAAE,eAAe,CAAC,IAAI,CAAC,MAAM,CAAC;AAClC,oBAAA,SAAS,EAAE,6BAA6B;AACzC,iBAAA,CAAC;YACJ;QACF,CAAC;KACF,CAAC;AACF,IAAA,cAAc,EAAE,EAAE;;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"component-name.d.mts","sourceRoot":"","sources":["../../../../src/plugins/react-coding-style/rules/component-name.mts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,KAAK,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAGzE,KAAK,mBAAmB,GAAG,QAAQ,CAAC;IAClC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC,CAAC;AAEH,KAAK,OAAO,GAAG,SAAS,CAAC,mBAAmB,CAAC,GAAG,SAAS,EAAE,CAAC;AAE5D,KAAK,UAAU,GAAG,sBAAsB,GAAG,2BAA2B,CAAC;AAcvE,eAAO,MAAM,iBAAiB,EAAE,QAAQ,CAAC,UAAU,CAAC,UAAU,EAAE,OAAO,CAqEtE,CAAC"}
1
+ {"version":3,"file":"component-name.d.mts","sourceRoot":"","sources":["../../../../src/plugins/react-coding-style/rules/component-name.mts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,KAAK,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAGzE,KAAK,mBAAmB,GAAG,QAAQ,CAAC;IAClC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC,CAAC;AAEH,KAAK,OAAO,GAAG,SAAS,CAAC,mBAAmB,CAAC,GAAG,SAAS,EAAE,CAAC;AAE5D,KAAK,UAAU,GAAG,sBAAsB,GAAG,2BAA2B,CAAC;AAcvE,eAAO,MAAM,iBAAiB,EAAE,QAAQ,CAAC,UAAU,CAAC,UAAU,EAAE,OAAO,CAwEtE,CAAC"}
@@ -1,5 +1,5 @@
1
1
  import { AST_NODE_TYPES } from '@typescript-eslint/utils';
2
- import { isReactCallExpression } from './shared.mjs';
2
+ import { isReactApiCall } from './shared.mjs';
3
3
 
4
4
  // NOTE:
5
5
  // `const Name = React.memo<Props>((props) => {`
@@ -45,8 +45,10 @@ const componentNameRule = {
45
45
  return {
46
46
  VariableDeclarator: (node) => {
47
47
  if (node.id.type !== AST_NODE_TYPES.Identifier ||
48
- node.init?.type !== AST_NODE_TYPES.CallExpression ||
49
- !isReactCallExpression(node.init, 'memo')) {
48
+ node.init?.type !== AST_NODE_TYPES.CallExpression) {
49
+ return;
50
+ }
51
+ if (!isReactApiCall(context, node.init, 'memo')) {
50
52
  return;
51
53
  }
52
54
  if (node.id.name.length >= maxLength) {
@@ -1 +1 @@
1
- {"version":3,"file":"component-name.mjs","sources":["../../../../src/plugins/react-coding-style/rules/component-name.mts"],"sourcesContent":[null],"names":[],"mappings":";;;AAYA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEO,MAAM,iBAAiB,GAA6C;AACzE,IAAA,IAAI,EAAE;AACJ,QAAA,IAAI,EAAE,YAAY;AAClB,QAAA,IAAI,EAAE;AACJ,YAAA,WAAW,EACT,mFAAmF;AACtF,SAAA;AACD,QAAA,MAAM,EAAE;AACN,YAAA;AACE,gBAAA,IAAI,EAAE,QAAQ;AACd,gBAAA,UAAU,EAAE;AACV,oBAAA,SAAS,EAAE;AACT,wBAAA,IAAI,EAAE,SAAS;AACf,wBAAA,OAAO,EAAE,CAAC;AACX,qBAAA;AACD,oBAAA,OAAO,EAAE;AACP,wBAAA,IAAI,EAAE,QAAQ;AACf,qBAAA;AACF,iBAAA;AACD,gBAAA,oBAAoB,EAAE,KAAK;AAC5B,aAAA;AACF,SAAA;AACD,QAAA,QAAQ,EAAE;AACR,YAAA,oBAAoB,EAClB,mLAAmL;AACrL,YAAA,yBAAyB,EACvB,gDAAgD;AACnD,SAAA;AACF,KAAA;AACD,IAAA,MAAM,EAAE,CAAC,OAAO,KAAI;QAClB,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;AACjC,QAAA,MAAM,SAAS,GAAG,MAAM,EAAE,SAAS,IAAI,EAAE;AACzC,QAAA,MAAM,OAAO,GAAG,MAAM,EAAE,OAAO;QAE/B,OAAO;AACL,YAAA,kBAAkB,EAAE,CAAC,IAAI,KAAI;gBAC3B,IACE,IAAI,CAAC,EAAE,CAAC,IAAI,KAAK,cAAc,CAAC,UAAU;AAC1C,oBAAA,IAAI,CAAC,IAAI,EAAE,IAAI,KAAK,cAAc,CAAC,cAAc;oBACjD,CAAC,qBAAqB,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,EACzC;oBACA;gBACF;gBAEA,IAAI,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,IAAI,SAAS,EAAE;oBACpC,OAAO,CAAC,MAAM,CAAC;wBACb,IAAI,EAAE,IAAI,CAAC,EAAE;AACb,wBAAA,SAAS,EAAE,sBAAsB;AACjC,wBAAA,IAAI,EAAE;AACJ,4BAAA,SAAS,EAAE,SAAS,CAAC,QAAQ,EAAE;AAChC,yBAAA;AACF,qBAAA,CAAC;oBAEF;gBACF;AAEA,gBAAA,IAAI,OAAO,KAAK,SAAS,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE;oBACxD,OAAO,CAAC,MAAM,CAAC;wBACb,IAAI,EAAE,IAAI,CAAC,EAAE;AACb,wBAAA,SAAS,EAAE,2BAA2B;AACtC,wBAAA,IAAI,EAAE;AACJ,4BAAA,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC;AACzB,yBAAA;AACF,qBAAA,CAAC;gBACJ;YACF,CAAC;SACF;IACH,CAAC;AACD,IAAA,cAAc,EAAE,EAAE;;;;;"}
1
+ {"version":3,"file":"component-name.mjs","sources":["../../../../src/plugins/react-coding-style/rules/component-name.mts"],"sourcesContent":[null],"names":[],"mappings":";;;AAYA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEO,MAAM,iBAAiB,GAA6C;AACzE,IAAA,IAAI,EAAE;AACJ,QAAA,IAAI,EAAE,YAAY;AAClB,QAAA,IAAI,EAAE;AACJ,YAAA,WAAW,EACT,mFAAmF;AACtF,SAAA;AACD,QAAA,MAAM,EAAE;AACN,YAAA;AACE,gBAAA,IAAI,EAAE,QAAQ;AACd,gBAAA,UAAU,EAAE;AACV,oBAAA,SAAS,EAAE;AACT,wBAAA,IAAI,EAAE,SAAS;AACf,wBAAA,OAAO,EAAE,CAAC;AACX,qBAAA;AACD,oBAAA,OAAO,EAAE;AACP,wBAAA,IAAI,EAAE,QAAQ;AACf,qBAAA;AACF,iBAAA;AACD,gBAAA,oBAAoB,EAAE,KAAK;AAC5B,aAAA;AACF,SAAA;AACD,QAAA,QAAQ,EAAE;AACR,YAAA,oBAAoB,EAClB,mLAAmL;AACrL,YAAA,yBAAyB,EACvB,gDAAgD;AACnD,SAAA;AACF,KAAA;AACD,IAAA,MAAM,EAAE,CAAC,OAAO,KAAI;QAClB,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;AACjC,QAAA,MAAM,SAAS,GAAG,MAAM,EAAE,SAAS,IAAI,EAAE;AACzC,QAAA,MAAM,OAAO,GAAG,MAAM,EAAE,OAAO;QAE/B,OAAO;AACL,YAAA,kBAAkB,EAAE,CAAC,IAAI,KAAI;gBAC3B,IACE,IAAI,CAAC,EAAE,CAAC,IAAI,KAAK,cAAc,CAAC,UAAU;oBAC1C,IAAI,CAAC,IAAI,EAAE,IAAI,KAAK,cAAc,CAAC,cAAc,EACjD;oBACA;gBACF;AAEA,gBAAA,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE;oBAC/C;gBACF;gBAEA,IAAI,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,IAAI,SAAS,EAAE;oBACpC,OAAO,CAAC,MAAM,CAAC;wBACb,IAAI,EAAE,IAAI,CAAC,EAAE;AACb,wBAAA,SAAS,EAAE,sBAAsB;AACjC,wBAAA,IAAI,EAAE;AACJ,4BAAA,SAAS,EAAE,SAAS,CAAC,QAAQ,EAAE;AAChC,yBAAA;AACF,qBAAA,CAAC;oBAEF;gBACF;AAEA,gBAAA,IAAI,OAAO,KAAK,SAAS,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE;oBACxD,OAAO,CAAC,MAAM,CAAC;wBACb,IAAI,EAAE,IAAI,CAAC,EAAE;AACb,wBAAA,SAAS,EAAE,2BAA2B;AACtC,wBAAA,IAAI,EAAE;AACJ,4BAAA,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC;AACzB,yBAAA;AACF,qBAAA,CAAC;gBACJ;YACF,CAAC;SACF;IACH,CAAC;AACD,IAAA,cAAc,EAAE,EAAE;;;;;"}
@@ -0,0 +1,14 @@
1
+ import { type TSESLint } from '@typescript-eslint/utils';
2
+ type Options = readonly [
3
+ Readonly<{
4
+ ignoreTranspilerName?: boolean;
5
+ }>?
6
+ ];
7
+ type MessageIds = 'missingDisplayName';
8
+ /**
9
+ * Rule to require displayName property for React components
10
+ * This helps with debugging and component identification in React DevTools
11
+ */
12
+ export declare const displayNameRule: TSESLint.RuleModule<MessageIds, Options>;
13
+ export {};
14
+ //# sourceMappingURL=display-name.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"display-name.d.mts","sourceRoot":"","sources":["../../../../src/plugins/react-coding-style/rules/display-name.mts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,QAAQ,EAEd,MAAM,0BAA0B,CAAC;AAIlC,KAAK,OAAO,GAAG,SAAS;IACtB,QAAQ,CAAC;QACP,oBAAoB,CAAC,EAAE,OAAO,CAAC;KAChC,CAAC,CAAC;CACJ,CAAC;AAEF,KAAK,UAAU,GAAG,oBAAoB,CAAC;AAEvC;;;GAGG;AACH,eAAO,MAAM,eAAe,EAAE,QAAQ,CAAC,UAAU,CAAC,UAAU,EAAE,OAAO,CAgGpE,CAAC"}
@@ -0,0 +1,86 @@
1
+ import { AST_NODE_TYPES } from '@typescript-eslint/utils';
2
+ import 'ts-data-forge';
3
+ import { isReactApiCall } from './shared.mjs';
4
+
5
+ /**
6
+ * Rule to require displayName property for React components
7
+ * This helps with debugging and component identification in React DevTools
8
+ */
9
+ const displayNameRule = {
10
+ meta: {
11
+ type: 'suggestion',
12
+ docs: {
13
+ description: 'Require displayName property for React components created with React.memo',
14
+ },
15
+ schema: [
16
+ {
17
+ type: 'object',
18
+ properties: {
19
+ ignoreTranspilerName: {
20
+ type: 'boolean',
21
+ description: 'When true, ignores components that get displayName from variable name',
22
+ },
23
+ },
24
+ additionalProperties: false,
25
+ },
26
+ ],
27
+ messages: {
28
+ missingDisplayName: 'Component should have a displayName property for better debugging',
29
+ },
30
+ },
31
+ create: (context) => {
32
+ const options = context.options[0] ?? {};
33
+ const ignoreTranspilerName = options.ignoreTranspilerName ?? false;
34
+ const checkComponent = (node) => {
35
+ if (node.id.type !== AST_NODE_TYPES.Identifier) {
36
+ return;
37
+ }
38
+ if (node.init?.type !== AST_NODE_TYPES.CallExpression) {
39
+ return;
40
+ }
41
+ if (!isReactApiCall(context, node.init, 'memo')) {
42
+ return;
43
+ }
44
+ const componentName = node.id.name;
45
+ if (ignoreTranspilerName) {
46
+ return;
47
+ }
48
+ const parent = node.parent;
49
+ const grandParent = parent.parent;
50
+ if (grandParent.type !== AST_NODE_TYPES.Program) {
51
+ return;
52
+ }
53
+ const program = grandParent;
54
+ const componentIndex = program.body.indexOf(parent);
55
+ if (componentIndex === -1) {
56
+ return;
57
+ }
58
+ const nextStatement = program.body[componentIndex + 1];
59
+ const hasDisplayName = nextStatement !== undefined &&
60
+ nextStatement.type === AST_NODE_TYPES.ExpressionStatement &&
61
+ nextStatement.expression.type === AST_NODE_TYPES.AssignmentExpression &&
62
+ nextStatement.expression.left.type ===
63
+ AST_NODE_TYPES.MemberExpression &&
64
+ nextStatement.expression.left.object.type ===
65
+ AST_NODE_TYPES.Identifier &&
66
+ nextStatement.expression.left.object.name === componentName &&
67
+ nextStatement.expression.left.property.type ===
68
+ AST_NODE_TYPES.Identifier &&
69
+ nextStatement.expression.left.property.name === 'displayName';
70
+ if (!hasDisplayName) {
71
+ context.report({
72
+ // eslint-disable-next-line total-functions/no-unsafe-type-assertion
73
+ node: node.id,
74
+ messageId: 'missingDisplayName',
75
+ });
76
+ }
77
+ };
78
+ return {
79
+ VariableDeclarator: checkComponent,
80
+ };
81
+ },
82
+ defaultOptions: [{ ignoreTranspilerName: false }],
83
+ };
84
+
85
+ export { displayNameRule };
86
+ //# sourceMappingURL=display-name.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"display-name.mjs","sources":["../../../../src/plugins/react-coding-style/rules/display-name.mts"],"sourcesContent":[null],"names":[],"mappings":";;;;AAgBA;;;AAGG;AACI,MAAM,eAAe,GAA6C;AACvE,IAAA,IAAI,EAAE;AACJ,QAAA,IAAI,EAAE,YAAY;AAClB,QAAA,IAAI,EAAE;AACJ,YAAA,WAAW,EACT,2EAA2E;AAC9E,SAAA;AACD,QAAA,MAAM,EAAE;AACN,YAAA;AACE,gBAAA,IAAI,EAAE,QAAQ;AACd,gBAAA,UAAU,EAAE;AACV,oBAAA,oBAAoB,EAAE;AACpB,wBAAA,IAAI,EAAE,SAAS;AACf,wBAAA,WAAW,EACT,uEAAuE;AAC1E,qBAAA;AACF,iBAAA;AACD,gBAAA,oBAAoB,EAAE,KAAK;AAC5B,aAAA;AACF,SAAA;AACD,QAAA,QAAQ,EAAE;AACR,YAAA,kBAAkB,EAChB,mEAAmE;AACtE,SAAA;AACF,KAAA;AACD,IAAA,MAAM,EAAE,CAAC,OAAO,KAAI;QAClB,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,EAAE;AACxC,QAAA,MAAM,oBAAoB,GAAG,OAAO,CAAC,oBAAoB,IAAI,KAAK;AAElE,QAAA,MAAM,cAAc,GAAG,CACrB,IAA+C,KACvC;YACR,IAAI,IAAI,CAAC,EAAE,CAAC,IAAI,KAAK,cAAc,CAAC,UAAU,EAAE;gBAC9C;;YAGF,IAAI,IAAI,CAAC,IAAI,EAAE,IAAI,KAAK,cAAc,CAAC,cAAc,EAAE;gBACrD;;AAGF,YAAA,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE;gBAC/C;;AAGF,YAAA,MAAM,aAAa,GAAG,IAAI,CAAC,EAAE,CAAC,IAAI;YAElC,IAAI,oBAAoB,EAAE;gBACxB;;AAGF,YAAA,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM;AAI1B,YAAA,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM;YAEjC,IAAI,WAAW,CAAC,IAAI,KAAK,cAAc,CAAC,OAAO,EAAE;gBAC/C;;YAGF,MAAM,OAAO,GAAG,WAAW;YAC3B,MAAM,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC;AAEnD,YAAA,IAAI,cAAc,KAAK,EAAE,EAAE;gBACzB;;YAGF,MAAM,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,cAAc,GAAG,CAAC,CAAC;AAEtD,YAAA,MAAM,cAAc,GAClB,aAAa,KAAK,SAAS;AAC3B,gBAAA,aAAa,CAAC,IAAI,KAAK,cAAc,CAAC,mBAAmB;AACzD,gBAAA,aAAa,CAAC,UAAU,CAAC,IAAI,KAAK,cAAc,CAAC,oBAAoB;AACrE,gBAAA,aAAa,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI;AAChC,oBAAA,cAAc,CAAC,gBAAgB;AACjC,gBAAA,aAAa,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI;AACvC,oBAAA,cAAc,CAAC,UAAU;gBAC3B,aAAa,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,aAAa;AAC3D,gBAAA,aAAa,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI;AACzC,oBAAA,cAAc,CAAC,UAAU;gBAC3B,aAAa,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,KAAK,aAAa;YAE/D,IAAI,CAAC,cAAc,EAAE;gBACnB,OAAO,CAAC,MAAM,CAAC;;oBAEb,IAAI,EAAE,IAAI,CAAC,EAAW;AACtB,oBAAA,SAAS,EAAE,oBAAoB;AAChC,iBAAA,CAAC;;AAEN,QAAA,CAAC;QAED,OAAO;AACL,YAAA,kBAAkB,EAAE,cAAc;SACnC;KACF;AACD,IAAA,cAAc,EAAE,CAAC,EAAE,oBAAoB,EAAE,KAAK,EAAE,CAAC;;;;;"}
@@ -1,5 +1,11 @@
1
1
  import { type TSESLint } from '@typescript-eslint/utils';
2
- type MessageIds = 'namespaceImportRequired' | 'namespaceNameMustBeReact';
3
- export declare const importStyleRule: TSESLint.RuleModule<MessageIds>;
2
+ type ImportStyle = 'namespace' | 'named';
3
+ type Options = readonly [
4
+ Readonly<{
5
+ importStyle?: ImportStyle;
6
+ }>?
7
+ ];
8
+ type MessageIds = 'namespaceImportRequired' | 'namespaceNameMustBeReact' | 'namedImportRequired';
9
+ export declare const importStyleRule: TSESLint.RuleModule<MessageIds, Options>;
4
10
  export {};
5
11
  //# sourceMappingURL=import-style.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"import-style.d.mts","sourceRoot":"","sources":["../../../../src/plugins/react-coding-style/rules/import-style.mts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,KAAK,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAEzE,KAAK,UAAU,GAAG,yBAAyB,GAAG,0BAA0B,CAAC;AAMzE,eAAO,MAAM,eAAe,EAAE,QAAQ,CAAC,UAAU,CAAC,UAAU,CA6C3D,CAAC"}
1
+ {"version":3,"file":"import-style.d.mts","sourceRoot":"","sources":["../../../../src/plugins/react-coding-style/rules/import-style.mts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,KAAK,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAEzE,KAAK,WAAW,GAAG,WAAW,GAAG,OAAO,CAAC;AAEzC,KAAK,OAAO,GAAG,SAAS;IACtB,QAAQ,CAAC;QACP,WAAW,CAAC,EAAE,WAAW,CAAC;KAC3B,CAAC,CAAC;CACJ,CAAC;AAEF,KAAK,UAAU,GACX,yBAAyB,GACzB,0BAA0B,GAC1B,qBAAqB,CAAC;AAQ1B,eAAO,MAAM,eAAe,EAAE,QAAQ,CAAC,UAAU,CAAC,UAAU,EAAE,OAAO,CA0FpE,CAAC"}
@@ -1,43 +1,80 @@
1
1
  import { AST_NODE_TYPES } from '@typescript-eslint/utils';
2
2
 
3
- // NOTE: React の import 方法を `import * as React from 'react'` と namespace import のみに限定するルール。
3
+ // NOTE: React の import 方法を指定するルール。
4
+ // デフォルトは `import * as React from 'react'` と namespace import のみに限定。
4
5
  // import を1回で済ませられて便利なのと、 React.* に対する以降のルールを書きやすくするため。
5
6
  // tree-shaking に悪影響は無い。
7
+ // オプションで named imports `import { useState, useEffect } from 'react'` も許可可能。
6
8
  const importStyleRule = {
7
9
  meta: {
8
10
  type: 'suggestion',
9
11
  docs: {
10
- description: "Enforces importing React with a single namespace import named 'React'.",
12
+ description: 'Enforces importing React with a specific style (namespace or named imports).',
11
13
  },
12
- schema: [],
14
+ schema: [
15
+ {
16
+ type: 'object',
17
+ properties: {
18
+ importStyle: {
19
+ type: 'string',
20
+ enum: ['namespace', 'named'],
21
+ description: 'Import style to enforce: "namespace" for `import * as React` or "named" for `import { ... }`',
22
+ },
23
+ },
24
+ additionalProperties: false,
25
+ },
26
+ ],
13
27
  messages: {
14
28
  namespaceImportRequired: "React should be imported as `import * as React from 'react'`.",
15
29
  namespaceNameMustBeReact: "The namespace name imported from 'react' must be 'React'.",
30
+ namedImportRequired: "React should be imported as named imports like `import { useState } from 'react'`.",
16
31
  },
17
32
  },
18
- create: (context) => ({
19
- ImportDeclaration: (node) => {
20
- if (node.source.value !== 'react') {
21
- return;
22
- }
23
- const [firstSpecifier] = node.specifiers;
24
- if (firstSpecifier === undefined ||
25
- firstSpecifier.type !== AST_NODE_TYPES.ImportNamespaceSpecifier ||
26
- node.specifiers.length !== 1) {
27
- context.report({
28
- node,
29
- messageId: 'namespaceImportRequired',
30
- });
31
- return;
32
- }
33
- if (firstSpecifier.local.name !== 'React') {
34
- context.report({
35
- node: firstSpecifier.local,
36
- messageId: 'namespaceNameMustBeReact',
37
- });
38
- }
39
- },
40
- }),
33
+ create: (context) => {
34
+ const options = context.options[0] ?? {};
35
+ const importStyle = options.importStyle ?? 'namespace';
36
+ return {
37
+ ImportDeclaration: (node) => {
38
+ if (node.source.value !== 'react') {
39
+ return;
40
+ }
41
+ switch (importStyle) {
42
+ case 'named': {
43
+ // Check that all specifiers are named imports
44
+ const hasInvalidSpecifier = node.specifiers.some((spec) => spec.type === AST_NODE_TYPES.ImportNamespaceSpecifier ||
45
+ spec.type === AST_NODE_TYPES.ImportDefaultSpecifier);
46
+ if (hasInvalidSpecifier) {
47
+ context.report({
48
+ node,
49
+ messageId: 'namedImportRequired',
50
+ });
51
+ }
52
+ break;
53
+ }
54
+ case 'namespace': {
55
+ // namespace import mode (default)
56
+ const [firstSpecifier] = node.specifiers;
57
+ if (firstSpecifier === undefined ||
58
+ firstSpecifier.type !== AST_NODE_TYPES.ImportNamespaceSpecifier ||
59
+ node.specifiers.length !== 1) {
60
+ context.report({
61
+ node,
62
+ messageId: 'namespaceImportRequired',
63
+ });
64
+ return;
65
+ }
66
+ if (firstSpecifier.local.name !== 'React') {
67
+ context.report({
68
+ node: firstSpecifier.local,
69
+ messageId: 'namespaceNameMustBeReact',
70
+ });
71
+ }
72
+ break;
73
+ }
74
+ }
75
+ },
76
+ };
77
+ },
41
78
  defaultOptions: [],
42
79
  };
43
80
 
@@ -1 +1 @@
1
- {"version":3,"file":"import-style.mjs","sources":["../../../../src/plugins/react-coding-style/rules/import-style.mts"],"sourcesContent":[null],"names":[],"mappings":";;AAIA;AACA;AACA;AAEO,MAAM,eAAe,GAAoC;AAC9D,IAAA,IAAI,EAAE;AACJ,QAAA,IAAI,EAAE,YAAY;AAClB,QAAA,IAAI,EAAE;AACJ,YAAA,WAAW,EACT,wEAAwE;AAC3E,SAAA;AACD,QAAA,MAAM,EAAE,EAAE;AACV,QAAA,QAAQ,EAAE;AACR,YAAA,uBAAuB,EACrB,+DAA+D;AACjE,YAAA,wBAAwB,EACtB,2DAA2D;AAC9D,SAAA;AACF,KAAA;AACD,IAAA,MAAM,EAAE,CAAC,OAAO,MAAM;AACpB,QAAA,iBAAiB,EAAE,CAAC,IAAI,KAAI;YAC1B,IAAI,IAAI,CAAC,MAAM,CAAC,KAAK,KAAK,OAAO,EAAE;gBACjC;YACF;AAEA,YAAA,MAAM,CAAC,cAAc,CAAC,GAAG,IAAI,CAAC,UAAU;YAExC,IACE,cAAc,KAAK,SAAS;AAC5B,gBAAA,cAAc,CAAC,IAAI,KAAK,cAAc,CAAC,wBAAwB;AAC/D,gBAAA,IAAI,CAAC,UAAU,CAAC,MAAM,KAAK,CAAC,EAC5B;gBACA,OAAO,CAAC,MAAM,CAAC;oBACb,IAAI;AACJ,oBAAA,SAAS,EAAE,yBAAyB;AACrC,iBAAA,CAAC;gBAEF;YACF;YAEA,IAAI,cAAc,CAAC,KAAK,CAAC,IAAI,KAAK,OAAO,EAAE;gBACzC,OAAO,CAAC,MAAM,CAAC;oBACb,IAAI,EAAE,cAAc,CAAC,KAAK;AAC1B,oBAAA,SAAS,EAAE,0BAA0B;AACtC,iBAAA,CAAC;YACJ;QACF,CAAC;KACF,CAAC;AACF,IAAA,cAAc,EAAE,EAAE;;;;;"}
1
+ {"version":3,"file":"import-style.mjs","sources":["../../../../src/plugins/react-coding-style/rules/import-style.mts"],"sourcesContent":[null],"names":[],"mappings":";;AAeA;AACA;AACA;AACA;AACA;AAEO,MAAM,eAAe,GAA6C;AACvE,IAAA,IAAI,EAAE;AACJ,QAAA,IAAI,EAAE,YAAY;AAClB,QAAA,IAAI,EAAE;AACJ,YAAA,WAAW,EACT,8EAA8E;AACjF,SAAA;AACD,QAAA,MAAM,EAAE;AACN,YAAA;AACE,gBAAA,IAAI,EAAE,QAAQ;AACd,gBAAA,UAAU,EAAE;AACV,oBAAA,WAAW,EAAE;AACX,wBAAA,IAAI,EAAE,QAAQ;AACd,wBAAA,IAAI,EAAE,CAAC,WAAW,EAAE,OAAO,CAAC;AAC5B,wBAAA,WAAW,EACT,8FAA8F;AACjG,qBAAA;AACF,iBAAA;AACD,gBAAA,oBAAoB,EAAE,KAAK;AAC5B,aAAA;AACF,SAAA;AACD,QAAA,QAAQ,EAAE;AACR,YAAA,uBAAuB,EACrB,+DAA+D;AACjE,YAAA,wBAAwB,EACtB,2DAA2D;AAC7D,YAAA,mBAAmB,EACjB,oFAAoF;AACvF,SAAA;AACF,KAAA;AACD,IAAA,MAAM,EAAE,CAAC,OAAO,KAAI;QAClB,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,EAAE;AACxC,QAAA,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,IAAI,WAAW;QAEtD,OAAO;AACL,YAAA,iBAAiB,EAAE,CAAC,IAAI,KAAI;gBAC1B,IAAI,IAAI,CAAC,MAAM,CAAC,KAAK,KAAK,OAAO,EAAE;oBACjC;gBACF;gBAEA,QAAQ,WAAW;oBACjB,KAAK,OAAO,EAAE;;AAEZ,wBAAA,MAAM,mBAAmB,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,CAC9C,CAAC,IAAI,KACH,IAAI,CAAC,IAAI,KAAK,cAAc,CAAC,wBAAwB;AACrD,4BAAA,IAAI,CAAC,IAAI,KAAK,cAAc,CAAC,sBAAsB,CACtD;wBAED,IAAI,mBAAmB,EAAE;4BACvB,OAAO,CAAC,MAAM,CAAC;gCACb,IAAI;AACJ,gCAAA,SAAS,EAAE,qBAAqB;AACjC,6BAAA,CAAC;wBACJ;wBAEA;oBACF;oBAEA,KAAK,WAAW,EAAE;;AAEhB,wBAAA,MAAM,CAAC,cAAc,CAAC,GAAG,IAAI,CAAC,UAAU;wBAExC,IACE,cAAc,KAAK,SAAS;AAC5B,4BAAA,cAAc,CAAC,IAAI,KAAK,cAAc,CAAC,wBAAwB;AAC/D,4BAAA,IAAI,CAAC,UAAU,CAAC,MAAM,KAAK,CAAC,EAC5B;4BACA,OAAO,CAAC,MAAM,CAAC;gCACb,IAAI;AACJ,gCAAA,SAAS,EAAE,yBAAyB;AACrC,6BAAA,CAAC;4BAEF;wBACF;wBAEA,IAAI,cAAc,CAAC,KAAK,CAAC,IAAI,KAAK,OAAO,EAAE;4BACzC,OAAO,CAAC,MAAM,CAAC;gCACb,IAAI,EAAE,cAAc,CAAC,KAAK;AAC1B,gCAAA,SAAS,EAAE,0BAA0B;AACtC,6BAAA,CAAC;wBACJ;wBAEA;oBACF;;YAEJ,CAAC;SACF;IACH,CAAC;AACD,IAAA,cAAc,EAAE,EAAE;;;;;"}
@@ -1,6 +1,6 @@
1
1
  import { AST_NODE_TYPES } from '@typescript-eslint/utils';
2
2
  import { castDeepMutable } from 'ts-data-forge';
3
- import { isReactCallExpression, getReactMemoArrowFunction } from './shared.mjs';
3
+ import { isReactApiCall, getReactMemoArrowFunction } from './shared.mjs';
4
4
 
5
5
  // 前提: Arrow function の使用が強制されていること。
6
6
  const propsTypeAnnotationStyleRule = {
@@ -16,7 +16,7 @@ const propsTypeAnnotationStyleRule = {
16
16
  },
17
17
  create: (context) => ({
18
18
  CallExpression: (node) => {
19
- if (!isReactCallExpression(node, 'memo')) {
19
+ if (!isReactApiCall(context, node, 'memo')) {
20
20
  return;
21
21
  }
22
22
  const arrowFunction = getReactMemoArrowFunction(node);
@@ -1 +1 @@
1
- {"version":3,"file":"props-type-annotation-style.mjs","sources":["../../../../src/plugins/react-coding-style/rules/props-type-annotation-style.mts"],"sourcesContent":[null],"names":[],"mappings":";;;;AAUA;AAEO,MAAM,4BAA4B,GAAoC;AAC3E,IAAA,IAAI,EAAE;AACJ,QAAA,IAAI,EAAE,YAAY;AAClB,QAAA,IAAI,EAAE;AACJ,YAAA,WAAW,EACT,+EAA+E;AAClF,SAAA;AACD,QAAA,MAAM,EAAE,EAAE;AACV,QAAA,QAAQ,EAAE;AACR,YAAA,2BAA2B,EACzB,+FAA+F;AAClG,SAAA;AACF,KAAA;AACD,IAAA,MAAM,EAAE,CAAC,OAAO,MAAM;AACpB,QAAA,cAAc,EAAE,CAAC,IAA2C,KAAI;YAC9D,IAAI,CAAC,qBAAqB,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE;gBACxC;YACF;AAEA,YAAA,MAAM,aAAa,GAAG,yBAAyB,CAAC,IAAI,CAAC;YAErD,IACE,aAAa,KAAK,SAAS;gBAC3B,aAAa,CAAC,IAAI,CAAC,IAAI,KAAK,cAAc,CAAC,cAAc,EACzD;gBACA;YACF;AAEA,YAAA,MAAM,CAAC,UAAU,CAAC,GAAG,aAAa,CAAC,MAAM;YAEzC,IACE,UAAU,KAAK,SAAS;AACxB,gBAAA,UAAU,CAAC,IAAI,KAAK,cAAc,CAAC,UAAU,EAC7C;gBACA;YACF;AAEA,YAAA,IAAI,UAAU,CAAC,cAAc,KAAK,SAAS,EAAE;gBAC3C,OAAO,CAAC,MAAM,CAAC;AACb,oBAAA,IAAI,EAAE,eAAe,CAAC,UAAU,CAAC,cAAc,CAAC;AAChD,oBAAA,SAAS,EAAE,6BAA6B;AACzC,iBAAA,CAAC;YACJ;QACF,CAAC;KACF,CAAC;AACF,IAAA,cAAc,EAAE,EAAE;;;;;"}
1
+ {"version":3,"file":"props-type-annotation-style.mjs","sources":["../../../../src/plugins/react-coding-style/rules/props-type-annotation-style.mts"],"sourcesContent":[null],"names":[],"mappings":";;;;AAUA;AAEO,MAAM,4BAA4B,GAAoC;AAC3E,IAAA,IAAI,EAAE;AACJ,QAAA,IAAI,EAAE,YAAY;AAClB,QAAA,IAAI,EAAE;AACJ,YAAA,WAAW,EACT,+EAA+E;AAClF,SAAA;AACD,QAAA,MAAM,EAAE,EAAE;AACV,QAAA,QAAQ,EAAE;AACR,YAAA,2BAA2B,EACzB,+FAA+F;AAClG,SAAA;AACF,KAAA;AACD,IAAA,MAAM,EAAE,CAAC,OAAO,MAAM;AACpB,QAAA,cAAc,EAAE,CAAC,IAA2C,KAAI;YAC9D,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE,IAAI,EAAE,MAAM,CAAC,EAAE;gBAC1C;YACF;AAEA,YAAA,MAAM,aAAa,GAAG,yBAAyB,CAAC,IAAI,CAAC;YAErD,IACE,aAAa,KAAK,SAAS;gBAC3B,aAAa,CAAC,IAAI,CAAC,IAAI,KAAK,cAAc,CAAC,cAAc,EACzD;gBACA;YACF;AAEA,YAAA,MAAM,CAAC,UAAU,CAAC,GAAG,aAAa,CAAC,MAAM;YAEzC,IACE,UAAU,KAAK,SAAS;AACxB,gBAAA,UAAU,CAAC,IAAI,KAAK,cAAc,CAAC,UAAU,EAC7C;gBACA;YACF;AAEA,YAAA,IAAI,UAAU,CAAC,cAAc,KAAK,SAAS,EAAE;gBAC3C,OAAO,CAAC,MAAM,CAAC;AACb,oBAAA,IAAI,EAAE,eAAe,CAAC,UAAU,CAAC,cAAc,CAAC;AAChD,oBAAA,SAAS,EAAE,6BAA6B;AACzC,iBAAA,CAAC;YACJ;QACF,CAAC;KACF,CAAC;AACF,IAAA,cAAc,EAAE,EAAE;;;;;"}
@@ -1,6 +1,6 @@
1
1
  import { AST_NODE_TYPES } from '@typescript-eslint/utils';
2
2
  import { castDeepMutable } from 'ts-data-forge';
3
- import { isReactCallExpression, getReactMemoArrowFunction } from './shared.mjs';
3
+ import { isReactApiCall, getReactMemoArrowFunction } from './shared.mjs';
4
4
 
5
5
  // NOTE: component props を "props" という名前に限定する。
6
6
  // return 文を含む component の props を "props" という名前の変数に限定する。
@@ -19,7 +19,7 @@ const reactMemoPropsArgumentNameRule = {
19
19
  },
20
20
  create: (context) => ({
21
21
  CallExpression: (node) => {
22
- if (!isReactCallExpression(node, 'memo')) {
22
+ if (!isReactApiCall(context, node, 'memo')) {
23
23
  return;
24
24
  }
25
25
  const arrowFunction = getReactMemoArrowFunction(node);
@@ -1 +1 @@
1
- {"version":3,"file":"react-memo-props-argument-name.mjs","sources":["../../../../src/plugins/react-coding-style/rules/react-memo-props-argument-name.mts"],"sourcesContent":[null],"names":[],"mappings":";;;;AAUA;AACA;AACA;AAEO,MAAM,8BAA8B,GAAoC;AAC7E,IAAA,IAAI,EAAE;AACJ,QAAA,IAAI,EAAE,YAAY;AAClB,QAAA,IAAI,EAAE;AACJ,YAAA,WAAW,EACT,0FAA0F;AAC7F,SAAA;AACD,QAAA,MAAM,EAAE,EAAE;AACV,QAAA,QAAQ,EAAE;AACR,YAAA,0BAA0B,EACxB,iFAAiF;AACnF,YAAA,0BAA0B,EACxB,iGAAiG;AACpG,SAAA;AACF,KAAA;AACD,IAAA,MAAM,EAAE,CAAC,OAAO,MAAM;AACpB,QAAA,cAAc,EAAE,CAAC,IAA2C,KAAI;YAC9D,IAAI,CAAC,qBAAqB,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE;gBACxC;YACF;AAEA,YAAA,MAAM,aAAa,GAAG,yBAAyB,CAAC,IAAI,CAAC;;YAGrD,IACE,aAAa,KAAK,SAAS;gBAC3B,aAAa,CAAC,IAAI,CAAC,IAAI,KAAK,cAAc,CAAC,cAAc,EACzD;gBACA;YACF;AAEA,YAAA,MAAM,CAAC,UAAU,CAAC,GAAG,aAAa,CAAC,MAAM;AAEzC,YAAA,IAAI,UAAU,KAAK,SAAS,EAAE;gBAC5B;YACF;YAEA,IAAI,UAAU,CAAC,IAAI,KAAK,cAAc,CAAC,UAAU,EAAE;;AAEjD,gBAAA,IAAI,UAAU,CAAC,IAAI,KAAK,OAAO,EAAE;oBAC/B,OAAO,CAAC,MAAM,CAAC;AACb,wBAAA,IAAI,EAAE,eAAe,CAAC,UAAU,CAAC;AACjC,wBAAA,SAAS,EAAE,4BAA4B;AACxC,qBAAA,CAAC;gBACJ;gBAEA;YACF;YAEA,OAAO,CAAC,MAAM,CAAC;AACb,gBAAA,IAAI,EAAE,eAAe,CAAC,UAAU,CAAC;AACjC,gBAAA,SAAS,EAAE,4BAA4B;AACxC,aAAA,CAAC;QACJ,CAAC;KACF,CAAC;AACF,IAAA,cAAc,EAAE,EAAE;;;;;"}
1
+ {"version":3,"file":"react-memo-props-argument-name.mjs","sources":["../../../../src/plugins/react-coding-style/rules/react-memo-props-argument-name.mts"],"sourcesContent":[null],"names":[],"mappings":";;;;AAUA;AACA;AACA;AAEO,MAAM,8BAA8B,GAAoC;AAC7E,IAAA,IAAI,EAAE;AACJ,QAAA,IAAI,EAAE,YAAY;AAClB,QAAA,IAAI,EAAE;AACJ,YAAA,WAAW,EACT,0FAA0F;AAC7F,SAAA;AACD,QAAA,MAAM,EAAE,EAAE;AACV,QAAA,QAAQ,EAAE;AACR,YAAA,0BAA0B,EACxB,iFAAiF;AACnF,YAAA,0BAA0B,EACxB,iGAAiG;AACpG,SAAA;AACF,KAAA;AACD,IAAA,MAAM,EAAE,CAAC,OAAO,MAAM;AACpB,QAAA,cAAc,EAAE,CAAC,IAA2C,KAAI;YAC9D,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE,IAAI,EAAE,MAAM,CAAC,EAAE;gBAC1C;YACF;AAEA,YAAA,MAAM,aAAa,GAAG,yBAAyB,CAAC,IAAI,CAAC;;YAGrD,IACE,aAAa,KAAK,SAAS;gBAC3B,aAAa,CAAC,IAAI,CAAC,IAAI,KAAK,cAAc,CAAC,cAAc,EACzD;gBACA;YACF;AAEA,YAAA,MAAM,CAAC,UAAU,CAAC,GAAG,aAAa,CAAC,MAAM;AAEzC,YAAA,IAAI,UAAU,KAAK,SAAS,EAAE;gBAC5B;YACF;YAEA,IAAI,UAAU,CAAC,IAAI,KAAK,cAAc,CAAC,UAAU,EAAE;;AAEjD,gBAAA,IAAI,UAAU,CAAC,IAAI,KAAK,OAAO,EAAE;oBAC/B,OAAO,CAAC,MAAM,CAAC;AACb,wBAAA,IAAI,EAAE,eAAe,CAAC,UAAU,CAAC;AACjC,wBAAA,SAAS,EAAE,4BAA4B;AACxC,qBAAA,CAAC;gBACJ;gBAEA;YACF;YAEA,OAAO,CAAC,MAAM,CAAC;AACb,gBAAA,IAAI,EAAE,eAAe,CAAC,UAAU,CAAC;AACjC,gBAAA,SAAS,EAAE,4BAA4B;AACxC,aAAA,CAAC;QACJ,CAAC;KACF,CAAC;AACF,IAAA,cAAc,EAAE,EAAE;;;;;"}
@@ -1,6 +1,6 @@
1
1
  import { AST_NODE_TYPES } from '@typescript-eslint/utils';
2
2
  import { castDeepMutable } from 'ts-data-forge';
3
- import { isReactCallExpression, getReactMemoArrowFunction } from './shared.mjs';
3
+ import { isReactApiCall, getReactMemoArrowFunction } from './shared.mjs';
4
4
 
5
5
  // NOTE: React.memo の型引数を `Props` に限定する。
6
6
  // これは 1ファイル1コンポーネントの強制も意味する。
@@ -19,7 +19,7 @@ const reactMemoTypeParameterRule = {
19
19
  },
20
20
  create: (context) => ({
21
21
  CallExpression: (node) => {
22
- if (!isReactCallExpression(node, 'memo')) {
22
+ if (!isReactApiCall(context, node, 'memo')) {
23
23
  return;
24
24
  }
25
25
  const arrowFunction = getReactMemoArrowFunction(node);
@@ -1 +1 @@
1
- {"version":3,"file":"react-memo-type-parameter.mjs","sources":["../../../../src/plugins/react-coding-style/rules/react-memo-type-parameter.mts"],"sourcesContent":[null],"names":[],"mappings":";;;;AAYA;AACA;AACA;AAEO,MAAM,0BAA0B,GAAoC;AACzE,IAAA,IAAI,EAAE;AACJ,QAAA,IAAI,EAAE,YAAY;AAClB,QAAA,IAAI,EAAE;AACJ,YAAA,WAAW,EACT,+DAA+D;AAClE,SAAA;AACD,QAAA,MAAM,EAAE,EAAE;AACV,QAAA,QAAQ,EAAE;AACR,YAAA,yBAAyB,EACvB,gDAAgD;AAClD,YAAA,+BAA+B,EAC7B,qFAAqF;AACxF,SAAA;AACF,KAAA;AACD,IAAA,MAAM,EAAE,CAAC,OAAO,MAAM;AACpB,QAAA,cAAc,EAAE,CAAC,IAA2C,KAAI;YAC9D,IAAI,CAAC,qBAAqB,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE;gBACxC;YACF;AAEA,YAAA,MAAM,aAAa,GAAG,yBAAyB,CAAC,IAAI,CAAC;AACrD,YAAA,MAAM,aAAa,GAAG,IAAI,CAAC,aAAa;;AAGxC,YAAA,IAAI,aAAa,KAAK,SAAS,EAAE;gBAC/B,IAAI,aAAa,EAAE,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE;oBACtC;gBACF;gBAEA,OAAO,CAAC,MAAM,CAAC;AACb,oBAAA,IAAI,EAAE,eAAe,CAAC,IAAI,CAAC,MAAM,CAAC;AAClC,oBAAA,SAAS,EAAE,2BAA2B;AACvC,iBAAA,CAAC;gBAEF;YACF;YAEA,IAAI,aAAa,EAAE,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE;gBACtC,OAAO,CAAC,MAAM,CAAC;AACb,oBAAA,IAAI,EAAE,eAAe,CAAC,aAAa,CAAC;AACpC,oBAAA,SAAS,EAAE,iCAAiC;AAC7C,iBAAA,CAAC;gBAEF;YACF;YAEA,IAAI,aAAa,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE;gBACrC,OAAO,CAAC,MAAM,CAAC;AACb,oBAAA,IAAI,EAAE,eAAe,CAAC,aAAa,CAAC;AACpC,oBAAA,SAAS,EAAE,2BAA2B;AACvC,iBAAA,CAAC;gBAEF;YACF;AAEA,YAAA,MAAM,CAAC,cAAc,CAAC,GAAG,aAAa,CAAC,MAAM;AAE7C,YAAA,IAAI,CAAC,oBAAoB,CAAC,cAAc,CAAC,EAAE;AACzC,gBAAA,MAAM,YAAY,GAAG,cAAc,IAAI,IAAI,CAAC,MAAM;gBAElD,OAAO,CAAC,MAAM,CAAC;AACb,oBAAA,IAAI,EAAE,eAAe,CAAC,YAAY,CAAC;AACnC,oBAAA,SAAS,EAAE,2BAA2B;AACvC,iBAAA,CAAC;YACJ;QACF,CAAC;KACF,CAAC;AACF,IAAA,cAAc,EAAE,EAAE;;AAGpB,MAAM,oBAAoB,GAAG,CAC3B,IAAiD,KACtC;AACX,IAAA,IAAI,IAAI,KAAK,SAAS,EAAE;AACtB,QAAA,OAAO,KAAK;IACd;;IAGA,IAAI,IAAI,CAAC,IAAI,KAAK,cAAc,CAAC,eAAe,EAAE;AAChD,QAAA,OAAO,KAAK;IACd;AAEA,IAAA,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ;;AAG9B,IAAA,QACE,QAAQ,CAAC,IAAI,KAAK,cAAc,CAAC,UAAU,IAAI,QAAQ,CAAC,IAAI,KAAK,OAAO;AAE5E,CAAC;;;;"}
1
+ {"version":3,"file":"react-memo-type-parameter.mjs","sources":["../../../../src/plugins/react-coding-style/rules/react-memo-type-parameter.mts"],"sourcesContent":[null],"names":[],"mappings":";;;;AAYA;AACA;AACA;AAEO,MAAM,0BAA0B,GAAoC;AACzE,IAAA,IAAI,EAAE;AACJ,QAAA,IAAI,EAAE,YAAY;AAClB,QAAA,IAAI,EAAE;AACJ,YAAA,WAAW,EACT,+DAA+D;AAClE,SAAA;AACD,QAAA,MAAM,EAAE,EAAE;AACV,QAAA,QAAQ,EAAE;AACR,YAAA,yBAAyB,EACvB,gDAAgD;AAClD,YAAA,+BAA+B,EAC7B,qFAAqF;AACxF,SAAA;AACF,KAAA;AACD,IAAA,MAAM,EAAE,CAAC,OAAO,MAAM;AACpB,QAAA,cAAc,EAAE,CAAC,IAA2C,KAAI;YAC9D,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE,IAAI,EAAE,MAAM,CAAC,EAAE;gBAC1C;YACF;AAEA,YAAA,MAAM,aAAa,GAAG,yBAAyB,CAAC,IAAI,CAAC;AACrD,YAAA,MAAM,aAAa,GAAG,IAAI,CAAC,aAAa;;AAGxC,YAAA,IAAI,aAAa,KAAK,SAAS,EAAE;gBAC/B,IAAI,aAAa,EAAE,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE;oBACtC;gBACF;gBAEA,OAAO,CAAC,MAAM,CAAC;AACb,oBAAA,IAAI,EAAE,eAAe,CAAC,IAAI,CAAC,MAAM,CAAC;AAClC,oBAAA,SAAS,EAAE,2BAA2B;AACvC,iBAAA,CAAC;gBAEF;YACF;YAEA,IAAI,aAAa,EAAE,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE;gBACtC,OAAO,CAAC,MAAM,CAAC;AACb,oBAAA,IAAI,EAAE,eAAe,CAAC,aAAa,CAAC;AACpC,oBAAA,SAAS,EAAE,iCAAiC;AAC7C,iBAAA,CAAC;gBAEF;YACF;YAEA,IAAI,aAAa,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE;gBACrC,OAAO,CAAC,MAAM,CAAC;AACb,oBAAA,IAAI,EAAE,eAAe,CAAC,aAAa,CAAC;AACpC,oBAAA,SAAS,EAAE,2BAA2B;AACvC,iBAAA,CAAC;gBAEF;YACF;AAEA,YAAA,MAAM,CAAC,cAAc,CAAC,GAAG,aAAa,CAAC,MAAM;AAE7C,YAAA,IAAI,CAAC,oBAAoB,CAAC,cAAc,CAAC,EAAE;AACzC,gBAAA,MAAM,YAAY,GAAG,cAAc,IAAI,IAAI,CAAC,MAAM;gBAElD,OAAO,CAAC,MAAM,CAAC;AACb,oBAAA,IAAI,EAAE,eAAe,CAAC,YAAY,CAAC;AACnC,oBAAA,SAAS,EAAE,2BAA2B;AACvC,iBAAA,CAAC;YACJ;QACF,CAAC;KACF,CAAC;AACF,IAAA,cAAc,EAAE,EAAE;;AAGpB,MAAM,oBAAoB,GAAG,CAC3B,IAAiD,KACtC;AACX,IAAA,IAAI,IAAI,KAAK,SAAS,EAAE;AACtB,QAAA,OAAO,KAAK;IACd;;IAGA,IAAI,IAAI,CAAC,IAAI,KAAK,cAAc,CAAC,eAAe,EAAE;AAChD,QAAA,OAAO,KAAK;IACd;AAEA,IAAA,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ;;AAG9B,IAAA,QACE,QAAQ,CAAC,IAAI,KAAK,cAAc,CAAC,UAAU,IAAI,QAAQ,CAAC,IAAI,KAAK,OAAO;AAE5E,CAAC;;;;"}
@@ -4,11 +4,16 @@ export declare const reactCodingStyleRules: {
4
4
  pattern?: RegExp;
5
5
  }>], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
6
6
  readonly 'component-var-type-annotation': import("@typescript-eslint/utils/ts-eslint").RuleModule<"disallowReactFunctionalComponentTypes", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
7
- readonly 'import-style': import("@typescript-eslint/utils/ts-eslint").RuleModule<"namespaceImportRequired" | "namespaceNameMustBeReact", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
7
+ readonly 'import-style': import("@typescript-eslint/utils/ts-eslint").RuleModule<"namespaceImportRequired" | "namespaceNameMustBeReact" | "namedImportRequired", readonly [(Readonly<{
8
+ importStyle?: "named" | "namespace";
9
+ }> | undefined)?], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
8
10
  readonly 'props-type-annotation-style': import("@typescript-eslint/utils/ts-eslint").RuleModule<"disallowPropsTypeAnnotation", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
9
11
  readonly 'react-memo-props-argument-name': import("@typescript-eslint/utils/ts-eslint").RuleModule<"propsParamMustBeNamedProps" | "propsParamMustBeIdentifier", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
10
12
  readonly 'react-memo-type-parameter': import("@typescript-eslint/utils/ts-eslint").RuleModule<"requirePropsTypeParameter" | "omitTypeParameterWhenPropsEmpty", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
11
13
  readonly 'use-memo-hook-style': import("@typescript-eslint/utils/ts-eslint").RuleModule<"disallowUseMemoTypeAnnotation", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
12
14
  readonly 'ban-use-imperative-handle-hook': import("@typescript-eslint/utils/ts-eslint").RuleModule<"disallowUseImperativeHandle", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
15
+ readonly 'display-name': import("@typescript-eslint/utils/ts-eslint").RuleModule<"missingDisplayName", readonly [(Readonly<{
16
+ ignoreTranspilerName?: boolean;
17
+ }> | undefined)?], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
13
18
  };
14
19
  //# sourceMappingURL=rules.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"rules.d.mts","sourceRoot":"","sources":["../../../../src/plugins/react-coding-style/rules/rules.mts"],"names":[],"mappings":"AAUA,eAAO,MAAM,qBAAqB;;;;;;;;;;;;CASQ,CAAC"}
1
+ {"version":3,"file":"rules.d.mts","sourceRoot":"","sources":["../../../../src/plugins/react-coding-style/rules/rules.mts"],"names":[],"mappings":"AAWA,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;CAUQ,CAAC"}
@@ -1,6 +1,7 @@
1
1
  import { banUseImperativeHandleHook } from './ban-use-imperative-handle-hook.mjs';
2
2
  import { componentNameRule } from './component-name.mjs';
3
3
  import { componentVarTypeAnnotationRule } from './component-var-type-annotation.mjs';
4
+ import { displayNameRule } from './display-name.mjs';
4
5
  import { importStyleRule } from './import-style.mjs';
5
6
  import { propsTypeAnnotationStyleRule } from './props-type-annotation-style.mjs';
6
7
  import { reactMemoPropsArgumentNameRule } from './react-memo-props-argument-name.mjs';
@@ -16,6 +17,7 @@ const reactCodingStyleRules = {
16
17
  'react-memo-type-parameter': reactMemoTypeParameterRule,
17
18
  'use-memo-hook-style': useMemoHooksStyleRule,
18
19
  'ban-use-imperative-handle-hook': banUseImperativeHandleHook,
20
+ 'display-name': displayNameRule,
19
21
  };
20
22
 
21
23
  export { reactCodingStyleRules };
@@ -1 +1 @@
1
- {"version":3,"file":"rules.mjs","sources":["../../../../src/plugins/react-coding-style/rules/rules.mts"],"sourcesContent":[null],"names":[],"mappings":";;;;;;;;;AAUO,MAAM,qBAAqB,GAAG;AACnC,IAAA,gBAAgB,EAAE,iBAAiB;AACnC,IAAA,+BAA+B,EAAE,8BAA8B;AAC/D,IAAA,cAAc,EAAE,eAAe;AAC/B,IAAA,6BAA6B,EAAE,4BAA4B;AAC3D,IAAA,gCAAgC,EAAE,8BAA8B;AAChE,IAAA,2BAA2B,EAAE,0BAA0B;AACvD,IAAA,qBAAqB,EAAE,qBAAqB;AAC5C,IAAA,gCAAgC,EAAE,0BAA0B;;;;;"}
1
+ {"version":3,"file":"rules.mjs","sources":["../../../../src/plugins/react-coding-style/rules/rules.mts"],"sourcesContent":[null],"names":[],"mappings":";;;;;;;;;;AAWO,MAAM,qBAAqB,GAAG;AACnC,IAAA,gBAAgB,EAAE,iBAAiB;AACnC,IAAA,+BAA+B,EAAE,8BAA8B;AAC/D,IAAA,cAAc,EAAE,eAAe;AAC/B,IAAA,6BAA6B,EAAE,4BAA4B;AAC3D,IAAA,gCAAgC,EAAE,8BAA8B;AAChE,IAAA,2BAA2B,EAAE,0BAA0B;AACvD,IAAA,qBAAqB,EAAE,qBAAqB;AAC5C,IAAA,gCAAgC,EAAE,0BAA0B;AAC5D,IAAA,cAAc,EAAE,eAAe;;;;;"}
@@ -1,5 +1,9 @@
1
- import { type TSESTree } from '@typescript-eslint/utils';
2
- export declare const isReactMemberExpression: (node: DeepReadonly<TSESTree.MemberExpression>, propertyName: string) => boolean;
3
- export declare const isReactCallExpression: (node: DeepReadonly<TSESTree.CallExpression>, propertyName: string) => boolean;
1
+ import { type TSESLint, type TSESTree } from '@typescript-eslint/utils';
2
+ /**
3
+ * Check if the given CallExpression is a React API call.
4
+ * Supports both namespace imports (React.memo) and named imports (memo).
5
+ * Verifies that the identifier is actually imported from "react".
6
+ */
7
+ export declare const isReactApiCall: (context: DeepReadonly<TSESLint.RuleContext<string, readonly unknown[]>>, node: DeepReadonly<TSESTree.CallExpression>, apiName: string) => boolean;
4
8
  export declare const getReactMemoArrowFunction: (node: DeepReadonly<TSESTree.CallExpression>) => DeepReadonly<TSESTree.ArrowFunctionExpression> | undefined;
5
9
  //# sourceMappingURL=shared.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"shared.d.mts","sourceRoot":"","sources":["../../../../src/plugins/react-coding-style/rules/shared.mts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,KAAK,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAEzE,eAAO,MAAM,uBAAuB,GAClC,MAAM,YAAY,CAAC,QAAQ,CAAC,gBAAgB,CAAC,EAC7C,cAAc,MAAM,KACnB,OAKa,CAAC;AAEjB,eAAO,MAAM,qBAAqB,GAChC,MAAM,YAAY,CAAC,QAAQ,CAAC,cAAc,CAAC,EAC3C,cAAc,MAAM,KACnB,OAEiD,CAAC;AAErD,eAAO,MAAM,yBAAyB,GACpC,MAAM,YAAY,CAAC,QAAQ,CAAC,cAAc,CAAC,KAC1C,YAAY,CAAC,QAAQ,CAAC,uBAAuB,CAAC,GAAG,SAYnD,CAAC"}
1
+ {"version":3,"file":"shared.d.mts","sourceRoot":"","sources":["../../../../src/plugins/react-coding-style/rules/shared.mts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,QAAQ,EACb,KAAK,QAAQ,EACd,MAAM,0BAA0B,CAAC;AAuElC;;;;GAIG;AACH,eAAO,MAAM,cAAc,GACzB,SAAS,YAAY,CAAC,QAAQ,CAAC,WAAW,CAAC,MAAM,EAAE,SAAS,OAAO,EAAE,CAAC,CAAC,EACvE,MAAM,YAAY,CAAC,QAAQ,CAAC,cAAc,CAAC,EAC3C,SAAS,MAAM,KACd,OAkBF,CAAC;AAEF,eAAO,MAAM,yBAAyB,GACpC,MAAM,YAAY,CAAC,QAAQ,CAAC,cAAc,CAAC,KAC1C,YAAY,CAAC,QAAQ,CAAC,uBAAuB,CAAC,GAAG,SAYnD,CAAC"}
@@ -5,8 +5,66 @@ const isReactMemberExpression = (node, propertyName) => node.object.type === AST
5
5
  node.property.type === AST_NODE_TYPES.Identifier &&
6
6
  node.property.name === propertyName &&
7
7
  !node.computed;
8
- const isReactCallExpression = (node, propertyName) => node.callee.type === AST_NODE_TYPES.MemberExpression &&
9
- isReactMemberExpression(node.callee, propertyName);
8
+ /**
9
+ * Check if the given identifier is imported from "react"
10
+ */
11
+ const isImportedFromReact = (context, identifierName) => {
12
+ const sourceCode = context.sourceCode;
13
+ // Get the global scope to search for imports
14
+ const globalScope = sourceCode.scopeManager?.globalScope ?? undefined;
15
+ if (globalScope === undefined) {
16
+ // If no scope manager, assume it's React (for backward compatibility)
17
+ return true;
18
+ }
19
+ // Search through all scopes for the variable
20
+ const scopes = [globalScope, ...globalScope.childScopes];
21
+ const variables = scopes
22
+ .map((scope) => scope.set.get(identifierName))
23
+ .filter((v) => v !== undefined);
24
+ if (variables.length === 0) {
25
+ // If variable is not found in any scope, assume it's a global (React)
26
+ // This handles cases where React is used without explicit import
27
+ return true;
28
+ }
29
+ // Check if any variable is imported from 'react'
30
+ for (const variable of variables) {
31
+ for (const def of variable.defs) {
32
+ // Type narrowing: def.type is a string literal type, not enum
33
+ if (Object.hasOwn(def, 'type') &&
34
+ typeof def.type === 'string' &&
35
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-enum-comparison
36
+ def.type === 'ImportBinding') {
37
+ const importDeclaration = def.parent;
38
+ if (importDeclaration.type === AST_NODE_TYPES.ImportDeclaration &&
39
+ importDeclaration.source.value === 'react') {
40
+ return true;
41
+ }
42
+ // Found an import, but not from 'react'
43
+ return false;
44
+ }
45
+ }
46
+ }
47
+ // Variable was found but not as an import, it's a local definition
48
+ return false;
49
+ };
50
+ /**
51
+ * Check if the given CallExpression is a React API call.
52
+ * Supports both namespace imports (React.memo) and named imports (memo).
53
+ * Verifies that the identifier is actually imported from "react".
54
+ */
55
+ const isReactApiCall = (context, node, apiName) => {
56
+ // Check for named import: memo(...)
57
+ if (node.callee.type === AST_NODE_TYPES.Identifier &&
58
+ node.callee.name === apiName) {
59
+ return isImportedFromReact(context, apiName);
60
+ }
61
+ // Check for namespace import: React.memo(...)
62
+ if (node.callee.type === AST_NODE_TYPES.MemberExpression &&
63
+ isReactMemberExpression(node.callee, apiName)) {
64
+ return isImportedFromReact(context, 'React');
65
+ }
66
+ return false;
67
+ };
10
68
  const getReactMemoArrowFunction = (node) => {
11
69
  const [firstArgument] = node.arguments;
12
70
  if (firstArgument === undefined) {
@@ -18,5 +76,5 @@ const getReactMemoArrowFunction = (node) => {
18
76
  return firstArgument;
19
77
  };
20
78
 
21
- export { getReactMemoArrowFunction, isReactCallExpression, isReactMemberExpression };
79
+ export { getReactMemoArrowFunction, isReactApiCall };
22
80
  //# sourceMappingURL=shared.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"shared.mjs","sources":["../../../../src/plugins/react-coding-style/rules/shared.mts"],"sourcesContent":[null],"names":[],"mappings":";;AAEO,MAAM,uBAAuB,GAAG,CACrC,IAA6C,EAC7C,YAAoB,KAEpB,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,cAAc,CAAC,UAAU;AAC9C,IAAA,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,OAAO;AAC5B,IAAA,IAAI,CAAC,QAAQ,CAAC,IAAI,KAAK,cAAc,CAAC,UAAU;AAChD,IAAA,IAAI,CAAC,QAAQ,CAAC,IAAI,KAAK,YAAY;IACnC,CAAC,IAAI,CAAC;AAED,MAAM,qBAAqB,GAAG,CACnC,IAA2C,EAC3C,YAAoB,KAEpB,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,cAAc,CAAC,gBAAgB;AACpD,IAAA,uBAAuB,CAAC,IAAI,CAAC,MAAM,EAAE,YAAY;AAE5C,MAAM,yBAAyB,GAAG,CACvC,IAA2C,KACmB;AAC9D,IAAA,MAAM,CAAC,aAAa,CAAC,GAAG,IAAI,CAAC,SAAS;AAEtC,IAAA,IAAI,aAAa,KAAK,SAAS,EAAE;AAC/B,QAAA,OAAO,SAAS;IAClB;IAEA,IAAI,aAAa,CAAC,IAAI,KAAK,cAAc,CAAC,uBAAuB,EAAE;AACjE,QAAA,OAAO,SAAS;IAClB;AAEA,IAAA,OAAO,aAAa;AACtB;;;;"}
1
+ {"version":3,"file":"shared.mjs","sources":["../../../../src/plugins/react-coding-style/rules/shared.mts"],"sourcesContent":[null],"names":[],"mappings":";;AAMA,MAAM,uBAAuB,GAAG,CAC9B,IAA6C,EAC7C,YAAoB,KAEpB,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,cAAc,CAAC,UAAU;AAC9C,IAAA,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,OAAO;AAC5B,IAAA,IAAI,CAAC,QAAQ,CAAC,IAAI,KAAK,cAAc,CAAC,UAAU;AAChD,IAAA,IAAI,CAAC,QAAQ,CAAC,IAAI,KAAK,YAAY;IACnC,CAAC,IAAI,CAAC,QAAQ;AAEhB;;AAEG;AACH,MAAM,mBAAmB,GAAG,CAC1B,OAAuE,EACvE,cAAsB,KACX;AACX,IAAA,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU;;IAGrC,MAAM,WAAW,GAAG,UAAU,CAAC,YAAY,EAAE,WAAW,IAAI,SAAS;AAErE,IAAA,IAAI,WAAW,KAAK,SAAS,EAAE;;AAE7B,QAAA,OAAO,IAAI;IACb;;IAGA,MAAM,MAAM,GAAG,CAAC,WAAW,EAAE,GAAG,WAAW,CAAC,WAAW,CAAC;IAExD,MAAM,SAAS,GAAG;AACf,SAAA,GAAG,CAAC,CAAC,KAAK,KAAK,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,cAAc,CAAC;SAC5C,MAAM,CAAC,CAAC,CAAC,KAAiC,CAAC,KAAK,SAAS,CAAC;AAE7D,IAAA,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE;;;AAG1B,QAAA,OAAO,IAAI;IACb;;AAGA,IAAA,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE;AAChC,QAAA,KAAK,MAAM,GAAG,IAAI,QAAQ,CAAC,IAAI,EAAE;;AAE/B,YAAA,IACE,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC;AAC1B,gBAAA,OAAO,GAAG,CAAC,IAAI,KAAK,QAAQ;;AAE5B,gBAAA,GAAG,CAAC,IAAI,KAAK,eAAe,EAC5B;AACA,gBAAA,MAAM,iBAAiB,GAAG,GAAG,CAAC,MAAM;AAEpC,gBAAA,IACE,iBAAiB,CAAC,IAAI,KAAK,cAAc,CAAC,iBAAiB;AAC3D,oBAAA,iBAAiB,CAAC,MAAM,CAAC,KAAK,KAAK,OAAO,EAC1C;AACA,oBAAA,OAAO,IAAI;gBACb;;AAGA,gBAAA,OAAO,KAAK;YACd;QACF;IACF;;AAGA,IAAA,OAAO,KAAK;AACd,CAAC;AAED;;;;AAIG;AACI,MAAM,cAAc,GAAG,CAC5B,OAAuE,EACvE,IAA2C,EAC3C,OAAe,KACJ;;IAEX,IACE,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,cAAc,CAAC,UAAU;AAC9C,QAAA,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,OAAO,EAC5B;AACA,QAAA,OAAO,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC;IAC9C;;IAGA,IACE,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,cAAc,CAAC,gBAAgB;QACpD,uBAAuB,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7C;AACA,QAAA,OAAO,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC;IAC9C;AAEA,IAAA,OAAO,KAAK;AACd;AAEO,MAAM,yBAAyB,GAAG,CACvC,IAA2C,KACmB;AAC9D,IAAA,MAAM,CAAC,aAAa,CAAC,GAAG,IAAI,CAAC,SAAS;AAEtC,IAAA,IAAI,aAAa,KAAK,SAAS,EAAE;AAC/B,QAAA,OAAO,SAAS;IAClB;IAEA,IAAI,aAAa,CAAC,IAAI,KAAK,cAAc,CAAC,uBAAuB,EAAE;AACjE,QAAA,OAAO,SAAS;IAClB;AAEA,IAAA,OAAO,aAAa;AACtB;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"use-memo-hooks-style.d.mts","sourceRoot":"","sources":["../../../../src/plugins/react-coding-style/rules/use-memo-hooks-style.mts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,QAAQ,EAEd,MAAM,0BAA0B,CAAC;AAIlC,KAAK,UAAU,GAAG,+BAA+B,CAAC;AAElD,eAAO,MAAM,qBAAqB,EAAE,QAAQ,CAAC,UAAU,CAAC,UAAU,CAyCjE,CAAC"}
1
+ {"version":3,"file":"use-memo-hooks-style.d.mts","sourceRoot":"","sources":["../../../../src/plugins/react-coding-style/rules/use-memo-hooks-style.mts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,QAAQ,EAEd,MAAM,0BAA0B,CAAC;AAIlC,KAAK,UAAU,GAAG,+BAA+B,CAAC;AAElD,eAAO,MAAM,qBAAqB,EAAE,QAAQ,CAAC,UAAU,CAAC,UAAU,CAwDjE,CAAC"}