oxlint-plugin-arch 0.3.3 → 0.3.4
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/CHANGELOG.md +10 -2
- package/README.md +17 -0
- package/dist/index.js +102 -68
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,8 +1,16 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
##
|
|
3
|
+
## Unreleased
|
|
4
4
|
|
|
5
|
-
-
|
|
5
|
+
- Options that took one regex string now also take a non-empty list, where any pattern may match: `pattern`, `allowPattern`, `allowNamePattern`, `denyTypePattern`, `hookPattern`, `rootPattern`, `factoryPattern`, `forbid`, and `require`. Single strings keep their behavior.
|
|
6
|
+
- `no-type-declarations` `allowPattern` entries starting with `=` or `^=` match a type alias's value (`= ` plus its source text) instead of its name, so `'^= ReturnType<typeof '` keeps factory return types next to their factory. A name pattern that starts with `=` or `^=` is now read as a value pattern.
|
|
7
|
+
- Fix `declaration-name` `pattern` with `g` or `y` flags rejecting every name after the first match.
|
|
8
|
+
|
|
9
|
+
## 0.3.3
|
|
10
|
+
|
|
11
|
+
Version 0.3.2 was tagged but never published to npm; 0.3.3 contains its fixes.
|
|
12
|
+
|
|
13
|
+
- Fix `chain-newline` reporting chains that already have one call per line when the root is parenthesized (`(db as TestDb)\n .insertInto()`), the root spans several lines, or a comment sits between two links.
|
|
6
14
|
- Autofix `call-array-multiline` arrays with parenthesized elements, like `Promise.all([(a), (b)])`.
|
|
7
15
|
|
|
8
16
|
## 0.3.1
|
package/README.md
CHANGED
|
@@ -76,6 +76,8 @@ export default defineConfig({
|
|
|
76
76
|
|
|
77
77
|
42 rules in 9 groups. 🔧 means the rule can autofix. Each rule file in [`src/rules/`](src/rules) explains its behavior in plain English, and the tests in [`src/tests/`](src/tests) show every option shape.
|
|
78
78
|
|
|
79
|
+
Options that take one regex string (`pattern`, `allowPattern`, `forbid`, `require`, and the other `*Pattern` options) also take a non-empty list; any pattern in the list may match. Options that were already lists, such as `allowPatterns` and `allowCallees`, are unchanged.
|
|
80
|
+
|
|
79
81
|
### 📁 Files & folders
|
|
80
82
|
|
|
81
83
|
| Rule | What it enforces |
|
|
@@ -198,6 +200,21 @@ Use `no-type-declarations` separately to control where named types may live. Wit
|
|
|
198
200
|
|
|
199
201
|
</details>
|
|
200
202
|
|
|
203
|
+
### `no-type-declarations`
|
|
204
|
+
|
|
205
|
+
Rejects type aliases and interfaces in matched files, so types live in one place.
|
|
206
|
+
|
|
207
|
+
| Option | Default | What it does |
|
|
208
|
+
| --- | --- | --- |
|
|
209
|
+
| `allowPattern` | none | Keep a declaration whose **name** matches. A pattern that starts with `=` or `^=` matches a type alias's **value** instead: `= ` followed by the value's source text, without surrounding parentheses or comments. Interfaces have no value, so only name patterns apply to them. |
|
|
210
|
+
|
|
211
|
+
```ts
|
|
212
|
+
// allowPattern: ['(Service|Deps)$', '^= ReturnType<typeof ']
|
|
213
|
+
export type AiRetry = ReturnType<typeof makeAiRetry> // ✅ value matches
|
|
214
|
+
export interface OrderDeps { db: Database } // ✅ name matches
|
|
215
|
+
export type OrderCreateParams = { id: string } // ❌ move it to your types file
|
|
216
|
+
```
|
|
217
|
+
|
|
201
218
|
### `only-export-constants`
|
|
202
219
|
|
|
203
220
|
Every runtime export must point to a local `const`. Direct, destructured, renamed, and default exports of local constants all work.
|
package/dist/index.js
CHANGED
|
@@ -551,6 +551,27 @@ function factoriesObjectPropertyName(property) {
|
|
|
551
551
|
function optionsFirst(context, fallback) {
|
|
552
552
|
return context.options[0] ?? fallback;
|
|
553
553
|
}
|
|
554
|
+
var optionsPatternSchema = {
|
|
555
|
+
anyOf: [
|
|
556
|
+
{ type: "string" },
|
|
557
|
+
{ type: "array", items: { type: "string" }, minItems: 1 }
|
|
558
|
+
]
|
|
559
|
+
};
|
|
560
|
+
function optionsPatterns(pattern, flags) {
|
|
561
|
+
return pattern === undefined ? [] : [pattern].flat().map((source) => new RegExp(source, flags));
|
|
562
|
+
}
|
|
563
|
+
function optionsOptionalPatterns(pattern, flags) {
|
|
564
|
+
return optionsPatterns(pattern === undefined ? undefined : [pattern].flat().filter((source) => source !== ""), flags);
|
|
565
|
+
}
|
|
566
|
+
function optionsPatternLabel(pattern) {
|
|
567
|
+
return pattern === undefined ? "" : [pattern].flat().join(" | ");
|
|
568
|
+
}
|
|
569
|
+
function optionsPatternsTest(patterns, value) {
|
|
570
|
+
return patterns.some((pattern) => {
|
|
571
|
+
pattern.lastIndex = 0;
|
|
572
|
+
return pattern.test(value);
|
|
573
|
+
});
|
|
574
|
+
}
|
|
554
575
|
// src/utils/helpers/orpc.ts
|
|
555
576
|
function orpcFindChainCall(expression, method) {
|
|
556
577
|
if (expression.type === "CallExpression") {
|
|
@@ -947,7 +968,7 @@ function chainNewlineRootIdentifier(node) {
|
|
|
947
968
|
function chainNewlineMatches(root, links, group) {
|
|
948
969
|
if (links.length < group.minDepth)
|
|
949
970
|
return false;
|
|
950
|
-
const hasCriteria = group.methods !== undefined || group.onlyMethods !== undefined || group.
|
|
971
|
+
const hasCriteria = group.methods !== undefined || group.onlyMethods !== undefined || group.rootPatterns.length > 0;
|
|
951
972
|
if (!hasCriteria)
|
|
952
973
|
return true;
|
|
953
974
|
if (group.methods && links.some((link) => link.methodName !== null && group.methods?.has(link.methodName))) {
|
|
@@ -956,7 +977,7 @@ function chainNewlineMatches(root, links, group) {
|
|
|
956
977
|
if (group.onlyMethods && links.every((link) => link.methodName !== null && group.onlyMethods?.has(link.methodName)))
|
|
957
978
|
return true;
|
|
958
979
|
const rootName = chainNewlineRootIdentifier(root);
|
|
959
|
-
return rootName !== null && group.
|
|
980
|
+
return rootName !== null && optionsPatternsTest(group.rootPatterns, rootName);
|
|
960
981
|
}
|
|
961
982
|
var chainNewline = defineRule2({
|
|
962
983
|
meta: {
|
|
@@ -975,7 +996,7 @@ var chainNewline = defineRule2({
|
|
|
975
996
|
minDepth: { type: "integer", minimum: 1 },
|
|
976
997
|
methods: { type: "array", items: { type: "string" } },
|
|
977
998
|
onlyMethods: { type: "array", items: { type: "string" } },
|
|
978
|
-
rootPattern:
|
|
999
|
+
rootPattern: optionsPatternSchema
|
|
979
1000
|
},
|
|
980
1001
|
required: ["minDepth"]
|
|
981
1002
|
}
|
|
@@ -1001,7 +1022,7 @@ var chainNewline = defineRule2({
|
|
|
1001
1022
|
minDepth: group.minDepth,
|
|
1002
1023
|
methods: group.methods ? new Set(group.methods) : undefined,
|
|
1003
1024
|
onlyMethods: group.onlyMethods ? new Set(group.onlyMethods) : undefined,
|
|
1004
|
-
|
|
1025
|
+
rootPatterns: optionsPatterns(group.rootPattern)
|
|
1005
1026
|
}));
|
|
1006
1027
|
indentUnit = layoutIndentUnit(options.indent);
|
|
1007
1028
|
newline = layoutNewline(context.sourceCode.text);
|
|
@@ -1074,14 +1095,14 @@ var declarationName = defineRule3({
|
|
|
1074
1095
|
type: "array",
|
|
1075
1096
|
items: { type: "string", enum: [...declarationsKinds] }
|
|
1076
1097
|
},
|
|
1077
|
-
pattern:
|
|
1098
|
+
pattern: optionsPatternSchema,
|
|
1078
1099
|
flags: { type: "string" },
|
|
1079
1100
|
stem: { type: "string", enum: [...namingStemModes] },
|
|
1080
1101
|
trailingRoles: { type: "array", items: { type: "string" } },
|
|
1081
1102
|
roleSeparators: { type: "array", items: { type: "string" } },
|
|
1082
1103
|
normalize: { type: "string", enum: ["remove-separators", "none"] },
|
|
1083
1104
|
singularize: { type: "string", enum: ["none", "trailing-s"] },
|
|
1084
|
-
allowPattern:
|
|
1105
|
+
allowPattern: optionsPatternSchema
|
|
1085
1106
|
}
|
|
1086
1107
|
}],
|
|
1087
1108
|
messages: {
|
|
@@ -1092,23 +1113,23 @@ var declarationName = defineRule3({
|
|
|
1092
1113
|
createOnce(context) {
|
|
1093
1114
|
let options = {};
|
|
1094
1115
|
let kinds = null;
|
|
1095
|
-
let allowed =
|
|
1096
|
-
let expected =
|
|
1116
|
+
let allowed = [];
|
|
1117
|
+
let expected = [];
|
|
1097
1118
|
let prefixes = [];
|
|
1098
1119
|
function check(node) {
|
|
1099
1120
|
const item = declarationsNamedFromNode(node);
|
|
1100
|
-
if (!item || kinds && !kinds.has(item.kind) || allowed
|
|
1121
|
+
if (!item || kinds && !kinds.has(item.kind) || optionsPatternsTest(allowed, item.name)) {
|
|
1101
1122
|
return;
|
|
1102
1123
|
}
|
|
1103
1124
|
const comparableName = options.normalize === "none" ? item.name : item.name.replaceAll("_", "").toLowerCase();
|
|
1104
|
-
const matches = expected ? expected
|
|
1125
|
+
const matches = expected.length > 0 ? optionsPatternsTest(expected, item.name) : prefixes.some((prefix) => comparableName.startsWith(prefix));
|
|
1105
1126
|
if (matches) {
|
|
1106
1127
|
return;
|
|
1107
1128
|
}
|
|
1108
1129
|
context.report({
|
|
1109
1130
|
node: item.node,
|
|
1110
|
-
messageId: expected ? "pattern" : "prefix",
|
|
1111
|
-
data: expected ? { name: item.name, pattern: options.pattern ?? "" } : { name: item.name, prefix: prefixes.join(" or ") }
|
|
1131
|
+
messageId: expected.length > 0 ? "pattern" : "prefix",
|
|
1132
|
+
data: expected.length > 0 ? { name: item.name, pattern: optionsPatternLabel([options.pattern ?? []].flat().filter((source) => source !== "")) } : { name: item.name, prefix: prefixes.join(" or ") }
|
|
1112
1133
|
});
|
|
1113
1134
|
}
|
|
1114
1135
|
return {
|
|
@@ -1118,8 +1139,8 @@ var declarationName = defineRule3({
|
|
|
1118
1139
|
normalize: "remove-separators"
|
|
1119
1140
|
});
|
|
1120
1141
|
kinds = options.kinds && options.kinds.length > 0 ? new Set(options.kinds) : null;
|
|
1121
|
-
allowed =
|
|
1122
|
-
expected =
|
|
1142
|
+
allowed = optionsOptionalPatterns(options.allowPattern);
|
|
1143
|
+
expected = optionsOptionalPatterns(options.pattern, options.flags);
|
|
1123
1144
|
const basename = namingFileBasename(context.filename).replace(/\.(tsx?|jsx?)$/, "");
|
|
1124
1145
|
const stem = namingFileStem(basename, options.stem, options.trailingRoles, options.roleSeparators);
|
|
1125
1146
|
prefixes = namingFilePrefixes(stem, options.normalize ?? "remove-separators", options.singularize ?? "none");
|
|
@@ -1149,7 +1170,7 @@ var exportFilePrefix = defineRule4({
|
|
|
1149
1170
|
normalize: { type: "string", enum: ["remove-separators", "none"] },
|
|
1150
1171
|
singularize: { type: "string", enum: ["none", "trailing-s"] },
|
|
1151
1172
|
allDeclarations: { type: "boolean" },
|
|
1152
|
-
allowPattern:
|
|
1173
|
+
allowPattern: optionsPatternSchema
|
|
1153
1174
|
}
|
|
1154
1175
|
}],
|
|
1155
1176
|
messages: {
|
|
@@ -1166,7 +1187,7 @@ var exportFilePrefix = defineRule4({
|
|
|
1166
1187
|
const basename = namingFileBasename(context.filename).replace(/\.(tsx?|jsx?)$/, "");
|
|
1167
1188
|
const stem = namingFileStem(basename, options.stem, options.trailingRoles, options.roleSeparators);
|
|
1168
1189
|
const prefixes = namingFilePrefixes(stem, options.normalize ?? "remove-separators", options.singularize ?? "none");
|
|
1169
|
-
const allowed =
|
|
1190
|
+
const allowed = optionsOptionalPatterns(options.allowPattern);
|
|
1170
1191
|
const names = options.allDeclarations ? declarationsCollectNamed(program) : exportsCollect(program).map((binding) => ({
|
|
1171
1192
|
name: binding.localName ?? binding.exportedName,
|
|
1172
1193
|
node: binding.node
|
|
@@ -1175,7 +1196,7 @@ var exportFilePrefix = defineRule4({
|
|
|
1175
1196
|
for (const item of names) {
|
|
1176
1197
|
const key = `${item.name}:${item.node.start}:${item.node.end}`;
|
|
1177
1198
|
const comparableName = options.normalize === "none" ? item.name : item.name.replaceAll("_", "").toLowerCase();
|
|
1178
|
-
if (seen.has(key) || allowed
|
|
1199
|
+
if (seen.has(key) || optionsPatternsTest(allowed, item.name) || prefixes.some((prefix) => comparableName.startsWith(prefix))) {
|
|
1179
1200
|
continue;
|
|
1180
1201
|
}
|
|
1181
1202
|
seen.add(key);
|
|
@@ -1199,11 +1220,11 @@ var exportNamePattern = defineRule5({
|
|
|
1199
1220
|
type: "object",
|
|
1200
1221
|
additionalProperties: false,
|
|
1201
1222
|
properties: {
|
|
1202
|
-
pattern:
|
|
1223
|
+
pattern: optionsPatternSchema,
|
|
1203
1224
|
flags: { type: "string" },
|
|
1204
1225
|
ignoreTypeExports: { type: "boolean" },
|
|
1205
1226
|
allDeclarations: { type: "boolean" },
|
|
1206
|
-
allowPattern:
|
|
1227
|
+
allowPattern: optionsPatternSchema
|
|
1207
1228
|
},
|
|
1208
1229
|
required: ["pattern"]
|
|
1209
1230
|
}],
|
|
@@ -1221,19 +1242,20 @@ var exportNamePattern = defineRule5({
|
|
|
1221
1242
|
allDeclarations = false,
|
|
1222
1243
|
allowPattern
|
|
1223
1244
|
} = optionsFirst(context);
|
|
1224
|
-
const allowed =
|
|
1245
|
+
const allowed = optionsOptionalPatterns(allowPattern);
|
|
1246
|
+
const expected = optionsPatterns(pattern, flags);
|
|
1225
1247
|
const names = allDeclarations ? declarationsCollectNamed(program) : exportsCollect(program).flatMap((binding) => ignoreTypeExports && binding.typeOnly ? [] : [{ name: binding.localName ?? binding.exportedName, node: binding.node }]);
|
|
1226
1248
|
const seen = new Set;
|
|
1227
1249
|
for (const item of names) {
|
|
1228
1250
|
const key = `${item.name}:${item.node.start}:${item.node.end}`;
|
|
1229
|
-
if (seen.has(key) || allowed
|
|
1251
|
+
if (seen.has(key) || optionsPatternsTest(allowed, item.name) || optionsPatternsTest(expected, item.name)) {
|
|
1230
1252
|
continue;
|
|
1231
1253
|
}
|
|
1232
1254
|
seen.add(key);
|
|
1233
1255
|
context.report({
|
|
1234
1256
|
node: item.node,
|
|
1235
1257
|
messageId: "pattern",
|
|
1236
|
-
data: { name: item.name, pattern }
|
|
1258
|
+
data: { name: item.name, pattern: optionsPatternLabel(pattern) }
|
|
1237
1259
|
});
|
|
1238
1260
|
}
|
|
1239
1261
|
}
|
|
@@ -1312,7 +1334,7 @@ var filenameMatch = defineRule7({
|
|
|
1312
1334
|
type: "object",
|
|
1313
1335
|
additionalProperties: false,
|
|
1314
1336
|
properties: {
|
|
1315
|
-
pattern:
|
|
1337
|
+
pattern: optionsPatternSchema,
|
|
1316
1338
|
message: { type: "string" },
|
|
1317
1339
|
flags: { type: "string" }
|
|
1318
1340
|
},
|
|
@@ -1326,7 +1348,8 @@ var filenameMatch = defineRule7({
|
|
|
1326
1348
|
return {
|
|
1327
1349
|
Program(program) {
|
|
1328
1350
|
const { pattern, message, flags } = optionsFirst(context);
|
|
1329
|
-
|
|
1351
|
+
const patterns = optionsPatterns(pattern, flags);
|
|
1352
|
+
if (!optionsPatternsTest(patterns, namingFileBasename(context.filename))) {
|
|
1330
1353
|
context.report({
|
|
1331
1354
|
node: program,
|
|
1332
1355
|
messageId: "mismatch",
|
|
@@ -1798,7 +1821,7 @@ import { defineRule as defineRule13 } from "@oxlint/plugins";
|
|
|
1798
1821
|
function compileFactoryKeys(pattern, keys, requireKeys) {
|
|
1799
1822
|
const allowedList = keys.concat(requireKeys.filter((key) => !keys.includes(key)));
|
|
1800
1823
|
return {
|
|
1801
|
-
|
|
1824
|
+
patterns: optionsPatterns(pattern),
|
|
1802
1825
|
allowed: new Set(allowedList),
|
|
1803
1826
|
allowedList,
|
|
1804
1827
|
requireKeys
|
|
@@ -1812,7 +1835,7 @@ var noExtraFactoryKeys = defineRule13({
|
|
|
1812
1835
|
additionalProperties: false,
|
|
1813
1836
|
properties: {
|
|
1814
1837
|
keys: { type: "array", items: { type: "string" } },
|
|
1815
|
-
factoryPattern:
|
|
1838
|
+
factoryPattern: optionsPatternSchema,
|
|
1816
1839
|
requireKeys: { type: "array", items: { type: "string" } },
|
|
1817
1840
|
keySets: {
|
|
1818
1841
|
type: "array",
|
|
@@ -1820,7 +1843,7 @@ var noExtraFactoryKeys = defineRule13({
|
|
|
1820
1843
|
type: "object",
|
|
1821
1844
|
additionalProperties: false,
|
|
1822
1845
|
properties: {
|
|
1823
|
-
factoryPattern:
|
|
1846
|
+
factoryPattern: optionsPatternSchema,
|
|
1824
1847
|
keys: { type: "array", items: { type: "string" } },
|
|
1825
1848
|
requireKeys: { type: "array", items: { type: "string" } }
|
|
1826
1849
|
},
|
|
@@ -1839,11 +1862,11 @@ var noExtraFactoryKeys = defineRule13({
|
|
|
1839
1862
|
let keySets = [];
|
|
1840
1863
|
let fallback;
|
|
1841
1864
|
function resolveFactoryKeys(name) {
|
|
1842
|
-
const matched = keySets.find((item) => item.
|
|
1865
|
+
const matched = keySets.find((item) => optionsPatternsTest(item.patterns, name));
|
|
1843
1866
|
if (matched) {
|
|
1844
1867
|
return matched;
|
|
1845
1868
|
}
|
|
1846
|
-
if (fallback
|
|
1869
|
+
if (fallback && optionsPatternsTest(fallback.patterns, name)) {
|
|
1847
1870
|
return fallback;
|
|
1848
1871
|
}
|
|
1849
1872
|
}
|
|
@@ -1910,9 +1933,9 @@ var noFileLevelHelpers = defineRule14({
|
|
|
1910
1933
|
type: "object",
|
|
1911
1934
|
additionalProperties: false,
|
|
1912
1935
|
properties: {
|
|
1913
|
-
allowPattern:
|
|
1936
|
+
allowPattern: optionsPatternSchema,
|
|
1914
1937
|
detectComponents: { type: "boolean" },
|
|
1915
|
-
hookPattern:
|
|
1938
|
+
hookPattern: optionsPatternSchema
|
|
1916
1939
|
}
|
|
1917
1940
|
}],
|
|
1918
1941
|
messages: {
|
|
@@ -1927,10 +1950,10 @@ var noFileLevelHelpers = defineRule14({
|
|
|
1927
1950
|
detectComponents = true,
|
|
1928
1951
|
hookPattern = "^use[A-Z]"
|
|
1929
1952
|
} = optionsFirst(context, {});
|
|
1930
|
-
const allowed =
|
|
1931
|
-
const hooks =
|
|
1953
|
+
const allowed = optionsOptionalPatterns(allowPattern);
|
|
1954
|
+
const hooks = optionsPatterns(hookPattern);
|
|
1932
1955
|
for (const candidate of declarationsFileLevelFunctionCandidates(program)) {
|
|
1933
|
-
if (detectComponents && reactComponentsIsLike(program, candidate) || hooks
|
|
1956
|
+
if (detectComponents && reactComponentsIsLike(program, candidate) || optionsPatternsTest(hooks, candidate.name) || optionsPatternsTest(allowed, candidate.name)) {
|
|
1934
1957
|
continue;
|
|
1935
1958
|
}
|
|
1936
1959
|
context.report({
|
|
@@ -2443,7 +2466,7 @@ var noModuleMutableState = defineRule21({
|
|
|
2443
2466
|
type: "array",
|
|
2444
2467
|
items: { type: "string", enum: ["let", "var"] }
|
|
2445
2468
|
},
|
|
2446
|
-
allowNamePattern:
|
|
2469
|
+
allowNamePattern: optionsPatternSchema
|
|
2447
2470
|
}
|
|
2448
2471
|
}],
|
|
2449
2472
|
messages: {
|
|
@@ -2452,12 +2475,12 @@ var noModuleMutableState = defineRule21({
|
|
|
2452
2475
|
},
|
|
2453
2476
|
createOnce(context) {
|
|
2454
2477
|
let kindSet = new Set(["let", "var"]);
|
|
2455
|
-
let allowed =
|
|
2478
|
+
let allowed = [];
|
|
2456
2479
|
return {
|
|
2457
2480
|
before() {
|
|
2458
2481
|
const { kinds = ["let", "var"], allowNamePattern } = optionsFirst(context, {});
|
|
2459
2482
|
kindSet = new Set(kinds);
|
|
2460
|
-
allowed =
|
|
2483
|
+
allowed = optionsOptionalPatterns(allowNamePattern);
|
|
2461
2484
|
},
|
|
2462
2485
|
VariableDeclaration(node) {
|
|
2463
2486
|
if (node.declare || !kindSet.has(node.kind)) {
|
|
@@ -2468,7 +2491,7 @@ var noModuleMutableState = defineRule21({
|
|
|
2468
2491
|
}
|
|
2469
2492
|
for (const declarator of node.declarations) {
|
|
2470
2493
|
for (const binding of moduleMutableStateBindings(declarator.id)) {
|
|
2471
|
-
if (!allowed
|
|
2494
|
+
if (!optionsPatternsTest(allowed, binding.name)) {
|
|
2472
2495
|
context.report({
|
|
2473
2496
|
node: binding.node,
|
|
2474
2497
|
messageId: "moduleState"
|
|
@@ -3349,7 +3372,7 @@ var noTopLevelFunctions = defineRule29({
|
|
|
3349
3372
|
additionalProperties: false,
|
|
3350
3373
|
properties: {
|
|
3351
3374
|
banReExports: { type: "boolean" },
|
|
3352
|
-
allowPattern:
|
|
3375
|
+
allowPattern: optionsPatternSchema
|
|
3353
3376
|
}
|
|
3354
3377
|
}],
|
|
3355
3378
|
defaultOptions: [{ banReExports: true }],
|
|
@@ -3362,7 +3385,7 @@ var noTopLevelFunctions = defineRule29({
|
|
|
3362
3385
|
return {
|
|
3363
3386
|
Program(program) {
|
|
3364
3387
|
const { banReExports, allowPattern } = optionsFirst(context);
|
|
3365
|
-
const allowed =
|
|
3388
|
+
const allowed = optionsOptionalPatterns(allowPattern);
|
|
3366
3389
|
for (const statement of program.body) {
|
|
3367
3390
|
if (banReExports && (statement.type === "ExportAllDeclaration" || statement.type === "ExportNamedDeclaration" && statement.source)) {
|
|
3368
3391
|
context.report({ node: statement, messageId: "noReExport" });
|
|
@@ -3370,7 +3393,7 @@ var noTopLevelFunctions = defineRule29({
|
|
|
3370
3393
|
}
|
|
3371
3394
|
const declaration = statement.type === "ExportNamedDeclaration" || statement.type === "ExportDefaultDeclaration" ? statement.declaration : statement;
|
|
3372
3395
|
if (declaration?.type === "FunctionDeclaration") {
|
|
3373
|
-
if (!allowed
|
|
3396
|
+
if (!optionsPatternsTest(allowed, declarationsFunctionName(declaration))) {
|
|
3374
3397
|
context.report({
|
|
3375
3398
|
node: declaration,
|
|
3376
3399
|
messageId: "noFunction",
|
|
@@ -3383,7 +3406,7 @@ var noTopLevelFunctions = defineRule29({
|
|
|
3383
3406
|
continue;
|
|
3384
3407
|
}
|
|
3385
3408
|
for (const item of declaration.declarations) {
|
|
3386
|
-
if ((item.init?.type === "FunctionExpression" || item.init?.type === "ArrowFunctionExpression") && !allowed
|
|
3409
|
+
if ((item.init?.type === "FunctionExpression" || item.init?.type === "ArrowFunctionExpression") && !optionsPatternsTest(allowed, declarationsFunctionName(item))) {
|
|
3387
3410
|
context.report({
|
|
3388
3411
|
node: item,
|
|
3389
3412
|
messageId: "noFunction",
|
|
@@ -3432,7 +3455,7 @@ var noTrivialFunctions = defineRule30({
|
|
|
3432
3455
|
type: "object",
|
|
3433
3456
|
additionalProperties: false,
|
|
3434
3457
|
properties: {
|
|
3435
|
-
allowPattern:
|
|
3458
|
+
allowPattern: optionsPatternSchema,
|
|
3436
3459
|
allowCallees: { type: "array", items: { type: "string" } },
|
|
3437
3460
|
allowAsync: { type: "boolean" }
|
|
3438
3461
|
}
|
|
@@ -3442,13 +3465,13 @@ var noTrivialFunctions = defineRule30({
|
|
|
3442
3465
|
}
|
|
3443
3466
|
},
|
|
3444
3467
|
createOnce(context) {
|
|
3445
|
-
let allowed =
|
|
3468
|
+
let allowed = [];
|
|
3446
3469
|
let allowedCallees = [];
|
|
3447
3470
|
let allowAsync = false;
|
|
3448
3471
|
return {
|
|
3449
3472
|
before() {
|
|
3450
3473
|
const { allowPattern, allowCallees: calleePatterns = [], allowAsync: asyncAllowed = false } = optionsFirst(context, {});
|
|
3451
|
-
allowed =
|
|
3474
|
+
allowed = optionsOptionalPatterns(allowPattern);
|
|
3452
3475
|
allowedCallees = calleePatterns.map((pattern) => new RegExp(pattern));
|
|
3453
3476
|
allowAsync = asyncAllowed;
|
|
3454
3477
|
},
|
|
@@ -3456,7 +3479,7 @@ var noTrivialFunctions = defineRule30({
|
|
|
3456
3479
|
const seen = new Set;
|
|
3457
3480
|
for (const item of [...exportsCollectFunctions(program), ...declarationsTopLevelUnexportedFunctions(program)]) {
|
|
3458
3481
|
const key = `${item.name}:${item.node.start}:${item.node.end}`;
|
|
3459
|
-
if (seen.has(key) || allowed
|
|
3482
|
+
if (seen.has(key) || optionsPatternsTest(allowed, item.name) || !declarationsIsTrivialFunction(item.node)) {
|
|
3460
3483
|
continue;
|
|
3461
3484
|
}
|
|
3462
3485
|
const expression = forwardedExpression(item.node);
|
|
@@ -3486,7 +3509,7 @@ var noTypeDeclarations = defineRule31({
|
|
|
3486
3509
|
type: "object",
|
|
3487
3510
|
additionalProperties: false,
|
|
3488
3511
|
properties: {
|
|
3489
|
-
allowPattern:
|
|
3512
|
+
allowPattern: optionsPatternSchema
|
|
3490
3513
|
}
|
|
3491
3514
|
}],
|
|
3492
3515
|
messages: {
|
|
@@ -3494,11 +3517,13 @@ var noTypeDeclarations = defineRule31({
|
|
|
3494
3517
|
}
|
|
3495
3518
|
},
|
|
3496
3519
|
createOnce(context) {
|
|
3497
|
-
let
|
|
3520
|
+
let allowedNames = [];
|
|
3521
|
+
let allowedValues = [];
|
|
3498
3522
|
function check(node) {
|
|
3499
|
-
if (
|
|
3523
|
+
if (optionsPatternsTest(allowedNames, node.id.name))
|
|
3524
|
+
return;
|
|
3525
|
+
if (node.type === "TSTypeAliasDeclaration" && allowedValues.length > 0 && optionsPatternsTest(allowedValues, `= ${context.sourceCode.getText(node.typeAnnotation)}`))
|
|
3500
3526
|
return;
|
|
3501
|
-
}
|
|
3502
3527
|
context.report({
|
|
3503
3528
|
node,
|
|
3504
3529
|
messageId: "typeDeclaration",
|
|
@@ -3508,7 +3533,10 @@ var noTypeDeclarations = defineRule31({
|
|
|
3508
3533
|
return {
|
|
3509
3534
|
before() {
|
|
3510
3535
|
const { allowPattern } = optionsFirst(context, {});
|
|
3511
|
-
|
|
3536
|
+
const sources = allowPattern === undefined ? [] : [allowPattern].flat();
|
|
3537
|
+
const isValuePattern = (source) => /^\^?=/.test(source);
|
|
3538
|
+
allowedNames = optionsOptionalPatterns(sources.filter((source) => !isValuePattern(source)));
|
|
3539
|
+
allowedValues = optionsOptionalPatterns(sources.filter(isValuePattern));
|
|
3512
3540
|
},
|
|
3513
3541
|
TSTypeAliasDeclaration: check,
|
|
3514
3542
|
TSInterfaceDeclaration: check
|
|
@@ -3671,7 +3699,7 @@ var onlyExportComponents = defineRule34({
|
|
|
3671
3699
|
properties: {
|
|
3672
3700
|
matchFileName: { type: "boolean" },
|
|
3673
3701
|
allowTypeExports: { type: "boolean" },
|
|
3674
|
-
denyTypePattern:
|
|
3702
|
+
denyTypePattern: optionsPatternSchema
|
|
3675
3703
|
}
|
|
3676
3704
|
}],
|
|
3677
3705
|
messages: {
|
|
@@ -3690,7 +3718,7 @@ var onlyExportComponents = defineRule34({
|
|
|
3690
3718
|
denyTypePattern
|
|
3691
3719
|
} = optionsFirst(context, {});
|
|
3692
3720
|
const expected = reactComponentsPascalFromBasename(namingFileBasename(context.filename));
|
|
3693
|
-
const denied =
|
|
3721
|
+
const denied = optionsOptionalPatterns(denyTypePattern);
|
|
3694
3722
|
const components = [];
|
|
3695
3723
|
for (const candidate of reactComponentsExportCandidates(program)) {
|
|
3696
3724
|
if (candidate.typeOnly) {
|
|
@@ -3700,7 +3728,7 @@ var onlyExportComponents = defineRule34({
|
|
|
3700
3728
|
messageId: "typeExport",
|
|
3701
3729
|
data: { name: candidate.name, expected }
|
|
3702
3730
|
});
|
|
3703
|
-
} else if (denied
|
|
3731
|
+
} else if (optionsPatternsTest(denied, candidate.name)) {
|
|
3704
3732
|
context.report({
|
|
3705
3733
|
node: candidate.node,
|
|
3706
3734
|
messageId: "deniedType",
|
|
@@ -4053,7 +4081,7 @@ var requireObjectParams = defineRule38({
|
|
|
4053
4081
|
properties: {
|
|
4054
4082
|
maxParams: { type: "integer", minimum: 1 },
|
|
4055
4083
|
allDeclarations: { type: "boolean" },
|
|
4056
|
-
allowPattern:
|
|
4084
|
+
allowPattern: optionsPatternSchema
|
|
4057
4085
|
}
|
|
4058
4086
|
}],
|
|
4059
4087
|
messages: {
|
|
@@ -4064,12 +4092,12 @@ var requireObjectParams = defineRule38({
|
|
|
4064
4092
|
return {
|
|
4065
4093
|
Program(program) {
|
|
4066
4094
|
const { maxParams = 1, allDeclarations = false, allowPattern } = optionsFirst(context, {});
|
|
4067
|
-
const allowed =
|
|
4095
|
+
const allowed = optionsOptionalPatterns(allowPattern);
|
|
4068
4096
|
const seen = new Set;
|
|
4069
4097
|
const functions = allDeclarations ? [...exportsCollectFunctions(program), ...declarationsTopLevelUnexportedFunctions(program)] : exportsCollectFunctions(program);
|
|
4070
4098
|
for (const item of functions) {
|
|
4071
4099
|
const key = `${item.name}:${item.node.start}:${item.node.end}`;
|
|
4072
|
-
if (seen.has(key) || allowed
|
|
4100
|
+
if (seen.has(key) || optionsPatternsTest(allowed, item.name)) {
|
|
4073
4101
|
continue;
|
|
4074
4102
|
}
|
|
4075
4103
|
seen.add(key);
|
|
@@ -4291,6 +4319,9 @@ function regexMatches(regex, value) {
|
|
|
4291
4319
|
regex.lastIndex = 0;
|
|
4292
4320
|
return regex.test(value);
|
|
4293
4321
|
}
|
|
4322
|
+
function titlePatterns(pattern, flags) {
|
|
4323
|
+
return pattern === undefined ? [] : [pattern].flat().map((source) => ({ regex: new RegExp(source, flags), pattern: source }));
|
|
4324
|
+
}
|
|
4294
4325
|
var testTitlePattern = defineRule42({
|
|
4295
4326
|
meta: {
|
|
4296
4327
|
type: "suggestion",
|
|
@@ -4299,8 +4330,8 @@ var testTitlePattern = defineRule42({
|
|
|
4299
4330
|
additionalProperties: false,
|
|
4300
4331
|
properties: {
|
|
4301
4332
|
callees: { type: "array", items: { type: "string" } },
|
|
4302
|
-
forbid:
|
|
4303
|
-
require:
|
|
4333
|
+
forbid: optionsPatternSchema,
|
|
4334
|
+
require: optionsPatternSchema,
|
|
4304
4335
|
flags: { type: "string", pattern: "^[dgimsuvy]*$" }
|
|
4305
4336
|
}
|
|
4306
4337
|
}],
|
|
@@ -4315,16 +4346,18 @@ var testTitlePattern = defineRule42({
|
|
|
4315
4346
|
},
|
|
4316
4347
|
createOnce(context) {
|
|
4317
4348
|
let callees = [];
|
|
4318
|
-
let forbid;
|
|
4319
|
-
let required;
|
|
4349
|
+
let forbid = [];
|
|
4350
|
+
let required = [];
|
|
4351
|
+
let requiredLabel = "";
|
|
4320
4352
|
return {
|
|
4321
4353
|
before() {
|
|
4322
4354
|
const options = optionsFirst(context);
|
|
4323
4355
|
callees = options.callees;
|
|
4324
4356
|
const flags = options.flags ?? "";
|
|
4325
|
-
forbid =
|
|
4326
|
-
required =
|
|
4327
|
-
|
|
4357
|
+
forbid = titlePatterns(options.forbid, flags);
|
|
4358
|
+
required = titlePatterns(options.require, flags);
|
|
4359
|
+
requiredLabel = optionsPatternLabel(options.require);
|
|
4360
|
+
if (forbid.length === 0 && required.length === 0) {
|
|
4328
4361
|
return false;
|
|
4329
4362
|
}
|
|
4330
4363
|
},
|
|
@@ -4340,18 +4373,19 @@ var testTitlePattern = defineRule42({
|
|
|
4340
4373
|
if (text === undefined) {
|
|
4341
4374
|
return;
|
|
4342
4375
|
}
|
|
4343
|
-
|
|
4376
|
+
const forbidden = forbid.find((item) => regexMatches(item.regex, text));
|
|
4377
|
+
if (forbidden) {
|
|
4344
4378
|
context.report({
|
|
4345
4379
|
node: title,
|
|
4346
4380
|
messageId: "forbidden",
|
|
4347
|
-
data: { pattern:
|
|
4381
|
+
data: { pattern: forbidden.pattern }
|
|
4348
4382
|
});
|
|
4349
4383
|
}
|
|
4350
|
-
if (required && !regexMatches(
|
|
4384
|
+
if (required.length > 0 && !required.some((item) => regexMatches(item.regex, text))) {
|
|
4351
4385
|
context.report({
|
|
4352
4386
|
node: title,
|
|
4353
4387
|
messageId: "required",
|
|
4354
|
-
data: { pattern:
|
|
4388
|
+
data: { pattern: requiredLabel }
|
|
4355
4389
|
});
|
|
4356
4390
|
}
|
|
4357
4391
|
}
|