@eslint-react/core 3.0.0-next.70 → 3.0.0-next.74

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
@@ -627,14 +627,14 @@ declare function isHookName(name: string): boolean;
627
627
  type JsxAttributeValue = {
628
628
  kind: "missing";
629
629
  node: TSESTree.JSXEmptyExpression;
630
- toStatic(): "{}";
630
+ toStatic(): null;
631
631
  } | {
632
632
  kind: "boolean";
633
633
  toStatic(): true;
634
634
  } | {
635
635
  kind: "element";
636
636
  node: TSESTree.JSXElement;
637
- toStatic(): unknown;
637
+ toStatic(): null;
638
638
  } | {
639
639
  kind: "literal";
640
640
  node: TSESTree.Literal;
@@ -647,12 +647,12 @@ type JsxAttributeValue = {
647
647
  kind: "spreadProps";
648
648
  getProperty(name: string): unknown;
649
649
  node: TSESTree.JSXSpreadAttribute["argument"];
650
- toStatic(): unknown;
650
+ toStatic(): null;
651
651
  } | {
652
652
  kind: "spreadChild";
653
653
  getChildren(at: number): unknown;
654
654
  node: TSESTree.JSXSpreadChild["expression"];
655
- toStatic(): unknown;
655
+ toStatic(): null;
656
656
  };
657
657
  //#endregion
658
658
  //#region src/jsx/jsx-config.d.ts
@@ -786,9 +786,8 @@ declare class JsxInspector {
786
786
  * later props win), or `undefined` if not found.
787
787
  * @param node The JSX element to search for the attribute.
788
788
  * @param name The name of the attribute to find (e.g. `"className"`).
789
- * @param initialScope An optional scope to use for resolving spread attributes. If not provided,
790
789
  */
791
- findAttribute(node: TSESTree.JSXElement, name: string, initialScope?: Scope): ast.TSESTreeJSXAttributeLike | undefined;
790
+ findAttribute(node: TSESTree.JSXElement, name: string): ast.TSESTreeJSXAttributeLike | undefined;
792
791
  /**
793
792
  * Get the stringified name of a `JSXAttribute` node
794
793
  * (e.g. `"className"`, `"aria-label"`, `"xml:space"`).
@@ -810,10 +809,9 @@ declare class JsxInspector {
810
809
  * cannot be statically determined.
811
810
  * @param node The JSX element to search for the attribute.
812
811
  * @param name The name of the attribute to resolve (e.g. `"className"`).
813
- * @param initialScope An optional scope to use for resolving spread attributes. If not provided, the scope will be determined from the context of the attribute node.
814
812
  * @returns The static value of the attribute, or `undefined` if not found or not statically resolvable.
815
813
  */
816
- getAttributeStaticValue(node: TSESTree.JSXElement, name: string, initialScope?: Scope): unknown;
814
+ getAttributeStaticValue(node: TSESTree.JSXElement, name: string): unknown;
817
815
  /**
818
816
  * **All-in-one helper** – find an attribute by name on an element *and*
819
817
  * resolve its value in a single call.
@@ -821,10 +819,9 @@ declare class JsxInspector {
821
819
  * Returns `undefined` when the attribute is not present.
822
820
  * @param node The JSX element to search for the attribute.
823
821
  * @param name The name of the attribute to find and resolve (e.g. `"className"`).
824
- * @param initialScope An optional scope to use for resolving spread attributes. If not provided, the scope will be determined from the context of the attribute node.
825
822
  * @returns A descriptor of the attribute's value that can be further inspected, or `undefined` if the attribute is not found.
826
823
  */
827
- getAttributeValue(node: TSESTree.JSXElement, name: string, initialScope?: Scope): JsxAttributeValue | undefined;
824
+ getAttributeValue(node: TSESTree.JSXElement, name: string): JsxAttributeValue | undefined;
828
825
  /**
829
826
  * Get the **self name** (last segment) of a JSX element type.
830
827
  *
@@ -848,10 +845,9 @@ declare class JsxInspector {
848
845
  * Shorthand: check whether an attribute exists on the element.
849
846
  * @param node The JSX element to check for the attribute.
850
847
  * @param name The name of the attribute to check for (e.g. `"className"`).
851
- * @param initialScope An optional scope to use for resolving spread attributes. If not provided, the scope will be determined from the context of the attribute node.
852
848
  * @returns `true` if the attribute exists on the element, `false` otherwise.
853
849
  */
854
- hasAttribute(node: TSESTree.JSXElement, name: string, initialScope?: Scope): boolean;
850
+ hasAttribute(node: TSESTree.JSXElement, name: string): boolean;
855
851
  /**
856
852
  * Whether the node is a React **Fragment** element (either `<Fragment>` /
857
853
  * `<React.Fragment>` or the shorthand `<>` syntax).
@@ -887,7 +883,7 @@ declare class JsxInspector {
887
883
  } | {
888
884
  readonly kind: "missing";
889
885
  readonly node: TSESTree.JSXEmptyExpression;
890
- readonly toStatic: () => "{}";
886
+ readonly toStatic: () => null;
891
887
  readonly getChildren?: never;
892
888
  } | {
893
889
  readonly kind: "expression";
@@ -901,14 +897,14 @@ declare class JsxInspector {
901
897
  readonly getChildren?: never;
902
898
  } | {
903
899
  readonly kind: "spreadChild";
904
- readonly getChildren: (_at: number) => null;
905
900
  readonly node: TSESTree.JSXEmptyExpression | TSESTree.Expression;
906
- readonly toStatic: () => unknown;
901
+ readonly toStatic: () => null;
902
+ readonly getChildren: (_at: number) => null;
907
903
  } | {
908
904
  readonly kind: "spreadProps";
909
- readonly getProperty: (name: string) => unknown;
910
905
  readonly node: TSESTree.Expression;
911
- readonly toStatic: () => unknown;
906
+ readonly toStatic: () => null;
907
+ readonly getProperty: (name: string) => unknown;
912
908
  };
913
909
  }
914
910
  //#endregion
package/dist/index.js CHANGED
@@ -1,5 +1,4 @@
1
1
  import * as ast from "@eslint-react/ast";
2
- import { constFalse, dual, flip, getOrElseUpdate, identity } from "@eslint-react/eff";
3
2
  import { AST_NODE_TYPES } from "@typescript-eslint/types";
4
3
  import { findVariable, getStaticValue } from "@typescript-eslint/utils/ast-utils";
5
4
  import { P, match } from "ts-pattern";
@@ -7,6 +6,165 @@ import { IdGenerator, RE_ANNOTATION_JSX, RE_ANNOTATION_JSX_FRAG, RE_ANNOTATION_J
7
6
  import { resolve } from "@eslint-react/var";
8
7
  import { AST_NODE_TYPES as AST_NODE_TYPES$1 } from "@typescript-eslint/utils";
9
8
 
9
+ //#region ../../.pkgs/eff/dist/index.js
10
+ /**
11
+ * Returns its argument.
12
+ *
13
+ * @param x - The value to return.
14
+ * @returns The input value unchanged.
15
+ */
16
+ function identity(x) {
17
+ return x;
18
+ }
19
+ /**
20
+ * Creates a function that can be used in a data-last (aka `pipe`able) or
21
+ * data-first style.
22
+ *
23
+ * The first parameter to `dual` is either the arity of the uncurried function
24
+ * or a predicate that determines if the function is being used in a data-first
25
+ * or data-last style.
26
+ *
27
+ * Using the arity is the most common use case, but there are some cases where
28
+ * you may want to use a predicate. For example, if you have a function that
29
+ * takes an optional argument, you can use a predicate to determine if the
30
+ * function is being used in a data-first or data-last style.
31
+ *
32
+ * You can pass either the arity of the uncurried function or a predicate
33
+ * which determines if the function is being used in a data-first or
34
+ * data-last style.
35
+ *
36
+ * **Example** (Using arity to determine data-first or data-last style)
37
+ *
38
+ * ```ts
39
+ * import { dual, pipe } from "effect/Function"
40
+ *
41
+ * const sum = dual<
42
+ * (that: number) => (self: number) => number,
43
+ * (self: number, that: number) => number
44
+ * >(2, (self, that) => self + that)
45
+ *
46
+ * console.log(sum(2, 3)) // 5
47
+ * console.log(pipe(2, sum(3))) // 5
48
+ * ```
49
+ *
50
+ * **Example** (Using call signatures to define the overloads)
51
+ *
52
+ * ```ts
53
+ * import { dual, pipe } from "effect/Function"
54
+ *
55
+ * const sum: {
56
+ * (that: number): (self: number) => number
57
+ * (self: number, that: number): number
58
+ * } = dual(2, (self: number, that: number): number => self + that)
59
+ *
60
+ * console.log(sum(2, 3)) // 5
61
+ * console.log(pipe(2, sum(3))) // 5
62
+ * ```
63
+ *
64
+ * **Example** (Using a predicate to determine data-first or data-last style)
65
+ *
66
+ * ```ts
67
+ * import { dual, pipe } from "effect/Function"
68
+ *
69
+ * const sum = dual<
70
+ * (that: number) => (self: number) => number,
71
+ * (self: number, that: number) => number
72
+ * >(
73
+ * (args) => args.length === 2,
74
+ * (self, that) => self + that
75
+ * )
76
+ *
77
+ * console.log(sum(2, 3)) // 5
78
+ * console.log(pipe(2, sum(3))) // 5
79
+ * ```
80
+ *
81
+ * @param arity - The arity of the uncurried function or a predicate that determines if the function is being used in a data-first or data-last style.
82
+ * @param body - The function to be curried.
83
+ * @since 1.0.0
84
+ */
85
+ const dual = function(arity, body) {
86
+ if (typeof arity === "function") return function() {
87
+ return arity(arguments) ? body.apply(this, arguments) : ((self) => body(self, ...arguments));
88
+ };
89
+ switch (arity) {
90
+ case 0:
91
+ case 1: throw new RangeError(`Invalid arity ${arity}`);
92
+ case 2: return function(a, b) {
93
+ if (arguments.length >= 2) return body(a, b);
94
+ return function(self) {
95
+ return body(self, a);
96
+ };
97
+ };
98
+ case 3: return function(a, b, c) {
99
+ if (arguments.length >= 3) return body(a, b, c);
100
+ return function(self) {
101
+ return body(self, a, b);
102
+ };
103
+ };
104
+ default: return function() {
105
+ if (arguments.length >= arity) return body.apply(this, arguments);
106
+ const args = arguments;
107
+ return function(self) {
108
+ return body(self, ...args);
109
+ };
110
+ };
111
+ }
112
+ };
113
+ /**
114
+ * Do nothing and return `false`.
115
+ *
116
+ * @returns false
117
+ */
118
+ function constFalse() {
119
+ return false;
120
+ }
121
+ /**
122
+ * Reverses the order of arguments for a curried function.
123
+ *
124
+ * @param f - The function to flip.
125
+ * @returns A new function with the argument order reversed.
126
+ * @example
127
+ * ```ts
128
+ * import * as assert from "node:assert"
129
+ * import { flip } from "effect/Function"
130
+ *
131
+ * const f = (a: number) => (b: string) => a - b.length
132
+ *
133
+ * assert.deepStrictEqual(flip(f)('aaa')(2), -1)
134
+ * ```
135
+ *
136
+ * @since 1.0.0
137
+ */
138
+ const flip = (f) => (...b) => (...a) => f(...a)(...b);
139
+ /**
140
+ * Composes two functions, `ab` and `bc` into a single function that takes in an argument `a` of type `A` and returns a result of type `C`.
141
+ * The result is obtained by first applying the `ab` function to `a` and then applying the `bc` function to the result of `ab`.
142
+ *
143
+ * @param self - The first function to apply (or the composed function in data-last style).
144
+ * @param bc - The second function to apply.
145
+ * @returns A composed function that applies both functions in sequence.
146
+ * @example
147
+ * ```ts
148
+ * import * as assert from "node:assert"
149
+ * import { compose } from "effect/Function"
150
+ *
151
+ * const increment = (n: number) => n + 1;
152
+ * const square = (n: number) => n * n;
153
+ *
154
+ * assert.strictEqual(compose(increment, square)(2), 9);
155
+ * ```
156
+ *
157
+ * @since 1.0.0
158
+ */
159
+ const compose = dual(2, (ab, bc) => (a) => bc(ab(a)));
160
+ function getOrElseUpdate(map, key, callback) {
161
+ if (map.has(key)) return map.get(key);
162
+ const value = callback();
163
+ map.set(key, value);
164
+ return value;
165
+ }
166
+
167
+ //#endregion
10
168
  //#region src/api/find-import-source.ts
11
169
  /**
12
170
  * Get the arguments of a require expression
@@ -596,10 +754,8 @@ var JsxInspector = class JsxInspector {
596
754
  * later props win), or `undefined` if not found.
597
755
  * @param node The JSX element to search for the attribute.
598
756
  * @param name The name of the attribute to find (e.g. `"className"`).
599
- * @param initialScope An optional scope to use for resolving spread attributes. If not provided,
600
757
  */
601
- findAttribute(node, name, initialScope) {
602
- initialScope ?? this.context.sourceCode.getScope(node);
758
+ findAttribute(node, name) {
603
759
  return node.openingElement.attributes.findLast((attr) => {
604
760
  if (attr.type === AST_NODE_TYPES.JSXAttribute) return stringifyJsx(attr.name) === name;
605
761
  switch (attr.argument.type) {
@@ -636,11 +792,10 @@ var JsxInspector = class JsxInspector {
636
792
  * cannot be statically determined.
637
793
  * @param node The JSX element to search for the attribute.
638
794
  * @param name The name of the attribute to resolve (e.g. `"className"`).
639
- * @param initialScope An optional scope to use for resolving spread attributes. If not provided, the scope will be determined from the context of the attribute node.
640
795
  * @returns The static value of the attribute, or `undefined` if not found or not statically resolvable.
641
796
  */
642
- getAttributeStaticValue(node, name, initialScope) {
643
- const attr = this.findAttribute(node, name, initialScope);
797
+ getAttributeStaticValue(node, name) {
798
+ const attr = this.findAttribute(node, name);
644
799
  if (attr == null) return void 0;
645
800
  const resolved = this.resolveAttributeValue(attr);
646
801
  if (resolved.kind === "spreadProps") return resolved.getProperty(name);
@@ -653,11 +808,10 @@ var JsxInspector = class JsxInspector {
653
808
  * Returns `undefined` when the attribute is not present.
654
809
  * @param node The JSX element to search for the attribute.
655
810
  * @param name The name of the attribute to find and resolve (e.g. `"className"`).
656
- * @param initialScope An optional scope to use for resolving spread attributes. If not provided, the scope will be determined from the context of the attribute node.
657
811
  * @returns A descriptor of the attribute's value that can be further inspected, or `undefined` if the attribute is not found.
658
812
  */
659
- getAttributeValue(node, name, initialScope) {
660
- const attr = this.findAttribute(node, name, initialScope);
813
+ getAttributeValue(node, name) {
814
+ const attr = this.findAttribute(node, name);
661
815
  if (attr == null) return void 0;
662
816
  return this.resolveAttributeValue(attr);
663
817
  }
@@ -689,11 +843,10 @@ var JsxInspector = class JsxInspector {
689
843
  * Shorthand: check whether an attribute exists on the element.
690
844
  * @param node The JSX element to check for the attribute.
691
845
  * @param name The name of the attribute to check for (e.g. `"className"`).
692
- * @param initialScope An optional scope to use for resolving spread attributes. If not provided, the scope will be determined from the context of the attribute node.
693
846
  * @returns `true` if the attribute exists on the element, `false` otherwise.
694
847
  */
695
- hasAttribute(node, name, initialScope) {
696
- return this.findAttribute(node, name, initialScope) != null;
848
+ hasAttribute(node, name) {
849
+ return this.findAttribute(node, name) != null;
697
850
  }
698
851
  /**
699
852
  * Whether the node is a React **Fragment** element (either `<Fragment>` /
@@ -725,11 +878,11 @@ var JsxInspector = class JsxInspector {
725
878
  * @returns A descriptor of the attribute's value that can be further inspected.
726
879
  */
727
880
  resolveAttributeValue(attribute) {
728
- const initialScope = this.context.sourceCode.getScope(attribute);
729
- if (attribute.type === AST_NODE_TYPES.JSXAttribute) return this.#resolveJsxAttribute(attribute, initialScope);
730
- return this.#resolveJsxSpreadAttribute(attribute, initialScope);
881
+ if (attribute.type === AST_NODE_TYPES.JSXAttribute) return this.#resolveJsxAttribute(attribute);
882
+ return this.#resolveJsxSpreadAttribute(attribute);
731
883
  }
732
- #resolveJsxAttribute(node, initialScope) {
884
+ #resolveJsxAttribute(node) {
885
+ const scope = this.context.sourceCode.getScope(node);
733
886
  if (node.value == null) return {
734
887
  kind: "boolean",
735
888
  toStatic() {
@@ -753,14 +906,14 @@ var JsxInspector = class JsxInspector {
753
906
  kind: "missing",
754
907
  node: expr,
755
908
  toStatic() {
756
- return "{}";
909
+ return null;
757
910
  }
758
911
  };
759
912
  return {
760
913
  kind: "expression",
761
914
  node: expr,
762
915
  toStatic() {
763
- return getStaticValue(expr, initialScope)?.value;
916
+ return getStaticValue(expr, scope)?.value;
764
917
  }
765
918
  };
766
919
  }
@@ -771,30 +924,30 @@ var JsxInspector = class JsxInspector {
771
924
  return null;
772
925
  }
773
926
  };
774
- case AST_NODE_TYPES.JSXSpreadChild: {
775
- const expr = node.value.expression;
927
+ case AST_NODE_TYPES.JSXSpreadChild:
928
+ node.value.expression;
776
929
  return {
777
930
  kind: "spreadChild",
778
- getChildren(_at) {
779
- return null;
780
- },
781
931
  node: node.value.expression,
782
932
  toStatic() {
783
- return getStaticValue(expr, initialScope)?.value;
933
+ return null;
934
+ },
935
+ getChildren(_at) {
936
+ return null;
784
937
  }
785
938
  };
786
- }
787
939
  }
788
940
  }
789
- #resolveJsxSpreadAttribute(node, initialScope) {
941
+ #resolveJsxSpreadAttribute(node) {
942
+ const scope = this.context.sourceCode.getScope(node);
790
943
  return {
791
944
  kind: "spreadProps",
792
- getProperty(name) {
793
- return match(getStaticValue(node.argument, initialScope)?.value).with({ [name]: P.select(P.any) }, identity).otherwise(() => null);
794
- },
795
945
  node: node.argument,
796
946
  toStatic() {
797
- return getStaticValue(node.argument, initialScope)?.value;
947
+ return null;
948
+ },
949
+ getProperty(name) {
950
+ return match(getStaticValue(node.argument, scope)?.value).with({ [name]: P.select(P.any) }, identity).otherwise(() => null);
798
951
  }
799
952
  };
800
953
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eslint-react/core",
3
- "version": "3.0.0-next.70",
3
+ "version": "3.0.0-next.74",
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,18 +34,18 @@
34
34
  "@typescript-eslint/types": "canary",
35
35
  "@typescript-eslint/utils": "canary",
36
36
  "ts-pattern": "^5.9.0",
37
- "@eslint-react/ast": "3.0.0-next.70",
38
- "@eslint-react/eff": "3.0.0-next.70",
39
- "@eslint-react/var": "3.0.0-next.70",
40
- "@eslint-react/shared": "3.0.0-next.70"
37
+ "@eslint-react/ast": "3.0.0-next.74",
38
+ "@eslint-react/shared": "3.0.0-next.74",
39
+ "@eslint-react/var": "3.0.0-next.74",
40
+ "@local/eff": "3.0.0-beta.72"
41
41
  },
42
42
  "devDependencies": {
43
43
  "tsdown": "^0.21.0-beta.2",
44
44
  "@local/configs": "0.0.0"
45
45
  },
46
46
  "peerDependencies": {
47
- "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
48
- "typescript": ">=4.8.4 <6.0.0"
47
+ "eslint": "^10.0.0",
48
+ "typescript": "*"
49
49
  },
50
50
  "engines": {
51
51
  "node": ">=22.0.0"