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/clients/sg-runner.ts
CHANGED
|
@@ -168,11 +168,30 @@ export class SgRunner {
|
|
|
168
168
|
|
|
169
169
|
proc.on("close", (code: number | null) => {
|
|
170
170
|
if (code !== 0 && !stdout.trim()) {
|
|
171
|
+
// Enhanced error messages for common pattern issues
|
|
172
|
+
let errorMsg = stderr.trim() || `Exit code ${code}`;
|
|
173
|
+
|
|
174
|
+
if (stderr.includes("Multiple AST nodes are detected")) {
|
|
175
|
+
errorMsg =
|
|
176
|
+
`Invalid AST pattern: The pattern appears to contain multiple AST nodes or is malformed.\n` +
|
|
177
|
+
`Common causes:\n` +
|
|
178
|
+
` 1. Missing parentheses: use it($TEST) not it"test"\n` +
|
|
179
|
+
` 2. Raw text without structure: use console.log($MSG) not just "console.log"\n` +
|
|
180
|
+
` 3. Unclosed quotes or brackets\n\n` +
|
|
181
|
+
`Original error: ${errorMsg}`;
|
|
182
|
+
} else if (stderr.includes("Cannot parse query")) {
|
|
183
|
+
errorMsg =
|
|
184
|
+
`Pattern syntax error: The pattern could not be parsed as valid code.\n` +
|
|
185
|
+
`Tips:\n` +
|
|
186
|
+
` - Patterns must be valid ${args.includes("--lang") ? args[args.indexOf("--lang") + 1] : "language"} syntax\n` +
|
|
187
|
+
` - Use metavariables like $NAME, $ARGS for variable parts\n` +
|
|
188
|
+
` - Example: 'function $NAME($$$PARAMS) { $$$BODY }'\n\n` +
|
|
189
|
+
`Original error: ${errorMsg}`;
|
|
190
|
+
}
|
|
191
|
+
|
|
171
192
|
resolve({
|
|
172
193
|
matches: [],
|
|
173
|
-
error: stderr.includes("No files found")
|
|
174
|
-
? undefined
|
|
175
|
-
: stderr.trim() || `Exit code ${code}`,
|
|
194
|
+
error: stderr.includes("No files found") ? undefined : errorMsg,
|
|
176
195
|
});
|
|
177
196
|
return;
|
|
178
197
|
}
|
|
@@ -43,6 +43,8 @@ export class TreeSitterClient {
|
|
|
43
43
|
this.ParserClass = null;
|
|
44
44
|
// biome-ignore lint/suspicious/noExplicitAny: Language loader from module
|
|
45
45
|
this.LanguageLoader = null;
|
|
46
|
+
// biome-ignore lint/suspicious/noExplicitAny: Compiled query cache by language+pattern hash
|
|
47
|
+
this.queryCache = new Map();
|
|
46
48
|
this.queryLoader = new TreeSitterQueryLoader();
|
|
47
49
|
this.queriesLoaded = false;
|
|
48
50
|
this.grammarsDir = this.findGrammarsDir();
|
|
@@ -347,8 +349,24 @@ export class TreeSitterClient {
|
|
|
347
349
|
// If we can't convert, return empty to trigger fallback
|
|
348
350
|
return { query: "", metavars: [] };
|
|
349
351
|
}
|
|
350
|
-
/**
|
|
352
|
+
/** Generate cache key for compiled query */
|
|
353
|
+
getQueryCacheKey(pattern, languageId) {
|
|
354
|
+
// Simple hash for the query string
|
|
355
|
+
let hash = 0;
|
|
356
|
+
for (let i = 0; i < pattern.length; i++) {
|
|
357
|
+
const char = pattern.charCodeAt(i);
|
|
358
|
+
hash = ((hash << 5) - hash + char) | 0;
|
|
359
|
+
}
|
|
360
|
+
return `${languageId}:${hash.toString(36)}`;
|
|
361
|
+
}
|
|
362
|
+
/** Compile a pattern into a tree-sitter Query with caching */
|
|
351
363
|
async compileQuery(pattern, languageId) {
|
|
364
|
+
const cacheKey = this.getQueryCacheKey(pattern, languageId);
|
|
365
|
+
// Check cache first
|
|
366
|
+
if (this.queryCache.has(cacheKey)) {
|
|
367
|
+
this.dbg(`Query cache hit: ${cacheKey}`);
|
|
368
|
+
return this.queryCache.get(cacheKey);
|
|
369
|
+
}
|
|
352
370
|
const language = await this.loadLanguage(languageId);
|
|
353
371
|
if (!language) {
|
|
354
372
|
this.dbg(`Could not load language ${languageId}`);
|
|
@@ -362,7 +380,10 @@ export class TreeSitterClient {
|
|
|
362
380
|
// biome-ignore lint/suspicious/noExplicitAny: Language type compatibility
|
|
363
381
|
const query = new Query(language, queryStr);
|
|
364
382
|
this.dbg(`Query compiled with ${query.patternCount} patterns`);
|
|
365
|
-
|
|
383
|
+
const result = { query, metavars, postFilter, postFilterParams };
|
|
384
|
+
// Cache the compiled query
|
|
385
|
+
this.queryCache.set(cacheKey, result);
|
|
386
|
+
return result;
|
|
366
387
|
}
|
|
367
388
|
catch (err) {
|
|
368
389
|
this.dbg(`Query compilation failed: ${err}`);
|
|
@@ -93,6 +93,8 @@ export class TreeSitterClient {
|
|
|
93
93
|
private ParserClass: any = null;
|
|
94
94
|
// biome-ignore lint/suspicious/noExplicitAny: Language loader from module
|
|
95
95
|
private LanguageLoader: any = null;
|
|
96
|
+
// biome-ignore lint/suspicious/noExplicitAny: Compiled query cache by language+pattern hash
|
|
97
|
+
private queryCache = new Map<string, any>();
|
|
96
98
|
private queryLoader = new TreeSitterQueryLoader();
|
|
97
99
|
private queriesLoaded = false;
|
|
98
100
|
private verbose: boolean;
|
|
@@ -518,7 +520,18 @@ export class TreeSitterClient {
|
|
|
518
520
|
return { query: "", metavars: [] };
|
|
519
521
|
}
|
|
520
522
|
|
|
521
|
-
/**
|
|
523
|
+
/** Generate cache key for compiled query */
|
|
524
|
+
private getQueryCacheKey(pattern: string, languageId: string): string {
|
|
525
|
+
// Simple hash for the query string
|
|
526
|
+
let hash = 0;
|
|
527
|
+
for (let i = 0; i < pattern.length; i++) {
|
|
528
|
+
const char = pattern.charCodeAt(i);
|
|
529
|
+
hash = ((hash << 5) - hash + char) | 0;
|
|
530
|
+
}
|
|
531
|
+
return `${languageId}:${hash.toString(36)}`;
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
/** Compile a pattern into a tree-sitter Query with caching */
|
|
522
535
|
private async compileQuery(
|
|
523
536
|
pattern: string,
|
|
524
537
|
languageId: string,
|
|
@@ -528,6 +541,14 @@ export class TreeSitterClient {
|
|
|
528
541
|
postFilter?: string;
|
|
529
542
|
postFilterParams?: unknown;
|
|
530
543
|
} | null> {
|
|
544
|
+
const cacheKey = this.getQueryCacheKey(pattern, languageId);
|
|
545
|
+
|
|
546
|
+
// Check cache first
|
|
547
|
+
if (this.queryCache.has(cacheKey)) {
|
|
548
|
+
this.dbg(`Query cache hit: ${cacheKey}`);
|
|
549
|
+
return this.queryCache.get(cacheKey);
|
|
550
|
+
}
|
|
551
|
+
|
|
531
552
|
const language = await this.loadLanguage(languageId);
|
|
532
553
|
if (!language) {
|
|
533
554
|
this.dbg(`Could not load language ${languageId}`);
|
|
@@ -548,7 +569,11 @@ export class TreeSitterClient {
|
|
|
548
569
|
// biome-ignore lint/suspicious/noExplicitAny: Language type compatibility
|
|
549
570
|
const query = new Query(language as any, queryStr);
|
|
550
571
|
this.dbg(`Query compiled with ${query.patternCount} patterns`);
|
|
551
|
-
|
|
572
|
+
|
|
573
|
+
const result = { query, metavars, postFilter, postFilterParams };
|
|
574
|
+
// Cache the compiled query
|
|
575
|
+
this.queryCache.set(cacheKey, result);
|
|
576
|
+
return result;
|
|
552
577
|
} catch (err) {
|
|
553
578
|
this.dbg(`Query compilation failed: ${err}`);
|
|
554
579
|
return null;
|