Skip to content

Commit a257f86

Browse files
refactor(oxlint-plugin): consolidate isAllLiteralArrayExpression helper
The 12-line helper that recognises an ArrayExpression of primitive literals (`[1, 2, 3]` etc.) was duplicated in: - rules/correctness/no-array-index-as-key.ts - rules/react-builtins/no-array-index-key.ts Functionally equivalent (one had a redundant cast). Promote to utils/is-all-literal-array-expression.ts. Behaviour-neutral. Co-authored-by: Aiden Bai <aidenybai@users.noreply.github.com>
1 parent 6011d90 commit a257f86

3 files changed

Lines changed: 25 additions & 28 deletions

File tree

packages/oxlint-plugin-react-doctor/src/plugin/rules/correctness/no-array-index-as-key.ts

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { defineRule } from "../../utils/define-rule.js";
33
import type { EsTreeNode } from "../../utils/es-tree-node.js";
44
import type { Rule } from "../../utils/rule.js";
55
import type { RuleContext } from "../../utils/rule-context.js";
6+
import { isAllLiteralArrayExpression } from "../../utils/is-all-literal-array-expression.js";
67
import { isNodeOfType } from "../../utils/is-node-of-type.js";
78
import type { EsTreeNodeOfType } from "../../utils/es-tree-node-of-type.js";
89
import {
@@ -107,20 +108,6 @@ const isArrayFromCall = (node: EsTreeNode | null | undefined): boolean => {
107108
* (number/string/boolean literal) — `[1, 2, 3]`, `['a', 'b']`. Such arrays
108109
* have a fixed order at every render, so an index key is stable.
109110
*/
110-
const isAllLiteralArrayExpression = (node: EsTreeNode): boolean => {
111-
if (!isNodeOfType(node, "ArrayExpression")) return false;
112-
const elements = node.elements ?? [];
113-
if (elements.length < 1) return false;
114-
for (const element of elements) {
115-
if (!element) return false;
116-
if (!isNodeOfType(element, "Literal")) return false;
117-
const value = element.value;
118-
if (typeof value !== "string" && typeof value !== "number" && typeof value !== "boolean")
119-
return false;
120-
}
121-
return true;
122-
};
123-
124111
/**
125112
* True if the call expression looks like a placeholder constructor whose
126113
* elements have no identity beyond their position — i.e. `Array.from(...)`,

packages/oxlint-plugin-react-doctor/src/plugin/rules/react-builtins/no-array-index-key.ts

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { defineRule } from "../../utils/define-rule.js";
22
import type { EsTreeNode } from "../../utils/es-tree-node.js";
33
import type { EsTreeNodeOfType } from "../../utils/es-tree-node-of-type.js";
44
import { hasJsxPropIgnoreCase } from "../../utils/has-jsx-prop-ignore-case.js";
5+
import { isAllLiteralArrayExpression } from "../../utils/is-all-literal-array-expression.js";
56
import { isNodeOfType } from "../../utils/is-node-of-type.js";
67
import {
78
containsStatefulDescendant,
@@ -36,20 +37,6 @@ const THIRD_INDEX_METHODS: ReadonlySet<string> = new Set(["reduce", "reduceRight
3637
// In each of these the array's identity-vs-position is fixed by the
3738
// source string/length — reordering can't happen, so using the index
3839
// as the key is semantically right.
39-
const isAllLiteralArrayExpression = (node: EsTreeNode): boolean => {
40-
if (!isNodeOfType(node, "ArrayExpression")) return false;
41-
const elements = node.elements ?? [];
42-
if (elements.length < 1) return false;
43-
for (const element of elements) {
44-
if (!element) return false;
45-
if (!isNodeOfType(element, "Literal")) return false;
46-
const value = (element as { value: unknown }).value;
47-
if (typeof value !== "string" && typeof value !== "number" && typeof value !== "boolean")
48-
return false;
49-
}
50-
return true;
51-
};
52-
5340
const isPositionallyStableIterationReceiver = (receiver: EsTreeNode): boolean => {
5441
// `[lit, lit, lit].map(...)` — fixed-shape literal array, order is stable.
5542
if (isAllLiteralArrayExpression(receiver)) return true;
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import type { EsTreeNode } from "./es-tree-node.js";
2+
import { isNodeOfType } from "./is-node-of-type.js";
3+
4+
/**
5+
* True when the node is an `ArrayExpression` whose elements are all
6+
* primitive literals (string / number / boolean). Used by the two
7+
* "no array-index key" rule variants to detect a `keys={[1, 2, 3]}`
8+
* style stable-id array.
9+
*/
10+
export const isAllLiteralArrayExpression = (node: EsTreeNode): boolean => {
11+
if (!isNodeOfType(node, "ArrayExpression")) return false;
12+
const elements = node.elements ?? [];
13+
if (elements.length < 1) return false;
14+
for (const element of elements) {
15+
if (!element) return false;
16+
if (!isNodeOfType(element, "Literal")) return false;
17+
const value = element.value;
18+
if (typeof value !== "string" && typeof value !== "number" && typeof value !== "boolean") {
19+
return false;
20+
}
21+
}
22+
return true;
23+
};

0 commit comments

Comments
 (0)