pi-lens 3.3.0 → 3.6.0
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 +91 -0
- package/README.md +175 -13
- package/clients/cache/rule-cache.js +72 -0
- package/clients/cache/rule-cache.ts +104 -0
- package/clients/dispatch/integration.js +48 -1
- package/clients/dispatch/integration.ts +60 -2
- package/clients/dispatch/plan.js +5 -2
- package/clients/dispatch/plan.ts +5 -2
- package/clients/dispatch/runners/ast-grep-napi.js +175 -56
- package/clients/dispatch/runners/ast-grep-napi.test.js +2 -1
- package/clients/dispatch/runners/ast-grep-napi.test.ts +2 -1
- package/clients/dispatch/runners/ast-grep-napi.ts +191 -79
- package/clients/dispatch/runners/similarity.js +1 -1
- package/clients/dispatch/runners/similarity.ts +2 -2
- package/clients/dispatch/runners/tree-sitter.js +137 -10
- package/clients/dispatch/runners/tree-sitter.ts +168 -13
- package/clients/dispatch/runners/ts-lsp.js +3 -2
- package/clients/dispatch/runners/ts-lsp.ts +3 -2
- package/clients/dispatch/runners/yaml-rule-parser.js +70 -2
- package/clients/dispatch/runners/yaml-rule-parser.ts +71 -2
- package/clients/dispatch/types.js +1 -1
- package/clients/dispatch/types.ts +1 -1
- package/clients/lsp/__tests__/service.test.js +3 -0
- package/clients/lsp/__tests__/service.test.ts +3 -0
- package/clients/lsp/client.js +42 -0
- package/clients/lsp/client.ts +79 -0
- package/clients/lsp/index.js +27 -0
- package/clients/lsp/index.ts +35 -0
- package/clients/lsp/launch.js +11 -6
- package/clients/lsp/launch.ts +11 -6
- package/clients/metrics-client.js +3 -160
- package/clients/metrics-client.tdr.test.js +78 -0
- package/clients/metrics-client.test.js +30 -43
- package/clients/metrics-client.test.ts +30 -54
- package/clients/metrics-client.ts +5 -219
- package/clients/metrics-history.js +33 -7
- package/clients/metrics-history.ts +47 -10
- package/clients/pipeline.js +272 -0
- package/clients/pipeline.ts +371 -0
- package/clients/sg-runner.js +21 -3
- package/clients/sg-runner.ts +22 -3
- package/clients/tree-sitter-client.js +23 -2
- package/clients/tree-sitter-client.ts +27 -2
- package/index.ts +604 -771
- package/package.json +1 -1
- package/rules/ast-grep-rules/rules/no-architecture-violation.yml +7 -4
- package/rules/ast-grep-rules/rules/no-single-char-var.yml +3 -3
- package/rules/ast-grep-rules/slop-patterns.yml +85 -62
- package/skills/ast-grep/SKILL.md +42 -1
- package/skills/lsp-navigation/SKILL.md +62 -0
- package/tsconfig.json +1 -1
- package/rules/ast-grep-rules/rules/no-console-log.yml +0 -10
- package/rules/ast-grep-rules/rules/no-default-export.yml +0 -19
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-lens",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.6.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "pi extension for real-time code quality — 31 LSP servers, tree-sitter structural analysis, AST pattern matching, auto-install for TypeScript/Python tooling, duplicate detection, complexity metrics, and inline blockers with comprehensive /lens-booboo reports",
|
|
6
6
|
"repository": {
|
|
@@ -9,7 +9,10 @@ note: |
|
|
|
9
9
|
BAD: import { User } from '../models/user';
|
|
10
10
|
GOOD: import { User } from '../types/user';
|
|
11
11
|
rule:
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
any:
|
|
13
|
+
- pattern: import { $$$ } from "../models/$_"
|
|
14
|
+
- pattern: import { $$$ } from "../../models/$_"
|
|
15
|
+
- pattern: import { $$$ } from "../database/$_"
|
|
16
|
+
- pattern: import { $$$ } from "../../database/$_"
|
|
17
|
+
- pattern: import { $$$ } from "../prisma/$_"
|
|
18
|
+
- pattern: import { $$$ } from "../../prisma/$_"
|
|
@@ -6,7 +6,7 @@ note: |
|
|
|
6
6
|
Single-character variable names reduce readability.
|
|
7
7
|
Exception: loop counters (i, j, k, n) and underscore (_) are acceptable.
|
|
8
8
|
rule:
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
kind: variable_declarator
|
|
10
|
+
has:
|
|
11
|
+
kind: identifier
|
|
12
12
|
regex: "^[a-df-hm-z]$" # Excludes i, j, k, n
|
|
@@ -23,19 +23,27 @@ rule:
|
|
|
23
23
|
kind: while_statement
|
|
24
24
|
pattern: "while ($I < $ARR.length) { $$$ }"
|
|
25
25
|
---
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
26
|
+
# DISABLED: Complex block patterns don't match with current ast-grep-napi runner
|
|
27
|
+
# Requires implementation support for multi-statement patterns with blocks
|
|
28
|
+
# Consider migrating to tree-sitter for better structural matching
|
|
29
|
+
# id: ts-manual-min-max
|
|
30
|
+
# language: typescript
|
|
31
|
+
# severity: warning
|
|
32
|
+
# message: Manual min/max logic - use Math.min() or Math.max()
|
|
33
|
+
# metadata:
|
|
34
|
+
# weight: 3
|
|
35
|
+
# category: slop
|
|
36
|
+
# rule:
|
|
37
|
+
# any:
|
|
38
|
+
# # Pattern for MAX: if (a > b) result = a else result = b
|
|
39
|
+
# - pattern: "if ($A > $B) { $M = $A; } else { $M = $B; }"
|
|
40
|
+
# # Pattern for MIN: if (a < b) result = a else result = b
|
|
41
|
+
# - pattern: "if ($A < $B) { $M = $A; } else { $M = $B; }"
|
|
42
|
+
# # Pattern for MAX (reversed): if (a < b) result = b else result = a
|
|
43
|
+
# - pattern: "if ($A < $B) { $M = $B; } else { $M = $A; }"
|
|
44
|
+
# # Pattern for MIN (reversed): if (a > b) result = b else result = a
|
|
45
|
+
# - pattern: "if ($A > $B) { $M = $B; } else { $M = $A; }"
|
|
46
|
+
# ---
|
|
39
47
|
id: ts-array-map-ceremony
|
|
40
48
|
language: typescript
|
|
41
49
|
severity: warning
|
|
@@ -129,17 +137,18 @@ rule:
|
|
|
129
137
|
- pattern: "if ($X === null || $X === undefined) { return null; }"
|
|
130
138
|
- pattern: "if ($X == null) { return null; }"
|
|
131
139
|
---
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
140
|
+
# DISABLED: Duplicate of prefer-optional-chain.yml which has more comprehensive patterns
|
|
141
|
+
# id: ts-optional-chain-opportunity
|
|
142
|
+
# language: typescript
|
|
143
|
+
# severity: warning
|
|
144
|
+
# message: obj && obj.prop && obj.prop.nested - use optional chaining obj?.prop?.nested
|
|
145
|
+
# metadata:
|
|
146
|
+
# weight: 3
|
|
147
|
+
# category: slop
|
|
148
|
+
# rule:
|
|
149
|
+
# kind: binary_expression
|
|
150
|
+
# pattern: "$A && $A.$B && $A.$B.$C"
|
|
151
|
+
# ---
|
|
143
152
|
id: ts-explicit-undefined-check
|
|
144
153
|
language: typescript
|
|
145
154
|
severity: warning
|
|
@@ -189,19 +198,20 @@ rule:
|
|
|
189
198
|
kind: call_expression
|
|
190
199
|
pattern: "$ARR.filter($F).map($G)"
|
|
191
200
|
---
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
201
|
+
# DISABLED: Pattern doesn't match with current ast-grep-napi runner
|
|
202
|
+
# The AST representation of boolean literals differs from string patterns
|
|
203
|
+
# id: ts-unnecessary-ternary-boolean
|
|
204
|
+
# language: typescript
|
|
205
|
+
# severity: warning
|
|
206
|
+
# message: cond ? true : false - use Boolean(cond) or cond directly
|
|
207
|
+
# metadata:
|
|
208
|
+
# weight: 2
|
|
209
|
+
# category: slop
|
|
210
|
+
# rule:
|
|
211
|
+
# any:
|
|
212
|
+
# - pattern: "$COND ? true : false"
|
|
213
|
+
# - pattern: "$COND ? false : true"
|
|
214
|
+
# ---
|
|
205
215
|
id: ts-typeof-equality
|
|
206
216
|
language: typescript
|
|
207
217
|
severity: warning
|
|
@@ -232,12 +242,32 @@ metadata:
|
|
|
232
242
|
weight: 2
|
|
233
243
|
category: slop
|
|
234
244
|
rule:
|
|
235
|
-
kind: call_expression
|
|
236
245
|
pattern: "$ARR.slice()"
|
|
237
246
|
not:
|
|
238
|
-
|
|
239
|
-
kind: arguments
|
|
247
|
+
pattern: "$ARR.slice($START)"
|
|
240
248
|
---
|
|
249
|
+
# DISABLED: nthChild is unsupported - need to rewrite without it
|
|
250
|
+
# id: ts-parseint-no-radix
|
|
251
|
+
# language: typescript
|
|
252
|
+
# severity: warning
|
|
253
|
+
# message: parseInt(x) without radix - use parseInt(x, 10)
|
|
254
|
+
# metadata:
|
|
255
|
+
# weight: 2
|
|
256
|
+
# category: slop
|
|
257
|
+
# rule:
|
|
258
|
+
# kind: call_expression
|
|
259
|
+
# all:
|
|
260
|
+
# - has:
|
|
261
|
+
# kind: identifier
|
|
262
|
+
# regex: ^parseInt$
|
|
263
|
+
# - has:
|
|
264
|
+
# kind: arguments
|
|
265
|
+
# not:
|
|
266
|
+
# has:
|
|
267
|
+
# nthChild:
|
|
268
|
+
# position: 2
|
|
269
|
+
# ---
|
|
270
|
+
# Rewritten rule using pattern matching instead of nthChild:
|
|
241
271
|
id: ts-parseint-no-radix
|
|
242
272
|
language: typescript
|
|
243
273
|
severity: warning
|
|
@@ -246,17 +276,9 @@ metadata:
|
|
|
246
276
|
weight: 2
|
|
247
277
|
category: slop
|
|
248
278
|
rule:
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
kind: identifier
|
|
253
|
-
regex: ^parseInt$
|
|
254
|
-
- has:
|
|
255
|
-
kind: arguments
|
|
256
|
-
not:
|
|
257
|
-
has:
|
|
258
|
-
nthChild:
|
|
259
|
-
position: 2
|
|
279
|
+
pattern: "parseInt($X)"
|
|
280
|
+
not:
|
|
281
|
+
pattern: "parseInt($X, $RADIX)"
|
|
260
282
|
---
|
|
261
283
|
id: ts-isnan-check
|
|
262
284
|
language: typescript
|
|
@@ -304,17 +326,18 @@ rule:
|
|
|
304
326
|
kind: call_expression
|
|
305
327
|
pattern: "$FN.bind(this)"
|
|
306
328
|
---
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
329
|
+
# DISABLED: Debatable value - arr.length === 0 is often clearer than !arr.length
|
|
330
|
+
# id: ts-empty-array-check
|
|
331
|
+
# language: typescript
|
|
332
|
+
# severity: warning
|
|
333
|
+
# message: arr.length === 0 - use !arr.length or arr.length (truthiness)
|
|
334
|
+
# metadata:
|
|
335
|
+
# weight: 2
|
|
336
|
+
# category: slop
|
|
337
|
+
# rule:
|
|
338
|
+
# kind: binary_expression
|
|
339
|
+
# pattern: "$ARR.length === 0"
|
|
340
|
+
# ---
|
|
318
341
|
id: ts-array-every-some
|
|
319
342
|
language: typescript
|
|
320
343
|
severity: warning
|
package/skills/ast-grep/SKILL.md
CHANGED
|
@@ -62,6 +62,40 @@ class $CLASS($$$BASE):
|
|
|
62
62
|
$$$BODY
|
|
63
63
|
```
|
|
64
64
|
|
|
65
|
+
## Testing Tips
|
|
66
|
+
|
|
67
|
+
**Workflow: Search → Dry-run → Apply**
|
|
68
|
+
|
|
69
|
+
```typescript
|
|
70
|
+
// Step 1: Verify pattern matches what you expect
|
|
71
|
+
ast_grep_search
|
|
72
|
+
pattern: "console.log($MSG)"
|
|
73
|
+
lang: typescript
|
|
74
|
+
paths: ["src/"]
|
|
75
|
+
// → Check the matches are correct
|
|
76
|
+
|
|
77
|
+
// Step 2: Then do dry-run replace
|
|
78
|
+
ast_grep_replace
|
|
79
|
+
pattern: "console.log($MSG)"
|
|
80
|
+
rewrite: "logger.debug($MSG)"
|
|
81
|
+
lang: typescript
|
|
82
|
+
paths: ["src/"]
|
|
83
|
+
apply: false
|
|
84
|
+
|
|
85
|
+
// Step 3: Finally apply
|
|
86
|
+
// apply: true
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
**Metavariable selection guide:**
|
|
90
|
+
| Use | Pattern | Matches |
|
|
91
|
+
|-----|---------|---------|
|
|
92
|
+
| Single arg | `console.log($MSG)` | `console.log("hi")` |
|
|
93
|
+
| Multiple args | `console.log($$$ARGS)` | `console.log("hi", obj, 42)` |
|
|
94
|
+
| Single node | `const $X = $Y` | `const x = 1` |
|
|
95
|
+
| Many nodes | `const $X = $$$REST` | `const x = 1 + 2 + 3` |
|
|
96
|
+
|
|
97
|
+
**Indentation doesn't matter:** ast-grep normalizes whitespace, so tabs vs spaces work the same.
|
|
98
|
+
|
|
65
99
|
## Examples
|
|
66
100
|
|
|
67
101
|
```typescript
|
|
@@ -86,7 +120,12 @@ ast_grep_search
|
|
|
86
120
|
## Common Failures
|
|
87
121
|
|
|
88
122
|
```typescript
|
|
89
|
-
// ❌ INVALID:
|
|
123
|
+
// ❌ INVALID: Multiple AST nodes (missing parentheses)
|
|
124
|
+
pattern: "it\"test name\""
|
|
125
|
+
// ✅ VALID: Single AST node with metavariable
|
|
126
|
+
pattern: "it($TEST)"
|
|
127
|
+
|
|
128
|
+
// ❌ INVALID: Incomplete code
|
|
90
129
|
pattern: "function $NAME("
|
|
91
130
|
// ✅ VALID: Complete code
|
|
92
131
|
pattern: "function $NAME($$$PARAMS) { $$$BODY }"
|
|
@@ -102,6 +141,8 @@ pattern: "console.log(.*)"
|
|
|
102
141
|
pattern: "console.log($$$ARGS)"
|
|
103
142
|
```
|
|
104
143
|
|
|
144
|
+
**Error: "Multiple AST nodes detected"** → Your pattern has multiple code fragments. Use metavariables like `$TEST` instead of literal text in quotes.
|
|
145
|
+
|
|
105
146
|
**Fallback:** If pattern fails twice → `grep -rn "pattern" src/`
|
|
106
147
|
|
|
107
148
|
**Debug:** https://ast-grep.github.io/playground.html
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: lsp-navigation
|
|
3
|
+
description: Navigate code with IDE features - definitions, references, types, call hierarchy. Use as PRIMARY for code intelligence.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# LSP Navigation
|
|
7
|
+
|
|
8
|
+
Use `lsp_navigation` as **PRIMARY** for code intelligence. Do NOT use grep/glob/ast-grep first.
|
|
9
|
+
|
|
10
|
+
**Requires:** `--lens-lsp` flag
|
|
11
|
+
|
|
12
|
+
## When to Use (Code Intelligence)
|
|
13
|
+
|
|
14
|
+
| Question | Operation | Parameters |
|
|
15
|
+
|----------|-----------|------------|
|
|
16
|
+
| "Where is this defined?" | `definition` | filePath, line, character |
|
|
17
|
+
| "Find all usages" | `references` | filePath, line, character |
|
|
18
|
+
| "What type is this?" | `hover` | filePath, line, character |
|
|
19
|
+
| "What symbols in this file?" | `documentSymbol` | filePath |
|
|
20
|
+
| "Find symbol across project" | `workspaceSymbol` | filePath, query |
|
|
21
|
+
| "Who implements this interface?" | `implementation` | filePath, line, character |
|
|
22
|
+
| "Who calls this function?" | `prepareCallHierarchy` → `incomingCalls` | filePath, line, character |
|
|
23
|
+
| "What does this function call?" | `prepareCallHierarchy` → `outgoingCalls` | filePath, line, character |
|
|
24
|
+
|
|
25
|
+
## Call Hierarchy Pattern
|
|
26
|
+
|
|
27
|
+
```typescript
|
|
28
|
+
// Step 1: Prepare (get the callable item)
|
|
29
|
+
const items = await lsp_navigation({
|
|
30
|
+
operation: "prepareCallHierarchy",
|
|
31
|
+
filePath: "src/api.ts",
|
|
32
|
+
line: 42,
|
|
33
|
+
character: 10
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
// Step 2: Get callers (who calls this function)
|
|
37
|
+
const callers = await lsp_navigation({
|
|
38
|
+
operation: "incomingCalls",
|
|
39
|
+
filePath: "src/api.ts",
|
|
40
|
+
callHierarchyItem: items[0]
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
// Step 2: Get callees (what this function calls)
|
|
44
|
+
const callees = await lsp_navigation({
|
|
45
|
+
operation: "outgoingCalls",
|
|
46
|
+
filePath: "src/api.ts",
|
|
47
|
+
callHierarchyItem: items[0]
|
|
48
|
+
});
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## When NOT to Use LSP
|
|
52
|
+
|
|
53
|
+
| Task | Use Instead | Why |
|
|
54
|
+
|------|-------------|-----|
|
|
55
|
+
| Find patterns (console.log) | `ast_grep_search` | Pattern matching |
|
|
56
|
+
| Find text/TODOs | `grep` | Text search |
|
|
57
|
+
| Find files by name | `glob` | File discovery |
|
|
58
|
+
| Read file content | `read` | Direct access |
|
|
59
|
+
|
|
60
|
+
## Golden Rule
|
|
61
|
+
|
|
62
|
+
**Code intelligence → LSP first. Text/pattern search → grep/ast-grep.**
|
package/tsconfig.json
CHANGED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
id: no-console-log
|
|
2
|
-
language: TypeScript
|
|
3
|
-
message: "console.log found — remove or replace with proper logging"
|
|
4
|
-
severity: warning
|
|
5
|
-
note: |
|
|
6
|
-
console.log statements should not be left in production code.
|
|
7
|
-
Use a proper logging framework or remove before committing.
|
|
8
|
-
Grade 2.8 — low complexity, improved production quality.
|
|
9
|
-
rule:
|
|
10
|
-
pattern: console.log($$$ARGS)
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
id: no-default-export
|
|
2
|
-
message: >-
|
|
3
|
-
Use named exports instead of default exports.
|
|
4
|
-
Named exports improve grep-ability: agents can precisely locate
|
|
5
|
-
`export const Foo` and all `import { Foo } from` usages.
|
|
6
|
-
severity: info
|
|
7
|
-
language: typescript
|
|
8
|
-
rule:
|
|
9
|
-
pattern: export default $X
|
|
10
|
-
note: |
|
|
11
|
-
Named exports make code searchable for agents and humans.
|
|
12
|
-
|
|
13
|
-
Before:
|
|
14
|
-
export default function helper() { }
|
|
15
|
-
|
|
16
|
-
After:
|
|
17
|
-
export function helper() { }
|
|
18
|
-
|
|
19
|
-
Exception: Entry points (index.ts) typically require default exports.
|