@eslint-react/core 2.0.0-beta.18 → 2.0.0-beta.4

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 (3) hide show
  1. package/dist/index.d.ts +28 -28
  2. package/dist/index.js +20 -13
  3. package/package.json +12 -12
package/dist/index.d.ts CHANGED
@@ -2,7 +2,7 @@ import { RuleContext } from '@eslint-react/kit';
2
2
  import { TSESTree } from '@typescript-eslint/types';
3
3
  import { ESLintUtils, TSESTree as TSESTree$1 } from '@typescript-eslint/utils';
4
4
  import * as AST from '@eslint-react/ast';
5
- import { _ } from '@eslint-react/eff';
5
+ import { unit } from '@eslint-react/eff';
6
6
  import * as birecord from 'birecord';
7
7
  import { Scope } from '@typescript-eslint/scope-manager';
8
8
  import * as VAR from '@eslint-react/var';
@@ -80,10 +80,10 @@ interface SemanticEntry {
80
80
  }
81
81
 
82
82
  interface SemanticNode {
83
- id: _ | TSESTree.Identifier | TSESTree.Identifier[];
83
+ id: unit | TSESTree.Identifier | TSESTree.Identifier[];
84
84
  key: string;
85
85
  kind: string;
86
- name: _ | string;
86
+ name: unit | string;
87
87
  node: TSESTree.Node;
88
88
  flag: bigint;
89
89
  hint: bigint;
@@ -100,23 +100,23 @@ declare const ComponentFlag: {
100
100
  };
101
101
 
102
102
  interface FunctionComponent extends SemanticNode {
103
- id: _ | TSESTree.Identifier | TSESTree.Identifier[];
103
+ id: unit | TSESTree.Identifier | TSESTree.Identifier[];
104
104
  kind: "function";
105
105
  node: AST.TSESTreeFunction;
106
106
  flag: ComponentFlag;
107
107
  hint: ComponentDetectionHint;
108
- initPath: _ | AST.FunctionInitPath;
108
+ initPath: unit | AST.FunctionInitPath;
109
109
  hookCalls: TSESTree.CallExpression[];
110
- displayName: _ | TSESTree.Expression;
110
+ displayName: unit | TSESTree.Expression;
111
111
  }
112
112
  interface ClassComponent extends SemanticNode {
113
- id: _ | TSESTree.Identifier;
113
+ id: unit | TSESTree.Identifier;
114
114
  kind: "class";
115
115
  node: AST.TSESTreeClass;
116
116
  flag: ComponentFlag;
117
117
  hint: ComponentDetectionHint;
118
118
  methods: AST.TSESTreeMethodOrProperty[];
119
- displayName: _ | TSESTree.Expression;
119
+ displayName: unit | TSESTree.Expression;
120
120
  }
121
121
  type Component = ClassComponent | FunctionComponent;
122
122
 
@@ -136,7 +136,7 @@ declare namespace useComponentCollector {
136
136
  ctx: {
137
137
  getAllComponents: (node: TSESTree.Program) => Map<string, FunctionComponent>;
138
138
  getCurrentEntries: () => FunctionEntry[];
139
- getCurrentEntry: () => FunctionEntry | _;
139
+ getCurrentEntry: () => FunctionEntry | unit;
140
140
  };
141
141
  listeners: ESLintUtils.RuleListener;
142
142
  };
@@ -178,7 +178,7 @@ declare function useComponentCollectorLegacy(): useComponentCollectorLegacy.Retu
178
178
  declare function isFunctionOfRenderMethod(node: AST.TSESTreeFunction): boolean;
179
179
  declare function isValidComponentDefinition(context: RuleContext, node: AST.TSESTreeFunction, hint: bigint): boolean;
180
180
 
181
- declare function getFunctionComponentId(context: RuleContext, node: AST.TSESTreeFunction): TSESTree.Identifier | TSESTree.Identifier[] | _;
181
+ declare function getFunctionComponentId(context: RuleContext, node: AST.TSESTreeFunction): TSESTree.Identifier | TSESTree.Identifier[] | unit;
182
182
 
183
183
  declare function getComponentFlagFromInitPath(initPath: FunctionComponent["initPath"]): bigint;
184
184
 
@@ -217,7 +217,7 @@ declare function isGetDerivedStateFromError(node: TSESTree.Node): node is AST.TS
217
217
 
218
218
  declare function isComponentName(name: string): boolean;
219
219
  declare function isComponentNameLoose(name: string): boolean;
220
- declare function getComponentNameFromId(id: TSESTree.Identifier | TSESTree.Identifier[] | _): string | undefined;
220
+ declare function getComponentNameFromId(id: TSESTree.Identifier | TSESTree.Identifier[] | unit): string | undefined;
221
221
  declare function hasNoneOrLooseComponentName(context: RuleContext, fn: AST.TSESTreeFunction): boolean;
222
222
 
223
223
  /**
@@ -332,7 +332,7 @@ declare function isComponentWrapperCallLoose(context: RuleContext, node: TSESTre
332
332
  type EffectKind = "useEffect" | "useLayoutEffect" | "useInsertionEffect";
333
333
 
334
334
  interface Hook extends SemanticNode {
335
- id: TSESTree.Identifier | _;
335
+ id: TSESTree.Identifier | unit;
336
336
  node: AST.TSESTreeFunction;
337
337
  name: string;
338
338
  hookCalls: TSESTree.CallExpression[];
@@ -350,17 +350,17 @@ declare function useHookCollector(): useHookCollector.ReturnType;
350
350
 
351
351
  declare function isReactHookId(id: TSESTree.Identifier | TSESTree.MemberExpression): boolean;
352
352
 
353
- declare function isReactHook(node: AST.TSESTreeFunction | _): boolean;
353
+ declare function isReactHook(node: AST.TSESTreeFunction | unit): boolean;
354
354
  /**
355
355
  * Check if the given node is a React Hook call by its name.
356
356
  * @param node The node to check.
357
357
  * @returns `true` if the node is a React Hook call, `false` otherwise.
358
358
  */
359
- declare function isReactHookCall(node: TSESTree.Node | _): boolean;
360
- declare function isReactHookCallWithName(context: RuleContext, node: TSESTree.Node | _): (name: string) => boolean;
361
- declare function isReactHookCallWithNameLoose(node: TSESTree.Node | _): (name: string) => boolean;
362
- declare function isReactHookCallWithNameAlias(context: RuleContext, name: string, alias?: _ | string[]): (node: TSESTree.CallExpression) => boolean;
363
- declare function isUseEffectCallLoose(node: TSESTree.Node | _): boolean;
359
+ declare function isReactHookCall(node: TSESTree.Node | unit): boolean;
360
+ declare function isReactHookCallWithName(context: RuleContext, node: TSESTree.Node | unit): (name: string) => boolean;
361
+ declare function isReactHookCallWithNameLoose(node: TSESTree.Node | unit): (name: string) => boolean;
362
+ declare function isReactHookCallWithNameAlias(context: RuleContext, name: string, alias?: unit | string[]): (node: TSESTree.CallExpression) => boolean;
363
+ declare function isUseEffectCallLoose(node: TSESTree.Node | unit): boolean;
364
364
  declare const isUseCall: (context: RuleContext, node: TSESTree.Node | undefined) => boolean;
365
365
  declare const isUseActionStateCall: (context: RuleContext, node: TSESTree.Node | undefined) => boolean;
366
366
  declare const isUseCallbackCall: (context: RuleContext, node: TSESTree.Node | undefined) => boolean;
@@ -398,7 +398,7 @@ declare function isReactHookName(name: string): boolean;
398
398
  * @param initialScope The initial scope to use for variable resolution
399
399
  * @returns The JSX attribute node or undefined
400
400
  */
401
- declare function getAttribute(context: RuleContext, name: string, attributes: (TSESTree$1.JSXAttribute | TSESTree$1.JSXSpreadAttribute)[], initialScope?: Scope): TSESTree$1.JSXAttribute | TSESTree$1.JSXSpreadAttribute | _;
401
+ declare function getAttribute(context: RuleContext, name: string, attributes: (TSESTree$1.JSXAttribute | TSESTree$1.JSXSpreadAttribute)[], initialScope?: Scope): TSESTree$1.JSXAttribute | TSESTree$1.JSXSpreadAttribute | unit;
402
402
 
403
403
  /**
404
404
  * Get the stringified name of a JSX attribute
@@ -441,7 +441,7 @@ declare const DEFAULT_JSX_DETECTION_HINT: bigint;
441
441
  * @param node The AST node to check
442
442
  * @returns `true` if the node is a `JSXText` or a `Literal` node
443
443
  */
444
- declare function isJsxText(node: TSESTree$1.Node | null | _): node is TSESTree$1.JSXText | TSESTree$1.Literal;
444
+ declare function isJsxText(node: TSESTree$1.Node | null | unit): node is TSESTree$1.JSXText | TSESTree$1.Literal;
445
445
  /**
446
446
  * Heuristic decision to determine if a node is a JSX-like node.
447
447
  * @param code The sourceCode object
@@ -452,7 +452,7 @@ declare function isJsxText(node: TSESTree$1.Node | null | _): node is TSESTree$1
452
452
  */
453
453
  declare function isJsxLike(code: {
454
454
  getScope: (node: TSESTree$1.Node) => Scope;
455
- }, node: TSESTree$1.Node | _ | null, hint?: JSXDetectionHint): boolean;
455
+ }, node: TSESTree$1.Node | unit | null, hint?: JSXDetectionHint): boolean;
456
456
 
457
457
  /**
458
458
  * Get the stringified type of a JSX element
@@ -472,12 +472,12 @@ declare function hasEveryAttribute(context: RuleContext, names: string[], attrib
472
472
  * @param test The test to apply to the parent attribute
473
473
  * @returns The parent attribute node or undefined
474
474
  */
475
- declare function findParentAttribute(node: TSESTree.Node, test?: (node: TSESTree.JSXAttribute) => boolean): TSESTree.JSXAttribute | _;
475
+ declare function findParentAttribute(node: TSESTree.Node, test?: (node: TSESTree.JSXAttribute) => boolean): TSESTree.JSXAttribute | unit;
476
476
 
477
477
  declare function isHostElement(context: RuleContext, node: TSESTree.Node): boolean;
478
478
  declare function isKeyedElement(context: RuleContext, node: TSESTree.Node, initialScope?: Scope): boolean;
479
- declare function isFragmentElement(context: RuleContext, node: TSESTree.Node | null | _, allowJSXFragment?: false): node is TSESTree.JSXElement;
480
- declare function isFragmentElement(context: RuleContext, node: TSESTree.Node | null | _, allowJSXFragment?: true): node is TSESTree.JSXElement | TSESTree.JSXFragment;
479
+ declare function isFragmentElement(context: RuleContext, node: TSESTree.Node | null | unit, allowJSXFragment?: false): node is TSESTree.JSXElement;
480
+ declare function isFragmentElement(context: RuleContext, node: TSESTree.Node | null | unit, allowJSXFragment?: true): node is TSESTree.JSXElement | TSESTree.JSXFragment;
481
481
 
482
482
  /**
483
483
  * Get the stringified representation of a JSX node
@@ -503,15 +503,15 @@ declare function isInstanceIdEqual(context: RuleContext, a: TSESTree.Node, b: TS
503
503
 
504
504
  declare namespace isReactAPI {
505
505
  type ReturnType = {
506
- (context: RuleContext, node: _ | null | TSESTree.Node): node is TSESTree.Identifier | TSESTree.MemberExpression;
507
- (context: RuleContext): (node: _ | null | TSESTree.Node) => node is TSESTree.MemberExpression | TSESTree.Identifier;
506
+ (context: RuleContext, node: unit | null | TSESTree.Node): node is TSESTree.Identifier | TSESTree.MemberExpression;
507
+ (context: RuleContext): (node: unit | null | TSESTree.Node) => node is TSESTree.MemberExpression | TSESTree.Identifier;
508
508
  };
509
509
  }
510
510
  declare function isReactAPI(api: string): isReactAPI.ReturnType;
511
511
  declare namespace isReactAPICall {
512
512
  type ReturnType = {
513
- (context: RuleContext, node: _ | null | TSESTree.Node): node is TSESTree.CallExpression;
514
- (context: RuleContext): (node: _ | null | TSESTree.Node) => node is TSESTree.CallExpression;
513
+ (context: RuleContext, node: unit | null | TSESTree.Node): node is TSESTree.CallExpression;
514
+ (context: RuleContext): (node: unit | null | TSESTree.Node) => node is TSESTree.CallExpression;
515
515
  };
516
516
  }
517
517
  declare function isReactAPICall(api: string): isReactAPICall.ReturnType;
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { AST_NODE_TYPES } from '@typescript-eslint/types';
2
2
  import * as AST14 from '@eslint-react/ast';
3
- import { flip, dual, constFalse, identity, constTrue, _ } from '@eslint-react/eff';
3
+ import { flip, dual, constFalse, identity, constTrue, unit } from '@eslint-react/eff';
4
4
  import { RegExp, Selector } from '@eslint-react/kit';
5
5
  import { coerceSettings, DEFAULT_ESLINT_REACT_SETTINGS, getId } from '@eslint-react/shared';
6
6
  import * as VAR3 from '@eslint-react/var';
@@ -70,7 +70,7 @@ function getInstanceId(node, prev) {
70
70
  case (node.type === AST_NODE_TYPES.PropertyDefinition && node.value === prev):
71
71
  return node.key;
72
72
  case (node.type === AST_NODE_TYPES.BlockStatement || node.type === AST_NODE_TYPES.Program || node.parent === node):
73
- return _;
73
+ return unit;
74
74
  default:
75
75
  return getInstanceId(node.parent, node);
76
76
  }
@@ -432,6 +432,9 @@ function isJsxLike(code, node, hint = DEFAULT_JSX_DETECTION_HINT) {
432
432
  return !(hint & JSXDetectionHint.SkipStringLiteral);
433
433
  }
434
434
  case AST_NODE_TYPES.ArrayExpression: {
435
+ if (node.elements.length === 0) {
436
+ return !(hint & JSXDetectionHint.SkipEmptyArray);
437
+ }
435
438
  if (hint & JSXDetectionHint.StrictArray) {
436
439
  return node.elements.every((n) => isJsxLike(code, n, hint));
437
440
  }
@@ -664,7 +667,7 @@ function getFunctionComponentId(context, node) {
664
667
  if (parent.type === AST_NODE_TYPES.CallExpression && isComponentWrapperCallLoose(context, parent) && parent.parent.type === AST_NODE_TYPES.CallExpression && isComponentWrapperCallLoose(context, parent.parent) && parent.parent.parent.type === AST_NODE_TYPES.VariableDeclarator && parent.parent.parent.id.type === AST_NODE_TYPES.Identifier) {
665
668
  return parent.parent.parent.id;
666
669
  }
667
- return _;
670
+ return unit;
668
671
  }
669
672
 
670
673
  // src/component/component-flag.ts
@@ -695,7 +698,7 @@ function isComponentNameLoose(name) {
695
698
  return RegExp.COMPONENT_NAME_LOOSE.test(name);
696
699
  }
697
700
  function getComponentNameFromId(id) {
698
- if (id == null) return _;
701
+ if (id == null) return unit;
699
702
  return Array.isArray(id) ? id.map((n) => n.name).join(".") : id.name;
700
703
  }
701
704
  function hasNoneOrLooseComponentName(context, fn) {
@@ -723,11 +726,15 @@ function useComponentCollector(context, options = {}) {
723
726
  const entry = functionEntries.at(-1);
724
727
  if (entry == null) return;
725
728
  if (!entry.isComponent) return functionEntries.pop();
726
- const shouldDrop = AST14.getNestedReturnStatements(entry.node.body).slice().reverse().some((r) => {
727
- return context.sourceCode.getScope(r).block === entry.node && r.argument != null && !isJsxLike(context.sourceCode, r.argument, hint);
728
- });
729
- if (shouldDrop) {
730
- components.delete(entry.key);
729
+ const rets = AST14.getNestedReturnStatements(entry.node.body);
730
+ for (let i = rets.length - 1; i >= 0; i--) {
731
+ const ret = rets[i];
732
+ if (ret == null) continue;
733
+ const shouldDrop = context.sourceCode.getScope(ret).block === entry.node && ret.argument != null && !isJsxLike(context.sourceCode, ret.argument, hint);
734
+ if (shouldDrop) {
735
+ components.delete(entry.key);
736
+ break;
737
+ }
731
738
  }
732
739
  return functionEntries.pop();
733
740
  };
@@ -760,7 +767,7 @@ function useComponentCollector(context, options = {}) {
760
767
  kind: "function",
761
768
  name,
762
769
  node: entry.node,
763
- displayName: _,
770
+ displayName: unit,
764
771
  flag: getComponentFlagFromInitPath(initPath),
765
772
  hint,
766
773
  hookCalls: entry.hookCalls,
@@ -771,7 +778,7 @@ function useComponentCollector(context, options = {}) {
771
778
  [Selector.DISPLAY_NAME_ASSIGNMENT_EXPRESSION](node) {
772
779
  const { left, right } = node;
773
780
  if (left.type !== AST_NODE_TYPES.MemberExpression) return;
774
- const componentName = left.object.type === AST_NODE_TYPES.Identifier ? left.object.name : _;
781
+ const componentName = left.object.type === AST_NODE_TYPES.Identifier ? left.object.name : unit;
775
782
  const component = [...components.values()].findLast(({ name }) => name != null && name === componentName);
776
783
  if (component == null) return;
777
784
  component.displayName = right;
@@ -800,7 +807,7 @@ function useComponentCollector(context, options = {}) {
800
807
  kind: "function",
801
808
  name,
802
809
  node: entry.node,
803
- displayName: _,
810
+ displayName: unit,
804
811
  flag: getComponentFlagFromInitPath(initPath),
805
812
  hint,
806
813
  hookCalls: entry.hookCalls,
@@ -834,7 +841,7 @@ function useComponentCollectorLegacy() {
834
841
  name: id?.name,
835
842
  node,
836
843
  // TODO: Get displayName of class component
837
- displayName: _,
844
+ displayName: unit,
838
845
  flag,
839
846
  hint: 0n,
840
847
  // TODO: Get methods of class component
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eslint-react/core",
3
- "version": "2.0.0-beta.18",
3
+ "version": "2.0.0-beta.4",
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": {
@@ -27,20 +27,20 @@
27
27
  "./package.json"
28
28
  ],
29
29
  "dependencies": {
30
- "@typescript-eslint/scope-manager": "^8.32.0",
31
- "@typescript-eslint/type-utils": "^8.32.0",
32
- "@typescript-eslint/types": "^8.32.0",
33
- "@typescript-eslint/utils": "^8.32.0",
30
+ "@typescript-eslint/scope-manager": "^8.35.0",
31
+ "@typescript-eslint/type-utils": "^8.35.0",
32
+ "@typescript-eslint/types": "^8.35.0",
33
+ "@typescript-eslint/utils": "^8.35.0",
34
34
  "birecord": "^0.1.1",
35
- "ts-pattern": "^5.7.0",
36
- "@eslint-react/ast": "2.0.0-beta.18",
37
- "@eslint-react/eff": "2.0.0-beta.18",
38
- "@eslint-react/shared": "2.0.0-beta.18",
39
- "@eslint-react/kit": "2.0.0-beta.18",
40
- "@eslint-react/var": "2.0.0-beta.18"
35
+ "ts-pattern": "^5.7.1",
36
+ "@eslint-react/ast": "2.0.0-beta.4",
37
+ "@eslint-react/eff": "2.0.0-beta.4",
38
+ "@eslint-react/kit": "2.0.0-beta.4",
39
+ "@eslint-react/shared": "2.0.0-beta.4",
40
+ "@eslint-react/var": "2.0.0-beta.4"
41
41
  },
42
42
  "devDependencies": {
43
- "tsup": "^8.4.0",
43
+ "tsup": "^8.5.0",
44
44
  "@local/configs": "0.0.0"
45
45
  },
46
46
  "engines": {