@timmo001/oxlint-rules 0.1.4 → 0.2.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 +12 -5
- package/dist/cli.js +184 -77
- package/dist/configs/effect.js +144 -72
- package/dist/configs/recommended.js +74 -2
- package/dist/generic/index.js +70 -0
- package/package.json +5 -2
- package/skills/add-oxlint-rule/SKILL.md +6 -2
- package/skills/install-timmo-oxlint-rules/SKILL.md +8 -8
- package/skills/release-oxlint-rules/SKILL.md +38 -0
- package/src/generic/index.ts +12 -0
- package/src/generic/rules/prefer-event-parameter-type.ts +83 -0
package/README.md
CHANGED
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
Shared Oxlint plugins and configs built around the unchanged
|
|
4
4
|
[`dmmulroy/anti-slop`](https://github.com/dmmulroy/anti-slop) rules, with
|
|
5
|
-
|
|
5
|
+
locally owned generic rules under `timmo` and Effect rules under
|
|
6
|
+
`timmo-effect`.
|
|
6
7
|
|
|
7
8
|
Oxlint's JavaScript plugin API is alpha. Consumers must keep `oxlint` and
|
|
8
9
|
`@oxlint/plugins` on the exact peer versions declared by this package.
|
|
@@ -49,10 +50,10 @@ Copy a reviewed snapshot when a repository should own the rule source:
|
|
|
49
50
|
npx --yes @timmo001/oxlint-rules copy tools/oxlint/timmo-rules
|
|
50
51
|
```
|
|
51
52
|
|
|
52
|
-
The command prints
|
|
53
|
-
|
|
54
|
-
It excludes tests and repository metadata, and refuses to
|
|
55
|
-
destination unless `--force` is passed.
|
|
53
|
+
The command prints every copied plugin entry point and the rule settings from
|
|
54
|
+
the package configs to merge into the target Oxlint config. Effect settings
|
|
55
|
+
remain opt-in. It excludes tests and repository metadata, and refuses to
|
|
56
|
+
replace an existing destination unless `--force` is passed.
|
|
56
57
|
|
|
57
58
|
## Rules
|
|
58
59
|
|
|
@@ -74,6 +75,12 @@ destination unless `--force` is passed.
|
|
|
74
75
|
- `no-widen-then-assert`
|
|
75
76
|
- `require-safety-comment-for-type-assertion`
|
|
76
77
|
|
|
78
|
+
### `timmo`
|
|
79
|
+
|
|
80
|
+
- `prefer-event-parameter-type`: reports assertions on a handler parameter's
|
|
81
|
+
`target` or `currentTarget`. Express the target type in the function signature
|
|
82
|
+
instead so every use sees the same contract.
|
|
83
|
+
|
|
77
84
|
### `anti-slop-effect`
|
|
78
85
|
|
|
79
86
|
- `no-service-constructor-imports`
|
package/dist/cli.js
CHANGED
|
@@ -104,11 +104,67 @@ var timmoEffectPlugin = eslintCompatPlugin({
|
|
|
104
104
|
});
|
|
105
105
|
var effect_default = timmoEffectPlugin;
|
|
106
106
|
|
|
107
|
-
// vendor/anti-slop/src/index.ts
|
|
107
|
+
// vendor/anti-slop/src/effect/index.ts
|
|
108
108
|
import { eslintCompatPlugin as eslintCompatPlugin2 } from "@oxlint/plugins";
|
|
109
109
|
|
|
110
|
-
// vendor/anti-slop/src/rules/no-
|
|
110
|
+
// vendor/anti-slop/src/effect/rules/no-service-constructor-imports.ts
|
|
111
111
|
import { defineRule as defineRule2 } from "@oxlint/plugins";
|
|
112
|
+
var SERVICE_CONSTRUCTOR_NAME = /^make[A-Z]/u;
|
|
113
|
+
var TEST_FILE = /\.(?:test|spec)\.[cm]?[jt]sx?$/u;
|
|
114
|
+
function isProjectLocalImport(source) {
|
|
115
|
+
return source.startsWith("./") || source.startsWith("../");
|
|
116
|
+
}
|
|
117
|
+
function getImportedName(specifier) {
|
|
118
|
+
if (specifier.imported.type === "Identifier")
|
|
119
|
+
return specifier.imported.name;
|
|
120
|
+
return specifier.imported.value;
|
|
121
|
+
}
|
|
122
|
+
var noServiceConstructorImportsRule = defineRule2({
|
|
123
|
+
meta: {
|
|
124
|
+
type: "problem",
|
|
125
|
+
docs: {
|
|
126
|
+
description: "Disallow project-local make<CapabilityName> imports outside test and spec files."
|
|
127
|
+
},
|
|
128
|
+
messages: {
|
|
129
|
+
serviceConstructorImport: 'Do not import Effect service constructor "{{name}}" into runtime code. Import the owning Layer, yield the contextual service, and allow its requirements to propagate to the composition root.'
|
|
130
|
+
}
|
|
131
|
+
},
|
|
132
|
+
create(context) {
|
|
133
|
+
const isTestFile = TEST_FILE.test(context.filename.replaceAll("\\", "/"));
|
|
134
|
+
return {
|
|
135
|
+
ImportDeclaration(node) {
|
|
136
|
+
if (isTestFile || !isProjectLocalImport(node.source.value))
|
|
137
|
+
return;
|
|
138
|
+
for (const specifier of node.specifiers) {
|
|
139
|
+
if (specifier.type !== "ImportSpecifier")
|
|
140
|
+
continue;
|
|
141
|
+
const importedName = getImportedName(specifier);
|
|
142
|
+
if (!SERVICE_CONSTRUCTOR_NAME.test(importedName))
|
|
143
|
+
continue;
|
|
144
|
+
context.report({
|
|
145
|
+
node: specifier,
|
|
146
|
+
messageId: "serviceConstructorImport",
|
|
147
|
+
data: { name: importedName }
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
// vendor/anti-slop/src/effect/index.ts
|
|
156
|
+
var antiSlopEffectPlugin = eslintCompatPlugin2({
|
|
157
|
+
meta: { name: "anti-slop-effect" },
|
|
158
|
+
rules: {
|
|
159
|
+
"no-service-constructor-imports": noServiceConstructorImportsRule
|
|
160
|
+
}
|
|
161
|
+
});
|
|
162
|
+
var effect_default2 = antiSlopEffectPlugin;
|
|
163
|
+
// vendor/anti-slop/src/index.ts
|
|
164
|
+
import { eslintCompatPlugin as eslintCompatPlugin3 } from "@oxlint/plugins";
|
|
165
|
+
|
|
166
|
+
// vendor/anti-slop/src/rules/no-chained-type-assertions.ts
|
|
167
|
+
import { defineRule as defineRule3 } from "@oxlint/plugins";
|
|
112
168
|
function isTypeAssertionExpression(node) {
|
|
113
169
|
return node.type === "TSAsExpression" || node.type === "TSTypeAssertion";
|
|
114
170
|
}
|
|
@@ -143,7 +199,7 @@ function isForbiddenAssertionChain(node) {
|
|
|
143
199
|
}
|
|
144
200
|
return assertionCount > 1 && hasNonConstAssertion;
|
|
145
201
|
}
|
|
146
|
-
var noChainedTypeAssertionsRule =
|
|
202
|
+
var noChainedTypeAssertionsRule = defineRule3({
|
|
147
203
|
meta: {
|
|
148
204
|
type: "problem",
|
|
149
205
|
docs: {
|
|
@@ -167,7 +223,7 @@ var noChainedTypeAssertionsRule = defineRule2({
|
|
|
167
223
|
});
|
|
168
224
|
|
|
169
225
|
// vendor/anti-slop/src/rules/no-conditional-empty-object-spread.ts
|
|
170
|
-
import { defineRule as
|
|
226
|
+
import { defineRule as defineRule4 } from "@oxlint/plugins";
|
|
171
227
|
function unwrapParentheses(node) {
|
|
172
228
|
let current = node;
|
|
173
229
|
while (current.type === "ParenthesizedExpression") {
|
|
@@ -182,7 +238,7 @@ function isConditionalEmptyObjectSpread(node) {
|
|
|
182
238
|
const conditional = unwrapParentheses(node);
|
|
183
239
|
return conditional.type === "ConditionalExpression" && (isEmptyObjectExpression(conditional.consequent) || isEmptyObjectExpression(conditional.alternate));
|
|
184
240
|
}
|
|
185
|
-
var noConditionalEmptyObjectSpreadRule =
|
|
241
|
+
var noConditionalEmptyObjectSpreadRule = defineRule4({
|
|
186
242
|
meta: {
|
|
187
243
|
type: "suggestion",
|
|
188
244
|
docs: {
|
|
@@ -206,7 +262,7 @@ var noConditionalEmptyObjectSpreadRule = defineRule3({
|
|
|
206
262
|
});
|
|
207
263
|
|
|
208
264
|
// vendor/anti-slop/src/rules/no-known-value-widening.ts
|
|
209
|
-
import { defineRule as
|
|
265
|
+
import { defineRule as defineRule5 } from "@oxlint/plugins";
|
|
210
266
|
|
|
211
267
|
// vendor/anti-slop/src/shared/lexical-type-parameters.ts
|
|
212
268
|
function isNode(value) {
|
|
@@ -905,7 +961,7 @@ function isDictionaryAccumulatorTarget(destination) {
|
|
|
905
961
|
function hasParentAssertion(node) {
|
|
906
962
|
return node.parent?.type === "TSAsExpression" || node.parent?.type === "TSTypeAssertion";
|
|
907
963
|
}
|
|
908
|
-
var noKnownValueWideningRule =
|
|
964
|
+
var noKnownValueWideningRule = defineRule5({
|
|
909
965
|
meta: {
|
|
910
966
|
type: "problem",
|
|
911
967
|
docs: {
|
|
@@ -1018,7 +1074,7 @@ var noKnownValueWideningRule = defineRule4({
|
|
|
1018
1074
|
});
|
|
1019
1075
|
|
|
1020
1076
|
// vendor/anti-slop/src/rules/no-module-mocking.ts
|
|
1021
|
-
import { defineRule as
|
|
1077
|
+
import { defineRule as defineRule6 } from "@oxlint/plugins";
|
|
1022
1078
|
var moduleMockMethods = new Set(["doMock", "mock", "unstable_mockModule"]);
|
|
1023
1079
|
function resolveVariable3(sourceCode, identifier) {
|
|
1024
1080
|
let scope = sourceCode.getScope(identifier);
|
|
@@ -1063,7 +1119,7 @@ function moduleMockCall(sourceCode, callee) {
|
|
|
1063
1119
|
const method = callee.computed ? property.type === "Literal" && (property.value === "doMock" || property.value === "mock" || property.value === "unstable_mockModule") ? property.value : null : property.type === "Identifier" ? property.name : null;
|
|
1064
1120
|
return method !== null && moduleMockMethods.has(method);
|
|
1065
1121
|
}
|
|
1066
|
-
var noModuleMockingRule =
|
|
1122
|
+
var noModuleMockingRule = defineRule6({
|
|
1067
1123
|
meta: {
|
|
1068
1124
|
type: "problem",
|
|
1069
1125
|
docs: {
|
|
@@ -1087,8 +1143,8 @@ var noModuleMockingRule = defineRule5({
|
|
|
1087
1143
|
});
|
|
1088
1144
|
|
|
1089
1145
|
// vendor/anti-slop/src/rules/no-object-parameters.ts
|
|
1090
|
-
import { defineRule as
|
|
1091
|
-
var noObjectParametersRule =
|
|
1146
|
+
import { defineRule as defineRule7 } from "@oxlint/plugins";
|
|
1147
|
+
var noObjectParametersRule = defineRule7({
|
|
1092
1148
|
meta: {
|
|
1093
1149
|
type: "problem",
|
|
1094
1150
|
docs: {
|
|
@@ -1141,7 +1197,7 @@ var noObjectParametersRule = defineRule6({
|
|
|
1141
1197
|
});
|
|
1142
1198
|
|
|
1143
1199
|
// vendor/anti-slop/src/rules/no-reflect-apply.ts
|
|
1144
|
-
import { defineRule as
|
|
1200
|
+
import { defineRule as defineRule8 } from "@oxlint/plugins";
|
|
1145
1201
|
|
|
1146
1202
|
// vendor/anti-slop/src/shared/reflect-method.ts
|
|
1147
1203
|
function resolveVariable4(sourceCode, identifier) {
|
|
@@ -1172,7 +1228,7 @@ function isGlobalReflectMethodCall(sourceCode, callee, methodName) {
|
|
|
1172
1228
|
}
|
|
1173
1229
|
|
|
1174
1230
|
// vendor/anti-slop/src/rules/no-reflect-apply.ts
|
|
1175
|
-
var noReflectApplyRule =
|
|
1231
|
+
var noReflectApplyRule = defineRule8({
|
|
1176
1232
|
meta: {
|
|
1177
1233
|
type: "problem",
|
|
1178
1234
|
docs: {
|
|
@@ -1196,8 +1252,8 @@ var noReflectApplyRule = defineRule7({
|
|
|
1196
1252
|
});
|
|
1197
1253
|
|
|
1198
1254
|
// vendor/anti-slop/src/rules/no-reflect-get.ts
|
|
1199
|
-
import { defineRule as
|
|
1200
|
-
var noReflectGetRule =
|
|
1255
|
+
import { defineRule as defineRule9 } from "@oxlint/plugins";
|
|
1256
|
+
var noReflectGetRule = defineRule9({
|
|
1201
1257
|
meta: {
|
|
1202
1258
|
type: "problem",
|
|
1203
1259
|
docs: {
|
|
@@ -1221,7 +1277,7 @@ var noReflectGetRule = defineRule8({
|
|
|
1221
1277
|
});
|
|
1222
1278
|
|
|
1223
1279
|
// vendor/anti-slop/src/rules/no-runtime-typeof.ts
|
|
1224
|
-
import { defineRule as
|
|
1280
|
+
import { defineRule as defineRule10 } from "@oxlint/plugins";
|
|
1225
1281
|
function isRuntimeFunction(node) {
|
|
1226
1282
|
return node.type === "ArrowFunctionExpression" || node.type === "FunctionDeclaration" || node.type === "FunctionExpression";
|
|
1227
1283
|
}
|
|
@@ -1244,7 +1300,7 @@ function isExistenceProbe(node) {
|
|
|
1244
1300
|
const other = parent.left === node ? parent.right : parent.left;
|
|
1245
1301
|
return other.type === "Literal" && other.value === "undefined";
|
|
1246
1302
|
}
|
|
1247
|
-
var noRuntimeTypeofRule =
|
|
1303
|
+
var noRuntimeTypeofRule = defineRule10({
|
|
1248
1304
|
meta: {
|
|
1249
1305
|
type: "problem",
|
|
1250
1306
|
docs: {
|
|
@@ -1278,7 +1334,7 @@ var noRuntimeTypeofRule = defineRule9({
|
|
|
1278
1334
|
});
|
|
1279
1335
|
|
|
1280
1336
|
// vendor/anti-slop/src/rules/no-shape-in-symbol-names.ts
|
|
1281
|
-
import { defineRule as
|
|
1337
|
+
import { defineRule as defineRule11 } from "@oxlint/plugins";
|
|
1282
1338
|
var FORBIDDEN_SYMBOL_NAME = "shape";
|
|
1283
1339
|
function containsForbiddenSymbolName(name) {
|
|
1284
1340
|
return name.toLowerCase().includes(FORBIDDEN_SYMBOL_NAME);
|
|
@@ -1289,7 +1345,7 @@ function isBorrowedMemberName(node) {
|
|
|
1289
1345
|
return false;
|
|
1290
1346
|
return parent.property === node && parent.computed === false;
|
|
1291
1347
|
}
|
|
1292
|
-
var noForbiddenTermInSymbolNamesRule =
|
|
1348
|
+
var noForbiddenTermInSymbolNamesRule = defineRule11({
|
|
1293
1349
|
meta: {
|
|
1294
1350
|
type: "problem",
|
|
1295
1351
|
docs: {
|
|
@@ -1318,12 +1374,12 @@ var noForbiddenTermInSymbolNamesRule = defineRule10({
|
|
|
1318
1374
|
});
|
|
1319
1375
|
|
|
1320
1376
|
// vendor/anti-slop/src/rules/no-unknown-parameters.ts
|
|
1321
|
-
import { defineRule as
|
|
1377
|
+
import { defineRule as defineRule12 } from "@oxlint/plugins";
|
|
1322
1378
|
function isTypePredicateSubject(owner, parameterName) {
|
|
1323
1379
|
const predicate = owner.returnType?.typeAnnotation;
|
|
1324
1380
|
return predicate?.type === "TSTypePredicate" && predicate.parameterName.type === "Identifier" && predicate.parameterName.name === parameterName;
|
|
1325
1381
|
}
|
|
1326
|
-
var noUnknownParametersRule =
|
|
1382
|
+
var noUnknownParametersRule = defineRule12({
|
|
1327
1383
|
meta: {
|
|
1328
1384
|
type: "problem",
|
|
1329
1385
|
docs: {
|
|
@@ -1367,8 +1423,8 @@ var noUnknownParametersRule = defineRule11({
|
|
|
1367
1423
|
});
|
|
1368
1424
|
|
|
1369
1425
|
// vendor/anti-slop/src/rules/no-unknown-returns.ts
|
|
1370
|
-
import { defineRule as
|
|
1371
|
-
var noUnknownReturnsRule =
|
|
1426
|
+
import { defineRule as defineRule13 } from "@oxlint/plugins";
|
|
1427
|
+
var noUnknownReturnsRule = defineRule13({
|
|
1372
1428
|
meta: {
|
|
1373
1429
|
type: "problem",
|
|
1374
1430
|
docs: {
|
|
@@ -1421,8 +1477,8 @@ var noUnknownReturnsRule = defineRule12({
|
|
|
1421
1477
|
});
|
|
1422
1478
|
|
|
1423
1479
|
// vendor/anti-slop/src/rules/no-unknown-type-aliases.ts
|
|
1424
|
-
import { defineRule as
|
|
1425
|
-
var noUnknownTypeAliasesRule =
|
|
1480
|
+
import { defineRule as defineRule14 } from "@oxlint/plugins";
|
|
1481
|
+
var noUnknownTypeAliasesRule = defineRule14({
|
|
1426
1482
|
meta: {
|
|
1427
1483
|
type: "problem",
|
|
1428
1484
|
docs: {
|
|
@@ -1460,7 +1516,7 @@ var noUnknownTypeAliasesRule = defineRule13({
|
|
|
1460
1516
|
});
|
|
1461
1517
|
|
|
1462
1518
|
// vendor/anti-slop/src/rules/no-unsafe-dictionary-type.ts
|
|
1463
|
-
import { defineRule as
|
|
1519
|
+
import { defineRule as defineRule15 } from "@oxlint/plugins";
|
|
1464
1520
|
var typeNodeKinds = new Set([
|
|
1465
1521
|
"JSDocNonNullableType",
|
|
1466
1522
|
"JSDocNullableType",
|
|
@@ -1547,7 +1603,7 @@ function shouldReportType(node, environment) {
|
|
|
1547
1603
|
}
|
|
1548
1604
|
return true;
|
|
1549
1605
|
}
|
|
1550
|
-
var noUnsafeDictionaryTypeRule =
|
|
1606
|
+
var noUnsafeDictionaryTypeRule = defineRule15({
|
|
1551
1607
|
meta: {
|
|
1552
1608
|
type: "problem",
|
|
1553
1609
|
docs: {
|
|
@@ -1589,7 +1645,7 @@ var noUnsafeDictionaryTypeRule = defineRule14({
|
|
|
1589
1645
|
});
|
|
1590
1646
|
|
|
1591
1647
|
// vendor/anti-slop/src/rules/no-widen-then-assert.ts
|
|
1592
|
-
import { defineRule as
|
|
1648
|
+
import { defineRule as defineRule16 } from "@oxlint/plugins";
|
|
1593
1649
|
var functionBoundaryTypes = new Set([
|
|
1594
1650
|
"ArrowFunctionExpression",
|
|
1595
1651
|
"FunctionDeclaration",
|
|
@@ -1785,7 +1841,7 @@ function assertionIsNarrower(sourceText, broadKind, evidence, assertedType) {
|
|
|
1785
1841
|
return isDefinitelyObjectType(assertedType);
|
|
1786
1842
|
return isDefinitelyNarrowerRecordType(assertedType);
|
|
1787
1843
|
}
|
|
1788
|
-
var noWidenThenAssertRule =
|
|
1844
|
+
var noWidenThenAssertRule = defineRule16({
|
|
1789
1845
|
meta: {
|
|
1790
1846
|
type: "problem",
|
|
1791
1847
|
docs: {
|
|
@@ -1825,7 +1881,7 @@ var noWidenThenAssertRule = defineRule15({
|
|
|
1825
1881
|
});
|
|
1826
1882
|
|
|
1827
1883
|
// vendor/anti-slop/src/rules/require-safety-comment-for-type-assertion.ts
|
|
1828
|
-
import { defineRule as
|
|
1884
|
+
import { defineRule as defineRule17 } from "@oxlint/plugins";
|
|
1829
1885
|
var DEFAULT_SAFETY_MARKERS = ["SAFETY"];
|
|
1830
1886
|
var commentOwnerKinds = new Set([
|
|
1831
1887
|
"ExpressionStatement",
|
|
@@ -1868,7 +1924,7 @@ function hasSafetyComment(sourceCode, node, pattern) {
|
|
|
1868
1924
|
current = current.parent;
|
|
1869
1925
|
}
|
|
1870
1926
|
}
|
|
1871
|
-
var requireSafetyCommentForTypeAssertionRule =
|
|
1927
|
+
var requireSafetyCommentForTypeAssertionRule = defineRule17({
|
|
1872
1928
|
meta: {
|
|
1873
1929
|
type: "problem",
|
|
1874
1930
|
docs: {
|
|
@@ -1918,7 +1974,7 @@ var requireSafetyCommentForTypeAssertionRule = defineRule16({
|
|
|
1918
1974
|
});
|
|
1919
1975
|
|
|
1920
1976
|
// vendor/anti-slop/src/index.ts
|
|
1921
|
-
var antiSlopPlugin =
|
|
1977
|
+
var antiSlopPlugin = eslintCompatPlugin3({
|
|
1922
1978
|
meta: { name: "anti-slop" },
|
|
1923
1979
|
rules: {
|
|
1924
1980
|
"no-chained-type-assertions": noChainedTypeAssertionsRule,
|
|
@@ -1939,70 +1995,120 @@ var antiSlopPlugin = eslintCompatPlugin2({
|
|
|
1939
1995
|
}
|
|
1940
1996
|
});
|
|
1941
1997
|
var src_default = antiSlopPlugin;
|
|
1942
|
-
//
|
|
1943
|
-
import { eslintCompatPlugin as
|
|
1998
|
+
// src/generic/index.ts
|
|
1999
|
+
import { eslintCompatPlugin as eslintCompatPlugin4 } from "@oxlint/plugins";
|
|
1944
2000
|
|
|
1945
|
-
//
|
|
1946
|
-
import { defineRule as
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
2001
|
+
// src/generic/rules/prefer-event-parameter-type.ts
|
|
2002
|
+
import { defineRule as defineRule18 } from "@oxlint/plugins";
|
|
2003
|
+
function nearestEnclosingFunction2(node) {
|
|
2004
|
+
let current = node.parent;
|
|
2005
|
+
while (current) {
|
|
2006
|
+
if (current.type === "FunctionDeclaration" || current.type === "FunctionExpression" || current.type === "ArrowFunctionExpression") {
|
|
2007
|
+
return current;
|
|
2008
|
+
}
|
|
2009
|
+
current = current.parent;
|
|
2010
|
+
}
|
|
2011
|
+
return null;
|
|
1951
2012
|
}
|
|
1952
|
-
function
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
2013
|
+
function assertedEventParameter(node) {
|
|
2014
|
+
const expression = node.expression;
|
|
2015
|
+
if (expression.type !== "MemberExpression" || expression.computed || expression.object.type !== "Identifier" || expression.property.type !== "Identifier" || expression.property.name !== "currentTarget" && expression.property.name !== "target") {
|
|
2016
|
+
return null;
|
|
2017
|
+
}
|
|
2018
|
+
const parameterName = expression.object.name;
|
|
2019
|
+
const property = expression.property.name;
|
|
2020
|
+
const owner = nearestEnclosingFunction2(node);
|
|
2021
|
+
if (!owner?.params.some((parameter) => parameter.type === "Identifier" && parameter.name === parameterName)) {
|
|
2022
|
+
return null;
|
|
2023
|
+
}
|
|
2024
|
+
return {
|
|
2025
|
+
parameter: parameterName,
|
|
2026
|
+
property
|
|
2027
|
+
};
|
|
1956
2028
|
}
|
|
1957
|
-
var
|
|
2029
|
+
var preferEventParameterTypeRule = defineRule18({
|
|
1958
2030
|
meta: {
|
|
1959
|
-
type: "
|
|
2031
|
+
type: "suggestion",
|
|
1960
2032
|
docs: {
|
|
1961
|
-
description: "
|
|
2033
|
+
description: "Prefer typing event target properties in the handler parameter instead of asserting them at use sites."
|
|
1962
2034
|
},
|
|
1963
2035
|
messages: {
|
|
1964
|
-
|
|
2036
|
+
typeEventParameter: "Type `{{parameter}}.{{property}}` in the function signature instead of asserting it at the use site."
|
|
1965
2037
|
}
|
|
1966
2038
|
},
|
|
1967
2039
|
create(context) {
|
|
1968
|
-
const
|
|
2040
|
+
const checkAssertion = (node) => {
|
|
2041
|
+
const eventParameter = assertedEventParameter(node);
|
|
2042
|
+
if (!eventParameter)
|
|
2043
|
+
return;
|
|
2044
|
+
context.report({
|
|
2045
|
+
node,
|
|
2046
|
+
messageId: "typeEventParameter",
|
|
2047
|
+
data: eventParameter
|
|
2048
|
+
});
|
|
2049
|
+
};
|
|
1969
2050
|
return {
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
return;
|
|
1973
|
-
for (const specifier of node.specifiers) {
|
|
1974
|
-
if (specifier.type !== "ImportSpecifier")
|
|
1975
|
-
continue;
|
|
1976
|
-
const importedName2 = getImportedName(specifier);
|
|
1977
|
-
if (!SERVICE_CONSTRUCTOR_NAME.test(importedName2))
|
|
1978
|
-
continue;
|
|
1979
|
-
context.report({
|
|
1980
|
-
node: specifier,
|
|
1981
|
-
messageId: "serviceConstructorImport",
|
|
1982
|
-
data: { name: importedName2 }
|
|
1983
|
-
});
|
|
1984
|
-
}
|
|
1985
|
-
}
|
|
2051
|
+
TSAsExpression: checkAssertion,
|
|
2052
|
+
TSTypeAssertion: checkAssertion
|
|
1986
2053
|
};
|
|
1987
2054
|
}
|
|
1988
2055
|
});
|
|
1989
2056
|
|
|
1990
|
-
//
|
|
1991
|
-
var
|
|
1992
|
-
meta: { name: "
|
|
2057
|
+
// src/generic/index.ts
|
|
2058
|
+
var timmoPlugin = eslintCompatPlugin4({
|
|
2059
|
+
meta: { name: "timmo" },
|
|
1993
2060
|
rules: {
|
|
1994
|
-
"
|
|
2061
|
+
"prefer-event-parameter-type": preferEventParameterTypeRule
|
|
1995
2062
|
}
|
|
1996
2063
|
});
|
|
1997
|
-
var
|
|
1998
|
-
|
|
1999
|
-
|
|
2064
|
+
var generic_default = timmoPlugin;
|
|
2065
|
+
|
|
2066
|
+
// node_modules/oxlint/dist/index.js
|
|
2067
|
+
function defineConfig(config) {
|
|
2068
|
+
return config;
|
|
2069
|
+
}
|
|
2000
2070
|
|
|
2001
2071
|
// src/configs/enable-plugin-rules.ts
|
|
2002
2072
|
function enablePluginRules(namespace, plugin) {
|
|
2003
2073
|
return Object.fromEntries(Object.keys(plugin.rules).sort().map((rule) => [`${namespace}/${rule}`, "error"]));
|
|
2004
2074
|
}
|
|
2005
2075
|
|
|
2076
|
+
// src/configs/recommended.ts
|
|
2077
|
+
var recommended = defineConfig({
|
|
2078
|
+
jsPlugins: [
|
|
2079
|
+
{
|
|
2080
|
+
name: "anti-slop",
|
|
2081
|
+
specifier: "@timmo001/oxlint-rules/upstream/anti-slop"
|
|
2082
|
+
},
|
|
2083
|
+
{ name: "timmo", specifier: "@timmo001/oxlint-rules/generic" }
|
|
2084
|
+
],
|
|
2085
|
+
rules: {
|
|
2086
|
+
...enablePluginRules("anti-slop", src_default),
|
|
2087
|
+
...enablePluginRules("timmo", generic_default)
|
|
2088
|
+
}
|
|
2089
|
+
});
|
|
2090
|
+
var recommended_default = recommended;
|
|
2091
|
+
|
|
2092
|
+
// src/configs/effect.ts
|
|
2093
|
+
var effect = defineConfig({
|
|
2094
|
+
extends: [recommended_default],
|
|
2095
|
+
jsPlugins: [
|
|
2096
|
+
{
|
|
2097
|
+
name: "anti-slop-effect",
|
|
2098
|
+
specifier: "@timmo001/oxlint-rules/upstream/effect"
|
|
2099
|
+
},
|
|
2100
|
+
{ name: "timmo-effect", specifier: "@timmo001/oxlint-rules/effect" }
|
|
2101
|
+
],
|
|
2102
|
+
rules: {
|
|
2103
|
+
...enablePluginRules("anti-slop-effect", effect_default2),
|
|
2104
|
+
...enablePluginRules("timmo-effect", effect_default)
|
|
2105
|
+
}
|
|
2106
|
+
});
|
|
2107
|
+
var effect_default3 = effect;
|
|
2108
|
+
|
|
2109
|
+
// src/cli.ts
|
|
2110
|
+
import { resolve as resolve2 } from "node:path";
|
|
2111
|
+
|
|
2006
2112
|
// src/install/copy.ts
|
|
2007
2113
|
import { cp, mkdir, readdir, rm } from "node:fs/promises";
|
|
2008
2114
|
import { dirname, join, relative, resolve, sep } from "node:path";
|
|
@@ -2039,11 +2145,14 @@ async function copyRules(destination, options = {}) {
|
|
|
2039
2145
|
await cp(join(root, "vendor/anti-slop/LICENSE"), join(target, "upstream/effect/LICENSE"));
|
|
2040
2146
|
await copyTree(join(root, "src/effect"), join(target, "effect"));
|
|
2041
2147
|
await cp(join(root, "LICENSE"), join(target, "effect/LICENSE"));
|
|
2148
|
+
await copyTree(join(root, "src/generic"), join(target, "generic"));
|
|
2149
|
+
await cp(join(root, "LICENSE"), join(target, "generic/LICENSE"));
|
|
2042
2150
|
const displayRoot = relative(process.cwd(), target) || ".";
|
|
2043
2151
|
const entryPoint = (path) => `./${path.split(sep).join("/")}`;
|
|
2044
2152
|
return {
|
|
2045
2153
|
antiSlop: entryPoint(join(displayRoot, "upstream/anti-slop/index.ts")),
|
|
2046
2154
|
antiSlopEffect: entryPoint(join(displayRoot, "upstream/effect/index.ts")),
|
|
2155
|
+
timmo: entryPoint(join(displayRoot, "generic/index.ts")),
|
|
2047
2156
|
timmoEffect: entryPoint(join(displayRoot, "effect/index.ts"))
|
|
2048
2157
|
};
|
|
2049
2158
|
}
|
|
@@ -2077,12 +2186,10 @@ if (command === "--help" || command === "-h") {
|
|
|
2077
2186
|
console.log("Copied Oxlint plugins:");
|
|
2078
2187
|
console.log(` anti-slop: ${entries.antiSlop}`);
|
|
2079
2188
|
console.log(` anti-slop-effect: ${entries.antiSlopEffect}`);
|
|
2189
|
+
console.log(` timmo: ${entries.timmo}`);
|
|
2080
2190
|
console.log(` timmo-effect: ${entries.timmoEffect}`);
|
|
2081
|
-
printRuleSettings("General rule settings:",
|
|
2082
|
-
printRuleSettings("Effect rule settings (opt-in):", {
|
|
2083
|
-
...enablePluginRules("anti-slop-effect", effect_default2),
|
|
2084
|
-
...enablePluginRules("timmo-effect", effect_default)
|
|
2085
|
-
});
|
|
2191
|
+
printRuleSettings("General rule settings:", recommended_default.rules ?? {});
|
|
2192
|
+
printRuleSettings("Effect rule settings (opt-in):", effect_default3.rules ?? {});
|
|
2086
2193
|
} catch (error) {
|
|
2087
2194
|
console.error(error instanceof Error ? error.message : String(error));
|
|
2088
2195
|
process.exitCode = 1;
|