corsa-oxlint 0.4.0 → 0.7.1
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/README.md +19 -0
- package/dist/rules/await_thenable.js +2 -18
- package/dist/rules/await_thenable.js.map +1 -1
- package/dist/rules/native_bridge.d.ts +25 -0
- package/dist/rules/native_bridge.js +120 -0
- package/dist/rules/native_bridge.js.map +1 -0
- package/dist/rules/no_array_delete.js +2 -24
- package/dist/rules/no_array_delete.js.map +1 -1
- package/dist/rules/no_base_to_string.js +1 -1
- package/dist/rules/no_floating_promises.js +1 -1
- package/dist/rules/no_for_in_array.js +2 -11
- package/dist/rules/no_for_in_array.js.map +1 -1
- package/dist/rules/no_implied_eval.js +2 -30
- package/dist/rules/no_implied_eval.js.map +1 -1
- package/dist/rules/no_mixed_enums.js +2 -36
- package/dist/rules/no_mixed_enums.js.map +1 -1
- package/dist/rules/no_unsafe_return.js +1 -1
- package/dist/rules/no_unsafe_unary_minus.js +2 -23
- package/dist/rules/no_unsafe_unary_minus.js.map +1 -1
- package/dist/rules/only_throw_error.js +2 -11
- package/dist/rules/only_throw_error.js.map +1 -1
- package/dist/rules/prefer_find.js +2 -20
- package/dist/rules/prefer_find.js.map +1 -1
- package/dist/rules/prefer_includes.js +2 -16
- package/dist/rules/prefer_includes.js.map +1 -1
- package/dist/rules/prefer_promise_reject_errors.js +1 -1
- package/dist/rules/prefer_regexp_exec.js +2 -15
- package/dist/rules/prefer_regexp_exec.js.map +1 -1
- package/dist/rules/prefer_string_starts_ends_with.js +1 -1
- package/dist/rules/require_array_sort_compare.js +3 -4
- package/dist/rules/require_array_sort_compare.js.map +1 -1
- package/dist/rules/use_unknown_in_catch_callback_variable.js +2 -14
- package/dist/rules/use_unknown_in_catch_callback_variable.js.map +1 -1
- package/dist/utils.d.ts +4 -3
- package/dist/utils.js +3 -2
- package/dist/utils.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -140,6 +140,25 @@ The remaining upstream rules stay listed in `pendingNativeRuleNames`, and
|
|
|
140
140
|
`native_rules.test.ts` fails if implemented + pending drift away from the
|
|
141
141
|
tracked upstream rule list.
|
|
142
142
|
|
|
143
|
+
## Rust-Authored Rule Lane
|
|
144
|
+
|
|
145
|
+
General-purpose built-in rules can be implemented as Rust rules and still ship
|
|
146
|
+
as Oxlint JS plugin rules. The bridge is:
|
|
147
|
+
|
|
148
|
+
1. Oxlint visits the ESTree node in JS.
|
|
149
|
+
2. `corsa-oxlint` collects compact node facts and type texts.
|
|
150
|
+
3. `@corsa-bind/napi` calls `corsa::lint::RustLintRule`.
|
|
151
|
+
4. Rust returns Oxlint-shaped diagnostics, suggestions, and fixes.
|
|
152
|
+
5. The JS rule reports them through `context.report()`.
|
|
153
|
+
|
|
154
|
+
The first rules on this path are `await-thenable`, `no-array-delete`,
|
|
155
|
+
`no-for-in-array`, `no-implied-eval`, `no-mixed-enums`,
|
|
156
|
+
`no-unsafe-unary-minus`, `only-throw-error`, `prefer-find`,
|
|
157
|
+
`prefer-includes`, `prefer-regexp-exec`, and
|
|
158
|
+
`use-unknown-in-catch-callback-variable`. Custom project-specific rules can
|
|
159
|
+
still be authored in JS/TS with `OxlintUtils.RuleCreator()`, while hot,
|
|
160
|
+
shared, tsgolint-parity rules can move into Rust incrementally.
|
|
161
|
+
|
|
143
162
|
## Runtime Safety Controls
|
|
144
163
|
|
|
145
164
|
The underlying `@corsa-bind/napi` client now exposes a few production-oriented
|
|
@@ -1,22 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { createNativeRule } from "./rule_creator.js";
|
|
3
|
-
import { isPromiseLikeNode } from "./type_utils.js";
|
|
1
|
+
import { createRustNativeRule } from "./native_bridge.js";
|
|
4
2
|
//#region src/bindings/nodejs/typescript_oxlint/ts/rules/await_thenable.ts
|
|
5
|
-
const awaitThenableRule =
|
|
6
|
-
docs: { description: "Disallow awaiting non-thenable values." },
|
|
7
|
-
messages: { unexpected: "Unexpected await of a non-thenable value." }
|
|
8
|
-
}, (context) => ({ AwaitExpression(node) {
|
|
9
|
-
if (!isPromiseLikeNode(context, node.argument) && !isObviouslyPromiseLike(node.argument)) context.report({
|
|
10
|
-
node,
|
|
11
|
-
messageId: "unexpected"
|
|
12
|
-
});
|
|
13
|
-
} }));
|
|
14
|
-
function isObviouslyPromiseLike(node) {
|
|
15
|
-
const current = stripChainExpression(node);
|
|
16
|
-
if (current?.type === "NewExpression" && isIdentifierNamed(current.callee, "Promise")) return true;
|
|
17
|
-
if (current?.type !== "CallExpression") return false;
|
|
18
|
-
return memberPropertyName(current.callee) === "resolve" && isIdentifierNamed(memberObject(current.callee), "Promise");
|
|
19
|
-
}
|
|
3
|
+
const awaitThenableRule = createRustNativeRule("await-thenable");
|
|
20
4
|
//#endregion
|
|
21
5
|
export { awaitThenableRule };
|
|
22
6
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"await_thenable.js","names":[],"sources":["../../ts/rules/await_thenable.ts"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"file":"await_thenable.js","names":[],"sources":["../../ts/rules/await_thenable.ts"],"sourcesContent":["import { createRustNativeRule } from \"./native_bridge\";\n\nexport const awaitThenableRule = createRustNativeRule(\"await-thenable\");\n"],"mappings":";;AAEA,MAAa,oBAAoB,qBAAqB,iBAAiB"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { ContextWithParserOptions } from "../types.js";
|
|
2
|
+
import { NativeLintDiagnostic, NativeLintNode } from "@corsa-bind/napi";
|
|
3
|
+
|
|
4
|
+
//#region src/bindings/nodejs/typescript_oxlint/ts/rules/native_bridge.d.ts
|
|
5
|
+
type RangedNode = {
|
|
6
|
+
readonly type: string;
|
|
7
|
+
readonly range: readonly [number, number];
|
|
8
|
+
};
|
|
9
|
+
declare function createRustNativeRule(ruleName: string): {
|
|
10
|
+
defaultOptions: never[];
|
|
11
|
+
meta: {
|
|
12
|
+
docs: {
|
|
13
|
+
requiresTypeChecking: boolean;
|
|
14
|
+
url: string;
|
|
15
|
+
};
|
|
16
|
+
type: "problem";
|
|
17
|
+
schema: never[];
|
|
18
|
+
};
|
|
19
|
+
create: (context: any) => Record<string, (node: any) => void>;
|
|
20
|
+
};
|
|
21
|
+
declare function toNativeNode(context: ContextWithParserOptions, node: RangedNode, includeTypeTexts?: boolean, maxDepth?: number): NativeLintNode;
|
|
22
|
+
declare function reportNativeDiagnostics(context: ContextWithParserOptions, node: RangedNode, diagnostics: readonly NativeLintDiagnostic[]): void;
|
|
23
|
+
//#endregion
|
|
24
|
+
export { createRustNativeRule, reportNativeDiagnostics, toNativeNode };
|
|
25
|
+
//# sourceMappingURL=native_bridge.d.ts.map
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { createNativeRule } from "./rule_creator.js";
|
|
2
|
+
import { propertyNamesOfNode, typeTextsAtNode } from "./type_utils.js";
|
|
3
|
+
import { nativeLintRuleMetas, runNativeLintRule } from "@corsa-bind/napi";
|
|
4
|
+
//#region src/bindings/nodejs/typescript_oxlint/ts/rules/native_bridge.ts
|
|
5
|
+
const MAX_NATIVE_NODE_DEPTH = 4;
|
|
6
|
+
const nativeRuleMetasByName = new Map(nativeLintRuleMetas().map((meta) => [meta.name, meta]));
|
|
7
|
+
function createRustNativeRule(ruleName) {
|
|
8
|
+
const meta = nativeRuleMeta(ruleName);
|
|
9
|
+
return createNativeRule(ruleName, {
|
|
10
|
+
docs: { description: meta.docsDescription },
|
|
11
|
+
hasSuggestions: meta.hasSuggestions,
|
|
12
|
+
messages: meta.messages
|
|
13
|
+
}, (context) => Object.fromEntries(meta.listeners.map((listener) => [listener, (node) => {
|
|
14
|
+
reportNativeDiagnostics(context, node, runNativeLintRule(ruleName, toNativeNode(context, node, meta.requiresTypeTexts)));
|
|
15
|
+
}])));
|
|
16
|
+
}
|
|
17
|
+
function toNativeNode(context, node, includeTypeTexts = true, maxDepth = MAX_NATIVE_NODE_DEPTH) {
|
|
18
|
+
const fields = {};
|
|
19
|
+
const children = {};
|
|
20
|
+
const childLists = {};
|
|
21
|
+
for (const [key, value] of Object.entries(node)) {
|
|
22
|
+
if (isSkippedField(key)) continue;
|
|
23
|
+
if (isNativeChildNode(value)) {
|
|
24
|
+
if (maxDepth > 0) children[key] = toNativeNode(context, value, includeTypeTexts, maxDepth - 1);
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
if (Array.isArray(value)) {
|
|
28
|
+
if (maxDepth > 0 && value.every(isNativeChildNode)) childLists[key] = value.map((child) => toNativeNode(context, child, includeTypeTexts, maxDepth - 1));
|
|
29
|
+
else if (value.every(isJsonPrimitive)) fields[key] = value;
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
32
|
+
if (isPrimitiveRecord(value)) {
|
|
33
|
+
fields[key] = value;
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
if (isJsonPrimitive(value)) fields[key] = value;
|
|
37
|
+
}
|
|
38
|
+
const nativeNode = {
|
|
39
|
+
kind: node.type,
|
|
40
|
+
range: nativeRange(node.range)
|
|
41
|
+
};
|
|
42
|
+
if (includeTypeTexts) {
|
|
43
|
+
nativeNode.typeTexts = typeTextsAtNode(context, node);
|
|
44
|
+
nativeNode.propertyNames = propertyNamesOfNode(context, node);
|
|
45
|
+
}
|
|
46
|
+
if (Object.keys(fields).length > 0) nativeNode.fields = fields;
|
|
47
|
+
if (Object.keys(children).length > 0) nativeNode.children = children;
|
|
48
|
+
if (Object.keys(childLists).length > 0) nativeNode.childLists = childLists;
|
|
49
|
+
return nativeNode;
|
|
50
|
+
}
|
|
51
|
+
function reportNativeDiagnostics(context, node, diagnostics) {
|
|
52
|
+
for (const diagnostic of diagnostics) context.report({
|
|
53
|
+
node: reportNodeForRange(node, diagnostic.range),
|
|
54
|
+
messageId: diagnostic.messageId,
|
|
55
|
+
...diagnostic.suggestions?.length ? { suggest: diagnostic.suggestions.map((suggestion) => ({
|
|
56
|
+
messageId: suggestion.messageId,
|
|
57
|
+
fix: (fixer) => suggestion.fixes.map((fix) => fixer.replaceTextRange(oxlintRange(fix.range), fix.replacementText))
|
|
58
|
+
})) } : {}
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
function reportNodeForRange(root, range) {
|
|
62
|
+
return findNodeByRange(root, range) ?? root;
|
|
63
|
+
}
|
|
64
|
+
function findNodeByRange(value, range, seen = /* @__PURE__ */ new Set()) {
|
|
65
|
+
if (typeof value !== "object" || value === null || seen.has(value)) return;
|
|
66
|
+
seen.add(value);
|
|
67
|
+
if (isNativeChildNode(value) && sameRange(value.range, range)) return value;
|
|
68
|
+
if (Array.isArray(value)) {
|
|
69
|
+
for (const item of value) {
|
|
70
|
+
const match = findNodeByRange(item, range, seen);
|
|
71
|
+
if (match) return match;
|
|
72
|
+
}
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
for (const [key, child] of Object.entries(value)) {
|
|
76
|
+
if (isSkippedField(key)) continue;
|
|
77
|
+
const match = findNodeByRange(child, range, seen);
|
|
78
|
+
if (match) return match;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
function nativeRuleMeta(ruleName) {
|
|
82
|
+
const meta = nativeRuleMetasByName.get(ruleName);
|
|
83
|
+
if (!meta) throw new Error(`corsa-oxlint native Rust rule is not registered: ${ruleName}`);
|
|
84
|
+
return meta;
|
|
85
|
+
}
|
|
86
|
+
function nativeRange(range) {
|
|
87
|
+
return {
|
|
88
|
+
start: range[0],
|
|
89
|
+
end: range[1]
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
function oxlintRange(range) {
|
|
93
|
+
return [range.start, range.end];
|
|
94
|
+
}
|
|
95
|
+
function sameRange(range, expected) {
|
|
96
|
+
return range[0] === expected.start && range[1] === expected.end;
|
|
97
|
+
}
|
|
98
|
+
function isNativeChildNode(value) {
|
|
99
|
+
return typeof value === "object" && value !== null && typeof value.type === "string" && isRange(value.range);
|
|
100
|
+
}
|
|
101
|
+
function isRange(value) {
|
|
102
|
+
return Array.isArray(value) && value.length === 2 && typeof value[0] === "number" && typeof value[1] === "number";
|
|
103
|
+
}
|
|
104
|
+
function isJsonPrimitive(value) {
|
|
105
|
+
return value === null || [
|
|
106
|
+
"boolean",
|
|
107
|
+
"number",
|
|
108
|
+
"string"
|
|
109
|
+
].includes(typeof value);
|
|
110
|
+
}
|
|
111
|
+
function isPrimitiveRecord(value) {
|
|
112
|
+
return typeof value === "object" && value !== null && !Array.isArray(value) && Object.values(value).every(isJsonPrimitive);
|
|
113
|
+
}
|
|
114
|
+
function isSkippedField(key) {
|
|
115
|
+
return key === "type" || key === "range" || key === "loc" || key === "parent";
|
|
116
|
+
}
|
|
117
|
+
//#endregion
|
|
118
|
+
export { createRustNativeRule, reportNativeDiagnostics, toNativeNode };
|
|
119
|
+
|
|
120
|
+
//# sourceMappingURL=native_bridge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"native_bridge.js","names":[],"sources":["../../ts/rules/native_bridge.ts"],"sourcesContent":["import { nativeLintRuleMetas, runNativeLintRule } from \"@corsa-bind/napi\";\nimport type {\n NativeLintDiagnostic,\n NativeLintNode,\n NativeLintRange,\n NativeLintRuleMeta,\n} from \"@corsa-bind/napi\";\n\nimport { createNativeRule } from \"./rule_creator\";\nimport { propertyNamesOfNode, typeTextsAtNode } from \"./type_utils\";\nimport type { ContextWithParserOptions } from \"../types\";\n\ntype RangedNode = {\n readonly type: string;\n readonly range: readonly [number, number];\n};\n\nconst MAX_NATIVE_NODE_DEPTH = 4;\nconst nativeRuleMetasByName = new Map(nativeLintRuleMetas().map((meta) => [meta.name, meta]));\n\nexport function createRustNativeRule(ruleName: string) {\n const meta = nativeRuleMeta(ruleName);\n return createNativeRule(\n ruleName,\n {\n docs: {\n description: meta.docsDescription,\n },\n hasSuggestions: meta.hasSuggestions,\n messages: meta.messages,\n },\n (context) =>\n Object.fromEntries(\n meta.listeners.map((listener) => [\n listener,\n (node: RangedNode) => {\n reportNativeDiagnostics(\n context,\n node,\n runNativeLintRule(ruleName, toNativeNode(context, node, meta.requiresTypeTexts)),\n );\n },\n ]),\n ),\n );\n}\n\nexport function toNativeNode(\n context: ContextWithParserOptions,\n node: RangedNode,\n includeTypeTexts = true,\n maxDepth = MAX_NATIVE_NODE_DEPTH,\n): NativeLintNode {\n const fields: Record<string, unknown> = {};\n const children: Record<string, NativeLintNode> = {};\n const childLists: Record<string, NativeLintNode[]> = {};\n\n for (const [key, value] of Object.entries(node)) {\n if (isSkippedField(key)) {\n continue;\n }\n if (isNativeChildNode(value)) {\n if (maxDepth > 0) {\n children[key] = toNativeNode(context, value, includeTypeTexts, maxDepth - 1);\n }\n continue;\n }\n if (Array.isArray(value)) {\n if (maxDepth > 0 && value.every(isNativeChildNode)) {\n childLists[key] = value.map((child) =>\n toNativeNode(context, child, includeTypeTexts, maxDepth - 1),\n );\n } else if (value.every(isJsonPrimitive)) {\n fields[key] = value;\n }\n continue;\n }\n if (isPrimitiveRecord(value)) {\n fields[key] = value;\n continue;\n }\n if (isJsonPrimitive(value)) {\n fields[key] = value;\n }\n }\n\n const nativeNode: NativeLintNode = {\n kind: node.type,\n range: nativeRange(node.range),\n };\n if (includeTypeTexts) {\n nativeNode.typeTexts = typeTextsAtNode(context, node);\n nativeNode.propertyNames = propertyNamesOfNode(context, node);\n }\n if (Object.keys(fields).length > 0) {\n nativeNode.fields = fields;\n }\n if (Object.keys(children).length > 0) {\n nativeNode.children = children;\n }\n if (Object.keys(childLists).length > 0) {\n nativeNode.childLists = childLists;\n }\n return nativeNode;\n}\n\nexport function reportNativeDiagnostics(\n context: ContextWithParserOptions,\n node: RangedNode,\n diagnostics: readonly NativeLintDiagnostic[],\n): void {\n for (const diagnostic of diagnostics) {\n context.report({\n node: reportNodeForRange(node, diagnostic.range),\n messageId: diagnostic.messageId,\n ...(diagnostic.suggestions?.length\n ? {\n suggest: diagnostic.suggestions.map((suggestion) => ({\n messageId: suggestion.messageId,\n fix: (fixer: any) =>\n suggestion.fixes.map((fix) =>\n fixer.replaceTextRange(oxlintRange(fix.range), fix.replacementText),\n ),\n })),\n }\n : {}),\n } as never);\n }\n}\n\nfunction reportNodeForRange(root: RangedNode, range: NativeLintRange): RangedNode {\n return findNodeByRange(root, range) ?? root;\n}\n\nfunction findNodeByRange(\n value: unknown,\n range: NativeLintRange,\n seen = new Set<object>(),\n): RangedNode | undefined {\n if (typeof value !== \"object\" || value === null || seen.has(value)) {\n return undefined;\n }\n seen.add(value);\n\n if (isNativeChildNode(value) && sameRange(value.range, range)) {\n return value;\n }\n\n if (Array.isArray(value)) {\n for (const item of value) {\n const match = findNodeByRange(item, range, seen);\n if (match) {\n return match;\n }\n }\n return undefined;\n }\n\n for (const [key, child] of Object.entries(value)) {\n if (isSkippedField(key)) {\n continue;\n }\n const match = findNodeByRange(child, range, seen);\n if (match) {\n return match;\n }\n }\n return undefined;\n}\n\nfunction nativeRuleMeta(ruleName: string): NativeLintRuleMeta {\n const meta = nativeRuleMetasByName.get(ruleName);\n if (!meta) {\n throw new Error(`corsa-oxlint native Rust rule is not registered: ${ruleName}`);\n }\n return meta;\n}\n\nfunction nativeRange(range: readonly [number, number]): NativeLintRange {\n return { start: range[0], end: range[1] };\n}\n\nfunction oxlintRange(range: NativeLintRange): [number, number] {\n return [range.start, range.end];\n}\n\nfunction sameRange(range: readonly [number, number], expected: NativeLintRange): boolean {\n return range[0] === expected.start && range[1] === expected.end;\n}\n\nfunction isNativeChildNode(value: unknown): value is RangedNode {\n return (\n typeof value === \"object\" &&\n value !== null &&\n typeof (value as { type?: unknown }).type === \"string\" &&\n isRange((value as { range?: unknown }).range)\n );\n}\n\nfunction isRange(value: unknown): value is readonly [number, number] {\n return (\n Array.isArray(value) &&\n value.length === 2 &&\n typeof value[0] === \"number\" &&\n typeof value[1] === \"number\"\n );\n}\n\nfunction isJsonPrimitive(value: unknown): value is string | number | boolean | null {\n return value === null || [\"boolean\", \"number\", \"string\"].includes(typeof value);\n}\n\nfunction isPrimitiveRecord(\n value: unknown,\n): value is Record<string, string | number | boolean | null> {\n return (\n typeof value === \"object\" &&\n value !== null &&\n !Array.isArray(value) &&\n Object.values(value).every(isJsonPrimitive)\n );\n}\n\nfunction isSkippedField(key: string): boolean {\n return key === \"type\" || key === \"range\" || key === \"loc\" || key === \"parent\";\n}\n"],"mappings":"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"}
|
|
@@ -1,28 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { isArrayLikeNode } from "./type_utils.js";
|
|
1
|
+
import { createRustNativeRule } from "./native_bridge.js";
|
|
3
2
|
//#region src/bindings/nodejs/typescript_oxlint/ts/rules/no_array_delete.ts
|
|
4
|
-
const noArrayDeleteRule =
|
|
5
|
-
docs: { description: "Disallow deleting elements from array-like values." },
|
|
6
|
-
hasSuggestions: true,
|
|
7
|
-
messages: {
|
|
8
|
-
unexpected: "Do not delete elements from an array-like value.",
|
|
9
|
-
useSplice: "Use array.splice(index, 1) instead."
|
|
10
|
-
}
|
|
11
|
-
}, (context) => ({ UnaryExpression(node) {
|
|
12
|
-
if (node.operator !== "delete" || node.argument?.type !== "MemberExpression" || !node.argument.computed) return;
|
|
13
|
-
if (isArrayLikeNode(context, node.argument.object)) context.report({
|
|
14
|
-
node,
|
|
15
|
-
messageId: "unexpected",
|
|
16
|
-
suggest: [{
|
|
17
|
-
messageId: "useSplice",
|
|
18
|
-
fix: (fixer) => [
|
|
19
|
-
fixer.removeRange([node.range[0], node.argument.object.range[1]]),
|
|
20
|
-
fixer.replaceTextRange([node.argument.object.range[1], node.argument.property.range[0]], ".splice("),
|
|
21
|
-
fixer.replaceTextRange([node.argument.property.range[1], node.argument.range[1]], ", 1)")
|
|
22
|
-
]
|
|
23
|
-
}]
|
|
24
|
-
});
|
|
25
|
-
} }));
|
|
3
|
+
const noArrayDeleteRule = createRustNativeRule("no-array-delete");
|
|
26
4
|
//#endregion
|
|
27
5
|
export { noArrayDeleteRule };
|
|
28
6
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"no_array_delete.js","names":[],"sources":["../../ts/rules/no_array_delete.ts"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"file":"no_array_delete.js","names":[],"sources":["../../ts/rules/no_array_delete.ts"],"sourcesContent":["import { createRustNativeRule } from \"./native_bridge\";\n\nexport const noArrayDeleteRule = createRustNativeRule(\"no-array-delete\");\n"],"mappings":";;AAEA,MAAa,oBAAoB,qBAAqB,kBAAkB"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { calleePropertyName, isIdentifierNamed, isLiteralString, stripChainExpression } from "./ast.js";
|
|
2
1
|
import { createNativeRule } from "./rule_creator.js";
|
|
2
|
+
import { calleePropertyName, isIdentifierNamed, isLiteralString, stripChainExpression } from "./ast.js";
|
|
3
3
|
import { classifyTypeText, isStringLikeNode, splitTopLevelTypeText, typeTextsAtNode } from "./type_utils.js";
|
|
4
4
|
//#region src/bindings/nodejs/typescript_oxlint/ts/rules/no_base_to_string.ts
|
|
5
5
|
const knownSafeObjectTypes = new Set([
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { calleePropertyName, memberObject, nearestFunctionAncestors, stripChainExpression } from "./ast.js";
|
|
2
1
|
import { createNativeRule } from "./rule_creator.js";
|
|
2
|
+
import { calleePropertyName, memberObject, nearestFunctionAncestors, stripChainExpression } from "./ast.js";
|
|
3
3
|
import { isPromiseLikeNode } from "./type_utils.js";
|
|
4
4
|
//#region src/bindings/nodejs/typescript_oxlint/ts/rules/no_floating_promises.ts
|
|
5
5
|
const noFloatingPromisesRule = createNativeRule("no-floating-promises", {
|
|
@@ -1,15 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { isArrayLikeNode } from "./type_utils.js";
|
|
1
|
+
import { createRustNativeRule } from "./native_bridge.js";
|
|
3
2
|
//#region src/bindings/nodejs/typescript_oxlint/ts/rules/no_for_in_array.ts
|
|
4
|
-
const noForInArrayRule =
|
|
5
|
-
docs: { description: "Disallow for-in iteration over array-like values." },
|
|
6
|
-
messages: { unexpected: "Do not iterate over an array with a for-in loop." }
|
|
7
|
-
}, (context) => ({ ForInStatement(node) {
|
|
8
|
-
if (isArrayLikeNode(context, node.right)) context.report({
|
|
9
|
-
node,
|
|
10
|
-
messageId: "unexpected"
|
|
11
|
-
});
|
|
12
|
-
} }));
|
|
3
|
+
const noForInArrayRule = createRustNativeRule("no-for-in-array");
|
|
13
4
|
//#endregion
|
|
14
5
|
export { noForInArrayRule };
|
|
15
6
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"no_for_in_array.js","names":[],"sources":["../../ts/rules/no_for_in_array.ts"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"file":"no_for_in_array.js","names":[],"sources":["../../ts/rules/no_for_in_array.ts"],"sourcesContent":["import { createRustNativeRule } from \"./native_bridge\";\n\nexport const noForInArrayRule = createRustNativeRule(\"no-for-in-array\");\n"],"mappings":";;AAEA,MAAa,mBAAmB,qBAAqB,kBAAkB"}
|
|
@@ -1,34 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { createNativeRule } from "./rule_creator.js";
|
|
3
|
-
import { isStringLikeNode } from "./type_utils.js";
|
|
1
|
+
import { createRustNativeRule } from "./native_bridge.js";
|
|
4
2
|
//#region src/bindings/nodejs/typescript_oxlint/ts/rules/no_implied_eval.ts
|
|
5
|
-
const
|
|
6
|
-
"execScript",
|
|
7
|
-
"setInterval",
|
|
8
|
-
"setTimeout"
|
|
9
|
-
]);
|
|
10
|
-
const noImpliedEvalRule = createNativeRule("no-implied-eval", {
|
|
11
|
-
docs: { description: "Disallow string-based dynamic code execution APIs." },
|
|
12
|
-
messages: { unexpected: "Do not pass a string to an implied eval API." }
|
|
13
|
-
}, (context) => ({
|
|
14
|
-
CallExpression(node) {
|
|
15
|
-
const callee = stripChainExpression(node.callee);
|
|
16
|
-
const calleeName = memberPropertyName(callee) ?? (callee?.type === "Identifier" ? callee.name : void 0);
|
|
17
|
-
if (!calleeName || !impliedEvalNames.has(calleeName)) return;
|
|
18
|
-
const [firstArgument] = node.arguments;
|
|
19
|
-
if (firstArgument && !firstArgument.type?.includes("Function") && (isLiteralString(firstArgument) || isStringLikeNode(context, firstArgument))) context.report({
|
|
20
|
-
node,
|
|
21
|
-
messageId: "unexpected"
|
|
22
|
-
});
|
|
23
|
-
},
|
|
24
|
-
NewExpression(node) {
|
|
25
|
-
if (!isIdentifierNamed(node.callee, "Function")) return;
|
|
26
|
-
if (node.arguments.some((argument) => isLiteralString(argument))) context.report({
|
|
27
|
-
node,
|
|
28
|
-
messageId: "unexpected"
|
|
29
|
-
});
|
|
30
|
-
}
|
|
31
|
-
}));
|
|
3
|
+
const noImpliedEvalRule = createRustNativeRule("no-implied-eval");
|
|
32
4
|
//#endregion
|
|
33
5
|
export { noImpliedEvalRule };
|
|
34
6
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"no_implied_eval.js","names":[],"sources":["../../ts/rules/no_implied_eval.ts"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"file":"no_implied_eval.js","names":[],"sources":["../../ts/rules/no_implied_eval.ts"],"sourcesContent":["import { createRustNativeRule } from \"./native_bridge\";\n\nexport const noImpliedEvalRule = createRustNativeRule(\"no-implied-eval\");\n"],"mappings":";;AAEA,MAAa,oBAAoB,qBAAqB,kBAAkB"}
|
|
@@ -1,40 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { isNumberLikeNode, isStringLikeNode } from "./type_utils.js";
|
|
1
|
+
import { createRustNativeRule } from "./native_bridge.js";
|
|
3
2
|
//#region src/bindings/nodejs/typescript_oxlint/ts/rules/no_mixed_enums.ts
|
|
4
|
-
const noMixedEnumsRule =
|
|
5
|
-
docs: { description: "Disallow mixing string and numeric enum members." },
|
|
6
|
-
messages: { mixed: "Mixing number and string enums can be confusing." }
|
|
7
|
-
}, (context) => ({ TSEnumDeclaration(node) {
|
|
8
|
-
const members = enumMembersOf(node);
|
|
9
|
-
if (members.length === 0) return;
|
|
10
|
-
const desiredKind = enumMemberKind(context, members[0]);
|
|
11
|
-
if (desiredKind === "unknown") return;
|
|
12
|
-
for (const member of members) {
|
|
13
|
-
const currentKind = enumMemberKind(context, member);
|
|
14
|
-
if (currentKind === "unknown") return;
|
|
15
|
-
if (currentKind !== desiredKind) {
|
|
16
|
-
context.report({
|
|
17
|
-
node: member.initializer ?? member,
|
|
18
|
-
messageId: "mixed"
|
|
19
|
-
});
|
|
20
|
-
return;
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
} }));
|
|
24
|
-
function enumMembersOf(node) {
|
|
25
|
-
return node.body?.members ?? node.members ?? [];
|
|
26
|
-
}
|
|
27
|
-
function enumMemberKind(context, member) {
|
|
28
|
-
const initializer = member.initializer;
|
|
29
|
-
if (!initializer) return "number";
|
|
30
|
-
if (initializer.type === "Literal") {
|
|
31
|
-
if (typeof initializer.value === "number") return "number";
|
|
32
|
-
if (typeof initializer.value === "string") return "string";
|
|
33
|
-
}
|
|
34
|
-
if (isStringLikeNode(context, initializer)) return "string";
|
|
35
|
-
if (isNumberLikeNode(context, initializer)) return "number";
|
|
36
|
-
return "unknown";
|
|
37
|
-
}
|
|
3
|
+
const noMixedEnumsRule = createRustNativeRule("no-mixed-enums");
|
|
38
4
|
//#endregion
|
|
39
5
|
export { noMixedEnumsRule };
|
|
40
6
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"no_mixed_enums.js","names":[],"sources":["../../ts/rules/no_mixed_enums.ts"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"file":"no_mixed_enums.js","names":[],"sources":["../../ts/rules/no_mixed_enums.ts"],"sourcesContent":["import { createRustNativeRule } from \"./native_bridge\";\n\nexport const noMixedEnumsRule = createRustNativeRule(\"no-mixed-enums\");\n"],"mappings":";;AAEA,MAAa,mBAAmB,qBAAqB,iBAAiB"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { nearestFunctionAncestors } from "./ast.js";
|
|
2
1
|
import { createNativeRule } from "./rule_creator.js";
|
|
2
|
+
import { nearestFunctionAncestors } from "./ast.js";
|
|
3
3
|
import { checkerFor, typeAtNode, typeTextsAtNode } from "./type_utils.js";
|
|
4
4
|
import { isUnsafeReturn } from "@corsa-bind/napi";
|
|
5
5
|
//#region src/bindings/nodejs/typescript_oxlint/ts/rules/no_unsafe_return.ts
|
|
@@ -1,27 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { classifyTypeText, splitTypeText, typeTextsAtNode } from "./type_utils.js";
|
|
1
|
+
import { createRustNativeRule } from "./native_bridge.js";
|
|
3
2
|
//#region src/bindings/nodejs/typescript_oxlint/ts/rules/no_unsafe_unary_minus.ts
|
|
4
|
-
const noUnsafeUnaryMinusRule =
|
|
5
|
-
docs: { description: "Disallow unary negation on non-number and non-bigint values." },
|
|
6
|
-
messages: { unaryMinus: "Argument of unary negation should be assignable to number | bigint." }
|
|
7
|
-
}, (context) => ({ UnaryExpression(node) {
|
|
8
|
-
if (node.operator !== "-") return;
|
|
9
|
-
if (isSafeLiteral(node.argument)) return;
|
|
10
|
-
const typeTexts = typeTextsAtNode(context, node.argument);
|
|
11
|
-
if (typeTexts.length > 0 && typeTexts.every((text) => {
|
|
12
|
-
return splitTypeText(text).every((part) => {
|
|
13
|
-
const kind = classifyTypeText(part);
|
|
14
|
-
return kind === "any" || kind === "number" || kind === "bigint";
|
|
15
|
-
});
|
|
16
|
-
})) return;
|
|
17
|
-
context.report({
|
|
18
|
-
node,
|
|
19
|
-
messageId: "unaryMinus"
|
|
20
|
-
});
|
|
21
|
-
} }));
|
|
22
|
-
function isSafeLiteral(node) {
|
|
23
|
-
return node?.type === "Literal" && (typeof node.value === "number" || typeof node.bigint === "string");
|
|
24
|
-
}
|
|
3
|
+
const noUnsafeUnaryMinusRule = createRustNativeRule("no-unsafe-unary-minus");
|
|
25
4
|
//#endregion
|
|
26
5
|
export { noUnsafeUnaryMinusRule };
|
|
27
6
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"no_unsafe_unary_minus.js","names":[],"sources":["../../ts/rules/no_unsafe_unary_minus.ts"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"file":"no_unsafe_unary_minus.js","names":[],"sources":["../../ts/rules/no_unsafe_unary_minus.ts"],"sourcesContent":["import { createRustNativeRule } from \"./native_bridge\";\n\nexport const noUnsafeUnaryMinusRule = createRustNativeRule(\"no-unsafe-unary-minus\");\n"],"mappings":";;AAEA,MAAa,yBAAyB,qBAAqB,wBAAwB"}
|
|
@@ -1,15 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { isErrorLikeNode } from "./type_utils.js";
|
|
1
|
+
import { createRustNativeRule } from "./native_bridge.js";
|
|
3
2
|
//#region src/bindings/nodejs/typescript_oxlint/ts/rules/only_throw_error.ts
|
|
4
|
-
const onlyThrowErrorRule =
|
|
5
|
-
docs: { description: "Require thrown values to be Error-like." },
|
|
6
|
-
messages: { unexpected: "Only Error-like values should be thrown." }
|
|
7
|
-
}, (context) => ({ ThrowStatement(node) {
|
|
8
|
-
if (node.argument && !isErrorLikeNode(context, node.argument)) context.report({
|
|
9
|
-
node,
|
|
10
|
-
messageId: "unexpected"
|
|
11
|
-
});
|
|
12
|
-
} }));
|
|
3
|
+
const onlyThrowErrorRule = createRustNativeRule("only-throw-error");
|
|
13
4
|
//#endregion
|
|
14
5
|
export { onlyThrowErrorRule };
|
|
15
6
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"only_throw_error.js","names":[],"sources":["../../ts/rules/only_throw_error.ts"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"file":"only_throw_error.js","names":[],"sources":["../../ts/rules/only_throw_error.ts"],"sourcesContent":["import { createRustNativeRule } from \"./native_bridge\";\n\nexport const onlyThrowErrorRule = createRustNativeRule(\"only-throw-error\");\n"],"mappings":";;AAEA,MAAa,qBAAqB,qBAAqB,mBAAmB"}
|
|
@@ -1,24 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { createNativeRule } from "./rule_creator.js";
|
|
1
|
+
import { createRustNativeRule } from "./native_bridge.js";
|
|
3
2
|
//#region src/bindings/nodejs/typescript_oxlint/ts/rules/prefer_find.ts
|
|
4
|
-
const preferFindRule =
|
|
5
|
-
docs: { description: "Prefer find over filtering and taking the first element." },
|
|
6
|
-
messages: { unexpected: "Use .find() instead of filtering and taking the first match." }
|
|
7
|
-
}, (context) => ({
|
|
8
|
-
MemberExpression(node) {
|
|
9
|
-
if (memberPropertyName(node) === "0" && calleePropertyName(node.object) === "filter") context.report({
|
|
10
|
-
node,
|
|
11
|
-
messageId: "unexpected"
|
|
12
|
-
});
|
|
13
|
-
},
|
|
14
|
-
CallExpression(node) {
|
|
15
|
-
if (calleePropertyName(node) !== "at" || node.arguments[0]?.value !== 0) return;
|
|
16
|
-
if (calleePropertyName(memberObject(node.callee)) === "filter") context.report({
|
|
17
|
-
node,
|
|
18
|
-
messageId: "unexpected"
|
|
19
|
-
});
|
|
20
|
-
}
|
|
21
|
-
}));
|
|
3
|
+
const preferFindRule = createRustNativeRule("prefer-find");
|
|
22
4
|
//#endregion
|
|
23
5
|
export { preferFindRule };
|
|
24
6
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prefer_find.js","names":[],"sources":["../../ts/rules/prefer_find.ts"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"file":"prefer_find.js","names":[],"sources":["../../ts/rules/prefer_find.ts"],"sourcesContent":["import { createRustNativeRule } from \"./native_bridge\";\n\nexport const preferFindRule = createRustNativeRule(\"prefer-find\");\n"],"mappings":";;AAEA,MAAa,iBAAiB,qBAAqB,cAAc"}
|
|
@@ -1,20 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { createNativeRule } from "./rule_creator.js";
|
|
1
|
+
import { createRustNativeRule } from "./native_bridge.js";
|
|
3
2
|
//#region src/bindings/nodejs/typescript_oxlint/ts/rules/prefer_includes.ts
|
|
4
|
-
const preferIncludesRule =
|
|
5
|
-
docs: { description: "Prefer includes over indexOf/lastIndexOf comparisons." },
|
|
6
|
-
messages: { unexpected: "Use .includes() instead of comparing an index result." }
|
|
7
|
-
}, (context) => ({ BinaryExpression(node) {
|
|
8
|
-
if (!isComparableIndexSearch(node.left) && !isComparableIndexSearch(node.right)) return;
|
|
9
|
-
if (isNegativeOneLiteral(node.left) || isNegativeOneLiteral(node.right) || isZeroLiteral(node.left) || isZeroLiteral(node.right)) context.report({
|
|
10
|
-
node,
|
|
11
|
-
messageId: "unexpected"
|
|
12
|
-
});
|
|
13
|
-
} }));
|
|
14
|
-
function isComparableIndexSearch(node) {
|
|
15
|
-
const propertyName = calleePropertyName(node);
|
|
16
|
-
return propertyName === "indexOf" || propertyName === "lastIndexOf";
|
|
17
|
-
}
|
|
3
|
+
const preferIncludesRule = createRustNativeRule("prefer-includes");
|
|
18
4
|
//#endregion
|
|
19
5
|
export { preferIncludesRule };
|
|
20
6
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prefer_includes.js","names":[],"sources":["../../ts/rules/prefer_includes.ts"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"file":"prefer_includes.js","names":[],"sources":["../../ts/rules/prefer_includes.ts"],"sourcesContent":["import { createRustNativeRule } from \"./native_bridge\";\n\nexport const preferIncludesRule = createRustNativeRule(\"prefer-includes\");\n"],"mappings":";;AAEA,MAAa,qBAAqB,qBAAqB,kBAAkB"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { isIdentifierNamed, memberObject, memberPropertyName, nearestFunctionAncestors, stripChainExpression } from "./ast.js";
|
|
2
1
|
import { createNativeRule } from "./rule_creator.js";
|
|
2
|
+
import { isIdentifierNamed, memberObject, memberPropertyName, nearestFunctionAncestors, stripChainExpression } from "./ast.js";
|
|
3
3
|
import { isAnyLikeNode, isErrorLikeNode, isPromiseLikeNode, isUnknownLikeNode } from "./type_utils.js";
|
|
4
4
|
//#region src/bindings/nodejs/typescript_oxlint/ts/rules/prefer_promise_reject_errors.ts
|
|
5
5
|
const defaults = {
|
|
@@ -1,19 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { createNativeRule } from "./rule_creator.js";
|
|
1
|
+
import { createRustNativeRule } from "./native_bridge.js";
|
|
3
2
|
//#region src/bindings/nodejs/typescript_oxlint/ts/rules/prefer_regexp_exec.ts
|
|
4
|
-
const preferRegexpExecRule =
|
|
5
|
-
docs: { description: "Prefer RegExp#exec over String#match for single matches." },
|
|
6
|
-
messages: { unexpected: "Use a RegExp exec() call instead of String match()." }
|
|
7
|
-
}, (context) => ({ CallExpression(node) {
|
|
8
|
-
if (calleePropertyName(node) !== "match") return;
|
|
9
|
-
const [firstArgument] = node.arguments;
|
|
10
|
-
if (!firstArgument) return;
|
|
11
|
-
const flags = regexFlags(firstArgument);
|
|
12
|
-
if (flags !== void 0 && !flags.includes("g")) context.report({
|
|
13
|
-
node,
|
|
14
|
-
messageId: "unexpected"
|
|
15
|
-
});
|
|
16
|
-
} }));
|
|
3
|
+
const preferRegexpExecRule = createRustNativeRule("prefer-regexp-exec");
|
|
17
4
|
//#endregion
|
|
18
5
|
export { preferRegexpExecRule };
|
|
19
6
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prefer_regexp_exec.js","names":[],"sources":["../../ts/rules/prefer_regexp_exec.ts"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"file":"prefer_regexp_exec.js","names":[],"sources":["../../ts/rules/prefer_regexp_exec.ts"],"sourcesContent":["import { createRustNativeRule } from \"./native_bridge\";\n\nexport const preferRegexpExecRule = createRustNativeRule(\"prefer-regexp-exec\");\n"],"mappings":";;AAEA,MAAa,uBAAuB,qBAAqB,qBAAqB"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { calleePropertyName, isZeroLiteral, memberObject, memberPropertyName, stripChainExpression } from "./ast.js";
|
|
2
1
|
import { createNativeRule } from "./rule_creator.js";
|
|
2
|
+
import { calleePropertyName, isZeroLiteral, memberObject, memberPropertyName, stripChainExpression } from "./ast.js";
|
|
3
3
|
//#region src/bindings/nodejs/typescript_oxlint/ts/rules/prefer_string_starts_ends_with.ts
|
|
4
4
|
const comparableOperators = new Set([
|
|
5
5
|
"==",
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { isStringArrayLikeTypeTexts } from "../utils.js";
|
|
2
2
|
import { createNativeRule } from "./rule_creator.js";
|
|
3
|
+
import { memberObject, memberPropertyName } from "./ast.js";
|
|
3
4
|
import { isArrayLikeNode, typeTextsAtNode } from "./type_utils.js";
|
|
4
5
|
//#region src/bindings/nodejs/typescript_oxlint/ts/rules/require_array_sort_compare.ts
|
|
5
6
|
const defaults = { ignoreStringArrays: true };
|
|
@@ -20,9 +21,7 @@ const requireArraySortCompareRule = createNativeRule("require-array-sort-compare
|
|
|
20
21
|
});
|
|
21
22
|
} }));
|
|
22
23
|
function isStringArrayLike(context, node) {
|
|
23
|
-
return typeTextsAtNode(context, node)
|
|
24
|
-
return text === "string[]" || text === "readonly string[]" || text.startsWith("Array<string>") || text.startsWith("ReadonlyArray<string>");
|
|
25
|
-
});
|
|
24
|
+
return isStringArrayLikeTypeTexts(typeTextsAtNode(context, node));
|
|
26
25
|
}
|
|
27
26
|
function resolveOptions(options) {
|
|
28
27
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"require_array_sort_compare.js","names":[],"sources":["../../ts/rules/require_array_sort_compare.ts"],"sourcesContent":["import { memberObject, memberPropertyName } from \"./ast\";\nimport { createNativeRule } from \"./rule_creator\";\nimport { isArrayLikeNode, typeTextsAtNode } from \"./type_utils\";\n\ntype Options = {\n ignoreStringArrays?: boolean;\n};\n\nconst defaults: Required<Options> = {\n ignoreStringArrays: true,\n};\n\nexport const requireArraySortCompareRule = createNativeRule(\n \"require-array-sort-compare\",\n {\n docs: {\n description: \"Require compare callbacks for array sorting calls.\",\n },\n messages: {\n requireCompare: \"Require a compare argument for array sorting.\",\n },\n schema: { type: \"array\" },\n },\n (context) => ({\n CallExpression(node: any) {\n if (node.arguments.length !== 0) {\n return;\n }\n const methodName = memberPropertyName(node.callee);\n if (methodName !== \"sort\" && methodName !== \"toSorted\") {\n return;\n }\n const object = memberObject(node.callee) as any;\n if (!object || !isArrayLikeNode(context, object)) {\n return;\n }\n if (\n resolveOptions(context.options).ignoreStringArrays &&\n isStringArrayLike(context, object)\n ) {\n return;\n }\n context.report({ node, messageId: \"requireCompare\" });\n },\n }),\n);\n\nfunction isStringArrayLike(context: any, node: any): boolean {\n return typeTextsAtNode(context, node)
|
|
1
|
+
{"version":3,"file":"require_array_sort_compare.js","names":[],"sources":["../../ts/rules/require_array_sort_compare.ts"],"sourcesContent":["import { memberObject, memberPropertyName } from \"./ast\";\nimport { createNativeRule } from \"./rule_creator\";\nimport { isArrayLikeNode, typeTextsAtNode } from \"./type_utils\";\nimport { isStringArrayLikeTypeTexts } from \"../utils\";\n\ntype Options = {\n ignoreStringArrays?: boolean;\n};\n\nconst defaults: Required<Options> = {\n ignoreStringArrays: true,\n};\n\nexport const requireArraySortCompareRule = createNativeRule(\n \"require-array-sort-compare\",\n {\n docs: {\n description: \"Require compare callbacks for array sorting calls.\",\n },\n messages: {\n requireCompare: \"Require a compare argument for array sorting.\",\n },\n schema: { type: \"array\" },\n },\n (context) => ({\n CallExpression(node: any) {\n if (node.arguments.length !== 0) {\n return;\n }\n const methodName = memberPropertyName(node.callee);\n if (methodName !== \"sort\" && methodName !== \"toSorted\") {\n return;\n }\n const object = memberObject(node.callee) as any;\n if (!object || !isArrayLikeNode(context, object)) {\n return;\n }\n if (\n resolveOptions(context.options).ignoreStringArrays &&\n isStringArrayLike(context, object)\n ) {\n return;\n }\n context.report({ node, messageId: \"requireCompare\" });\n },\n }),\n);\n\nfunction isStringArrayLike(context: any, node: any): boolean {\n return isStringArrayLikeTypeTexts(typeTextsAtNode(context, node));\n}\n\nfunction resolveOptions(options: readonly unknown[]): Required<Options> {\n return { ...defaults, ...(options[0] as Options | undefined) };\n}\n"],"mappings":";;;;;AASA,MAAM,WAA8B,EAClC,oBAAoB,MACrB;AAED,MAAa,8BAA8B,iBACzC,8BACA;CACE,MAAM,EACJ,aAAa,sDACd;CACD,UAAU,EACR,gBAAgB,iDACjB;CACD,QAAQ,EAAE,MAAM,SAAS;CAC1B,GACA,aAAa,EACZ,eAAe,MAAW;AACxB,KAAI,KAAK,UAAU,WAAW,EAC5B;CAEF,MAAM,aAAa,mBAAmB,KAAK,OAAO;AAClD,KAAI,eAAe,UAAU,eAAe,WAC1C;CAEF,MAAM,SAAS,aAAa,KAAK,OAAO;AACxC,KAAI,CAAC,UAAU,CAAC,gBAAgB,SAAS,OAAO,CAC9C;AAEF,KACE,eAAe,QAAQ,QAAQ,CAAC,sBAChC,kBAAkB,SAAS,OAAO,CAElC;AAEF,SAAQ,OAAO;EAAE;EAAM,WAAW;EAAkB,CAAC;GAExD,EACF;AAED,SAAS,kBAAkB,SAAc,MAAoB;AAC3D,QAAO,2BAA2B,gBAAgB,SAAS,KAAK,CAAC;;AAGnE,SAAS,eAAe,SAAgD;AACtE,QAAO;EAAE,GAAG;EAAU,GAAI,QAAQ;EAA4B"}
|
|
@@ -1,18 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { createNativeRule } from "./rule_creator.js";
|
|
1
|
+
import { createRustNativeRule } from "./native_bridge.js";
|
|
3
2
|
//#region src/bindings/nodejs/typescript_oxlint/ts/rules/use_unknown_in_catch_callback_variable.ts
|
|
4
|
-
const useUnknownInCatchCallbackVariableRule =
|
|
5
|
-
docs: { description: "Require Promise catch callback variables to use an explicit unknown annotation." },
|
|
6
|
-
messages: { unexpected: "Catch callback variables should be explicitly typed as unknown." }
|
|
7
|
-
}, (context) => ({ CallExpression(node) {
|
|
8
|
-
const propertyName = calleePropertyName(node);
|
|
9
|
-
const callback = propertyName === "catch" ? node.arguments[0] : propertyName === "then" ? node.arguments[1] : void 0;
|
|
10
|
-
const parameter = callback?.params?.[0];
|
|
11
|
-
if (callback?.type?.includes("Function") && parameter && !hasUnknownTypeAnnotation(parameter)) context.report({
|
|
12
|
-
node: parameter,
|
|
13
|
-
messageId: "unexpected"
|
|
14
|
-
});
|
|
15
|
-
} }));
|
|
3
|
+
const useUnknownInCatchCallbackVariableRule = createRustNativeRule("use-unknown-in-catch-callback-variable");
|
|
16
4
|
//#endregion
|
|
17
5
|
export { useUnknownInCatchCallbackVariableRule };
|
|
18
6
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use_unknown_in_catch_callback_variable.js","names":[],"sources":["../../ts/rules/use_unknown_in_catch_callback_variable.ts"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"file":"use_unknown_in_catch_callback_variable.js","names":[],"sources":["../../ts/rules/use_unknown_in_catch_callback_variable.ts"],"sourcesContent":["import { createRustNativeRule } from \"./native_bridge\";\n\nexport const useUnknownInCatchCallbackVariableRule = createRustNativeRule(\n \"use-unknown-in-catch-callback-variable\",\n);\n"],"mappings":";;AAEA,MAAa,wCAAwC,qBACnD,yCACD"}
|
package/dist/utils.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { TypeTextKind, classifyTypeText, isAnyLikeTypeTexts, isArrayLikeTypeTexts, isBigIntLikeTypeTexts, isErrorLikeTypeTexts, isNumberLikeTypeTexts, isPromiseLikeTypeTexts, isStringLikeTypeTexts, isUnknownLikeTypeTexts, splitTopLevelTypeText, splitTypeText } from "@corsa-bind/napi";
|
|
1
|
+
import { TypeTextKind, classifyTypeText, isAnyLikeTypeTexts, isArrayLikeTypeTexts, isBigIntLikeTypeTexts, isErrorLikeTypeTexts, isNumberLikeTypeTexts, isPromiseLikeTypeTexts, isStringArrayLikeTypeTexts, isStringLikeTypeTexts, isUnknownLikeTypeTexts, splitTopLevelTypeText, splitTypeText } from "@corsa-bind/napi";
|
|
2
2
|
|
|
3
3
|
//#region src/bindings/nodejs/typescript_oxlint/ts/utils.d.ts
|
|
4
4
|
declare namespace utils_d_exports {
|
|
5
|
-
export { TypeTextKind, Utils, classifyTypeText, isAnyLikeTypeTexts, isArrayLikeTypeTexts, isBigIntLikeTypeTexts, isErrorLikeTypeTexts, isNumberLikeTypeTexts, isPromiseLikeTypeTexts, isStringLikeTypeTexts, isUnknownLikeTypeTexts, splitTopLevelTypeText, splitTypeText };
|
|
5
|
+
export { TypeTextKind, Utils, classifyTypeText, isAnyLikeTypeTexts, isArrayLikeTypeTexts, isBigIntLikeTypeTexts, isErrorLikeTypeTexts, isNumberLikeTypeTexts, isPromiseLikeTypeTexts, isStringArrayLikeTypeTexts, isStringLikeTypeTexts, isUnknownLikeTypeTexts, splitTopLevelTypeText, splitTypeText };
|
|
6
6
|
}
|
|
7
7
|
declare const Utils: Readonly<{
|
|
8
8
|
classifyTypeText: typeof classifyTypeText;
|
|
@@ -14,9 +14,10 @@ declare const Utils: Readonly<{
|
|
|
14
14
|
isAnyLikeTypeTexts: typeof isAnyLikeTypeTexts;
|
|
15
15
|
isUnknownLikeTypeTexts: typeof isUnknownLikeTypeTexts;
|
|
16
16
|
isArrayLikeTypeTexts: typeof isArrayLikeTypeTexts;
|
|
17
|
+
isStringArrayLikeTypeTexts: typeof isStringArrayLikeTypeTexts;
|
|
17
18
|
isPromiseLikeTypeTexts: typeof isPromiseLikeTypeTexts;
|
|
18
19
|
isErrorLikeTypeTexts: typeof isErrorLikeTypeTexts;
|
|
19
20
|
}>;
|
|
20
21
|
//#endregion
|
|
21
|
-
export { type TypeTextKind, Utils, classifyTypeText, isAnyLikeTypeTexts, isArrayLikeTypeTexts, isBigIntLikeTypeTexts, isErrorLikeTypeTexts, isNumberLikeTypeTexts, isPromiseLikeTypeTexts, isStringLikeTypeTexts, isUnknownLikeTypeTexts, splitTopLevelTypeText, splitTypeText, utils_d_exports };
|
|
22
|
+
export { type TypeTextKind, Utils, classifyTypeText, isAnyLikeTypeTexts, isArrayLikeTypeTexts, isBigIntLikeTypeTexts, isErrorLikeTypeTexts, isNumberLikeTypeTexts, isPromiseLikeTypeTexts, isStringArrayLikeTypeTexts, isStringLikeTypeTexts, isUnknownLikeTypeTexts, splitTopLevelTypeText, splitTypeText, utils_d_exports };
|
|
22
23
|
//# sourceMappingURL=utils.d.ts.map
|
package/dist/utils.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { __exportAll } from "./_virtual/_rolldown/runtime.js";
|
|
2
|
-
import { Utils as Utils$1, classifyTypeText, isAnyLikeTypeTexts, isArrayLikeTypeTexts, isBigIntLikeTypeTexts, isErrorLikeTypeTexts, isNumberLikeTypeTexts, isPromiseLikeTypeTexts, isStringLikeTypeTexts, isUnknownLikeTypeTexts, splitTopLevelTypeText, splitTypeText } from "@corsa-bind/napi";
|
|
2
|
+
import { Utils as Utils$1, classifyTypeText, isAnyLikeTypeTexts, isArrayLikeTypeTexts, isBigIntLikeTypeTexts, isErrorLikeTypeTexts, isNumberLikeTypeTexts, isPromiseLikeTypeTexts, isStringArrayLikeTypeTexts, isStringLikeTypeTexts, isUnknownLikeTypeTexts, splitTopLevelTypeText, splitTypeText } from "@corsa-bind/napi";
|
|
3
3
|
//#region src/bindings/nodejs/typescript_oxlint/ts/utils.ts
|
|
4
4
|
var utils_exports = /* @__PURE__ */ __exportAll({
|
|
5
5
|
Utils: () => Utils,
|
|
@@ -10,6 +10,7 @@ var utils_exports = /* @__PURE__ */ __exportAll({
|
|
|
10
10
|
isErrorLikeTypeTexts: () => isErrorLikeTypeTexts,
|
|
11
11
|
isNumberLikeTypeTexts: () => isNumberLikeTypeTexts,
|
|
12
12
|
isPromiseLikeTypeTexts: () => isPromiseLikeTypeTexts,
|
|
13
|
+
isStringArrayLikeTypeTexts: () => isStringArrayLikeTypeTexts,
|
|
13
14
|
isStringLikeTypeTexts: () => isStringLikeTypeTexts,
|
|
14
15
|
isUnknownLikeTypeTexts: () => isUnknownLikeTypeTexts,
|
|
15
16
|
splitTopLevelTypeText: () => splitTopLevelTypeText,
|
|
@@ -17,6 +18,6 @@ var utils_exports = /* @__PURE__ */ __exportAll({
|
|
|
17
18
|
});
|
|
18
19
|
const Utils = Utils$1;
|
|
19
20
|
//#endregion
|
|
20
|
-
export { Utils, classifyTypeText, isAnyLikeTypeTexts, isArrayLikeTypeTexts, isBigIntLikeTypeTexts, isErrorLikeTypeTexts, isNumberLikeTypeTexts, isPromiseLikeTypeTexts, isStringLikeTypeTexts, isUnknownLikeTypeTexts, splitTopLevelTypeText, splitTypeText, utils_exports };
|
|
21
|
+
export { Utils, classifyTypeText, isAnyLikeTypeTexts, isArrayLikeTypeTexts, isBigIntLikeTypeTexts, isErrorLikeTypeTexts, isNumberLikeTypeTexts, isPromiseLikeTypeTexts, isStringArrayLikeTypeTexts, isStringLikeTypeTexts, isUnknownLikeTypeTexts, splitTopLevelTypeText, splitTypeText, utils_exports };
|
|
21
22
|
|
|
22
23
|
//# sourceMappingURL=utils.js.map
|
package/dist/utils.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","names":["NodeUtils"],"sources":["../ts/utils.ts"],"sourcesContent":["import {\n Utils as NodeUtils,\n classifyTypeText,\n isAnyLikeTypeTexts,\n isArrayLikeTypeTexts,\n isBigIntLikeTypeTexts,\n isErrorLikeTypeTexts,\n isNumberLikeTypeTexts,\n isPromiseLikeTypeTexts,\n isStringLikeTypeTexts,\n isUnknownLikeTypeTexts,\n splitTopLevelTypeText,\n splitTypeText,\n} from \"@corsa-bind/napi\";\n\nexport type { TypeTextKind } from \"@corsa-bind/napi\";\n\nexport {\n classifyTypeText,\n isAnyLikeTypeTexts,\n isArrayLikeTypeTexts,\n isBigIntLikeTypeTexts,\n isErrorLikeTypeTexts,\n isNumberLikeTypeTexts,\n isPromiseLikeTypeTexts,\n isStringLikeTypeTexts,\n isUnknownLikeTypeTexts,\n splitTopLevelTypeText,\n splitTypeText,\n};\n\nexport const Utils = NodeUtils;\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"utils.js","names":["NodeUtils"],"sources":["../ts/utils.ts"],"sourcesContent":["import {\n Utils as NodeUtils,\n classifyTypeText,\n isAnyLikeTypeTexts,\n isArrayLikeTypeTexts,\n isBigIntLikeTypeTexts,\n isErrorLikeTypeTexts,\n isNumberLikeTypeTexts,\n isPromiseLikeTypeTexts,\n isStringArrayLikeTypeTexts,\n isStringLikeTypeTexts,\n isUnknownLikeTypeTexts,\n splitTopLevelTypeText,\n splitTypeText,\n} from \"@corsa-bind/napi\";\n\nexport type { TypeTextKind } from \"@corsa-bind/napi\";\n\nexport {\n classifyTypeText,\n isAnyLikeTypeTexts,\n isArrayLikeTypeTexts,\n isBigIntLikeTypeTexts,\n isErrorLikeTypeTexts,\n isNumberLikeTypeTexts,\n isPromiseLikeTypeTexts,\n isStringArrayLikeTypeTexts,\n isStringLikeTypeTexts,\n isUnknownLikeTypeTexts,\n splitTopLevelTypeText,\n splitTypeText,\n};\n\nexport const Utils = NodeUtils;\n"],"mappings":";;;;;;;;;;;;;;;;;;AAiCA,MAAa,QAAQA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "corsa-oxlint",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.1",
|
|
4
4
|
"description": "Type-aware Oxlint helpers powered by corsa and typescript-go",
|
|
5
5
|
"homepage": "https://github.com/ubugeeei/corsa-bind/tree/main/src/bindings/nodejs/typescript_oxlint",
|
|
6
6
|
"bugs": {
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
"dependencies": {
|
|
62
62
|
"@oxlint/plugins": "1.57.0",
|
|
63
63
|
"oxlint": "1.57.0",
|
|
64
|
-
"@corsa-bind/napi": "0.
|
|
64
|
+
"@corsa-bind/napi": "0.7.1"
|
|
65
65
|
},
|
|
66
66
|
"engines": {
|
|
67
67
|
"node": ">=22"
|