@mmnto/totem 1.0.0 → 1.2.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/dist/ast-classifier.d.ts +8 -0
- package/dist/ast-classifier.d.ts.map +1 -1
- package/dist/ast-classifier.js +2 -2
- package/dist/ast-classifier.js.map +1 -1
- package/dist/ast-grep-query.d.ts +22 -0
- package/dist/ast-grep-query.d.ts.map +1 -0
- package/dist/ast-grep-query.js +86 -0
- package/dist/ast-grep-query.js.map +1 -0
- package/dist/ast-query.d.ts +18 -0
- package/dist/ast-query.d.ts.map +1 -0
- package/dist/ast-query.js +177 -0
- package/dist/ast-query.js.map +1 -0
- package/dist/ast-query.test.d.ts +2 -0
- package/dist/ast-query.test.d.ts.map +1 -0
- package/dist/ast-query.test.js +79 -0
- package/dist/ast-query.test.js.map +1 -0
- package/dist/compiler.d.ts +46 -10
- package/dist/compiler.d.ts.map +1 -1
- package/dist/compiler.js +138 -2
- package/dist/compiler.js.map +1 -1
- package/dist/config-schema.d.ts +4 -0
- package/dist/config-schema.d.ts.map +1 -1
- package/dist/config-schema.js +2 -0
- package/dist/config-schema.js.map +1 -1
- package/dist/index.d.ts +7 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -3
- package/dist/index.js.map +1 -1
- package/dist/ingest/pipeline.d.ts +11 -0
- package/dist/ingest/pipeline.d.ts.map +1 -1
- package/dist/ingest/pipeline.js +57 -0
- package/dist/ingest/pipeline.js.map +1 -1
- package/dist/ingest/sync.d.ts +1 -1
- package/dist/ingest/sync.d.ts.map +1 -1
- package/dist/ingest/sync.js +1 -1
- package/dist/ingest/sync.js.map +1 -1
- package/package.json +2 -1
package/dist/ast-classifier.d.ts
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
import type { AstContext } from './compiler.js';
|
|
2
2
|
export type SupportedLanguage = 'typescript' | 'tsx' | 'javascript';
|
|
3
|
+
/**
|
|
4
|
+
* Initialize web-tree-sitter WASM engine. Idempotent — safe to call multiple times.
|
|
5
|
+
*/
|
|
6
|
+
export declare function ensureInit(): Promise<void>;
|
|
7
|
+
/**
|
|
8
|
+
* Load a Tree-sitter grammar WASM file for the given language.
|
|
9
|
+
*/
|
|
10
|
+
export declare function loadGrammar(lang: SupportedLanguage): Promise<import('web-tree-sitter').Language>;
|
|
3
11
|
/**
|
|
4
12
|
* Classify specific lines of source code by their AST context.
|
|
5
13
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ast-classifier.d.ts","sourceRoot":"","sources":["../src/ast-classifier.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAIhD,MAAM,MAAM,iBAAiB,GAAG,YAAY,GAAG,KAAK,GAAG,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"ast-classifier.d.ts","sourceRoot":"","sources":["../src/ast-classifier.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAIhD,MAAM,MAAM,iBAAiB,GAAG,YAAY,GAAG,KAAK,GAAG,YAAY,CAAC;AASpE;;GAEG;AACH,wBAAsB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAgBhD;AAED;;GAEG;AACH,wBAAsB,WAAW,CAC/B,IAAI,EAAE,iBAAiB,GACtB,OAAO,CAAC,OAAO,iBAAiB,EAAE,QAAQ,CAAC,CA0B7C;AAqCD;;;;;;;GAOG;AACH,wBAAsB,aAAa,CACjC,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,MAAM,EAAE,EACrB,QAAQ,EAAE,iBAAiB,GAC1B,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CA+ClC;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,iBAAiB,GAAG,SAAS,CAe9E"}
|
package/dist/ast-classifier.js
CHANGED
|
@@ -6,7 +6,7 @@ const grammarCache = new Map();
|
|
|
6
6
|
/**
|
|
7
7
|
* Initialize web-tree-sitter WASM engine. Idempotent — safe to call multiple times.
|
|
8
8
|
*/
|
|
9
|
-
async function ensureInit() {
|
|
9
|
+
export async function ensureInit() {
|
|
10
10
|
if (Parser)
|
|
11
11
|
return;
|
|
12
12
|
if (initPromise)
|
|
@@ -25,7 +25,7 @@ async function ensureInit() {
|
|
|
25
25
|
/**
|
|
26
26
|
* Load a Tree-sitter grammar WASM file for the given language.
|
|
27
27
|
*/
|
|
28
|
-
async function loadGrammar(lang) {
|
|
28
|
+
export async function loadGrammar(lang) {
|
|
29
29
|
const cached = grammarCache.get(lang);
|
|
30
30
|
if (cached)
|
|
31
31
|
return cached;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ast-classifier.js","sourceRoot":"","sources":["../src/ast-classifier.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAQ5C,uDAAuD;AAEvD,IAAI,MAAM,GAAmD,IAAI,CAAC;AAClE,IAAI,WAAW,GAAyB,IAAI,CAAC;AAE7C,MAAM,YAAY,GAAG,IAAI,GAAG,EAAyD,CAAC;AAEtF;;GAEG;AACH,KAAK,UAAU,UAAU;
|
|
1
|
+
{"version":3,"file":"ast-classifier.js","sourceRoot":"","sources":["../src/ast-classifier.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAQ5C,uDAAuD;AAEvD,IAAI,MAAM,GAAmD,IAAI,CAAC;AAClE,IAAI,WAAW,GAAyB,IAAI,CAAC;AAE7C,MAAM,YAAY,GAAG,IAAI,GAAG,EAAyD,CAAC;AAEtF;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU;IAC9B,IAAI,MAAM;QAAE,OAAO;IACnB,IAAI,WAAW;QAAE,OAAO,WAAW,CAAC;IAEpC,WAAW,GAAG,CAAC,KAAK,IAAI,EAAE;QACxB,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC,iBAAiB,CAAC,CAAC;QACnD,MAAM,WAAW,GAAG,UAAU,CAAC,OAAO,EAAE,MAAM,IAAI,UAAU,CAAC,MAAM,CAAC;QACpE,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAE/C,8BAA8B;QAC9B,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,sCAAsC,CAAC,CAAC;QACzE,MAAM,WAAW,CAAC,IAAI,CAAC,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,CAAC;QACvD,MAAM,GAAG,WAAW,CAAC;IACvB,CAAC,CAAC,EAAE,CAAC;IAEL,OAAO,WAAW,CAAC;AACrB,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,IAAuB;IAEvB,MAAM,MAAM,GAAG,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACtC,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC;IAE1B,MAAM,UAAU,EAAE,CAAC;IACnB,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC,iBAAiB,CAAC,CAAC;IACnD,MAAM,aAAa,GAAG,UAAU,CAAC,OAAO,EAAE,QAAQ,IAAI,UAAU,CAAC,QAAQ,CAAC;IAE1E,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC/C,IAAI,QAAgB,CAAC;IAErB,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,YAAY;YACf,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,oDAAoD,CAAC,CAAC;YACjF,MAAM;QACR,KAAK,KAAK;YACR,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,6CAA6C,CAAC,CAAC;YAC1E,MAAM;QACR,KAAK,YAAY;YACf,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,oDAAoD,CAAC,CAAC;YACjF,MAAM;IACV,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,aAAa,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACnD,YAAY,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAChC,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,uDAAuD;AAEvD,4DAA4D;AAC5D,MAAM,iBAAiB,GAAG,IAAI,GAAG,CAAC;IAChC,QAAQ;IACR,iBAAiB;IACjB,iBAAiB;IACjB,uBAAuB;CACxB,CAAC,CAAC;AAEH,qDAAqD;AACrD,MAAM,kBAAkB,GAAG,IAAI,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;AAEhD,2DAA2D;AAC3D,MAAM,gBAAgB,GAAG,IAAI,GAAG,CAAC,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC,CAAC;AAE7D;;;GAGG;AACH,SAAS,YAAY,CAAC,IAAoC;IACxD,IAAI,OAAO,GAA0C,IAAI,CAAC;IAE1D,OAAO,OAAO,EAAE,CAAC;QACf,IAAI,iBAAiB,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC;YAAE,OAAO,QAAQ,CAAC;QACzD,IAAI,kBAAkB,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC;YAAE,OAAO,SAAS,CAAC;QAC3D,IAAI,gBAAgB,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC;YAAE,OAAO,OAAO,CAAC;QACvD,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC;IAC3B,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,uDAAuD;AAEvD;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,OAAe,EACf,WAAqB,EACrB,QAA2B;IAE3B,MAAM,MAAM,GAAG,IAAI,GAAG,EAAsB,CAAC;IAC7C,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,MAAM,CAAC;IAE5C,MAAM,UAAU,EAAE,CAAC;IAEnB,MAAM,OAAO,GAAG,MAAM,WAAW,CAAC,QAAQ,CAAC,CAAC;IAC5C,MAAM,MAAM,GAAG,IAAI,MAAO,EAAE,CAAC;IAC7B,IAAI,CAAC;QACH,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;QAC5B,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACnC,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,yDAAyD;YACzD,OAAO,MAAM,CAAC;QAChB,CAAC;QAED,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;YAC/B,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAElC,KAAK,MAAM,OAAO,IAAI,WAAW,EAAE,CAAC;gBAClC,gCAAgC;gBAChC,MAAM,GAAG,GAAG,OAAO,GAAG,CAAC,CAAC;gBACxB,yEAAyE;gBACzE,MAAM,QAAQ,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC;gBAC5B,IAAI,QAAQ,KAAK,SAAS;oBAAE,SAAS;gBAErC,MAAM,GAAG,GAAG,QAAQ,CAAC,MAAM,GAAG,QAAQ,CAAC,SAAS,EAAE,CAAC,MAAM,CAAC;gBAC1D,MAAM,IAAI,GAAG,QAAQ,CAAC,qBAAqB,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;gBAClE,IAAI,CAAC,IAAI;oBAAE,SAAS;gBAEpB,+DAA+D;gBAC/D,IAAI,IAAI,CAAC,IAAI,KAAK,OAAO,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;oBAC3C,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;oBAC5B,SAAS;gBACX,CAAC;gBAED,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC;YAC1C,CAAC;QACH,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,MAAM,EAAE,CAAC;QAChB,CAAC;IACH,CAAC;YAAS,CAAC;QACT,MAAM,CAAC,MAAM,EAAE,CAAC;IAClB,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CAAC,GAAW;IAC7C,QAAQ,GAAG,CAAC,WAAW,EAAE,EAAE,CAAC;QAC1B,KAAK,KAAK;YACR,OAAO,YAAY,CAAC;QACtB,KAAK,MAAM;YACT,OAAO,KAAK,CAAC;QACf,KAAK,KAAK,CAAC;QACX,KAAK,MAAM,CAAC;QACZ,KAAK,MAAM;YACT,OAAO,YAAY,CAAC;QACtB,KAAK,MAAM;YACT,OAAO,KAAK,CAAC,CAAC,0BAA0B;QAC1C;YACE,OAAO,SAAS,CAAC;IACrB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { NapiConfig } from '@ast-grep/napi';
|
|
2
|
+
/** ast-grep pattern: either a simple string or a full NapiConfig rule object */
|
|
3
|
+
export type AstGrepRule = string | NapiConfig;
|
|
4
|
+
export interface AstGrepMatch {
|
|
5
|
+
lineNumber: number;
|
|
6
|
+
lineText: string;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Run an ast-grep pattern against file content, filtering to added lines.
|
|
10
|
+
* Accepts either a string pattern or a NapiConfig rule object (compound rules).
|
|
11
|
+
*/
|
|
12
|
+
export declare function matchAstGrepPattern(content: string, ext: string, pattern: AstGrepRule, addedLineNumbers: number[]): AstGrepMatch[];
|
|
13
|
+
/**
|
|
14
|
+
* Parse a file once and run multiple ast-grep rules against it.
|
|
15
|
+
* O(M + N) — file parsed exactly once regardless of rule count.
|
|
16
|
+
* Returns results indexed by position in the input array.
|
|
17
|
+
*/
|
|
18
|
+
export declare function matchAstGrepPatternsBatch(content: string, ext: string, queries: Array<{
|
|
19
|
+
rule: AstGrepRule;
|
|
20
|
+
addedLineNumbers: number[];
|
|
21
|
+
}>): AstGrepMatch[][];
|
|
22
|
+
//# sourceMappingURL=ast-grep-query.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ast-grep-query.d.ts","sourceRoot":"","sources":["../src/ast-grep-query.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAKjD,gFAAgF;AAChF,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,UAAU,CAAC;AAE9C,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;CAClB;AA8DD;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,WAAW,EACpB,gBAAgB,EAAE,MAAM,EAAE,GACzB,YAAY,EAAE,CAUhB;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,gBAAgB,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,GAChE,YAAY,EAAE,EAAE,CAkBlB"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { Lang, parse } from '@ast-grep/napi';
|
|
2
|
+
// ─── Language mapping ───────────────────────────────
|
|
3
|
+
/** Map file extensions to ast-grep Lang enum. */
|
|
4
|
+
function extensionToLang(ext) {
|
|
5
|
+
switch (ext.toLowerCase()) {
|
|
6
|
+
case '.ts':
|
|
7
|
+
return Lang.TypeScript;
|
|
8
|
+
case '.tsx':
|
|
9
|
+
return Lang.Tsx;
|
|
10
|
+
case '.js':
|
|
11
|
+
case '.mjs':
|
|
12
|
+
case '.cjs':
|
|
13
|
+
return Lang.JavaScript;
|
|
14
|
+
case '.jsx':
|
|
15
|
+
return Lang.Tsx;
|
|
16
|
+
default:
|
|
17
|
+
return undefined;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
// ─── Core matching ──────────────────────────────────
|
|
21
|
+
function executeQuery(root, rule, addedLineNumbers, lines) {
|
|
22
|
+
if (addedLineNumbers.length === 0)
|
|
23
|
+
return [];
|
|
24
|
+
const addedSet = new Set(addedLineNumbers);
|
|
25
|
+
try {
|
|
26
|
+
// findAll accepts both string patterns and NapiConfig objects
|
|
27
|
+
const matches = root.root().findAll(rule);
|
|
28
|
+
const results = [];
|
|
29
|
+
for (const match of matches) {
|
|
30
|
+
const startLine = match.range().start.line + 1;
|
|
31
|
+
const endLine = match.range().end.line + 1;
|
|
32
|
+
for (let lineNum = startLine; lineNum <= endLine; lineNum++) {
|
|
33
|
+
if (addedSet.has(lineNum)) {
|
|
34
|
+
results.push({
|
|
35
|
+
lineNumber: lineNum,
|
|
36
|
+
lineText: lines[lineNum - 1] ?? '',
|
|
37
|
+
});
|
|
38
|
+
break;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return results;
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
return [];
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
// ─── Public API ─────────────────────────────────────
|
|
49
|
+
/**
|
|
50
|
+
* Run an ast-grep pattern against file content, filtering to added lines.
|
|
51
|
+
* Accepts either a string pattern or a NapiConfig rule object (compound rules).
|
|
52
|
+
*/
|
|
53
|
+
export function matchAstGrepPattern(content, ext, pattern, addedLineNumbers) {
|
|
54
|
+
const lang = extensionToLang(ext);
|
|
55
|
+
if (!lang)
|
|
56
|
+
return [];
|
|
57
|
+
try {
|
|
58
|
+
const root = parse(lang, content);
|
|
59
|
+
return executeQuery(root, pattern, addedLineNumbers, content.split('\n'));
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
return [];
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Parse a file once and run multiple ast-grep rules against it.
|
|
67
|
+
* O(M + N) — file parsed exactly once regardless of rule count.
|
|
68
|
+
* Returns results indexed by position in the input array.
|
|
69
|
+
*/
|
|
70
|
+
export function matchAstGrepPatternsBatch(content, ext, queries) {
|
|
71
|
+
if (queries.length === 0)
|
|
72
|
+
return [];
|
|
73
|
+
const lang = extensionToLang(ext);
|
|
74
|
+
if (!lang) {
|
|
75
|
+
return queries.map(() => []);
|
|
76
|
+
}
|
|
77
|
+
const lines = content.split('\n');
|
|
78
|
+
try {
|
|
79
|
+
const root = parse(lang, content);
|
|
80
|
+
return queries.map(({ rule, addedLineNumbers }) => executeQuery(root, rule, addedLineNumbers, lines));
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
return queries.map(() => []);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=ast-grep-query.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ast-grep-query.js","sourceRoot":"","sources":["../src/ast-grep-query.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface AstMatch {
|
|
2
|
+
lineNumber: number;
|
|
3
|
+
lineText: string;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Convenience wrapper: read + parse + query in one call.
|
|
7
|
+
* For batch operations, use `matchAstQueriesBatch` instead.
|
|
8
|
+
*/
|
|
9
|
+
export declare function matchAstQuery(filePath: string, astQuery: string, addedLineNumbers: number[], cwd: string): Promise<AstMatch[]>;
|
|
10
|
+
/**
|
|
11
|
+
* Parse a file once and run multiple AST queries against it efficiently.
|
|
12
|
+
* O(M + N) instead of O(M * N) — file is read and parsed exactly once.
|
|
13
|
+
*/
|
|
14
|
+
export declare function matchAstQueriesBatch(filePath: string, queries: Array<{
|
|
15
|
+
astQuery: string;
|
|
16
|
+
addedLineNumbers: number[];
|
|
17
|
+
}>, cwd: string): Promise<Map<string, AstMatch[]>>;
|
|
18
|
+
//# sourceMappingURL=ast-query.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ast-query.d.ts","sourceRoot":"","sources":["../src/ast-query.ts"],"names":[],"mappings":"AAYA,MAAM,WAAW,QAAQ;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;CAClB;AA6FD;;;GAGG;AACH,wBAAsB,aAAa,CACjC,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,gBAAgB,EAAE,MAAM,EAAE,EAC1B,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,QAAQ,EAAE,CAAC,CA0CrB;AAED;;;GAGG;AACH,wBAAsB,oBAAoB,CACxC,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,KAAK,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,gBAAgB,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,EAChE,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC,CA6DlC"}
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import { execFile } from 'node:child_process';
|
|
2
|
+
import * as fs from 'node:fs/promises';
|
|
3
|
+
import * as path from 'node:path';
|
|
4
|
+
import { promisify } from 'node:util';
|
|
5
|
+
import { ensureInit, extensionToLanguage, loadGrammar } from './ast-classifier.js';
|
|
6
|
+
const execFileAsync = promisify(execFile);
|
|
7
|
+
// ─── File reading ───────────────────────────────────
|
|
8
|
+
/**
|
|
9
|
+
* Read file content — try `git show :path` first (staged content), fall back to disk.
|
|
10
|
+
* Fully async — does not block the event loop.
|
|
11
|
+
*/
|
|
12
|
+
async function readFileContent(filePath, cwd) {
|
|
13
|
+
try {
|
|
14
|
+
const { stdout } = await execFileAsync('git', ['show', `:${filePath}`], {
|
|
15
|
+
cwd,
|
|
16
|
+
encoding: 'utf-8',
|
|
17
|
+
maxBuffer: 10 * 1024 * 1024, // 10MB safety cap
|
|
18
|
+
});
|
|
19
|
+
return stdout;
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
// Fall back to disk
|
|
23
|
+
}
|
|
24
|
+
try {
|
|
25
|
+
const fullPath = path.resolve(cwd, filePath);
|
|
26
|
+
return await fs.readFile(fullPath, 'utf-8');
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
// ─── Query execution ────────────────────────────────
|
|
33
|
+
/**
|
|
34
|
+
* Run a single S-expression query against a parsed tree.
|
|
35
|
+
* Returns matches that overlap with added line numbers.
|
|
36
|
+
*/
|
|
37
|
+
function runQuery(QueryClass, grammar, rootNode, lines, astQuery, addedLineNumbers) {
|
|
38
|
+
let query = null;
|
|
39
|
+
try {
|
|
40
|
+
query = new QueryClass(grammar, astQuery);
|
|
41
|
+
const matches = query.matches(rootNode);
|
|
42
|
+
const results = [];
|
|
43
|
+
for (const match of matches) {
|
|
44
|
+
// Find the @violation capture, or use the first capture
|
|
45
|
+
let targetNode = null;
|
|
46
|
+
for (const capture of match.captures) {
|
|
47
|
+
if (capture.name === 'violation') {
|
|
48
|
+
targetNode = capture.node;
|
|
49
|
+
break;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
if (!targetNode && match.captures.length > 0) {
|
|
53
|
+
targetNode = match.captures[0].node;
|
|
54
|
+
}
|
|
55
|
+
if (!targetNode)
|
|
56
|
+
continue;
|
|
57
|
+
const startLine = targetNode.startPosition.row + 1;
|
|
58
|
+
const endLine = targetNode.endPosition.row + 1;
|
|
59
|
+
for (let lineNum = startLine; lineNum <= endLine; lineNum++) {
|
|
60
|
+
if (addedLineNumbers.has(lineNum)) {
|
|
61
|
+
results.push({
|
|
62
|
+
lineNumber: lineNum,
|
|
63
|
+
lineText: lines[lineNum - 1] ?? '',
|
|
64
|
+
});
|
|
65
|
+
break;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return results;
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
// Invalid query — fail-open
|
|
73
|
+
return [];
|
|
74
|
+
}
|
|
75
|
+
finally {
|
|
76
|
+
query?.delete();
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
// ─── Public API ─────────────────────────────────────
|
|
80
|
+
/**
|
|
81
|
+
* Convenience wrapper: read + parse + query in one call.
|
|
82
|
+
* For batch operations, use `matchAstQueriesBatch` instead.
|
|
83
|
+
*/
|
|
84
|
+
export async function matchAstQuery(filePath, astQuery, addedLineNumbers, cwd) {
|
|
85
|
+
if (addedLineNumbers.length === 0)
|
|
86
|
+
return [];
|
|
87
|
+
const ext = path.extname(filePath);
|
|
88
|
+
const lang = extensionToLanguage(ext);
|
|
89
|
+
if (!lang)
|
|
90
|
+
return [];
|
|
91
|
+
const content = await readFileContent(filePath, cwd);
|
|
92
|
+
if (!content)
|
|
93
|
+
return [];
|
|
94
|
+
try {
|
|
95
|
+
await ensureInit();
|
|
96
|
+
const grammar = await loadGrammar(lang);
|
|
97
|
+
const TreeSitter = await import('web-tree-sitter');
|
|
98
|
+
const ParserClass = TreeSitter.default?.Parser ?? TreeSitter.Parser;
|
|
99
|
+
const QueryClass = TreeSitter.default?.Query ?? TreeSitter.Query;
|
|
100
|
+
const parser = new ParserClass();
|
|
101
|
+
try {
|
|
102
|
+
parser.setLanguage(grammar);
|
|
103
|
+
const tree = parser.parse(content);
|
|
104
|
+
if (!tree)
|
|
105
|
+
return [];
|
|
106
|
+
try {
|
|
107
|
+
return runQuery(QueryClass, grammar, tree.rootNode, content.split('\n'), astQuery, new Set(addedLineNumbers));
|
|
108
|
+
}
|
|
109
|
+
finally {
|
|
110
|
+
tree.delete();
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
finally {
|
|
114
|
+
parser.delete();
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
catch {
|
|
118
|
+
return [];
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Parse a file once and run multiple AST queries against it efficiently.
|
|
123
|
+
* O(M + N) instead of O(M * N) — file is read and parsed exactly once.
|
|
124
|
+
*/
|
|
125
|
+
export async function matchAstQueriesBatch(filePath, queries, cwd) {
|
|
126
|
+
const results = new Map();
|
|
127
|
+
if (queries.length === 0)
|
|
128
|
+
return results;
|
|
129
|
+
const ext = path.extname(filePath);
|
|
130
|
+
const lang = extensionToLanguage(ext);
|
|
131
|
+
if (!lang) {
|
|
132
|
+
for (const q of queries)
|
|
133
|
+
results.set(q.astQuery, []);
|
|
134
|
+
return results;
|
|
135
|
+
}
|
|
136
|
+
const content = await readFileContent(filePath, cwd);
|
|
137
|
+
if (!content) {
|
|
138
|
+
for (const q of queries)
|
|
139
|
+
results.set(q.astQuery, []);
|
|
140
|
+
return results;
|
|
141
|
+
}
|
|
142
|
+
try {
|
|
143
|
+
await ensureInit();
|
|
144
|
+
const grammar = await loadGrammar(lang);
|
|
145
|
+
const TreeSitter = await import('web-tree-sitter');
|
|
146
|
+
const ParserClass = TreeSitter.default?.Parser ?? TreeSitter.Parser;
|
|
147
|
+
const QueryClass = TreeSitter.default?.Query ?? TreeSitter.Query;
|
|
148
|
+
const parser = new ParserClass();
|
|
149
|
+
try {
|
|
150
|
+
parser.setLanguage(grammar);
|
|
151
|
+
const tree = parser.parse(content);
|
|
152
|
+
if (!tree) {
|
|
153
|
+
for (const q of queries)
|
|
154
|
+
results.set(q.astQuery, []);
|
|
155
|
+
return results;
|
|
156
|
+
}
|
|
157
|
+
const lines = content.split('\n');
|
|
158
|
+
try {
|
|
159
|
+
for (const { astQuery, addedLineNumbers } of queries) {
|
|
160
|
+
results.set(astQuery, runQuery(QueryClass, grammar, tree.rootNode, lines, astQuery, new Set(addedLineNumbers)));
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
finally {
|
|
164
|
+
tree.delete();
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
finally {
|
|
168
|
+
parser.delete();
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
catch {
|
|
172
|
+
for (const q of queries)
|
|
173
|
+
results.set(q.astQuery, []);
|
|
174
|
+
}
|
|
175
|
+
return results;
|
|
176
|
+
}
|
|
177
|
+
//# sourceMappingURL=ast-query.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ast-query.js","sourceRoot":"","sources":["../src/ast-query.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACvC,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAGtC,OAAO,EAAE,UAAU,EAAE,mBAAmB,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAEnF,MAAM,aAAa,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;AAS1C,uDAAuD;AAEvD;;;GAGG;AACH,KAAK,UAAU,eAAe,CAAC,QAAgB,EAAE,GAAW;IAC1D,IAAI,CAAC;QACH,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,aAAa,CAAC,KAAK,EAAE,CAAC,MAAM,EAAE,IAAI,QAAQ,EAAE,CAAC,EAAE;YACtE,GAAG;YACH,QAAQ,EAAE,OAAO;YACjB,SAAS,EAAE,EAAE,GAAG,IAAI,GAAG,IAAI,EAAE,kBAAkB;SAChD,CAAC,CAAC;QACH,OAAO,MAAM,CAAC;IAChB,CAAC;IAAC,MAAM,CAAC;QACP,oBAAoB;IACtB,CAAC;IAED,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;QAC7C,OAAO,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC9C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,uDAAuD;AAEvD;;;GAGG;AACH,SAAS,QAAQ,CACf,UAGoC,EACpC,OAA2C,EAC3C,QAAwC,EACxC,KAAe,EACf,QAAgB,EAChB,gBAA6B;IAE7B,IAAI,KAAK,GAA2C,IAAI,CAAC;IACzD,IAAI,CAAC;QACH,KAAK,GAAG,IAAI,UAAU,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;QAC1C,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QACxC,MAAM,OAAO,GAAe,EAAE,CAAC;QAE/B,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,wDAAwD;YACxD,IAAI,UAAU,GAA0C,IAAI,CAAC;YAE7D,KAAK,MAAM,OAAO,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;gBACrC,IAAI,OAAO,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;oBACjC,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;oBAC1B,MAAM;gBACR,CAAC;YACH,CAAC;YAED,IAAI,CAAC,UAAU,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC7C,UAAU,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAE,CAAC,IAAI,CAAC;YACvC,CAAC;YAED,IAAI,CAAC,UAAU;gBAAE,SAAS;YAE1B,MAAM,SAAS,GAAG,UAAU,CAAC,aAAa,CAAC,GAAG,GAAG,CAAC,CAAC;YACnD,MAAM,OAAO,GAAG,UAAU,CAAC,WAAW,CAAC,GAAG,GAAG,CAAC,CAAC;YAE/C,KAAK,IAAI,OAAO,GAAG,SAAS,EAAE,OAAO,IAAI,OAAO,EAAE,OAAO,EAAE,EAAE,CAAC;gBAC5D,IAAI,gBAAgB,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;oBAClC,OAAO,CAAC,IAAI,CAAC;wBACX,UAAU,EAAE,OAAO;wBACnB,QAAQ,EAAE,KAAK,CAAC,OAAO,GAAG,CAAC,CAAC,IAAI,EAAE;qBACnC,CAAC,CAAC;oBACH,MAAM;gBACR,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;IAAC,MAAM,CAAC;QACP,4BAA4B;QAC5B,OAAO,EAAE,CAAC;IACZ,CAAC;YAAS,CAAC;QACT,KAAK,EAAE,MAAM,EAAE,CAAC;IAClB,CAAC;AACH,CAAC;AAED,uDAAuD;AAEvD;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,QAAgB,EAChB,QAAgB,EAChB,gBAA0B,EAC1B,GAAW;IAEX,IAAI,gBAAgB,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAE7C,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACnC,MAAM,IAAI,GAAkC,mBAAmB,CAAC,GAAG,CAAC,CAAC;IACrE,IAAI,CAAC,IAAI;QAAE,OAAO,EAAE,CAAC;IAErB,MAAM,OAAO,GAAG,MAAM,eAAe,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;IACrD,IAAI,CAAC,OAAO;QAAE,OAAO,EAAE,CAAC;IAExB,IAAI,CAAC;QACH,MAAM,UAAU,EAAE,CAAC;QACnB,MAAM,OAAO,GAAG,MAAM,WAAW,CAAC,IAAI,CAAC,CAAC;QAExC,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC,iBAAiB,CAAC,CAAC;QACnD,MAAM,WAAW,GAAG,UAAU,CAAC,OAAO,EAAE,MAAM,IAAI,UAAU,CAAC,MAAM,CAAC;QACpE,MAAM,UAAU,GAAG,UAAU,CAAC,OAAO,EAAE,KAAK,IAAI,UAAU,CAAC,KAAK,CAAC;QAEjE,MAAM,MAAM,GAAG,IAAI,WAAW,EAAE,CAAC;QACjC,IAAI,CAAC;YACH,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;YAC5B,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YACnC,IAAI,CAAC,IAAI;gBAAE,OAAO,EAAE,CAAC;YAErB,IAAI,CAAC;gBACH,OAAO,QAAQ,CACb,UAAU,EACV,OAAO,EACP,IAAI,CAAC,QAAQ,EACb,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,EACnB,QAAQ,EACR,IAAI,GAAG,CAAC,gBAAgB,CAAC,CAC1B,CAAC;YACJ,CAAC;oBAAS,CAAC;gBACT,IAAI,CAAC,MAAM,EAAE,CAAC;YAChB,CAAC;QACH,CAAC;gBAAS,CAAC;YACT,MAAM,CAAC,MAAM,EAAE,CAAC;QAClB,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,QAAgB,EAChB,OAAgE,EAChE,GAAW;IAEX,MAAM,OAAO,GAAG,IAAI,GAAG,EAAsB,CAAC;IAC9C,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,OAAO,CAAC;IAEzC,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACnC,MAAM,IAAI,GAAkC,mBAAmB,CAAC,GAAG,CAAC,CAAC;IACrE,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,KAAK,MAAM,CAAC,IAAI,OAAO;YAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;QACrD,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,eAAe,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;IACrD,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,KAAK,MAAM,CAAC,IAAI,OAAO;YAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;QACrD,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,IAAI,CAAC;QACH,MAAM,UAAU,EAAE,CAAC;QACnB,MAAM,OAAO,GAAG,MAAM,WAAW,CAAC,IAAI,CAAC,CAAC;QAExC,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC,iBAAiB,CAAC,CAAC;QACnD,MAAM,WAAW,GAAG,UAAU,CAAC,OAAO,EAAE,MAAM,IAAI,UAAU,CAAC,MAAM,CAAC;QACpE,MAAM,UAAU,GAAG,UAAU,CAAC,OAAO,EAAE,KAAK,IAAI,UAAU,CAAC,KAAK,CAAC;QAEjE,MAAM,MAAM,GAAG,IAAI,WAAW,EAAE,CAAC;QACjC,IAAI,CAAC;YACH,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;YAC5B,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YACnC,IAAI,CAAC,IAAI,EAAE,CAAC;gBACV,KAAK,MAAM,CAAC,IAAI,OAAO;oBAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;gBACrD,OAAO,OAAO,CAAC;YACjB,CAAC;YAED,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAElC,IAAI,CAAC;gBACH,KAAK,MAAM,EAAE,QAAQ,EAAE,gBAAgB,EAAE,IAAI,OAAO,EAAE,CAAC;oBACrD,OAAO,CAAC,GAAG,CACT,QAAQ,EACR,QAAQ,CACN,UAAU,EACV,OAAO,EACP,IAAI,CAAC,QAAQ,EACb,KAAK,EACL,QAAQ,EACR,IAAI,GAAG,CAAC,gBAAgB,CAAC,CAC1B,CACF,CAAC;gBACJ,CAAC;YACH,CAAC;oBAAS,CAAC;gBACT,IAAI,CAAC,MAAM,EAAE,CAAC;YAChB,CAAC;QACH,CAAC;gBAAS,CAAC;YACT,MAAM,CAAC,MAAM,EAAE,CAAC;QAClB,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,KAAK,MAAM,CAAC,IAAI,OAAO;YAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;IACvD,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ast-query.test.d.ts","sourceRoot":"","sources":["../src/ast-query.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import * as fs from 'node:fs';
|
|
2
|
+
import * as os from 'node:os';
|
|
3
|
+
import * as path from 'node:path';
|
|
4
|
+
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
|
|
5
|
+
import { matchAstQuery } from './ast-query.js';
|
|
6
|
+
// ─── Helpers ────────────────────────────────────────
|
|
7
|
+
let tmpDir;
|
|
8
|
+
beforeEach(() => {
|
|
9
|
+
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'totem-ast-query-'));
|
|
10
|
+
});
|
|
11
|
+
afterEach(() => {
|
|
12
|
+
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
13
|
+
});
|
|
14
|
+
function writeFile(name, content) {
|
|
15
|
+
const filePath = path.join(tmpDir, name);
|
|
16
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
17
|
+
fs.writeFileSync(filePath, content, 'utf-8');
|
|
18
|
+
return name;
|
|
19
|
+
}
|
|
20
|
+
// ─── matchAstQuery ──────────────────────────────────
|
|
21
|
+
describe('matchAstQuery', () => {
|
|
22
|
+
it('matches a valid S-expression query against code', async () => {
|
|
23
|
+
const file = writeFile('src/app.ts', ['const x = 1;', 'console.log(x);', 'const y = 2;'].join('\n'));
|
|
24
|
+
// Query to find console.log calls — match member_expression with console.log
|
|
25
|
+
const query = '(call_expression function: (member_expression object: (identifier) @obj (#eq? @obj "console"))) @violation';
|
|
26
|
+
const matches = await matchAstQuery(file, query, [2], tmpDir);
|
|
27
|
+
expect(matches).toHaveLength(1);
|
|
28
|
+
expect(matches[0].lineNumber).toBe(2);
|
|
29
|
+
expect(matches[0].lineText).toContain('console.log');
|
|
30
|
+
});
|
|
31
|
+
it('filters matches to only added lines', async () => {
|
|
32
|
+
const file = writeFile('src/multi.ts', ['console.log("line 1");', 'const x = 1;', 'console.log("line 3");'].join('\n'));
|
|
33
|
+
const query = '(call_expression function: (member_expression object: (identifier) @obj (#eq? @obj "console"))) @violation';
|
|
34
|
+
// Only line 3 is "added"
|
|
35
|
+
const matches = await matchAstQuery(file, query, [3], tmpDir);
|
|
36
|
+
expect(matches).toHaveLength(1);
|
|
37
|
+
expect(matches[0].lineNumber).toBe(3);
|
|
38
|
+
});
|
|
39
|
+
it('returns empty array for invalid S-expression (fail-open)', async () => {
|
|
40
|
+
const file = writeFile('src/safe.ts', 'const x = 1;\n');
|
|
41
|
+
const matches = await matchAstQuery(file, '(this is not valid!!!', [1], tmpDir);
|
|
42
|
+
expect(matches).toEqual([]);
|
|
43
|
+
});
|
|
44
|
+
it('returns empty array for non-JS/TS files', async () => {
|
|
45
|
+
const file = writeFile('config.py', 'import os\nprint("hello")\n');
|
|
46
|
+
const query = '(identifier) @violation';
|
|
47
|
+
const matches = await matchAstQuery(file, query, [1, 2], tmpDir);
|
|
48
|
+
expect(matches).toEqual([]);
|
|
49
|
+
});
|
|
50
|
+
it('returns empty array when no added lines overlap with matches', async () => {
|
|
51
|
+
const file = writeFile('src/no-overlap.ts', ['console.log("line 1");', 'const x = 1;', 'const y = 2;'].join('\n'));
|
|
52
|
+
const query = '(call_expression function: (member_expression object: (identifier) @obj (#eq? @obj "console"))) @violation';
|
|
53
|
+
// Lines 2 and 3 are "added" but console.log is on line 1
|
|
54
|
+
const matches = await matchAstQuery(file, query, [2, 3], tmpDir);
|
|
55
|
+
expect(matches).toEqual([]);
|
|
56
|
+
});
|
|
57
|
+
it('returns empty array for nonexistent file', async () => {
|
|
58
|
+
const matches = await matchAstQuery('nonexistent.ts', '(identifier) @violation', [1], tmpDir);
|
|
59
|
+
expect(matches).toEqual([]);
|
|
60
|
+
});
|
|
61
|
+
it('returns empty array for empty addedLineNumbers', async () => {
|
|
62
|
+
const file = writeFile('src/empty.ts', 'const x = 1;\n');
|
|
63
|
+
const matches = await matchAstQuery(file, '(identifier) @violation', [], tmpDir);
|
|
64
|
+
expect(matches).toEqual([]);
|
|
65
|
+
});
|
|
66
|
+
it('handles JavaScript files', async () => {
|
|
67
|
+
const file = writeFile('src/app.js', ['const x = 1;', 'console.log(x);'].join('\n'));
|
|
68
|
+
const query = '(call_expression function: (member_expression object: (identifier) @obj (#eq? @obj "console"))) @violation';
|
|
69
|
+
const matches = await matchAstQuery(file, query, [2], tmpDir);
|
|
70
|
+
expect(matches).toHaveLength(1);
|
|
71
|
+
});
|
|
72
|
+
it('handles TSX files', async () => {
|
|
73
|
+
const file = writeFile('src/component.tsx', ['const x = 1;', 'console.log(x);', 'const el = <div>hello</div>;'].join('\n'));
|
|
74
|
+
const query = '(call_expression function: (member_expression object: (identifier) @obj (#eq? @obj "console"))) @violation';
|
|
75
|
+
const matches = await matchAstQuery(file, query, [2], tmpDir);
|
|
76
|
+
expect(matches).toHaveLength(1);
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
//# sourceMappingURL=ast-query.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ast-query.test.js","sourceRoot":"","sources":["../src/ast-query.test.ts"],"names":[],"mappings":"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"}
|
package/dist/compiler.d.ts
CHANGED
|
@@ -8,8 +8,12 @@ export declare const CompiledRuleSchema: z.ZodObject<{
|
|
|
8
8
|
pattern: z.ZodString;
|
|
9
9
|
/** Human-readable violation message shown when the pattern matches */
|
|
10
10
|
message: z.ZodString;
|
|
11
|
-
/** Engine type —
|
|
12
|
-
engine: z.
|
|
11
|
+
/** Engine type — 'regex' for line-level matching, 'ast' for Tree-sitter S-expression queries, 'ast-grep' for ast-grep structural patterns */
|
|
12
|
+
engine: z.ZodEnum<["regex", "ast", "ast-grep"]>;
|
|
13
|
+
/** Tree-sitter S-expression query (required when engine is 'ast') */
|
|
14
|
+
astQuery: z.ZodOptional<z.ZodString>;
|
|
15
|
+
/** ast-grep pattern — string for simple patterns, object for compound rules (has/inside/not) */
|
|
16
|
+
astGrepPattern: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodRecord<z.ZodString, z.ZodUnknown>]>>;
|
|
13
17
|
/** ISO timestamp of when this rule was compiled */
|
|
14
18
|
compiledAt: z.ZodString;
|
|
15
19
|
/** ISO timestamp of when this rule was first created (survives recompilation) */
|
|
@@ -25,8 +29,10 @@ export declare const CompiledRuleSchema: z.ZodObject<{
|
|
|
25
29
|
lessonHeading: string;
|
|
26
30
|
pattern: string;
|
|
27
31
|
message: string;
|
|
28
|
-
engine: "regex";
|
|
32
|
+
engine: "regex" | "ast" | "ast-grep";
|
|
29
33
|
compiledAt: string;
|
|
34
|
+
astQuery?: string | undefined;
|
|
35
|
+
astGrepPattern?: string | Record<string, unknown> | undefined;
|
|
30
36
|
createdAt?: string | undefined;
|
|
31
37
|
fileGlobs?: string[] | undefined;
|
|
32
38
|
category?: "security" | "architecture" | "style" | "performance" | undefined;
|
|
@@ -36,8 +42,10 @@ export declare const CompiledRuleSchema: z.ZodObject<{
|
|
|
36
42
|
lessonHeading: string;
|
|
37
43
|
pattern: string;
|
|
38
44
|
message: string;
|
|
39
|
-
engine: "regex";
|
|
45
|
+
engine: "regex" | "ast" | "ast-grep";
|
|
40
46
|
compiledAt: string;
|
|
47
|
+
astQuery?: string | undefined;
|
|
48
|
+
astGrepPattern?: string | Record<string, unknown> | undefined;
|
|
41
49
|
createdAt?: string | undefined;
|
|
42
50
|
fileGlobs?: string[] | undefined;
|
|
43
51
|
category?: "security" | "architecture" | "style" | "performance" | undefined;
|
|
@@ -55,8 +63,12 @@ export declare const CompiledRulesFileSchema: z.ZodObject<{
|
|
|
55
63
|
pattern: z.ZodString;
|
|
56
64
|
/** Human-readable violation message shown when the pattern matches */
|
|
57
65
|
message: z.ZodString;
|
|
58
|
-
/** Engine type —
|
|
59
|
-
engine: z.
|
|
66
|
+
/** Engine type — 'regex' for line-level matching, 'ast' for Tree-sitter S-expression queries, 'ast-grep' for ast-grep structural patterns */
|
|
67
|
+
engine: z.ZodEnum<["regex", "ast", "ast-grep"]>;
|
|
68
|
+
/** Tree-sitter S-expression query (required when engine is 'ast') */
|
|
69
|
+
astQuery: z.ZodOptional<z.ZodString>;
|
|
70
|
+
/** ast-grep pattern — string for simple patterns, object for compound rules (has/inside/not) */
|
|
71
|
+
astGrepPattern: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodRecord<z.ZodString, z.ZodUnknown>]>>;
|
|
60
72
|
/** ISO timestamp of when this rule was compiled */
|
|
61
73
|
compiledAt: z.ZodString;
|
|
62
74
|
/** ISO timestamp of when this rule was first created (survives recompilation) */
|
|
@@ -72,8 +84,10 @@ export declare const CompiledRulesFileSchema: z.ZodObject<{
|
|
|
72
84
|
lessonHeading: string;
|
|
73
85
|
pattern: string;
|
|
74
86
|
message: string;
|
|
75
|
-
engine: "regex";
|
|
87
|
+
engine: "regex" | "ast" | "ast-grep";
|
|
76
88
|
compiledAt: string;
|
|
89
|
+
astQuery?: string | undefined;
|
|
90
|
+
astGrepPattern?: string | Record<string, unknown> | undefined;
|
|
77
91
|
createdAt?: string | undefined;
|
|
78
92
|
fileGlobs?: string[] | undefined;
|
|
79
93
|
category?: "security" | "architecture" | "style" | "performance" | undefined;
|
|
@@ -83,8 +97,10 @@ export declare const CompiledRulesFileSchema: z.ZodObject<{
|
|
|
83
97
|
lessonHeading: string;
|
|
84
98
|
pattern: string;
|
|
85
99
|
message: string;
|
|
86
|
-
engine: "regex";
|
|
100
|
+
engine: "regex" | "ast" | "ast-grep";
|
|
87
101
|
compiledAt: string;
|
|
102
|
+
astQuery?: string | undefined;
|
|
103
|
+
astGrepPattern?: string | Record<string, unknown> | undefined;
|
|
88
104
|
createdAt?: string | undefined;
|
|
89
105
|
fileGlobs?: string[] | undefined;
|
|
90
106
|
category?: "security" | "architecture" | "style" | "performance" | undefined;
|
|
@@ -99,8 +115,10 @@ export declare const CompiledRulesFileSchema: z.ZodObject<{
|
|
|
99
115
|
lessonHeading: string;
|
|
100
116
|
pattern: string;
|
|
101
117
|
message: string;
|
|
102
|
-
engine: "regex";
|
|
118
|
+
engine: "regex" | "ast" | "ast-grep";
|
|
103
119
|
compiledAt: string;
|
|
120
|
+
astQuery?: string | undefined;
|
|
121
|
+
astGrepPattern?: string | Record<string, unknown> | undefined;
|
|
104
122
|
createdAt?: string | undefined;
|
|
105
123
|
fileGlobs?: string[] | undefined;
|
|
106
124
|
category?: "security" | "architecture" | "style" | "performance" | undefined;
|
|
@@ -114,8 +132,10 @@ export declare const CompiledRulesFileSchema: z.ZodObject<{
|
|
|
114
132
|
lessonHeading: string;
|
|
115
133
|
pattern: string;
|
|
116
134
|
message: string;
|
|
117
|
-
engine: "regex";
|
|
135
|
+
engine: "regex" | "ast" | "ast-grep";
|
|
118
136
|
compiledAt: string;
|
|
137
|
+
astQuery?: string | undefined;
|
|
138
|
+
astGrepPattern?: string | Record<string, unknown> | undefined;
|
|
119
139
|
createdAt?: string | undefined;
|
|
120
140
|
fileGlobs?: string[] | undefined;
|
|
121
141
|
category?: "security" | "architecture" | "style" | "performance" | undefined;
|
|
@@ -175,6 +195,13 @@ export type RuleEventCallback = (event: 'trigger' | 'suppress', lessonHash: stri
|
|
|
175
195
|
* Optional `onRuleEvent` callback enables observability metrics collection.
|
|
176
196
|
*/
|
|
177
197
|
export declare function applyRulesToAdditions(rules: CompiledRule[], additions: DiffAddition[], onRuleEvent?: RuleEventCallback): Violation[];
|
|
198
|
+
/**
|
|
199
|
+
* Apply AST-engine compiled rules against pre-extracted diff additions.
|
|
200
|
+
* Handles both Tree-sitter S-expression ('ast') and ast-grep ('ast-grep') engines.
|
|
201
|
+
* Async because it reads files and runs Tree-sitter queries.
|
|
202
|
+
* Handles fileGlobs filtering and suppression same as regex rules.
|
|
203
|
+
*/
|
|
204
|
+
export declare function applyAstRulesToAdditions(rules: CompiledRule[], additions: DiffAddition[], cwd: string, onRuleEvent?: RuleEventCallback): Promise<Violation[]>;
|
|
178
205
|
/**
|
|
179
206
|
* Apply compiled rules against added lines from a diff.
|
|
180
207
|
* Returns all violations found.
|
|
@@ -195,15 +222,24 @@ export declare const CompilerOutputSchema: z.ZodObject<{
|
|
|
195
222
|
pattern: z.ZodOptional<z.ZodString>;
|
|
196
223
|
message: z.ZodOptional<z.ZodString>;
|
|
197
224
|
fileGlobs: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
225
|
+
engine: z.ZodOptional<z.ZodEnum<["regex", "ast", "ast-grep"]>>;
|
|
226
|
+
astQuery: z.ZodOptional<z.ZodString>;
|
|
227
|
+
astGrepPattern: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodRecord<z.ZodString, z.ZodUnknown>]>>;
|
|
198
228
|
}, "strip", z.ZodTypeAny, {
|
|
199
229
|
compilable: boolean;
|
|
230
|
+
astQuery?: string | undefined;
|
|
200
231
|
pattern?: string | undefined;
|
|
201
232
|
message?: string | undefined;
|
|
233
|
+
engine?: "regex" | "ast" | "ast-grep" | undefined;
|
|
234
|
+
astGrepPattern?: string | Record<string, unknown> | undefined;
|
|
202
235
|
fileGlobs?: string[] | undefined;
|
|
203
236
|
}, {
|
|
204
237
|
compilable: boolean;
|
|
238
|
+
astQuery?: string | undefined;
|
|
205
239
|
pattern?: string | undefined;
|
|
206
240
|
message?: string | undefined;
|
|
241
|
+
engine?: "regex" | "ast" | "ast-grep" | undefined;
|
|
242
|
+
astGrepPattern?: string | Record<string, unknown> | undefined;
|
|
207
243
|
fileGlobs?: string[] | undefined;
|
|
208
244
|
}>;
|
|
209
245
|
export type CompilerOutput = z.infer<typeof CompilerOutputSchema>;
|
package/dist/compiler.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compiler.d.ts","sourceRoot":"","sources":["../src/compiler.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"compiler.d.ts","sourceRoot":"","sources":["../src/compiler.ts"],"names":[],"mappings":"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"}
|