pi-lens 2.0.0 โ†’ 2.0.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.
Files changed (2) hide show
  1. package/index.ts +41 -34
  2. package/package.json +1 -1
package/index.ts CHANGED
@@ -254,7 +254,7 @@ export default function (pi: ExtensionAPI) {
254
254
  });
255
255
 
256
256
  const output = result.stdout || result.stderr || "";
257
- if (output.trim() && result.status === 1) {
257
+ if (output.trim() && result.status !== undefined) {
258
258
  let issues: Array<{line: number; rule: string; message: string}> = [];
259
259
  const lines = output.split("\n").filter((l: string) => l.trim());
260
260
 
@@ -279,7 +279,7 @@ export default function (pi: ExtensionAPI) {
279
279
 
280
280
  if (issues.length > 0) {
281
281
  // UI summary (truncated)
282
- let report = `[Design Smells] ${issues.length} issue(s) found:\n`;
282
+ let report = `[ast-grep] ${issues.length} issue(s) found:\n`;
283
283
  for (const issue of issues.slice(0, 20)) {
284
284
  report += ` L${issue.line}: ${issue.rule} โ€” ${issue.message}\n`;
285
285
  }
@@ -289,7 +289,7 @@ export default function (pi: ExtensionAPI) {
289
289
  parts.push(report);
290
290
 
291
291
  // Full report for file
292
- let fullSection = `## Design Smells\n\n**${issues.length} issue(s) found**\n\n`;
292
+ let fullSection = `## ast-grep (Structural Issues)\n\n**${issues.length} issue(s) found**\n\n`;
293
293
  fullSection += "| Line | Rule | Message |\n|------|------|--------|\n";
294
294
  for (const issue of issues) {
295
295
  fullSection += `| ${issue.line} | ${issue.rule} | ${issue.message} |\n`;
@@ -1103,18 +1103,26 @@ export default function (pi: ExtensionAPI) {
1103
1103
  const otherDiags = diags.filter(d => d.code !== 6133 && d.code !== 6196);
1104
1104
 
1105
1105
  if (unusedImports.length > 0) {
1106
- lspOutput += `\n\n[Unused Imports] ${unusedImports.length} imported but never used:\n`;
1106
+ lspOutput += `\n\n๐Ÿงน Remove ${unusedImports.length} unused import(s) โ€” they are dead code:\n`;
1107
1107
  for (const d of unusedImports.slice(0, 10)) {
1108
1108
  lspOutput += ` L${d.range.start.line + 1}: ${d.message}\n`;
1109
1109
  }
1110
- lspOutput += ` โ†’ Remove unused imports to reduce noise\n`;
1111
1110
  }
1112
1111
 
1113
1112
  if (otherDiags.length > 0) {
1114
- lspOutput += `\n\n[TypeScript] ${otherDiags.length} issue(s):\n`;
1115
- for (const d of otherDiags.slice(0, 10)) {
1116
- const label = d.severity === 2 ? "Warning" : "Error";
1117
- lspOutput += ` [${label}] L${d.range.start.line + 1}: ${d.message}\n`;
1113
+ const errors = otherDiags.filter(d => d.severity !== 2);
1114
+ const warnings = otherDiags.filter(d => d.severity === 2);
1115
+ if (errors.length > 0) {
1116
+ lspOutput += `\n\n๐Ÿ”ด Fix ${errors.length} TypeScript error(s) โ€” these must be resolved:\n`;
1117
+ for (const d of errors.slice(0, 10)) {
1118
+ lspOutput += ` L${d.range.start.line + 1}: ${d.message}\n`;
1119
+ }
1120
+ }
1121
+ if (warnings.length > 0) {
1122
+ lspOutput += `\n\n๐ŸŸก ${warnings.length} TypeScript warning(s) โ€” address before moving on:\n`;
1123
+ for (const d of warnings.slice(0, 10)) {
1124
+ lspOutput += ` L${d.range.start.line + 1}: ${d.message}\n`;
1125
+ }
1118
1126
  }
1119
1127
  }
1120
1128
  }
@@ -1157,10 +1165,10 @@ export default function (pi: ExtensionAPI) {
1157
1165
  }
1158
1166
  } else {
1159
1167
  if (diags.length > 0)
1160
- lspOutput += `\n\n${ruffClient.formatDiagnostics(diags)}`;
1168
+ lspOutput += `\n\n๐ŸŸ  Fix ${diags.length} Ruff issue(s):\n${ruffClient.formatDiagnostics(diags)}`;
1161
1169
  if (fmtReport) lspOutput += `\n\n${fmtReport}`;
1162
1170
  if (fixable.length > 0 || hasFormatIssues) {
1163
- lspOutput += `\n\n[Ruff] ${fixable.length} fixable โ€” enable --autofix-ruff flag to auto-fix`;
1171
+ lspOutput += `\n โ†’ Enable --autofix-ruff to auto-fix ${fixable.length} of these on every write`;
1164
1172
  }
1165
1173
  }
1166
1174
  }
@@ -1195,17 +1203,16 @@ export default function (pi: ExtensionAPI) {
1195
1203
  }
1196
1204
 
1197
1205
  if (newViolations.length > 0) {
1198
- lspOutput += `\n\n[ast-grep] +${newViolations.length} new issue(s) introduced:\n`;
1206
+ const hasFixable = newViolations.some(v => v.fix);
1207
+ lspOutput += `\n\n๐Ÿ”ด You introduced ${newViolations.length} new structural violation(s) โ€” fix before moving on:\n`;
1199
1208
  lspOutput += astGrepClient.formatDiagnostics(newViolations);
1209
+ if (hasFixable) lspOutput += `\n Some are fixable โ€” check the โ†’ hints above`;
1200
1210
  }
1201
1211
  if (fixedRules.length > 0) {
1202
- lspOutput += `\n\n[ast-grep] โœ“ Fixed: ${fixedRules.join(", ")}`;
1212
+ lspOutput += `\n\nโœ… ast-grep: fixed ${fixedRules.join(", ")}`;
1203
1213
  }
1204
- // Show total count quietly so context isn't lost
1205
- if (after.length > 0 && newViolations.length === 0 && fixedRules.length === 0) {
1206
- // no change โ€” show nothing
1207
- } else if (after.length > 0) {
1208
- lspOutput += `\n (${after.length} total)`;
1214
+ if (after.length > 0 && newViolations.length > 0) {
1215
+ lspOutput += `\n (${after.length} total remaining)`;
1209
1216
  }
1210
1217
  }
1211
1218
 
@@ -1253,17 +1260,15 @@ export default function (pi: ExtensionAPI) {
1253
1260
  } else {
1254
1261
  if (newDiags.length > 0) {
1255
1262
  const fixable = newDiags.filter((d) => d.fixable);
1256
- lspOutput += `\n\n[Biome] +${newDiags.length} new issue(s) introduced:\n`;
1263
+ lspOutput += `\n\n๐ŸŸ  You introduced ${newDiags.length} new Biome violation(s) โ€” fix before moving on:\n`;
1257
1264
  lspOutput += biomeClient.formatDiagnostics(newDiags, filePath);
1258
- if (fixable.length > 0) lspOutput += `\n\n[Biome] ${fixable.length} fixable โ€” run /lens-format`;
1265
+ if (fixable.length > 0) lspOutput += `\n โ†’ Auto-fixable: \`npx @biomejs/biome check --write ${path.basename(filePath)}\``;
1259
1266
  }
1260
1267
  if (fixedRules.length > 0) {
1261
- lspOutput += `\n\n[Biome] โœ“ Fixed: ${fixedRules.join(", ")}`;
1268
+ lspOutput += `\n\nโœ… Biome: fixed ${fixedRules.join(", ")}`;
1262
1269
  }
1263
- if (after.length > 0 && newDiags.length === 0 && fixedRules.length === 0) {
1264
- // no change โ€” show nothing
1265
- } else if (after.length > 0) {
1266
- lspOutput += `\n (${after.length} total)`;
1270
+ if (after.length > 0 && newDiags.length > 0) {
1271
+ lspOutput += `\n (${after.length} total remaining)`;
1267
1272
  }
1268
1273
  }
1269
1274
  }
@@ -1291,11 +1296,14 @@ export default function (pi: ExtensionAPI) {
1291
1296
  if (metrics) {
1292
1297
  const warnings = complexityClient.checkThresholds(metrics);
1293
1298
  if (warnings.length > 0) {
1294
- let warningReport = `[Complexity Warnings]\n`;
1295
- for (const w of warnings) {
1296
- warningReport += ` โš  ${w}\n`;
1299
+ const isTestFile = /\.(test|spec)\.[jt]sx?$/.test(filePath);
1300
+ if (!isTestFile) {
1301
+ let warningReport = `๐ŸŸก Complexity issues โ€” refactor when you get a chance:\n`;
1302
+ for (const w of warnings) {
1303
+ warningReport += ` โš  ${w}\n`;
1304
+ }
1305
+ lspOutput += `\n\n${warningReport}`;
1297
1306
  }
1298
- lspOutput += `\n\n${warningReport}`;
1299
1307
  }
1300
1308
  }
1301
1309
  }
@@ -1335,17 +1343,16 @@ export default function (pi: ExtensionAPI) {
1335
1343
  );
1336
1344
  if (fileClones.length > 0) {
1337
1345
  dbg(` jscpd: ${fileClones.length} duplicate(s) involving ${filePath}`);
1338
- let dupReport = `[jscpd] ${fileClones.length} duplicate block(s) involving ${path.basename(filePath)}:\n`;
1346
+ let dupReport = `๐ŸŸ  This file has ${fileClones.length} duplicate block(s) โ€” extract to shared utilities:\n`;
1339
1347
  for (const clone of fileClones.slice(0, 3)) {
1340
1348
  const other = path.resolve(clone.fileA) === path.resolve(filePath)
1341
1349
  ? `${path.basename(clone.fileB)}:${clone.startB}`
1342
1350
  : `${path.basename(clone.fileA)}:${clone.startA}`;
1343
- dupReport += ` ${clone.lines} lines โ€” ${other}\n`;
1351
+ dupReport += ` ${clone.lines} lines duplicated with ${other}\n`;
1344
1352
  }
1345
1353
  if (fileClones.length > 3) {
1346
1354
  dupReport += ` ... and ${fileClones.length - 3} more\n`;
1347
1355
  }
1348
- dupReport += ` โ†’ Extract duplicated code to a shared utility function\n`;
1349
1356
  lspOutput += `\n\n${dupReport}`;
1350
1357
  }
1351
1358
  }
@@ -1365,11 +1372,11 @@ export default function (pi: ExtensionAPI) {
1365
1372
  }
1366
1373
  if (dupes.length > 0) {
1367
1374
  dbg(` duplicate exports: ${dupes.length} found`);
1368
- let exportReport = `[Duplicate Exports] ${dupes.length} function(s) already exist:\n`;
1375
+ let exportReport = `๐Ÿ”ด Do not redefine โ€” ${dupes.length} function(s) already exist elsewhere:\n`;
1369
1376
  for (const dupe of dupes.slice(0, 5)) {
1370
1377
  exportReport += ` ${dupe}\n`;
1371
1378
  }
1372
- exportReport += ` โ†’ Import the existing function instead of redefining it\n`;
1379
+ exportReport += ` โ†’ Import the existing function instead\n`;
1373
1380
  lspOutput += `\n\n${exportReport}`;
1374
1381
  }
1375
1382
  // Update cache with new exports
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-lens",
3
- "version": "2.0.0",
3
+ "version": "2.0.1",
4
4
  "description": "Real-time code feedback for pi โ€” TypeScript LSP, Biome, ast-grep, Ruff, TODO scanner, dead code, duplicate detection, type coverage",
5
5
  "repository": {
6
6
  "type": "git",