slop-police 0.3.1 → 0.3.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.
Files changed (2) hide show
  1. package/README.md +21 -14
  2. package/package.json +5 -5
package/README.md CHANGED
@@ -40,9 +40,9 @@ slop-police reads `slop-police.json` from the current directory:
40
40
  "no-redundant-value-alias": "error",
41
41
  "no-single-string-cn": "off",
42
42
  "no-pass-through-wrapper": "error",
43
+ "no-duplicate-code": "error",
43
44
  "no-duplicate-function": "warn",
44
45
  "no-placeholder-comment": "error",
45
- "no-promise-default-fallback": "error",
46
46
  "no-stringified-unknown-error": "warn"
47
47
  }
48
48
  }
@@ -153,6 +153,26 @@ function parse(input: string) {
153
153
  }
154
154
  ```
155
155
 
156
+ ### no-duplicate-code
157
+
158
+ Copy-pasted code: at least 50 tokens in a row that repeat earlier code (in the same file or one before it by path) and span at least 10 lines. Tokens are compared by their text, so a renamed variable ends a copy, but comments, formatting, imports and TypeScript-only syntax are left out: code that differs only in its types is still a copy, and repeated types aren't reported. Test files are neither reported nor compared. `// slop-police-ignore no-duplicate-code` above a statement, class member or object property takes it out of the comparison, so it is not reported as a copy or as the original. Options: `minLines` (default `10`, counting every line a copy spans), `minTokens` (default `50`) and `isolate`, folders (relative to the config) that aren't compared with each other, such as packages that can't share code: `["packages/api", "packages/frontend"]`.
159
+
160
+ ```ts
161
+ // update-card.ts and delete-card.ts both check the card the same way:
162
+ const userId = ctx.userId;
163
+ assert(userId);
164
+
165
+ const cards = await getCardsWithDeck(ctx.db, [input.id]);
166
+ if (cards.length === 0) {
167
+ throw notFound("Card not found");
168
+ }
169
+ const card = cards[0];
170
+ if (card.deckAuthorId !== userId) {
171
+ throw forbidden("You don't own this card");
172
+ }
173
+ // delete-card.ts:6:5 Lines 6-16 duplicate update-card.ts:6-16
174
+ ```
175
+
156
176
  ### no-duplicate-function
157
177
 
158
178
  A function whose body has the same shape as functions in at least two other files: a helper that was rewritten instead of reused. Shapes ignore the names of parameters and locals and the values of literals, but not the names of what the body calls or reads. Bodies with fewer than 2 statements or 16 syntax nodes, and functions in test files, don't count. Option: `minFiles` (default `3`, at least `2`), the number of files a shape has to appear in.
@@ -167,19 +187,6 @@ export async function loadUsers(id: string) {
167
187
  // Function loadUsers has the same body shape as loadPosts (posts.ts:1), loadTeams (teams.ts:1)
168
188
  ```
169
189
 
170
- ### no-promise-default-fallback
171
-
172
- A promise `.catch()` handler that hides the rejection: an empty handler, or one that only returns `null`, `undefined`, `false`, `0`, `""`, `[]` or `{}`, optionally after `console.*` or `logger.*` calls. Only `.catch` on promises and other thenables counts.
173
-
174
- ```ts
175
- const config = await fetchConfig().catch(() => null); // Promise rejection is replaced with null
176
- navigator.clipboard.writeText(text).catch(() => {}); // Promise rejection is swallowed by an empty catch handler
177
- const enabled = await fetchFlag().catch((error) => { // Promise rejection is logged and replaced with false
178
- console.error("flag load failed", error);
179
- return false;
180
- });
181
- ```
182
-
183
190
  ### no-stringified-unknown-error
184
191
 
185
192
  `error instanceof Error ? error.message : String(error)` (in either order), which flattens a caught value into a string and drops its type, stack and cause. A plain `instanceof Error` check counts when the variable is named `error`, `err`, `e` or `cause`; an `||` of `instanceof` checks counts for any name. A function that does nothing but this conversion, like `getErrorMessage(error)`, is where it belongs and isn't reported; use it instead of repeating the expression.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "slop-police",
3
- "version": "0.3.1",
3
+ "version": "0.3.3",
4
4
  "description": "Type-aware TypeScript linter for the dead code and needless indirection AI agents leave behind",
5
5
  "keywords": [
6
6
  "typescript",
@@ -41,9 +41,9 @@
41
41
  "node": ">=22.18"
42
42
  },
43
43
  "optionalDependencies": {
44
- "slop-police-darwin-arm64": "0.3.1",
45
- "slop-police-darwin-x64": "0.3.1",
46
- "slop-police-linux-arm64": "0.3.1",
47
- "slop-police-linux-x64": "0.3.1"
44
+ "slop-police-darwin-arm64": "0.3.3",
45
+ "slop-police-darwin-x64": "0.3.3",
46
+ "slop-police-linux-arm64": "0.3.3",
47
+ "slop-police-linux-x64": "0.3.3"
48
48
  }
49
49
  }