pi-lens 3.6.2 â 3.6.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/package.json +4 -4
- package/tsconfig.json +1 -1
- package/clients/__tests__/file-time.test.js +0 -216
- package/clients/__tests__/file-time.test.ts +0 -276
- package/clients/__tests__/format-service.test.js +0 -245
- package/clients/__tests__/format-service.test.ts +0 -339
- package/clients/__tests__/formatters.test.js +0 -271
- package/clients/__tests__/formatters.test.ts +0 -401
- package/clients/agent-behavior-client.js +0 -110
- package/clients/agent-behavior-client.test.js +0 -94
- package/clients/agent-behavior-client.test.ts +0 -116
- package/clients/amain-types.js +0 -164
- package/clients/architect-client.js +0 -291
- package/clients/ast-grep-client.js +0 -253
- package/clients/ast-grep-parser.js +0 -84
- package/clients/ast-grep-rule-manager.js +0 -89
- package/clients/ast-grep-types.js +0 -9
- package/clients/auto-loop.js +0 -131
- package/clients/biome-client.js +0 -420
- package/clients/biome-client.test.js +0 -144
- package/clients/biome-client.test.ts +0 -163
- package/clients/cache/rule-cache.js +0 -72
- package/clients/cache-manager.js +0 -245
- package/clients/cache-manager.test.js +0 -197
- package/clients/cache-manager.test.ts +0 -299
- package/clients/complexity-client.js +0 -675
- package/clients/complexity-client.test.js +0 -234
- package/clients/complexity-client.test.ts +0 -255
- package/clients/config-validator.js +0 -465
- package/clients/dependency-checker.js +0 -325
- package/clients/dependency-checker.test.js +0 -60
- package/clients/dependency-checker.test.ts +0 -71
- package/clients/dispatch/__tests__/autofix-integration.test.js +0 -245
- package/clients/dispatch/__tests__/autofix-integration.test.ts +0 -300
- package/clients/dispatch/__tests__/runner-registration.test.js +0 -234
- package/clients/dispatch/__tests__/runner-registration.test.ts +0 -286
- package/clients/dispatch/debug.log +0 -1
- package/clients/dispatch/dispatcher.edge.test.js +0 -82
- package/clients/dispatch/dispatcher.edge.test.ts +0 -100
- package/clients/dispatch/dispatcher.format.test.js +0 -46
- package/clients/dispatch/dispatcher.format.test.ts +0 -58
- package/clients/dispatch/dispatcher.inline.test.js +0 -74
- package/clients/dispatch/dispatcher.inline.test.ts +0 -93
- package/clients/dispatch/dispatcher.js +0 -381
- package/clients/dispatch/dispatcher.test.js +0 -116
- package/clients/dispatch/dispatcher.test.ts +0 -149
- package/clients/dispatch/integration.js +0 -108
- package/clients/dispatch/plan.js +0 -183
- package/clients/dispatch/runners/architect.js +0 -83
- package/clients/dispatch/runners/architect.test.js +0 -138
- package/clients/dispatch/runners/architect.test.ts +0 -162
- package/clients/dispatch/runners/ast-grep-napi.js +0 -405
- package/clients/dispatch/runners/ast-grep-napi.test.js +0 -107
- package/clients/dispatch/runners/ast-grep-napi.test.ts +0 -129
- package/clients/dispatch/runners/ast-grep.js +0 -157
- package/clients/dispatch/runners/biome.js +0 -55
- package/clients/dispatch/runners/config-validation.js +0 -67
- package/clients/dispatch/runners/go-vet.js +0 -48
- package/clients/dispatch/runners/index.js +0 -47
- package/clients/dispatch/runners/lsp.js +0 -102
- package/clients/dispatch/runners/oxlint.js +0 -67
- package/clients/dispatch/runners/oxlint.test.js +0 -230
- package/clients/dispatch/runners/oxlint.test.ts +0 -303
- package/clients/dispatch/runners/pyright.js +0 -100
- package/clients/dispatch/runners/pyright.test.js +0 -98
- package/clients/dispatch/runners/pyright.test.ts +0 -121
- package/clients/dispatch/runners/python-slop.js +0 -97
- package/clients/dispatch/runners/python-slop.test.js +0 -203
- package/clients/dispatch/runners/python-slop.test.ts +0 -298
- package/clients/dispatch/runners/ruff.js +0 -48
- package/clients/dispatch/runners/rust-clippy.js +0 -102
- package/clients/dispatch/runners/scan_codebase.test.js +0 -89
- package/clients/dispatch/runners/scan_codebase.test.ts +0 -105
- package/clients/dispatch/runners/shellcheck.js +0 -147
- package/clients/dispatch/runners/shellcheck.test.js +0 -98
- package/clients/dispatch/runners/shellcheck.test.ts +0 -129
- package/clients/dispatch/runners/similarity.js +0 -230
- package/clients/dispatch/runners/spellcheck.js +0 -106
- package/clients/dispatch/runners/spellcheck.test.js +0 -158
- package/clients/dispatch/runners/spellcheck.test.ts +0 -214
- package/clients/dispatch/runners/tree-sitter.js +0 -246
- package/clients/dispatch/runners/ts-lsp.js +0 -125
- package/clients/dispatch/runners/ts-slop.js +0 -113
- package/clients/dispatch/runners/type-safety.js +0 -142
- package/clients/dispatch/runners/utils/diagnostic-parsers.js +0 -134
- package/clients/dispatch/runners/utils/runner-helpers.js +0 -115
- package/clients/dispatch/runners/utils.js +0 -51
- package/clients/dispatch/runners/yaml-rule-parser.js +0 -360
- package/clients/dispatch/types.js +0 -16
- package/clients/dispatch/utils/format-utils.js +0 -44
- package/clients/dogfood.test.js +0 -201
- package/clients/dogfood.test.ts +0 -269
- package/clients/file-kinds.js +0 -177
- package/clients/file-kinds.test.js +0 -169
- package/clients/file-kinds.test.ts +0 -210
- package/clients/file-time.js +0 -152
- package/clients/file-utils.js +0 -40
- package/clients/fix-scanners.js +0 -204
- package/clients/format-service.js +0 -184
- package/clients/formatters.js +0 -488
- package/clients/go-client.js +0 -203
- package/clients/go-client.test.js +0 -127
- package/clients/go-client.test.ts +0 -143
- package/clients/installer/index.js +0 -403
- package/clients/interviewer-templates.js +0 -75
- package/clients/interviewer.js +0 -173
- package/clients/jscpd-client.js +0 -196
- package/clients/jscpd-client.test.js +0 -127
- package/clients/jscpd-client.test.ts +0 -145
- package/clients/knip-client.js +0 -239
- package/clients/knip-client.test.js +0 -112
- package/clients/knip-client.test.ts +0 -128
- package/clients/latency-logger.js +0 -40
- package/clients/lsp/__tests__/client.test.js +0 -310
- package/clients/lsp/__tests__/client.test.ts +0 -412
- package/clients/lsp/__tests__/config.test.js +0 -167
- package/clients/lsp/__tests__/config.test.ts +0 -217
- package/clients/lsp/__tests__/error-recovery.test.js +0 -213
- package/clients/lsp/__tests__/error-recovery.test.ts +0 -279
- package/clients/lsp/__tests__/integration.test.js +0 -127
- package/clients/lsp/__tests__/integration.test.ts +0 -160
- package/clients/lsp/__tests__/launch.test.js +0 -313
- package/clients/lsp/__tests__/launch.test.ts +0 -394
- package/clients/lsp/__tests__/server.test.js +0 -259
- package/clients/lsp/__tests__/server.test.ts +0 -332
- package/clients/lsp/__tests__/service.test.js +0 -438
- package/clients/lsp/__tests__/service.test.ts +0 -530
- package/clients/lsp/client.js +0 -350
- package/clients/lsp/config.js +0 -112
- package/clients/lsp/index.js +0 -318
- package/clients/lsp/installer/index.js +0 -391
- package/clients/lsp/interactive-install.js +0 -221
- package/clients/lsp/language.js +0 -170
- package/clients/lsp/launch.js +0 -329
- package/clients/lsp/lsp/launch.js +0 -116
- package/clients/lsp/lsp/server.js +0 -532
- package/clients/lsp/lsp-index.js +0 -10
- package/clients/lsp/path-utils.js +0 -5
- package/clients/lsp/server.js +0 -725
- package/clients/lsp/test-py-spawn/requirements.txt +0 -1
- package/clients/lsp/test-py-spawn/test.py +0 -3
- package/clients/lsp/test-py-svc/requirements.txt +0 -1
- package/clients/lsp/test-py-svc/test.py +0 -3
- package/clients/lsp/test-python-project/requirements.txt +0 -1
- package/clients/lsp/test-python-project/test.py +0 -5
- package/clients/metrics-client.js +0 -107
- package/clients/metrics-client.test.js +0 -128
- package/clients/metrics-client.test.ts +0 -163
- package/clients/metrics-history.js +0 -367
- package/clients/path-utils.js +0 -142
- package/clients/pipeline.js +0 -272
- package/clients/production-readiness.js +0 -522
- package/clients/project-index.js +0 -255
- package/clients/project-metadata.js +0 -531
- package/clients/ruff-client.js +0 -325
- package/clients/ruff-client.test.js +0 -132
- package/clients/ruff-client.test.ts +0 -153
- package/clients/rules-scanner.js +0 -97
- package/clients/runner-tracker.js +0 -152
- package/clients/rust-client.js +0 -205
- package/clients/rust-client.test.js +0 -108
- package/clients/rust-client.test.ts +0 -130
- package/clients/safe-spawn-async.js +0 -163
- package/clients/safe-spawn.js +0 -241
- package/clients/sanitize.js +0 -291
- package/clients/sanitize.test.js +0 -177
- package/clients/sanitize.test.ts +0 -223
- package/clients/scan-architectural-debt.js +0 -167
- package/clients/scan-utils.js +0 -83
- package/clients/secrets-scanner.js +0 -119
- package/clients/secrets-scanner.test.js +0 -100
- package/clients/secrets-scanner.test.ts +0 -113
- package/clients/sg-runner.js +0 -292
- package/clients/state-matrix.js +0 -160
- package/clients/subprocess-client.js +0 -65
- package/clients/symbol-types.js +0 -5
- package/clients/test-runner-client.js +0 -523
- package/clients/test-runner-client.test.js +0 -192
- package/clients/test-runner-client.test.ts +0 -253
- package/clients/test-utils.js +0 -27
- package/clients/test-utils.ts +0 -36
- package/clients/todo-scanner.js +0 -200
- package/clients/todo-scanner.test.js +0 -301
- package/clients/todo-scanner.test.ts +0 -352
- package/clients/tool-availability.js +0 -207
- package/clients/tree-sitter-client.js +0 -601
- package/clients/tree-sitter-query-loader.js +0 -355
- package/clients/tree-sitter-symbol-extractor.js +0 -289
- package/clients/ts-service.js +0 -129
- package/clients/type-coverage-client.js +0 -127
- package/clients/type-coverage-client.test.js +0 -105
- package/clients/type-coverage-client.test.ts +0 -125
- package/clients/type-safety-client.js +0 -138
- package/clients/types.js +0 -11
- package/clients/typescript-client.codefix.test.js +0 -157
- package/clients/typescript-client.codefix.test.ts +0 -186
- package/clients/typescript-client.js +0 -509
- package/clients/typescript-client.test.js +0 -105
- package/clients/typescript-client.test.ts +0 -126
- package/commands/booboo.js +0 -1007
- package/commands/fix-from-booboo.js +0 -398
- package/commands/fix-simplified.js +0 -618
- package/commands/rate.js +0 -281
- package/commands/rate.test.js +0 -119
- package/commands/rate.test.ts +0 -131
- package/commands/refactor.js +0 -130
package/clients/todo-scanner.js
DELETED
|
@@ -1,200 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* TODO Scanner for pi-local.
|
|
3
|
-
*
|
|
4
|
-
* Scans codebase for TODO, FIXME, HACK, XXX, and other annotations.
|
|
5
|
-
* Helps me understand what's already flagged as problematic or incomplete.
|
|
6
|
-
*
|
|
7
|
-
* No dependencies required â uses regex scanning.
|
|
8
|
-
*/
|
|
9
|
-
import * as fs from "node:fs";
|
|
10
|
-
import * as path from "node:path";
|
|
11
|
-
// --- Scanner ---
|
|
12
|
-
export class TodoScanner {
|
|
13
|
-
constructor() {
|
|
14
|
-
this.pattern = /\b(TODO|FIXME|HACK|XXX|NOTE|DEPRECATED|BUG)\b\s*[(:]?\s*(.+)/gi;
|
|
15
|
-
}
|
|
16
|
-
/**
|
|
17
|
-
* Check if a match position is inside a comment context.
|
|
18
|
-
* Handles: // line comments, star-slash block comments, * JSDoc lines, # Python comments
|
|
19
|
-
*/
|
|
20
|
-
isInComment(line, matchIndex) {
|
|
21
|
-
const trimmed = line.trimStart();
|
|
22
|
-
// Line starts with comment markers â entire line is a comment
|
|
23
|
-
if (/^\/\/|^\/\*|^\*|^#/.test(trimmed))
|
|
24
|
-
return true;
|
|
25
|
-
// Check if there's a // before the match position (not inside a string)
|
|
26
|
-
const beforeMatch = line.slice(0, matchIndex);
|
|
27
|
-
const lineCommentPos = beforeMatch.lastIndexOf("//");
|
|
28
|
-
if (lineCommentPos !== -1) {
|
|
29
|
-
// Count quotes before // to see if it's inside a string
|
|
30
|
-
const beforeComment = beforeMatch.slice(0, lineCommentPos);
|
|
31
|
-
const singleQuotes = (beforeComment.match(/'/g) || []).length;
|
|
32
|
-
const doubleQuotes = (beforeComment.match(/"/g) || []).length;
|
|
33
|
-
const backticks = (beforeComment.match(/`/g) || []).length;
|
|
34
|
-
if (singleQuotes % 2 === 0 &&
|
|
35
|
-
doubleQuotes % 2 === 0 &&
|
|
36
|
-
backticks % 2 === 0) {
|
|
37
|
-
return true;
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
// Check for /* ... */ block comment before match
|
|
41
|
-
const blockOpen = beforeMatch.lastIndexOf("/*");
|
|
42
|
-
const blockClose = beforeMatch.lastIndexOf("*/");
|
|
43
|
-
if (blockOpen !== -1 && blockClose < blockOpen)
|
|
44
|
-
return true;
|
|
45
|
-
// Check for # comment (Python)
|
|
46
|
-
const hashPos = beforeMatch.lastIndexOf("#");
|
|
47
|
-
if (hashPos !== -1) {
|
|
48
|
-
const beforeHash = beforeMatch.slice(0, hashPos);
|
|
49
|
-
const singleQuotes = (beforeHash.match(/'/g) || []).length;
|
|
50
|
-
const doubleQuotes = (beforeHash.match(/"/g) || []).length;
|
|
51
|
-
if (singleQuotes % 2 === 0 && doubleQuotes % 2 === 0) {
|
|
52
|
-
return true;
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
return false;
|
|
56
|
-
}
|
|
57
|
-
/**
|
|
58
|
-
* Scan a single file for TODOs
|
|
59
|
-
*/
|
|
60
|
-
scanFile(filePath) {
|
|
61
|
-
const absolutePath = path.resolve(filePath);
|
|
62
|
-
if (!fs.existsSync(absolutePath))
|
|
63
|
-
return [];
|
|
64
|
-
const content = fs.readFileSync(absolutePath, "utf-8");
|
|
65
|
-
const lines = content.split("\n");
|
|
66
|
-
const items = [];
|
|
67
|
-
for (let i = 0; i < lines.length; i++) {
|
|
68
|
-
const line = lines[i];
|
|
69
|
-
const matches = line.matchAll(this.pattern);
|
|
70
|
-
for (const match of matches) {
|
|
71
|
-
// Skip matches that aren't inside comments
|
|
72
|
-
if (!this.isInComment(line, match.index ?? 0))
|
|
73
|
-
continue;
|
|
74
|
-
const type = match[1].toUpperCase();
|
|
75
|
-
const message = (match[2] || "").trim().replace(/\s*\*\/\s*$/, ""); // Strip closing comment
|
|
76
|
-
items.push({
|
|
77
|
-
type,
|
|
78
|
-
message: message.slice(0, 200), // Limit message length
|
|
79
|
-
file: path.relative(process.cwd(), absolutePath),
|
|
80
|
-
line: i + 1,
|
|
81
|
-
column: match.index || 0,
|
|
82
|
-
});
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
return items;
|
|
86
|
-
}
|
|
87
|
-
/**
|
|
88
|
-
* Scan a directory recursively
|
|
89
|
-
*/
|
|
90
|
-
scanDirectory(dirPath, extensions = [".ts", ".tsx", ".js", ".jsx", ".py"]) {
|
|
91
|
-
const items = [];
|
|
92
|
-
const scan = (dir) => {
|
|
93
|
-
if (!fs.existsSync(dir))
|
|
94
|
-
return;
|
|
95
|
-
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
96
|
-
for (const entry of entries) {
|
|
97
|
-
const fullPath = path.join(dir, entry.name);
|
|
98
|
-
if (entry.isDirectory()) {
|
|
99
|
-
// Skip common non-source directories
|
|
100
|
-
if ([
|
|
101
|
-
"node_modules",
|
|
102
|
-
".git",
|
|
103
|
-
"dist",
|
|
104
|
-
"build",
|
|
105
|
-
".next",
|
|
106
|
-
"coverage",
|
|
107
|
-
].includes(entry.name))
|
|
108
|
-
continue;
|
|
109
|
-
scan(fullPath);
|
|
110
|
-
}
|
|
111
|
-
else if (extensions.some((ext) => entry.name.endsWith(ext))) {
|
|
112
|
-
// Skip this scanner file â its own type literals and regex cause false positives
|
|
113
|
-
if (entry.name === "todo-scanner.ts" ||
|
|
114
|
-
entry.name === "todo-scanner.js")
|
|
115
|
-
continue;
|
|
116
|
-
// Skip test files â intentional annotations are test fixtures, not work items
|
|
117
|
-
if (/\.(test|spec)\.[jt]sx?$/.test(entry.name))
|
|
118
|
-
continue;
|
|
119
|
-
items.push(...this.scanFile(fullPath));
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
};
|
|
123
|
-
scan(path.resolve(dirPath));
|
|
124
|
-
// Group by type
|
|
125
|
-
const byType = new Map();
|
|
126
|
-
for (const item of items) {
|
|
127
|
-
const existing = byType.get(item.type) || [];
|
|
128
|
-
existing.push(item);
|
|
129
|
-
byType.set(item.type, existing);
|
|
130
|
-
}
|
|
131
|
-
// Group by file
|
|
132
|
-
const byFile = new Map();
|
|
133
|
-
for (const item of items) {
|
|
134
|
-
const existing = byFile.get(item.file) || [];
|
|
135
|
-
existing.push(item);
|
|
136
|
-
byFile.set(item.file, existing);
|
|
137
|
-
}
|
|
138
|
-
return { items, byType, byFile };
|
|
139
|
-
}
|
|
140
|
-
/**
|
|
141
|
-
* Format scan results for LLM consumption
|
|
142
|
-
*/
|
|
143
|
-
formatResult(result, maxItems = 30) {
|
|
144
|
-
if (result.items.length === 0)
|
|
145
|
-
return "";
|
|
146
|
-
let output = `[TODOs] ${result.items.length} annotation(s) found`;
|
|
147
|
-
// Summary by type
|
|
148
|
-
const typeCounts = [];
|
|
149
|
-
for (const [type, items] of result.byType) {
|
|
150
|
-
typeCounts.push(`${items.length} ${type}`);
|
|
151
|
-
}
|
|
152
|
-
if (typeCounts.length > 0) {
|
|
153
|
-
output += ` (${typeCounts.join(", ")})`;
|
|
154
|
-
}
|
|
155
|
-
output += ":\n";
|
|
156
|
-
// Show by priority: FIXME/HACK first, then TODO
|
|
157
|
-
const priorityOrder = [
|
|
158
|
-
"FIXME",
|
|
159
|
-
"HACK",
|
|
160
|
-
"BUG",
|
|
161
|
-
"DEPRECATED",
|
|
162
|
-
"TODO",
|
|
163
|
-
"XXX",
|
|
164
|
-
"NOTE",
|
|
165
|
-
];
|
|
166
|
-
const sorted = [...result.items].sort((a, b) => {
|
|
167
|
-
const aIdx = priorityOrder.indexOf(a.type);
|
|
168
|
-
const bIdx = priorityOrder.indexOf(b.type);
|
|
169
|
-
return (aIdx === -1 ? 99 : aIdx) - (bIdx === -1 ? 99 : bIdx);
|
|
170
|
-
});
|
|
171
|
-
for (const item of sorted.slice(0, maxItems)) {
|
|
172
|
-
const icon = this.getIcon(item.type);
|
|
173
|
-
output += ` ${icon} ${item.file}:${item.line} â ${item.type}: ${item.message}\n`;
|
|
174
|
-
}
|
|
175
|
-
if (result.items.length > maxItems) {
|
|
176
|
-
output += ` ... and ${result.items.length - maxItems} more\n`;
|
|
177
|
-
}
|
|
178
|
-
return output;
|
|
179
|
-
}
|
|
180
|
-
getIcon(type) {
|
|
181
|
-
switch (type) {
|
|
182
|
-
case "FIXME":
|
|
183
|
-
return "đ´";
|
|
184
|
-
case "HACK":
|
|
185
|
-
return "đ ";
|
|
186
|
-
case "BUG":
|
|
187
|
-
return "đ";
|
|
188
|
-
case "DEPRECATED":
|
|
189
|
-
return "â ī¸";
|
|
190
|
-
case "TODO":
|
|
191
|
-
return "đ";
|
|
192
|
-
case "XXX":
|
|
193
|
-
return "â";
|
|
194
|
-
case "NOTE":
|
|
195
|
-
return "âšī¸";
|
|
196
|
-
default:
|
|
197
|
-
return "âĸ";
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
}
|
|
@@ -1,301 +0,0 @@
|
|
|
1
|
-
import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
|
2
|
-
import { createTempFile, setupTestEnvironment } from "./test-utils.js";
|
|
3
|
-
import { TodoScanner } from "./todo-scanner.js";
|
|
4
|
-
describe("TodoScanner", () => {
|
|
5
|
-
let client;
|
|
6
|
-
let tmpDir;
|
|
7
|
-
let cleanup;
|
|
8
|
-
beforeEach(() => {
|
|
9
|
-
client = new TodoScanner();
|
|
10
|
-
({ tmpDir, cleanup } = setupTestEnvironment("pi-lens-todo-test-"));
|
|
11
|
-
});
|
|
12
|
-
afterEach(() => {
|
|
13
|
-
cleanup();
|
|
14
|
-
});
|
|
15
|
-
describe("scanFile", () => {
|
|
16
|
-
it("should return empty array for non-existent files", () => {
|
|
17
|
-
const result = client.scanFile("/nonexistent/file.ts");
|
|
18
|
-
expect(result).toEqual([]);
|
|
19
|
-
});
|
|
20
|
-
it("should find TODO comments", () => {
|
|
21
|
-
const content = `
|
|
22
|
-
// TODO: implement this function
|
|
23
|
-
function foo() {}
|
|
24
|
-
`;
|
|
25
|
-
const filePath = createTempFile(tmpDir, "test.ts", content);
|
|
26
|
-
const result = client.scanFile(filePath);
|
|
27
|
-
expect(result.length).toBe(1);
|
|
28
|
-
expect(result[0].type).toBe("TODO");
|
|
29
|
-
expect(result[0].message).toContain("implement this function");
|
|
30
|
-
});
|
|
31
|
-
it("should find FIXME comments", () => {
|
|
32
|
-
const content = `
|
|
33
|
-
// FIXME: this is broken
|
|
34
|
-
function foo() {}
|
|
35
|
-
`;
|
|
36
|
-
const filePath = createTempFile(tmpDir, "test.ts", content);
|
|
37
|
-
const result = client.scanFile(filePath);
|
|
38
|
-
expect(result.length).toBe(1);
|
|
39
|
-
expect(result[0].type).toBe("FIXME");
|
|
40
|
-
});
|
|
41
|
-
it("should find HACK comments", () => {
|
|
42
|
-
const content = `
|
|
43
|
-
// HACK: temporary workaround
|
|
44
|
-
const x = 1;
|
|
45
|
-
`;
|
|
46
|
-
const filePath = createTempFile(tmpDir, "test.ts", content);
|
|
47
|
-
const result = client.scanFile(filePath);
|
|
48
|
-
expect(result.length).toBe(1);
|
|
49
|
-
expect(result[0].type).toBe("HACK");
|
|
50
|
-
});
|
|
51
|
-
it("should find BUG comments", () => {
|
|
52
|
-
const content = `
|
|
53
|
-
// BUG: this causes a crash
|
|
54
|
-
const x = 1;
|
|
55
|
-
`;
|
|
56
|
-
const filePath = createTempFile(tmpDir, "test.ts", content);
|
|
57
|
-
const result = client.scanFile(filePath);
|
|
58
|
-
expect(result.length).toBe(1);
|
|
59
|
-
expect(result[0].type).toBe("BUG");
|
|
60
|
-
});
|
|
61
|
-
it("should find NOTE comments", () => {
|
|
62
|
-
const content = `
|
|
63
|
-
// NOTE: important design decision
|
|
64
|
-
const x = 1;
|
|
65
|
-
`;
|
|
66
|
-
const filePath = createTempFile(tmpDir, "test.ts", content);
|
|
67
|
-
const result = client.scanFile(filePath);
|
|
68
|
-
expect(result.length).toBe(1);
|
|
69
|
-
expect(result[0].type).toBe("NOTE");
|
|
70
|
-
});
|
|
71
|
-
it("should find TODO in block comments", () => {
|
|
72
|
-
const content = `
|
|
73
|
-
/*
|
|
74
|
-
* TODO: refactor this later
|
|
75
|
-
*/
|
|
76
|
-
const x = 1;
|
|
77
|
-
`;
|
|
78
|
-
const filePath = createTempFile(tmpDir, "test.ts", content);
|
|
79
|
-
const result = client.scanFile(filePath);
|
|
80
|
-
expect(result.length).toBe(1);
|
|
81
|
-
expect(result[0].type).toBe("TODO");
|
|
82
|
-
});
|
|
83
|
-
it("should find TODO in JSDoc comments", () => {
|
|
84
|
-
const content = `
|
|
85
|
-
/**
|
|
86
|
-
* TODO: add proper documentation
|
|
87
|
-
*/
|
|
88
|
-
function foo() {}
|
|
89
|
-
`;
|
|
90
|
-
const filePath = createTempFile(tmpDir, "test.ts", content);
|
|
91
|
-
const result = client.scanFile(filePath);
|
|
92
|
-
expect(result.length).toBe(1);
|
|
93
|
-
expect(result[0].type).toBe("TODO");
|
|
94
|
-
});
|
|
95
|
-
it("should find TODO in Python comments", () => {
|
|
96
|
-
const content = `
|
|
97
|
-
# TODO: implement this
|
|
98
|
-
def foo():
|
|
99
|
-
pass
|
|
100
|
-
`;
|
|
101
|
-
const filePath = createTempFile(tmpDir, "test.py", content);
|
|
102
|
-
const result = client.scanFile(filePath);
|
|
103
|
-
expect(result.length).toBe(1);
|
|
104
|
-
expect(result[0].type).toBe("TODO");
|
|
105
|
-
});
|
|
106
|
-
it("should skip TODO in strings", () => {
|
|
107
|
-
const content = `
|
|
108
|
-
const message = "TODO: buy milk";
|
|
109
|
-
`;
|
|
110
|
-
const filePath = createTempFile(tmpDir, "test.ts", content);
|
|
111
|
-
const result = client.scanFile(filePath);
|
|
112
|
-
expect(result.length).toBe(0);
|
|
113
|
-
});
|
|
114
|
-
it("should report correct line numbers", () => {
|
|
115
|
-
const content = `
|
|
116
|
-
const x = 1;
|
|
117
|
-
const y = 2;
|
|
118
|
-
// TODO: fix this
|
|
119
|
-
const z = 3;
|
|
120
|
-
`;
|
|
121
|
-
const filePath = createTempFile(tmpDir, "test.ts", content);
|
|
122
|
-
const result = client.scanFile(filePath);
|
|
123
|
-
expect(result[0].line).toBe(4);
|
|
124
|
-
});
|
|
125
|
-
it("should find multiple annotations in one file", () => {
|
|
126
|
-
const content = `
|
|
127
|
-
// TODO: first
|
|
128
|
-
// FIXME: second
|
|
129
|
-
// HACK: third
|
|
130
|
-
`;
|
|
131
|
-
const filePath = createTempFile(tmpDir, "test.ts", content);
|
|
132
|
-
const result = client.scanFile(filePath);
|
|
133
|
-
expect(result.length).toBe(3);
|
|
134
|
-
});
|
|
135
|
-
});
|
|
136
|
-
describe("scanDirectory", () => {
|
|
137
|
-
it("should scan all files in directory", () => {
|
|
138
|
-
createTempFile(tmpDir, "file1.ts", "// TODO: task 1");
|
|
139
|
-
createTempFile(tmpDir, "file2.ts", "// FIXME: bug 1");
|
|
140
|
-
createTempFile(tmpDir, "file3.py", "# HACK: workaround");
|
|
141
|
-
const result = client.scanDirectory(tmpDir);
|
|
142
|
-
expect(result.items.length).toBe(3);
|
|
143
|
-
});
|
|
144
|
-
it("should skip node_modules", () => {
|
|
145
|
-
createTempFile(tmpDir, "src/file.ts", "// TODO: task 1");
|
|
146
|
-
createTempFile(tmpDir, "node_modules/lib/file.ts", "// TODO: should be skipped");
|
|
147
|
-
const result = client.scanDirectory(tmpDir);
|
|
148
|
-
expect(result.items.length).toBe(1);
|
|
149
|
-
expect(result.items[0].file).not.toContain("node_modules");
|
|
150
|
-
});
|
|
151
|
-
it("should group items by type", () => {
|
|
152
|
-
createTempFile(tmpDir, "file1.ts", "// TODO: task 1");
|
|
153
|
-
createTempFile(tmpDir, "file2.ts", "// TODO: task 2");
|
|
154
|
-
createTempFile(tmpDir, "file3.ts", "// FIXME: bug 1");
|
|
155
|
-
const result = client.scanDirectory(tmpDir);
|
|
156
|
-
expect(result.byType.get("TODO")?.length).toBe(2);
|
|
157
|
-
expect(result.byType.get("FIXME")?.length).toBe(1);
|
|
158
|
-
});
|
|
159
|
-
it("should group items by file", () => {
|
|
160
|
-
createTempFile(tmpDir, "file1.ts", "// TODO: task 1\n// FIXME: bug 1");
|
|
161
|
-
createTempFile(tmpDir, "file2.ts", "// TODO: task 2");
|
|
162
|
-
const result = client.scanDirectory(tmpDir);
|
|
163
|
-
const file1Items = [...result.byFile.entries()].find(([k]) => k.includes("file1.ts"));
|
|
164
|
-
expect(file1Items?.[1].length).toBe(2);
|
|
165
|
-
});
|
|
166
|
-
});
|
|
167
|
-
describe("formatResult", () => {
|
|
168
|
-
it("should return empty string for no results", () => {
|
|
169
|
-
const result = { items: [], byType: new Map(), byFile: new Map() };
|
|
170
|
-
expect(client.formatResult(result)).toBe("");
|
|
171
|
-
});
|
|
172
|
-
it("should format results with counts", () => {
|
|
173
|
-
const result = {
|
|
174
|
-
items: [
|
|
175
|
-
{
|
|
176
|
-
type: "TODO",
|
|
177
|
-
message: "task 1",
|
|
178
|
-
file: "test.ts",
|
|
179
|
-
line: 1,
|
|
180
|
-
column: 0,
|
|
181
|
-
},
|
|
182
|
-
{
|
|
183
|
-
type: "FIXME",
|
|
184
|
-
message: "bug 1",
|
|
185
|
-
file: "test.ts",
|
|
186
|
-
line: 2,
|
|
187
|
-
column: 0,
|
|
188
|
-
},
|
|
189
|
-
],
|
|
190
|
-
byType: new Map([
|
|
191
|
-
[
|
|
192
|
-
"TODO",
|
|
193
|
-
[
|
|
194
|
-
{
|
|
195
|
-
type: "TODO",
|
|
196
|
-
message: "task 1",
|
|
197
|
-
file: "test.ts",
|
|
198
|
-
line: 1,
|
|
199
|
-
column: 0,
|
|
200
|
-
},
|
|
201
|
-
],
|
|
202
|
-
],
|
|
203
|
-
]),
|
|
204
|
-
byFile: new Map([
|
|
205
|
-
[
|
|
206
|
-
"test.ts",
|
|
207
|
-
[
|
|
208
|
-
{
|
|
209
|
-
type: "TODO",
|
|
210
|
-
message: "task 1",
|
|
211
|
-
file: "test.ts",
|
|
212
|
-
line: 1,
|
|
213
|
-
column: 0,
|
|
214
|
-
},
|
|
215
|
-
],
|
|
216
|
-
],
|
|
217
|
-
]),
|
|
218
|
-
};
|
|
219
|
-
const formatted = client.formatResult(result);
|
|
220
|
-
expect(formatted).toContain("2 annotation(s)");
|
|
221
|
-
expect(formatted).toContain("TODO");
|
|
222
|
-
expect(formatted).toContain("FIXME");
|
|
223
|
-
});
|
|
224
|
-
it("should prioritize FIXME/HACK before TODO", () => {
|
|
225
|
-
const result = {
|
|
226
|
-
items: [
|
|
227
|
-
{
|
|
228
|
-
type: "FIXME",
|
|
229
|
-
message: "bug",
|
|
230
|
-
file: "test.ts",
|
|
231
|
-
line: 2,
|
|
232
|
-
column: 0,
|
|
233
|
-
},
|
|
234
|
-
{
|
|
235
|
-
type: "TODO",
|
|
236
|
-
message: "task",
|
|
237
|
-
file: "test.ts",
|
|
238
|
-
line: 1,
|
|
239
|
-
column: 0,
|
|
240
|
-
},
|
|
241
|
-
],
|
|
242
|
-
byType: new Map(),
|
|
243
|
-
byFile: new Map(),
|
|
244
|
-
};
|
|
245
|
-
const formatted = client.formatResult(result);
|
|
246
|
-
// Check that FIXME line comes before TODO line in the sorted output
|
|
247
|
-
const fixmeLineIndex = formatted.indexOf("đ´");
|
|
248
|
-
const todoLineIndex = formatted.indexOf("đ");
|
|
249
|
-
expect(fixmeLineIndex).toBeLessThan(todoLineIndex);
|
|
250
|
-
});
|
|
251
|
-
it("should show correct icons", () => {
|
|
252
|
-
const result = {
|
|
253
|
-
items: [
|
|
254
|
-
{
|
|
255
|
-
type: "FIXME",
|
|
256
|
-
message: "bug",
|
|
257
|
-
file: "test.ts",
|
|
258
|
-
line: 1,
|
|
259
|
-
column: 0,
|
|
260
|
-
},
|
|
261
|
-
{
|
|
262
|
-
type: "HACK",
|
|
263
|
-
message: "hack",
|
|
264
|
-
file: "test.ts",
|
|
265
|
-
line: 2,
|
|
266
|
-
column: 0,
|
|
267
|
-
},
|
|
268
|
-
{
|
|
269
|
-
type: "BUG",
|
|
270
|
-
message: "bug",
|
|
271
|
-
file: "test.ts",
|
|
272
|
-
line: 3,
|
|
273
|
-
column: 0,
|
|
274
|
-
},
|
|
275
|
-
{
|
|
276
|
-
type: "TODO",
|
|
277
|
-
message: "todo",
|
|
278
|
-
file: "test.ts",
|
|
279
|
-
line: 4,
|
|
280
|
-
column: 0,
|
|
281
|
-
},
|
|
282
|
-
{
|
|
283
|
-
type: "NOTE",
|
|
284
|
-
message: "note",
|
|
285
|
-
file: "test.ts",
|
|
286
|
-
line: 5,
|
|
287
|
-
column: 0,
|
|
288
|
-
},
|
|
289
|
-
],
|
|
290
|
-
byType: new Map(),
|
|
291
|
-
byFile: new Map(),
|
|
292
|
-
};
|
|
293
|
-
const formatted = client.formatResult(result);
|
|
294
|
-
expect(formatted).toContain("đ´"); // FIXME
|
|
295
|
-
expect(formatted).toContain("đ "); // HACK
|
|
296
|
-
expect(formatted).toContain("đ"); // BUG
|
|
297
|
-
expect(formatted).toContain("đ"); // TODO
|
|
298
|
-
expect(formatted).toContain("âšī¸"); // NOTE
|
|
299
|
-
});
|
|
300
|
-
});
|
|
301
|
-
});
|