pi-lens 1.3.12 → 1.3.14
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.
|
@@ -291,6 +291,17 @@ export class ComplexityClient {
|
|
|
291
291
|
warnings.push(`High entropy (${metrics.codeEntropy.toFixed(1)} bits) — follow project conventions`);
|
|
292
292
|
}
|
|
293
293
|
|
|
294
|
+
// Comments ratio (>30% = excessive comments, AI slop signal)
|
|
295
|
+
const totalLines = metrics.linesOfCode + metrics.commentLines;
|
|
296
|
+
if (totalLines > 10 && metrics.commentLines / totalLines > 0.3) {
|
|
297
|
+
warnings.push(`Excessive comments (${Math.round(metrics.commentLines / totalLines * 100)}%) — remove obvious comments`);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
// Verbose code (long functions with low complexity = overly verbose)
|
|
301
|
+
if (metrics.avgFunctionLength > 30 && metrics.cyclomaticComplexity < 3) {
|
|
302
|
+
warnings.push(`Verbose code (avg ${Math.round(metrics.avgFunctionLength)} lines, low complexity) — simplify or extract`);
|
|
303
|
+
}
|
|
304
|
+
|
|
294
305
|
return warnings;
|
|
295
306
|
}
|
|
296
307
|
|
package/index.ts
CHANGED
|
@@ -217,10 +217,10 @@ export default function (pi: ExtensionAPI) {
|
|
|
217
217
|
|
|
218
218
|
pi.registerCommand("lens-booboo", {
|
|
219
219
|
description:
|
|
220
|
-
"
|
|
220
|
+
"Full codebase review: design smells, complexity, AI slop detection, TODOs, dead code, duplicates, type coverage. Usage: /lens-booboo [path]",
|
|
221
221
|
handler: async (args, ctx) => {
|
|
222
222
|
const targetPath = args.trim() || ctx.cwd || process.cwd();
|
|
223
|
-
ctx.ui.notify("🔍 Running
|
|
223
|
+
ctx.ui.notify("🔍 Running full codebase review...", "info");
|
|
224
224
|
|
|
225
225
|
const parts: string[] = [];
|
|
226
226
|
|
|
@@ -304,8 +304,9 @@ export default function (pi: ExtensionAPI) {
|
|
|
304
304
|
}
|
|
305
305
|
}
|
|
306
306
|
|
|
307
|
-
// Part 3: Complexity metrics
|
|
307
|
+
// Part 3: Complexity metrics + AI slop detection
|
|
308
308
|
const results: import("./clients/complexity-client.js").FileComplexity[] = [];
|
|
309
|
+
const aiSlopIssues: string[] = [];
|
|
309
310
|
|
|
310
311
|
const scanDir = (dir: string) => {
|
|
311
312
|
if (!require("node:fs").existsSync(dir)) return;
|
|
@@ -320,6 +321,15 @@ export default function (pi: ExtensionAPI) {
|
|
|
320
321
|
const metrics = complexityClient.analyzeFile(fullPath);
|
|
321
322
|
if (metrics) {
|
|
322
323
|
results.push(metrics);
|
|
324
|
+
|
|
325
|
+
// Check AI slop indicators per file
|
|
326
|
+
const warnings = complexityClient.checkThresholds(metrics);
|
|
327
|
+
if (warnings.length > 0) {
|
|
328
|
+
aiSlopIssues.push(` ${metrics.filePath}:`);
|
|
329
|
+
for (const w of warnings) {
|
|
330
|
+
aiSlopIssues.push(` ⚠ ${w}`);
|
|
331
|
+
}
|
|
332
|
+
}
|
|
323
333
|
}
|
|
324
334
|
}
|
|
325
335
|
}
|
|
@@ -355,9 +365,40 @@ export default function (pi: ExtensionAPI) {
|
|
|
355
365
|
if (highCognitive.length > 5) summary += ` ... and ${highCognitive.length - 5} more\n`;
|
|
356
366
|
}
|
|
357
367
|
|
|
368
|
+
// Add AI slop issues
|
|
369
|
+
if (aiSlopIssues.length > 0) {
|
|
370
|
+
summary += `\n[AI Slop Indicators]\n${aiSlopIssues.join("\n")}`;
|
|
371
|
+
}
|
|
372
|
+
|
|
358
373
|
parts.push(summary);
|
|
359
374
|
}
|
|
360
375
|
|
|
376
|
+
// Part 4: TODOs scan
|
|
377
|
+
const todoResult = todoScanner.scanDirectory(targetPath);
|
|
378
|
+
const todoReport = todoScanner.formatResult(todoResult);
|
|
379
|
+
if (todoReport) parts.push(todoReport);
|
|
380
|
+
|
|
381
|
+
// Part 5: Dead code (knip)
|
|
382
|
+
if (knipClient.isAvailable()) {
|
|
383
|
+
const knipResult = knipClient.analyze(targetPath);
|
|
384
|
+
const knipReport = knipClient.formatResult(knipResult);
|
|
385
|
+
if (knipReport) parts.push(knipReport);
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
// Part 6: Code duplication
|
|
389
|
+
if (jscpdClient.isAvailable()) {
|
|
390
|
+
const jscpdResult = jscpdClient.scan(targetPath);
|
|
391
|
+
const jscpdReport = jscpdClient.formatResult(jscpdResult);
|
|
392
|
+
if (jscpdReport) parts.push(jscpdReport);
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
// Part 7: Type coverage
|
|
396
|
+
if (typeCoverageClient.isAvailable()) {
|
|
397
|
+
const tcResult = typeCoverageClient.scan(targetPath);
|
|
398
|
+
const tcReport = typeCoverageClient.formatResult(tcResult);
|
|
399
|
+
if (tcReport) parts.push(tcReport);
|
|
400
|
+
}
|
|
401
|
+
|
|
361
402
|
if (parts.length === 0) {
|
|
362
403
|
ctx.ui.notify("✓ Code review clean", "info");
|
|
363
404
|
} else {
|
|
@@ -711,10 +752,24 @@ export default function (pi: ExtensionAPI) {
|
|
|
711
752
|
|
|
712
753
|
const diags = tsClient.getDiagnostics(filePath);
|
|
713
754
|
if (diags.length > 0) {
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
755
|
+
// Separate unused imports (TS6133, TS6196) from other diagnostics
|
|
756
|
+
const unusedImports = diags.filter(d => d.code === 6133 || d.code === 6196);
|
|
757
|
+
const otherDiags = diags.filter(d => d.code !== 6133 && d.code !== 6196);
|
|
758
|
+
|
|
759
|
+
if (unusedImports.length > 0) {
|
|
760
|
+
lspOutput += `\n\n[Unused Imports] ${unusedImports.length} imported but never used:\n`;
|
|
761
|
+
for (const d of unusedImports.slice(0, 10)) {
|
|
762
|
+
lspOutput += ` L${d.range.start.line + 1}: ${d.message}\n`;
|
|
763
|
+
}
|
|
764
|
+
lspOutput += ` → Remove unused imports to reduce noise\n`;
|
|
765
|
+
}
|
|
766
|
+
|
|
767
|
+
if (otherDiags.length > 0) {
|
|
768
|
+
lspOutput += `\n\n[TypeScript] ${otherDiags.length} issue(s):\n`;
|
|
769
|
+
for (const d of otherDiags.slice(0, 10)) {
|
|
770
|
+
const label = d.severity === 2 ? "Warning" : "Error";
|
|
771
|
+
lspOutput += ` [${label}] L${d.range.start.line + 1}: ${d.message}\n`;
|
|
772
|
+
}
|
|
718
773
|
}
|
|
719
774
|
}
|
|
720
775
|
}
|
package/package.json
CHANGED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
id: magic-numbers
|
|
2
|
+
language: TypeScript
|
|
3
|
+
message: "Magic number detected — use a named constant"
|
|
4
|
+
severity: hint
|
|
5
|
+
note: |
|
|
6
|
+
Hardcoded numbers make code harder to understand and maintain.
|
|
7
|
+
Extract to a named constant with a descriptive name.
|
|
8
|
+
rule:
|
|
9
|
+
kind: number
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
id: silent-failure
|
|
2
|
+
language: TypeScript
|
|
3
|
+
message: "Silent failure detected — log or rethrow the error"
|
|
4
|
+
severity: warning
|
|
5
|
+
note: |
|
|
6
|
+
Empty catch blocks swallow errors silently.
|
|
7
|
+
Always log the error or rethrow it to aid debugging.
|
|
8
|
+
rule:
|
|
9
|
+
kind: catch_clause
|
|
10
|
+
has:
|
|
11
|
+
kind: statement_block
|
|
12
|
+
not:
|
|
13
|
+
has:
|
|
14
|
+
kind: throw_statement
|