ai-deslop 0.5.1 → 0.5.3

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 CHANGED
@@ -70,6 +70,7 @@ All rules below are enabled by the recommended config unless listed as opt-in.
70
70
 
71
71
  | Rule | Description |
72
72
  | --- | --- |
73
+ | [`max-boolean-conditions`](docs/max-boolean-conditions.md) | Limits top-level terms in `if` and loop conditions. Supports a custom limit and message. No fixer. |
73
74
  | [`no-duplicate-consts`](docs/no-duplicate-consts.md) | Reports all-caps constants with the same static value in different files. |
74
75
  | [`no-duplicate-types`](docs/no-duplicate-types.md) | Reports exact duplicate object contracts. No fixer. |
75
76
  | [`no-pass-through-schema`](docs/no-pass-through-schema.md) | Reports const aliases that only rename known schemas. Supports Zod, ArkType, and configured imports. No fixer. |
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { eslintCompatPlugin } from "@oxlint/plugins";
2
- /** Every `deslop/*` rule, plus selected standard rules, each set to `"error"`. Spread into the `rules` field of an oxlint config. */
2
+ /** Recommended `deslop/*` rules, plus selected standard rules, each set to `"error"`. Spread into the `rules` field of an oxlint config. */
3
3
  export declare const recommendedRules: Record<string, "error" | ["error", {
4
4
  selector: string;
5
5
  message: string;
package/dist/index.js CHANGED
@@ -26,8 +26,9 @@ import { noDuplicateTypesRule } from "./rules/no-duplicate-types.js";
26
26
  import { noDuplicateConstsRule } from "./rules/no-duplicate-consts.js";
27
27
  import { noRenamedImportsRule } from "./rules/no-renamed-imports.js";
28
28
  import { noReexportsOutsideEntrypointsRule } from "./rules/no-reexports-outside-entrypoints.js";
29
+ import { maxBooleanConditionsRule } from "./rules/max-boolean-conditions.js";
29
30
  import { canonicalClassNames } from "./tailwind/rule.js";
30
- /** Every `deslop/*` rule, plus selected standard rules, each set to `"error"`. Spread into the `rules` field of an oxlint config. */
31
+ /** Recommended `deslop/*` rules, plus selected standard rules, each set to `"error"`. Spread into the `rules` field of an oxlint config. */
31
32
  export const recommendedRules = {
32
33
  "deslop/no-array-filter-map": "error",
33
34
  "deslop/no-reduce-accumulator-copy": "error",
@@ -56,6 +57,8 @@ export const recommendedRules = {
56
57
  "typescript/no-floating-promises": "error",
57
58
  "typescript/await-thenable": "error",
58
59
  "typescript/no-unnecessary-condition": "error",
60
+ "typescript/switch-exhaustiveness-check": "error",
61
+ "typescript/no-inferrable-types": "error",
59
62
  "no-unreachable": "error",
60
63
  "deslop/no-restricted-syntax": [
61
64
  "error",
@@ -105,6 +108,7 @@ const deslopPlugin = eslintCompatPlugin({
105
108
  "no-duplicate-consts": noDuplicateConstsRule,
106
109
  "no-renamed-imports": noRenamedImportsRule,
107
110
  "no-reexports-outside-entrypoints": noReexportsOutsideEntrypointsRule,
111
+ "max-boolean-conditions": maxBooleanConditionsRule,
108
112
  // Opt-in: NOT in `recommendedRules`. Requires a `cssPath` option, so users add it manually.
109
113
  "canonical-class-names": canonicalClassNames,
110
114
  },
@@ -0,0 +1,2 @@
1
+ /** Limit top-level Boolean terms in control-flow conditions. */
2
+ export declare const maxBooleanConditionsRule: import("@oxlint/plugins").Rule;
@@ -0,0 +1,58 @@
1
+ import { defineRule } from "@oxlint/plugins";
2
+ /** Limit top-level Boolean terms in control-flow conditions. */
3
+ export const maxBooleanConditionsRule = defineRule({
4
+ meta: {
5
+ type: "suggestion",
6
+ docs: { description: "Limit top-level Boolean terms in control-flow conditions" },
7
+ messages: {
8
+ tooManyConditions: "This condition has {{count}} top-level terms (maximum {{max}}). Prefer a named variable that describes what these conditions mean.",
9
+ },
10
+ schema: [{
11
+ type: "object",
12
+ properties: {
13
+ maxConditions: { type: "integer", minimum: 1 },
14
+ message: { type: "string" },
15
+ },
16
+ additionalProperties: false,
17
+ }],
18
+ },
19
+ createOnce(context) {
20
+ let options;
21
+ function checkCondition(node) {
22
+ if (node.test === null)
23
+ return;
24
+ const pending = [node.test];
25
+ let count = 0;
26
+ while (pending.length > 0) {
27
+ const term = pending.pop();
28
+ const isGrouped = term !== node.test
29
+ && context.sourceCode.getTokenBefore(term)?.value === "("
30
+ && context.sourceCode.getTokenAfter(term)?.value === ")";
31
+ if (term.type === "LogicalExpression" && term.operator !== "??" && !isGrouped) {
32
+ pending.push(term.left, term.right);
33
+ }
34
+ else {
35
+ count++;
36
+ }
37
+ }
38
+ const max = options.maxConditions ?? 3;
39
+ if (count <= max)
40
+ return;
41
+ if (options.message !== undefined) {
42
+ context.report({ node: node.test, message: options.message });
43
+ }
44
+ else {
45
+ context.report({ node: node.test, messageId: "tooManyConditions", data: { count, max } });
46
+ }
47
+ }
48
+ return {
49
+ before() {
50
+ options = context.options[0] ?? {};
51
+ },
52
+ IfStatement: checkCondition,
53
+ WhileStatement: checkCondition,
54
+ DoWhileStatement: checkCondition,
55
+ ForStatement: checkCondition,
56
+ };
57
+ },
58
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-deslop",
3
- "version": "0.5.1",
3
+ "version": "0.5.3",
4
4
  "description": "Opinionated Oxlint rules that reject low-evidence, low-signal, AI-slop code patterns.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",