eslint-plugin-react-x 2.0.0-next.180 → 2.0.0-next.182

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 (2) hide show
  1. package/dist/index.js +84 -4
  2. package/package.json +9 -9
package/dist/index.js CHANGED
@@ -1,9 +1,11 @@
1
1
  import { DEFAULT_ESLINT_REACT_SETTINGS, coerceSettings, getConfigAdapters, getDocsUrl, getSettingsFromContext } from "@eslint-react/shared";
2
2
  import { AST_NODE_TYPES } from "@typescript-eslint/types";
3
3
  import { ESLintUtils } from "@typescript-eslint/utils";
4
+ import { isFalseLiteralType, isTrueLiteralType, isTypeFlagSet, unionConstituents } from "ts-api-utils";
5
+ import { P, isMatching, match } from "ts-pattern";
6
+ import ts from "typescript";
4
7
  import * as AST from "@eslint-react/ast";
5
8
  import * as VAR from "@eslint-react/var";
6
- import { P, isMatching, match } from "ts-pattern";
7
9
  import * as ER from "@eslint-react/core";
8
10
  import { SEL_DISPLAY_NAME_ASSIGNMENT_EXPRESSION, SEL_OBJECT_DESTRUCTURING_VARIABLE_DECLARATOR, isProcessEnvNodeEnvCompare, isViMockCallback, report, toRegExp } from "@eslint-react/kit";
9
11
  import { constFalse, constTrue, flow, getOrElseUpdate, identity, unit } from "@eslint-react/eff";
@@ -11,7 +13,6 @@ import { compare } from "compare-versions";
11
13
  import { camelCase } from "string-ts";
12
14
  import { getConstrainedTypeAtLocation, isTypeReadonly } from "@typescript-eslint/type-utils";
13
15
  import { getStaticValue } from "@typescript-eslint/utils/ast-utils";
14
- import { unionConstituents } from "ts-api-utils";
15
16
  import { getTypeImmutability, isImmutable, isReadonlyDeep, isReadonlyShallow, isUnknown } from "is-immutable-type";
16
17
 
17
18
  //#region rolldown:runtime
@@ -114,12 +115,91 @@ const settings = { ...settings$1 };
114
115
  //#endregion
115
116
  //#region package.json
116
117
  var name = "eslint-plugin-react-x";
117
- var version = "2.0.0-next.180";
118
+ var version = "2.0.0-next.182";
118
119
 
119
120
  //#endregion
120
121
  //#region src/utils/create-rule.ts
121
122
  const createRule = ESLintUtils.RuleCreator(getDocsUrl("x"));
122
123
 
124
+ //#endregion
125
+ //#region src/utils/type-is.ts
126
+ /** @internal */
127
+ const isAnyType = (type) => isTypeFlagSet(type, ts.TypeFlags.TypeParameter | ts.TypeFlags.Any);
128
+ /** @internal */
129
+ const isBigIntType = (type) => isTypeFlagSet(type, ts.TypeFlags.BigIntLike);
130
+ /** @internal */
131
+ const isBooleanType = (type) => isTypeFlagSet(type, ts.TypeFlags.BooleanLike);
132
+ /** @internal */
133
+ const isEnumType = (type) => isTypeFlagSet(type, ts.TypeFlags.EnumLike);
134
+ /** @internal */
135
+ const isFalsyBigIntType = (type) => type.isLiteral() && isMatching({ value: { base10Value: "0" } }, type);
136
+ /** @internal */
137
+ const isFalsyNumberType = (type) => type.isNumberLiteral() && type.value === 0;
138
+ /** @internal */
139
+ const isFalsyStringType = (type) => type.isStringLiteral() && type.value === "";
140
+ /** @internal */
141
+ const isNeverType = (type) => isTypeFlagSet(type, ts.TypeFlags.Never);
142
+ /** @internal */
143
+ const isNullishType = (type) => isTypeFlagSet(type, ts.TypeFlags.Null | ts.TypeFlags.Undefined | ts.TypeFlags.VoidLike);
144
+ /** @internal */
145
+ const isNumberType = (type) => isTypeFlagSet(type, ts.TypeFlags.NumberLike);
146
+ /** @internal */
147
+ const isObjectType = (type) => !isTypeFlagSet(type, ts.TypeFlags.Null | ts.TypeFlags.Undefined | ts.TypeFlags.VoidLike | ts.TypeFlags.BooleanLike | ts.TypeFlags.StringLike | ts.TypeFlags.NumberLike | ts.TypeFlags.BigIntLike | ts.TypeFlags.TypeParameter | ts.TypeFlags.Any | ts.TypeFlags.Unknown | ts.TypeFlags.Never);
148
+ /** @internal */
149
+ const isStringType = (type) => isTypeFlagSet(type, ts.TypeFlags.StringLike);
150
+ /** @internal */
151
+ const isTruthyBigIntType = (type) => type.isLiteral() && isMatching({ value: { base10Value: P.not("0") } }, type);
152
+ /** @internal */
153
+ const isTruthyNumberType = (type) => type.isNumberLiteral() && type.value !== 0;
154
+ /** @internal */
155
+ const isTruthyStringType = (type) => type.isStringLiteral() && type.value !== "";
156
+ /** @internal */
157
+ const isUnknownType = (type) => isTypeFlagSet(type, ts.TypeFlags.Unknown);
158
+
159
+ //#endregion
160
+ //#region src/utils/type-variant.ts
161
+ /**
162
+ * Ported from https://github.com/typescript-eslint/typescript-eslint/blob/eb736bbfc22554694400e6a4f97051d845d32e0b/packages/eslint-plugin/src/rules/strict-boolean-expressions.ts#L826 with some enhancements
163
+ * Get the variants of an array of types.
164
+ * @param types The types to get the variants of
165
+ * @returns The variants of the types
166
+ * @internal
167
+ */
168
+ function getTypeVariants(types) {
169
+ const variants = /* @__PURE__ */ new Set();
170
+ if (types.some(isUnknownType)) {
171
+ variants.add("unknown");
172
+ return variants;
173
+ }
174
+ if (types.some(isNullishType)) variants.add("nullish");
175
+ const booleans = types.filter(isBooleanType);
176
+ const boolean0 = booleans[0];
177
+ if (booleans.length === 1 && boolean0 != null) {
178
+ if (isFalseLiteralType(boolean0)) variants.add("falsy boolean");
179
+ else if (isTrueLiteralType(boolean0)) variants.add("truthy boolean");
180
+ } else if (booleans.length === 2) variants.add("boolean");
181
+ const strings = types.filter(isStringType);
182
+ if (strings.length > 0) {
183
+ const evaluated = match(strings).when((types$1) => types$1.every(isTruthyStringType), () => "truthy string").when((types$1) => types$1.every(isFalsyStringType), () => "falsy string").otherwise(() => "string");
184
+ variants.add(evaluated);
185
+ }
186
+ const bigints = types.filter(isBigIntType);
187
+ if (bigints.length > 0) {
188
+ const evaluated = match(bigints).when((types$1) => types$1.every(isTruthyBigIntType), () => "truthy bigint").when((types$1) => types$1.every(isFalsyBigIntType), () => "falsy bigint").otherwise(() => "bigint");
189
+ variants.add(evaluated);
190
+ }
191
+ const numbers = types.filter(isNumberType);
192
+ if (numbers.length > 0) {
193
+ const evaluated = match(numbers).when((types$1) => types$1.every(isTruthyNumberType), () => "truthy number").when((types$1) => types$1.every(isFalsyNumberType), () => "falsy number").otherwise(() => "number");
194
+ variants.add(evaluated);
195
+ }
196
+ if (types.some(isEnumType)) variants.add("enum");
197
+ if (types.some(isObjectType)) variants.add("object");
198
+ if (types.some(isAnyType)) variants.add("any");
199
+ if (types.some(isNeverType)) variants.add("never");
200
+ return variants;
201
+ }
202
+
123
203
  //#endregion
124
204
  //#region src/rules/jsx-key-before-spread.ts
125
205
  const RULE_NAME$61 = "jsx-key-before-spread";
@@ -1516,7 +1596,7 @@ function create$31(context) {
1516
1596
  data: { value: context.sourceCode.getText(left) }
1517
1597
  };
1518
1598
  const leftType = getConstrainedTypeAtLocation(services, left);
1519
- const leftTypeVariants = ER.getTypeVariants(unionConstituents(leftType));
1599
+ const leftTypeVariants = getTypeVariants(unionConstituents(leftType));
1520
1600
  if (Array.from(leftTypeVariants.values()).every((type) => allowedVariants.some((allowed) => allowed === type))) return getReportDescriptor(right);
1521
1601
  return {
1522
1602
  messageId: "noLeakedConditionalRendering",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-react-x",
3
- "version": "2.0.0-next.180",
3
+ "version": "2.0.0-next.182",
4
4
  "description": "A set of composable ESLint rules for for libraries and frameworks that use React as a UI runtime.",
5
5
  "keywords": [
6
6
  "react",
@@ -42,18 +42,18 @@
42
42
  "is-immutable-type": "^5.0.1",
43
43
  "string-ts": "^2.2.1",
44
44
  "ts-pattern": "^5.8.0",
45
- "@eslint-react/ast": "2.0.0-next.180",
46
- "@eslint-react/eff": "2.0.0-next.180",
47
- "@eslint-react/core": "2.0.0-next.180",
48
- "@eslint-react/kit": "2.0.0-next.180",
49
- "@eslint-react/var": "2.0.0-next.180",
50
- "@eslint-react/shared": "2.0.0-next.180"
45
+ "@eslint-react/core": "2.0.0-next.182",
46
+ "@eslint-react/ast": "2.0.0-next.182",
47
+ "@eslint-react/eff": "2.0.0-next.182",
48
+ "@eslint-react/kit": "2.0.0-next.182",
49
+ "@eslint-react/shared": "2.0.0-next.182",
50
+ "@eslint-react/var": "2.0.0-next.182"
51
51
  },
52
52
  "devDependencies": {
53
- "@types/react": "^19.1.12",
53
+ "@types/react": "^19.1.13",
54
54
  "@types/react-dom": "^19.1.9",
55
55
  "ts-api-utils": "^2.1.0",
56
- "tsdown": "^0.15.0",
56
+ "tsdown": "^0.15.1",
57
57
  "@local/configs": "0.0.0"
58
58
  },
59
59
  "peerDependencies": {