ragcode-context-engine 0.1.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/LICENSE +21 -0
- package/README.md +366 -0
- package/README.zh-CN.md +363 -0
- package/dist/src/cli/configure/app.d.ts +6 -0
- package/dist/src/cli/configure/app.js +81 -0
- package/dist/src/cli/configure/run.d.ts +5 -0
- package/dist/src/cli/configure/run.js +85 -0
- package/dist/src/cli/configure/state.d.ts +42 -0
- package/dist/src/cli/configure/state.js +174 -0
- package/dist/src/cli/configure.d.ts +31 -0
- package/dist/src/cli/configure.js +101 -0
- package/dist/src/cli/index.d.ts +2 -0
- package/dist/src/cli/index.js +503 -0
- package/dist/src/cli/tui/index-progress.d.ts +12 -0
- package/dist/src/cli/tui/index-progress.js +49 -0
- package/dist/src/cli/tui/watch-status.d.ts +10 -0
- package/dist/src/cli/tui/watch-status.js +27 -0
- package/dist/src/cli/update.d.ts +18 -0
- package/dist/src/cli/update.js +111 -0
- package/dist/src/config/dotenv.d.ts +1 -0
- package/dist/src/config/dotenv.js +14 -0
- package/dist/src/config/graph-runtime.d.ts +13 -0
- package/dist/src/config/graph-runtime.js +29 -0
- package/dist/src/config/runtime-config.d.ts +87 -0
- package/dist/src/config/runtime-config.js +215 -0
- package/dist/src/config/semantic-runtime.d.ts +24 -0
- package/dist/src/config/semantic-runtime.js +89 -0
- package/dist/src/context/context-builder.d.ts +20 -0
- package/dist/src/context/context-builder.js +277 -0
- package/dist/src/context/expansion-policy.d.ts +6 -0
- package/dist/src/context/expansion-policy.js +49 -0
- package/dist/src/context/skeletonizer.d.ts +2 -0
- package/dist/src/context/skeletonizer.js +79 -0
- package/dist/src/context/snippet-renderer.d.ts +2 -0
- package/dist/src/context/snippet-renderer.js +67 -0
- package/dist/src/core/contracts.d.ts +74 -0
- package/dist/src/core/contracts.js +1 -0
- package/dist/src/core/engine.d.ts +64 -0
- package/dist/src/core/engine.js +442 -0
- package/dist/src/core/types.d.ts +490 -0
- package/dist/src/core/types.js +1 -0
- package/dist/src/diagnostics/doctor.d.ts +66 -0
- package/dist/src/diagnostics/doctor.js +193 -0
- package/dist/src/diagnostics/embedding-test.d.ts +24 -0
- package/dist/src/diagnostics/embedding-test.js +83 -0
- package/dist/src/graph/diff-files.d.ts +1 -0
- package/dist/src/graph/diff-files.js +14 -0
- package/dist/src/graph/impact-report.d.ts +10 -0
- package/dist/src/graph/impact-report.js +173 -0
- package/dist/src/graph/in-memory-graph-store.d.ts +36 -0
- package/dist/src/graph/in-memory-graph-store.js +395 -0
- package/dist/src/graph/owner-ranking.d.ts +2 -0
- package/dist/src/graph/owner-ranking.js +41 -0
- package/dist/src/graph/sqlite-graph-store.d.ts +51 -0
- package/dist/src/graph/sqlite-graph-store.js +724 -0
- package/dist/src/graph/sqlite-statements.d.ts +36 -0
- package/dist/src/graph/sqlite-statements.js +105 -0
- package/dist/src/graph/target-matcher.d.ts +13 -0
- package/dist/src/graph/target-matcher.js +64 -0
- package/dist/src/index.d.ts +32 -0
- package/dist/src/index.js +32 -0
- package/dist/src/indexing/analyzers/fallback-analyzer.d.ts +6 -0
- package/dist/src/indexing/analyzers/fallback-analyzer.js +45 -0
- package/dist/src/indexing/analyzers/go-treesitter-analyzer.d.ts +2 -0
- package/dist/src/indexing/analyzers/go-treesitter-analyzer.js +87 -0
- package/dist/src/indexing/analyzers/java-treesitter-analyzer.d.ts +2 -0
- package/dist/src/indexing/analyzers/java-treesitter-analyzer.js +88 -0
- package/dist/src/indexing/analyzers/python-treesitter-analyzer.d.ts +2 -0
- package/dist/src/indexing/analyzers/python-treesitter-analyzer.js +96 -0
- package/dist/src/indexing/analyzers/registry.d.ts +5 -0
- package/dist/src/indexing/analyzers/registry.js +23 -0
- package/dist/src/indexing/analyzers/rust-treesitter-analyzer.d.ts +2 -0
- package/dist/src/indexing/analyzers/rust-treesitter-analyzer.js +96 -0
- package/dist/src/indexing/analyzers/tree-sitter-base.d.ts +30 -0
- package/dist/src/indexing/analyzers/tree-sitter-base.js +163 -0
- package/dist/src/indexing/analyzers/types.d.ts +17 -0
- package/dist/src/indexing/analyzers/types.js +1 -0
- package/dist/src/indexing/analyzers/typescript-analyzer.d.ts +5 -0
- package/dist/src/indexing/analyzers/typescript-analyzer.js +199 -0
- package/dist/src/indexing/ast-analyzer.d.ts +11 -0
- package/dist/src/indexing/ast-analyzer.js +11 -0
- package/dist/src/indexing/chunker.d.ts +11 -0
- package/dist/src/indexing/chunker.js +157 -0
- package/dist/src/indexing/ignore-policy.d.ts +6 -0
- package/dist/src/indexing/ignore-policy.js +40 -0
- package/dist/src/indexing/indexer.d.ts +13 -0
- package/dist/src/indexing/indexer.js +189 -0
- package/dist/src/indexing/language.d.ts +3 -0
- package/dist/src/indexing/language.js +24 -0
- package/dist/src/indexing/scanner.d.ts +13 -0
- package/dist/src/indexing/scanner.js +87 -0
- package/dist/src/lsp/definition-resolver.d.ts +6 -0
- package/dist/src/lsp/definition-resolver.js +60 -0
- package/dist/src/lsp/typescript-language-service.d.ts +21 -0
- package/dist/src/lsp/typescript-language-service.js +82 -0
- package/dist/src/mcp/server.d.ts +11 -0
- package/dist/src/mcp/server.js +64 -0
- package/dist/src/mcp/tools.d.ts +266 -0
- package/dist/src/mcp/tools.js +309 -0
- package/dist/src/project/project-identity.d.ts +2 -0
- package/dist/src/project/project-identity.js +24 -0
- package/dist/src/project/project-registry.d.ts +12 -0
- package/dist/src/project/project-registry.js +49 -0
- package/dist/src/project/workspace-resolver.d.ts +20 -0
- package/dist/src/project/workspace-resolver.js +62 -0
- package/dist/src/retrieval/graph-reranker.d.ts +11 -0
- package/dist/src/retrieval/graph-reranker.js +0 -0
- package/dist/src/retrieval/hybrid-retriever.d.ts +31 -0
- package/dist/src/retrieval/hybrid-retriever.js +111 -0
- package/dist/src/retrieval/path-classification.d.ts +6 -0
- package/dist/src/retrieval/path-classification.js +22 -0
- package/dist/src/retrieval/query-matching.d.ts +22 -0
- package/dist/src/retrieval/query-matching.js +166 -0
- package/dist/src/retrieval/query-planner.d.ts +5 -0
- package/dist/src/retrieval/query-planner.js +77 -0
- package/dist/src/retrieval/ranking-signals.d.ts +19 -0
- package/dist/src/retrieval/ranking-signals.js +97 -0
- package/dist/src/retrieval/topology-distance.d.ts +21 -0
- package/dist/src/retrieval/topology-distance.js +116 -0
- package/dist/src/reuse/reuse-detector.d.ts +12 -0
- package/dist/src/reuse/reuse-detector.js +564 -0
- package/dist/src/semantic/deterministic-embedding.d.ts +7 -0
- package/dist/src/semantic/deterministic-embedding.js +31 -0
- package/dist/src/semantic/in-memory-semantic-store.d.ts +11 -0
- package/dist/src/semantic/in-memory-semantic-store.js +65 -0
- package/dist/src/semantic/lance-semantic-store.d.ts +131 -0
- package/dist/src/semantic/lance-semantic-store.js +623 -0
- package/dist/src/semantic/openai-compatible-embedding.d.ts +19 -0
- package/dist/src/semantic/openai-compatible-embedding.js +75 -0
- package/dist/src/service/service-identity.d.ts +13 -0
- package/dist/src/service/service-identity.js +48 -0
- package/dist/src/service/service-manager.d.ts +29 -0
- package/dist/src/service/service-manager.js +231 -0
- package/dist/src/service/service-templates.d.ts +22 -0
- package/dist/src/service/service-templates.js +101 -0
- package/dist/src/subgraph/impact-explainer.d.ts +2 -0
- package/dist/src/subgraph/impact-explainer.js +54 -0
- package/dist/src/subgraph/node-expander.d.ts +13 -0
- package/dist/src/subgraph/node-expander.js +139 -0
- package/dist/src/subgraph/output-preset.d.ts +3 -0
- package/dist/src/subgraph/output-preset.js +102 -0
- package/dist/src/subgraph/subgraph-builder.d.ts +17 -0
- package/dist/src/subgraph/subgraph-builder.js +688 -0
- package/dist/src/topology/export-index.d.ts +7 -0
- package/dist/src/topology/export-index.js +14 -0
- package/dist/src/topology/framework-topology.d.ts +3 -0
- package/dist/src/topology/framework-topology.js +460 -0
- package/dist/src/topology/import-resolver.d.ts +2 -0
- package/dist/src/topology/import-resolver.js +29 -0
- package/dist/src/topology/orm-topology.d.ts +3 -0
- package/dist/src/topology/orm-topology.js +200 -0
- package/dist/src/topology/runtime-topology.d.ts +3 -0
- package/dist/src/topology/runtime-topology.js +204 -0
- package/dist/src/topology/symbol-resolver.d.ts +6 -0
- package/dist/src/topology/symbol-resolver.js +74 -0
- package/dist/src/topology/test-topology.d.ts +2 -0
- package/dist/src/topology/test-topology.js +82 -0
- package/dist/src/utils/hash.d.ts +2 -0
- package/dist/src/utils/hash.js +7 -0
- package/dist/src/utils/path.d.ts +2 -0
- package/dist/src/utils/path.js +7 -0
- package/dist/src/watch/event-journal.d.ts +17 -0
- package/dist/src/watch/event-journal.js +81 -0
- package/dist/src/watch/file-event-coalescer.d.ts +9 -0
- package/dist/src/watch/file-event-coalescer.js +39 -0
- package/dist/src/watch/index-scheduler.d.ts +52 -0
- package/dist/src/watch/index-scheduler.js +190 -0
- package/dist/src/watch/watch-daemon.d.ts +73 -0
- package/dist/src/watch/watch-daemon.js +368 -0
- package/dist/src/watch/watcher-liveness.d.ts +47 -0
- package/dist/src/watch/watcher-liveness.js +168 -0
- package/dist/src/web/server.d.ts +1 -0
- package/dist/src/web/server.js +375 -0
- package/package.json +94 -0
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { DatabaseSync } from "node:sqlite";
|
|
2
|
+
/**
|
|
3
|
+
* Prepared statement pool for SQLiteGraphStore.
|
|
4
|
+
* All SQL lives here — single source of truth for schema access patterns.
|
|
5
|
+
*/
|
|
6
|
+
export declare class SqliteStatements {
|
|
7
|
+
readonly upsertProject: any;
|
|
8
|
+
readonly selectProjectByRoot: any;
|
|
9
|
+
readonly listProjects: any;
|
|
10
|
+
readonly selectFiles: any;
|
|
11
|
+
readonly selectFile: any;
|
|
12
|
+
readonly insertFile: any;
|
|
13
|
+
readonly deleteFilesNotIn: any;
|
|
14
|
+
readonly selectSymbols: any;
|
|
15
|
+
readonly selectSymbolsByFile: any;
|
|
16
|
+
readonly selectSymbolByNameLike: any;
|
|
17
|
+
readonly insertSymbol: any;
|
|
18
|
+
readonly deleteSymbols: any;
|
|
19
|
+
readonly selectEdges: any;
|
|
20
|
+
readonly selectEdgesByKind: any;
|
|
21
|
+
readonly insertEdge: any;
|
|
22
|
+
readonly deleteEdges: any;
|
|
23
|
+
readonly selectChunks: any;
|
|
24
|
+
readonly selectChunksByFile: any;
|
|
25
|
+
readonly insertChunk: any;
|
|
26
|
+
readonly deleteChunks: any;
|
|
27
|
+
readonly searchFts: any;
|
|
28
|
+
readonly insertFts: any;
|
|
29
|
+
readonly deleteFts: any;
|
|
30
|
+
readonly selectSkippedFiles: any;
|
|
31
|
+
readonly insertSkippedFile: any;
|
|
32
|
+
readonly deleteSkippedFiles: any;
|
|
33
|
+
readonly deleteProjectData: any;
|
|
34
|
+
readonly selectFilePaths: any;
|
|
35
|
+
constructor(db: DatabaseSync);
|
|
36
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Prepared statement pool for SQLiteGraphStore.
|
|
3
|
+
* All SQL lives here — single source of truth for schema access patterns.
|
|
4
|
+
*/
|
|
5
|
+
export class SqliteStatements {
|
|
6
|
+
// Projects
|
|
7
|
+
upsertProject;
|
|
8
|
+
selectProjectByRoot;
|
|
9
|
+
listProjects;
|
|
10
|
+
// Files
|
|
11
|
+
selectFiles;
|
|
12
|
+
selectFile;
|
|
13
|
+
insertFile;
|
|
14
|
+
deleteFilesNotIn;
|
|
15
|
+
// Symbols
|
|
16
|
+
selectSymbols;
|
|
17
|
+
selectSymbolsByFile;
|
|
18
|
+
selectSymbolByNameLike;
|
|
19
|
+
insertSymbol;
|
|
20
|
+
deleteSymbols;
|
|
21
|
+
// Edges
|
|
22
|
+
selectEdges;
|
|
23
|
+
selectEdgesByKind;
|
|
24
|
+
insertEdge;
|
|
25
|
+
deleteEdges;
|
|
26
|
+
// Chunks
|
|
27
|
+
selectChunks;
|
|
28
|
+
selectChunksByFile;
|
|
29
|
+
insertChunk;
|
|
30
|
+
deleteChunks;
|
|
31
|
+
// FTS
|
|
32
|
+
searchFts;
|
|
33
|
+
insertFts;
|
|
34
|
+
deleteFts;
|
|
35
|
+
// Skipped files
|
|
36
|
+
selectSkippedFiles;
|
|
37
|
+
insertSkippedFile;
|
|
38
|
+
deleteSkippedFiles;
|
|
39
|
+
// Cleanup
|
|
40
|
+
deleteProjectData;
|
|
41
|
+
selectFilePaths;
|
|
42
|
+
constructor(db) {
|
|
43
|
+
// Projects
|
|
44
|
+
this.upsertProject = db.prepare(`INSERT INTO projects(
|
|
45
|
+
project_id,
|
|
46
|
+
repo_root,
|
|
47
|
+
canonical_root,
|
|
48
|
+
display_name,
|
|
49
|
+
git_remote,
|
|
50
|
+
git_head,
|
|
51
|
+
created_at_ms,
|
|
52
|
+
last_indexed_at_ms,
|
|
53
|
+
indexed_at_ms,
|
|
54
|
+
index_generation
|
|
55
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
56
|
+
ON CONFLICT(project_id) DO UPDATE SET
|
|
57
|
+
repo_root = excluded.repo_root,
|
|
58
|
+
canonical_root = excluded.canonical_root,
|
|
59
|
+
display_name = excluded.display_name,
|
|
60
|
+
git_remote = excluded.git_remote,
|
|
61
|
+
git_head = excluded.git_head,
|
|
62
|
+
created_at_ms = COALESCE(projects.created_at_ms, excluded.created_at_ms),
|
|
63
|
+
last_indexed_at_ms = excluded.last_indexed_at_ms,
|
|
64
|
+
indexed_at_ms = excluded.indexed_at_ms,
|
|
65
|
+
index_generation = excluded.index_generation`);
|
|
66
|
+
this.selectProjectByRoot = db.prepare("SELECT * FROM projects WHERE lower(repo_root) = lower(?) OR lower(COALESCE(canonical_root, repo_root)) = lower(?) ORDER BY indexed_at_ms DESC LIMIT 1");
|
|
67
|
+
this.listProjects = db.prepare("SELECT * FROM projects ORDER BY COALESCE(canonical_root, repo_root), project_id");
|
|
68
|
+
// Files
|
|
69
|
+
this.selectFiles = db.prepare("SELECT * FROM files WHERE project_id = ? ORDER BY path");
|
|
70
|
+
this.selectFile = db.prepare("SELECT * FROM files WHERE project_id = ? AND path = ?");
|
|
71
|
+
this.insertFile = db.prepare("INSERT INTO files(project_id, path, absolute_path, language, size_bytes, content_hash, modified_at_ms, indexed_at_ms, status, generation) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
|
|
72
|
+
this.selectFilePaths = db.prepare("SELECT path FROM files WHERE project_id = ?");
|
|
73
|
+
// Symbols
|
|
74
|
+
this.selectSymbols = db.prepare("SELECT * FROM symbols WHERE project_id = ? ORDER BY file_path, start_line");
|
|
75
|
+
this.selectSymbolsByFile = db.prepare("SELECT * FROM symbols WHERE project_id = ? AND file_path = ? ORDER BY start_line");
|
|
76
|
+
this.selectSymbolByNameLike = db.prepare("SELECT * FROM symbols WHERE project_id = ? AND lower(name) LIKE ? ESCAPE '\\' ORDER BY name");
|
|
77
|
+
this.insertSymbol = db.prepare("INSERT INTO symbols(project_id, id, file_path, name, kind, language, start_line, end_line, signature, exported, generation) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
|
|
78
|
+
this.deleteSymbols = db.prepare("DELETE FROM symbols WHERE project_id = ? AND file_path = ?");
|
|
79
|
+
// Edges
|
|
80
|
+
this.selectEdges = db.prepare("SELECT * FROM edges WHERE project_id = ? ORDER BY id");
|
|
81
|
+
this.selectEdgesByKind = db.prepare("SELECT * FROM edges WHERE project_id = ? AND kind = ? ORDER BY id");
|
|
82
|
+
this.insertEdge = db.prepare("INSERT INTO edges(project_id, source_id, target_id, kind, metadata_json, file_path, generation) VALUES (?, ?, ?, ?, ?, ?, ?)");
|
|
83
|
+
this.deleteEdges = db.prepare("DELETE FROM edges WHERE project_id = ? AND file_path = ?");
|
|
84
|
+
// Chunks
|
|
85
|
+
this.selectChunks = db.prepare("SELECT * FROM chunks WHERE project_id = ? ORDER BY file_path, start_line");
|
|
86
|
+
this.selectChunksByFile = db.prepare("SELECT * FROM chunks WHERE project_id = ? AND file_path = ? ORDER BY start_line");
|
|
87
|
+
this.insertChunk = db.prepare("INSERT INTO chunks(project_id, id, repo_root, file_path, language, kind, symbol_name, start_line, end_line, content, content_hash, generation) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
|
|
88
|
+
this.deleteChunks = db.prepare("DELETE FROM chunks WHERE project_id = ? AND file_path = ?");
|
|
89
|
+
// FTS
|
|
90
|
+
this.searchFts = db.prepare(`SELECT c.*, bm25(chunks_fts) AS rank
|
|
91
|
+
FROM chunks_fts
|
|
92
|
+
JOIN chunks c ON c.project_id = chunks_fts.project_id AND c.id = chunks_fts.id
|
|
93
|
+
WHERE chunks_fts.project_id = ? AND chunks_fts MATCH ?
|
|
94
|
+
ORDER BY rank, c.file_path, c.start_line
|
|
95
|
+
LIMIT ?`);
|
|
96
|
+
this.insertFts = db.prepare("INSERT INTO chunks_fts(project_id, id, file_path, symbol_name, content) VALUES (?, ?, ?, ?, ?)");
|
|
97
|
+
this.deleteFts = db.prepare("DELETE FROM chunks_fts WHERE project_id = ? AND file_path = ?");
|
|
98
|
+
// Skipped files
|
|
99
|
+
this.selectSkippedFiles = db.prepare("SELECT file_path, reason FROM skipped_files WHERE project_id = ? ORDER BY file_path");
|
|
100
|
+
this.insertSkippedFile = db.prepare("INSERT INTO skipped_files(project_id, file_path, reason) VALUES (?, ?, ?)");
|
|
101
|
+
this.deleteSkippedFiles = db.prepare("DELETE FROM skipped_files WHERE project_id = ?");
|
|
102
|
+
// Cleanup (used for table iteration in deleteProjectRows)
|
|
103
|
+
this.deleteProjectData = (table) => db.prepare(`DELETE FROM ${table} WHERE project_id = ?`);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { GraphEdge, SymbolNode } from "../core/types.js";
|
|
2
|
+
export interface ImpactTargetSpec {
|
|
3
|
+
raw: string;
|
|
4
|
+
normalized: string;
|
|
5
|
+
lowered: string;
|
|
6
|
+
filePath?: string;
|
|
7
|
+
symbolName?: string;
|
|
8
|
+
qualified: boolean;
|
|
9
|
+
}
|
|
10
|
+
export declare function parseImpactTarget(target: string): ImpactTargetSpec;
|
|
11
|
+
export declare function matchesImpactTarget(symbol: SymbolNode, target: ImpactTargetSpec): boolean;
|
|
12
|
+
export declare function isIncomingImpactEdge(edge: GraphEdge, matchedIds: Set<string>, target: ImpactTargetSpec): boolean;
|
|
13
|
+
export declare function isOutgoingImpactEdge(edge: GraphEdge, matchedIds: Set<string>, target: ImpactTargetSpec): boolean;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { normalizeUserPath } from "../utils/path.js";
|
|
2
|
+
export function parseImpactTarget(target) {
|
|
3
|
+
const normalized = normalizeUserPath(target.trim());
|
|
4
|
+
const qualified = parseQualifiedTarget(normalized);
|
|
5
|
+
if (qualified) {
|
|
6
|
+
return {
|
|
7
|
+
raw: target,
|
|
8
|
+
normalized,
|
|
9
|
+
lowered: normalized.toLowerCase(),
|
|
10
|
+
filePath: qualified.filePath,
|
|
11
|
+
symbolName: qualified.symbolName,
|
|
12
|
+
qualified: true
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
return {
|
|
16
|
+
raw: target,
|
|
17
|
+
normalized,
|
|
18
|
+
lowered: target.toLowerCase(),
|
|
19
|
+
qualified: false
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
export function matchesImpactTarget(symbol, target) {
|
|
23
|
+
if (target.qualified) {
|
|
24
|
+
return Boolean(target.filePath
|
|
25
|
+
&& target.symbolName
|
|
26
|
+
&& filePathMatches(symbol.filePath, target.filePath)
|
|
27
|
+
&& symbol.name === target.symbolName);
|
|
28
|
+
}
|
|
29
|
+
return symbol.name.toLowerCase().includes(target.lowered)
|
|
30
|
+
|| symbol.filePath === target.normalized
|
|
31
|
+
|| symbol.filePath.includes(target.normalized);
|
|
32
|
+
}
|
|
33
|
+
export function isIncomingImpactEdge(edge, matchedIds, target) {
|
|
34
|
+
if (matchedIds.has(edge.targetId))
|
|
35
|
+
return true;
|
|
36
|
+
if (target.qualified)
|
|
37
|
+
return false;
|
|
38
|
+
return String(edge.metadata?.targetName ?? "").toLowerCase().includes(target.lowered);
|
|
39
|
+
}
|
|
40
|
+
export function isOutgoingImpactEdge(edge, matchedIds, target) {
|
|
41
|
+
if (matchedIds.has(edge.sourceId))
|
|
42
|
+
return true;
|
|
43
|
+
const sourceFile = typeof edge.metadata?.sourceFile === "string" ? edge.metadata.sourceFile : undefined;
|
|
44
|
+
if (!sourceFile)
|
|
45
|
+
return false;
|
|
46
|
+
const fileTarget = target.filePath ?? target.normalized;
|
|
47
|
+
return target.symbolName ? false : filePathMatches(sourceFile, fileTarget);
|
|
48
|
+
}
|
|
49
|
+
function parseQualifiedTarget(target) {
|
|
50
|
+
const separatorIndex = Math.max(target.lastIndexOf(":"), target.lastIndexOf("#"));
|
|
51
|
+
if (separatorIndex <= 0 || separatorIndex === target.length - 1)
|
|
52
|
+
return undefined;
|
|
53
|
+
const filePath = target.slice(0, separatorIndex);
|
|
54
|
+
const symbolName = target.slice(separatorIndex + 1);
|
|
55
|
+
if (!looksLikePath(filePath) || !symbolName)
|
|
56
|
+
return undefined;
|
|
57
|
+
return { filePath, symbolName };
|
|
58
|
+
}
|
|
59
|
+
function looksLikePath(value) {
|
|
60
|
+
return value.includes("/") || /\.[cm]?[jt]sx?$/.test(value) || /\.[a-z0-9]+$/i.test(value);
|
|
61
|
+
}
|
|
62
|
+
function filePathMatches(actual, expected) {
|
|
63
|
+
return actual === expected || actual.endsWith(`/${expected}`);
|
|
64
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export * from "./core/contracts.js";
|
|
2
|
+
export * from "./core/engine.js";
|
|
3
|
+
export * from "./core/types.js";
|
|
4
|
+
export * from "./config/graph-runtime.js";
|
|
5
|
+
export * from "./config/semantic-runtime.js";
|
|
6
|
+
export * from "./config/runtime-config.js";
|
|
7
|
+
export * from "./config/dotenv.js";
|
|
8
|
+
export * from "./graph/in-memory-graph-store.js";
|
|
9
|
+
export * from "./graph/sqlite-graph-store.js";
|
|
10
|
+
export * from "./project/project-identity.js";
|
|
11
|
+
export * from "./project/project-registry.js";
|
|
12
|
+
export * from "./project/workspace-resolver.js";
|
|
13
|
+
export * from "./semantic/deterministic-embedding.js";
|
|
14
|
+
export * from "./semantic/in-memory-semantic-store.js";
|
|
15
|
+
export * from "./semantic/lance-semantic-store.js";
|
|
16
|
+
export * from "./semantic/openai-compatible-embedding.js";
|
|
17
|
+
export * from "./watch/file-event-coalescer.js";
|
|
18
|
+
export * from "./watch/event-journal.js";
|
|
19
|
+
export * from "./watch/index-scheduler.js";
|
|
20
|
+
export * from "./watch/watch-daemon.js";
|
|
21
|
+
export * from "./indexing/ast-analyzer.js";
|
|
22
|
+
export * from "./subgraph/subgraph-builder.js";
|
|
23
|
+
export * from "./subgraph/impact-explainer.js";
|
|
24
|
+
export * from "./subgraph/node-expander.js";
|
|
25
|
+
export * from "./subgraph/output-preset.js";
|
|
26
|
+
export * from "./reuse/reuse-detector.js";
|
|
27
|
+
export * from "./retrieval/hybrid-retriever.js";
|
|
28
|
+
export * from "./retrieval/path-classification.js";
|
|
29
|
+
export * from "./diagnostics/doctor.js";
|
|
30
|
+
export * from "./diagnostics/embedding-test.js";
|
|
31
|
+
export * from "./mcp/tools.js";
|
|
32
|
+
export * from "./mcp/server.js";
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export * from "./core/contracts.js";
|
|
2
|
+
export * from "./core/engine.js";
|
|
3
|
+
export * from "./core/types.js";
|
|
4
|
+
export * from "./config/graph-runtime.js";
|
|
5
|
+
export * from "./config/semantic-runtime.js";
|
|
6
|
+
export * from "./config/runtime-config.js";
|
|
7
|
+
export * from "./config/dotenv.js";
|
|
8
|
+
export * from "./graph/in-memory-graph-store.js";
|
|
9
|
+
export * from "./graph/sqlite-graph-store.js";
|
|
10
|
+
export * from "./project/project-identity.js";
|
|
11
|
+
export * from "./project/project-registry.js";
|
|
12
|
+
export * from "./project/workspace-resolver.js";
|
|
13
|
+
export * from "./semantic/deterministic-embedding.js";
|
|
14
|
+
export * from "./semantic/in-memory-semantic-store.js";
|
|
15
|
+
export * from "./semantic/lance-semantic-store.js";
|
|
16
|
+
export * from "./semantic/openai-compatible-embedding.js";
|
|
17
|
+
export * from "./watch/file-event-coalescer.js";
|
|
18
|
+
export * from "./watch/event-journal.js";
|
|
19
|
+
export * from "./watch/index-scheduler.js";
|
|
20
|
+
export * from "./watch/watch-daemon.js";
|
|
21
|
+
export * from "./indexing/ast-analyzer.js";
|
|
22
|
+
export * from "./subgraph/subgraph-builder.js";
|
|
23
|
+
export * from "./subgraph/impact-explainer.js";
|
|
24
|
+
export * from "./subgraph/node-expander.js";
|
|
25
|
+
export * from "./subgraph/output-preset.js";
|
|
26
|
+
export * from "./reuse/reuse-detector.js";
|
|
27
|
+
export * from "./retrieval/hybrid-retriever.js";
|
|
28
|
+
export * from "./retrieval/path-classification.js";
|
|
29
|
+
export * from "./diagnostics/doctor.js";
|
|
30
|
+
export * from "./diagnostics/embedding-test.js";
|
|
31
|
+
export * from "./mcp/tools.js";
|
|
32
|
+
export * from "./mcp/server.js";
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { CodeFile, GraphEdge, SymbolNode } from "../../core/types.js";
|
|
2
|
+
import type { AnalyzeFileInput, FileAnalysis, LanguageAnalyzer } from "./types.js";
|
|
3
|
+
export declare const fallbackAnalyzer: LanguageAnalyzer;
|
|
4
|
+
export declare function fallbackFileAnalysis(repoRoot: string, file: CodeFile, content: string, existingFileSymbol?: SymbolNode, existingEdges?: GraphEdge[]): FileAnalysis;
|
|
5
|
+
export declare function createFileSymbol(repoRoot: string, file: CodeFile, lineCount: number): SymbolNode;
|
|
6
|
+
export declare function analyzeFallbackFile(input: AnalyzeFileInput): FileAnalysis;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { sha256, stableId } from "../../utils/hash.js";
|
|
2
|
+
export const fallbackAnalyzer = {
|
|
3
|
+
language: "unknown",
|
|
4
|
+
capabilities: [],
|
|
5
|
+
analyzeFile: ({ repoRoot, file, content }) => fallbackFileAnalysis(repoRoot, file, content)
|
|
6
|
+
};
|
|
7
|
+
export function fallbackFileAnalysis(repoRoot, file, content, existingFileSymbol, existingEdges = []) {
|
|
8
|
+
const lines = content.split(/\r?\n/);
|
|
9
|
+
const fileSymbol = existingFileSymbol ?? createFileSymbol(repoRoot, file, lines.length);
|
|
10
|
+
const chunks = [];
|
|
11
|
+
for (let start = 0; start < lines.length; start += 80) {
|
|
12
|
+
const end = Math.min(lines.length, start + 80);
|
|
13
|
+
const chunkContent = lines.slice(start, end).join("\n");
|
|
14
|
+
if (!chunkContent.trim())
|
|
15
|
+
continue;
|
|
16
|
+
chunks.push({
|
|
17
|
+
id: stableId([repoRoot, file.path, start + 1, end, sha256(chunkContent)]),
|
|
18
|
+
projectId: file.projectId,
|
|
19
|
+
repoRoot,
|
|
20
|
+
filePath: file.path,
|
|
21
|
+
language: file.language,
|
|
22
|
+
kind: "block",
|
|
23
|
+
startLine: start + 1,
|
|
24
|
+
endLine: end,
|
|
25
|
+
content: chunkContent,
|
|
26
|
+
contentHash: sha256(chunkContent)
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
return { chunks, symbols: [fileSymbol], edges: existingEdges };
|
|
30
|
+
}
|
|
31
|
+
export function createFileSymbol(repoRoot, file, lineCount) {
|
|
32
|
+
return {
|
|
33
|
+
id: stableId([repoRoot, file.path, "file"]),
|
|
34
|
+
projectId: file.projectId,
|
|
35
|
+
filePath: file.path,
|
|
36
|
+
name: file.path,
|
|
37
|
+
kind: "file",
|
|
38
|
+
language: file.language,
|
|
39
|
+
startLine: 1,
|
|
40
|
+
endLine: Math.max(1, lineCount)
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
export function analyzeFallbackFile(input) {
|
|
44
|
+
return fallbackFileAnalysis(input.repoRoot, input.file, input.content);
|
|
45
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import Parser from "tree-sitter";
|
|
2
|
+
// @ts-ignore - tree-sitter-go doesn't have TypeScript definitions
|
|
3
|
+
import Go from "tree-sitter-go";
|
|
4
|
+
import { analyzeWithTreeSitter } from "./tree-sitter-base.js";
|
|
5
|
+
let parser = null;
|
|
6
|
+
function getParser() {
|
|
7
|
+
if (!parser) {
|
|
8
|
+
parser = new Parser();
|
|
9
|
+
parser.setLanguage(Go);
|
|
10
|
+
}
|
|
11
|
+
return parser;
|
|
12
|
+
}
|
|
13
|
+
const goConfig = {
|
|
14
|
+
symbolPatterns: [
|
|
15
|
+
{
|
|
16
|
+
type: "function_declaration",
|
|
17
|
+
kind: "function",
|
|
18
|
+
nameField: "name",
|
|
19
|
+
exportModifierCheck: (node) => {
|
|
20
|
+
const name = node.childForFieldName("name")?.text;
|
|
21
|
+
return name ? /^[A-Z]/.test(name) : false;
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
type: "method_declaration",
|
|
26
|
+
kind: "method",
|
|
27
|
+
nameField: "name",
|
|
28
|
+
exportModifierCheck: (node) => {
|
|
29
|
+
const name = node.childForFieldName("name")?.text;
|
|
30
|
+
return name ? /^[A-Z]/.test(name) : false;
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
type: "type_declaration",
|
|
35
|
+
kind: "type",
|
|
36
|
+
nameExtractor: typeDeclarationName,
|
|
37
|
+
exportModifierCheck: (node) => {
|
|
38
|
+
const name = typeDeclarationName(node);
|
|
39
|
+
return name ? /^[A-Z]/.test(name) : false;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
],
|
|
43
|
+
importPatterns: [
|
|
44
|
+
{
|
|
45
|
+
type: "import_spec",
|
|
46
|
+
sourceField: "path",
|
|
47
|
+
bindingsExtractor: (node) => {
|
|
48
|
+
const pathNode = node.childForFieldName("path");
|
|
49
|
+
if (!pathNode)
|
|
50
|
+
return [];
|
|
51
|
+
const path = pathNode.text.replace(/"/g, "");
|
|
52
|
+
const nameNode = node.childForFieldName("name");
|
|
53
|
+
const name = nameNode?.text ?? path.split("/").pop() ?? path;
|
|
54
|
+
return [{ imported: path, local: name }];
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
],
|
|
58
|
+
callPatterns: [
|
|
59
|
+
{
|
|
60
|
+
type: "call_expression",
|
|
61
|
+
nameExtractor: (node) => {
|
|
62
|
+
const functionNode = node.childForFieldName("function");
|
|
63
|
+
if (!functionNode)
|
|
64
|
+
return undefined;
|
|
65
|
+
if (functionNode.type === "identifier") {
|
|
66
|
+
return functionNode.text;
|
|
67
|
+
}
|
|
68
|
+
else if (functionNode.type === "selector_expression") {
|
|
69
|
+
const fieldNode = functionNode.childForFieldName("field");
|
|
70
|
+
return fieldNode?.text;
|
|
71
|
+
}
|
|
72
|
+
return undefined;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
]
|
|
76
|
+
};
|
|
77
|
+
export const goTreeSitterAnalyzer = {
|
|
78
|
+
language: "go",
|
|
79
|
+
capabilities: ["symbols", "imports", "exports", "calls", "tests"],
|
|
80
|
+
analyzeFile: ({ repoRoot, file, content }) => {
|
|
81
|
+
return analyzeWithTreeSitter(getParser(), goConfig, repoRoot, file, content);
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
function typeDeclarationName(node) {
|
|
85
|
+
const specNode = node.children.find((child) => child.type === "type_spec");
|
|
86
|
+
return specNode?.childForFieldName("name")?.text;
|
|
87
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import Parser from "tree-sitter";
|
|
2
|
+
// @ts-ignore - tree-sitter-java doesn't have TypeScript definitions
|
|
3
|
+
import Java from "tree-sitter-java";
|
|
4
|
+
import { analyzeWithTreeSitter } from "./tree-sitter-base.js";
|
|
5
|
+
let parser = null;
|
|
6
|
+
function getParser() {
|
|
7
|
+
if (!parser) {
|
|
8
|
+
parser = new Parser();
|
|
9
|
+
parser.setLanguage(Java);
|
|
10
|
+
}
|
|
11
|
+
return parser;
|
|
12
|
+
}
|
|
13
|
+
const javaConfig = {
|
|
14
|
+
symbolPatterns: [
|
|
15
|
+
{
|
|
16
|
+
type: "class_declaration",
|
|
17
|
+
kind: "class",
|
|
18
|
+
nameField: "name",
|
|
19
|
+
exportModifierCheck: (node) => {
|
|
20
|
+
return node.children.some((child) => child.type === "modifiers" && child.text.includes("public"));
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
type: "interface_declaration",
|
|
25
|
+
kind: "type",
|
|
26
|
+
nameField: "name",
|
|
27
|
+
exportModifierCheck: (node) => {
|
|
28
|
+
return node.children.some((child) => child.type === "modifiers" && child.text.includes("public"));
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
type: "enum_declaration",
|
|
33
|
+
kind: "type",
|
|
34
|
+
nameField: "name",
|
|
35
|
+
exportModifierCheck: (node) => {
|
|
36
|
+
return node.children.some((child) => child.type === "modifiers" && child.text.includes("public"));
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
type: "method_declaration",
|
|
41
|
+
kind: "method",
|
|
42
|
+
nameField: "name",
|
|
43
|
+
exportModifierCheck: (node) => {
|
|
44
|
+
return node.children.some((child) => child.type === "modifiers" && child.text.includes("public"));
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
type: "constructor_declaration",
|
|
49
|
+
kind: "method",
|
|
50
|
+
nameField: "name",
|
|
51
|
+
exportModifierCheck: (node) => {
|
|
52
|
+
return node.children.some((child) => child.type === "modifiers" && child.text.includes("public"));
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
],
|
|
56
|
+
importPatterns: [
|
|
57
|
+
{
|
|
58
|
+
type: "import_declaration",
|
|
59
|
+
sourceExtractor: javaImportName,
|
|
60
|
+
bindingsExtractor: (node) => {
|
|
61
|
+
const fullPath = javaImportName(node);
|
|
62
|
+
if (!fullPath)
|
|
63
|
+
return [];
|
|
64
|
+
const className = fullPath.split(".").pop() ?? fullPath;
|
|
65
|
+
return [{ imported: fullPath, local: className }];
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
],
|
|
69
|
+
callPatterns: [
|
|
70
|
+
{
|
|
71
|
+
type: "method_invocation",
|
|
72
|
+
nameExtractor: (node) => {
|
|
73
|
+
const nameNode = node.childForFieldName("name");
|
|
74
|
+
return nameNode?.text;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
]
|
|
78
|
+
};
|
|
79
|
+
export const javaTreeSitterAnalyzer = {
|
|
80
|
+
language: "java",
|
|
81
|
+
capabilities: ["symbols", "imports", "exports", "calls"],
|
|
82
|
+
analyzeFile: ({ repoRoot, file, content }) => {
|
|
83
|
+
return analyzeWithTreeSitter(getParser(), javaConfig, repoRoot, file, content);
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
function javaImportName(node) {
|
|
87
|
+
return node.children.find((child) => child.type === "scoped_identifier" || child.type === "identifier")?.text;
|
|
88
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import Parser from "tree-sitter";
|
|
2
|
+
// @ts-ignore - tree-sitter-python doesn't have TypeScript definitions
|
|
3
|
+
import Python from "tree-sitter-python";
|
|
4
|
+
import { analyzeWithTreeSitter } from "./tree-sitter-base.js";
|
|
5
|
+
let parser = null;
|
|
6
|
+
function getParser() {
|
|
7
|
+
if (!parser) {
|
|
8
|
+
parser = new Parser();
|
|
9
|
+
parser.setLanguage(Python);
|
|
10
|
+
}
|
|
11
|
+
return parser;
|
|
12
|
+
}
|
|
13
|
+
const pythonConfig = {
|
|
14
|
+
symbolPatterns: [
|
|
15
|
+
{
|
|
16
|
+
type: "function_definition",
|
|
17
|
+
kind: "function",
|
|
18
|
+
nameField: "name",
|
|
19
|
+
exportModifierCheck: (node) => {
|
|
20
|
+
const name = node.childForFieldName("name")?.text;
|
|
21
|
+
return name ? !name.startsWith("_") : false;
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
type: "class_definition",
|
|
26
|
+
kind: "class",
|
|
27
|
+
nameField: "name",
|
|
28
|
+
exportModifierCheck: (node) => {
|
|
29
|
+
const name = node.childForFieldName("name")?.text;
|
|
30
|
+
return name ? !name.startsWith("_") : false;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
],
|
|
34
|
+
importPatterns: [
|
|
35
|
+
{
|
|
36
|
+
type: "import_statement",
|
|
37
|
+
sourceField: "name",
|
|
38
|
+
bindingsExtractor: (node) => {
|
|
39
|
+
const name = node.childForFieldName("name");
|
|
40
|
+
if (!name)
|
|
41
|
+
return [];
|
|
42
|
+
const moduleName = name.text;
|
|
43
|
+
return [{ imported: moduleName, local: moduleName }];
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
type: "import_from_statement",
|
|
48
|
+
sourceField: "module_name",
|
|
49
|
+
bindingsExtractor: (node) => {
|
|
50
|
+
const bindings = [];
|
|
51
|
+
for (const child of node.children) {
|
|
52
|
+
if (child.type === "dotted_name" || child.type === "identifier") {
|
|
53
|
+
const name = child.text;
|
|
54
|
+
bindings.push({ imported: name, local: name });
|
|
55
|
+
}
|
|
56
|
+
else if (child.type === "aliased_import") {
|
|
57
|
+
const nameNode = child.childForFieldName("name");
|
|
58
|
+
const aliasNode = child.childForFieldName("alias");
|
|
59
|
+
if (nameNode) {
|
|
60
|
+
bindings.push({
|
|
61
|
+
imported: nameNode.text,
|
|
62
|
+
local: aliasNode?.text ?? nameNode.text
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return bindings;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
],
|
|
71
|
+
callPatterns: [
|
|
72
|
+
{
|
|
73
|
+
type: "call",
|
|
74
|
+
nameExtractor: (node) => {
|
|
75
|
+
const functionNode = node.childForFieldName("function");
|
|
76
|
+
if (!functionNode)
|
|
77
|
+
return undefined;
|
|
78
|
+
if (functionNode.type === "identifier") {
|
|
79
|
+
return functionNode.text;
|
|
80
|
+
}
|
|
81
|
+
else if (functionNode.type === "attribute") {
|
|
82
|
+
const attrNode = functionNode.childForFieldName("attribute");
|
|
83
|
+
return attrNode?.text;
|
|
84
|
+
}
|
|
85
|
+
return undefined;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
]
|
|
89
|
+
};
|
|
90
|
+
export const pythonTreeSitterAnalyzer = {
|
|
91
|
+
language: "python",
|
|
92
|
+
capabilities: ["symbols", "imports", "exports", "calls"],
|
|
93
|
+
analyzeFile: ({ repoRoot, file, content }) => {
|
|
94
|
+
return analyzeWithTreeSitter(getParser(), pythonConfig, repoRoot, file, content);
|
|
95
|
+
}
|
|
96
|
+
};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { LanguageId } from "../../core/types.js";
|
|
2
|
+
import type { AnalyzeFileInput, FileAnalysis, LanguageAnalyzer } from "./types.js";
|
|
3
|
+
export declare function analyzerFor(language: LanguageId): LanguageAnalyzer;
|
|
4
|
+
export declare function listAnalyzers(): LanguageAnalyzer[];
|
|
5
|
+
export declare function analyzeFileWithRegistry(input: AnalyzeFileInput): FileAnalysis;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { fallbackAnalyzer } from "./fallback-analyzer.js";
|
|
2
|
+
import { javascriptAnalyzer, typescriptAnalyzer } from "./typescript-analyzer.js";
|
|
3
|
+
import { pythonTreeSitterAnalyzer } from "./python-treesitter-analyzer.js";
|
|
4
|
+
import { goTreeSitterAnalyzer } from "./go-treesitter-analyzer.js";
|
|
5
|
+
import { rustTreeSitterAnalyzer } from "./rust-treesitter-analyzer.js";
|
|
6
|
+
import { javaTreeSitterAnalyzer } from "./java-treesitter-analyzer.js";
|
|
7
|
+
const analyzers = new Map([
|
|
8
|
+
["typescript", typescriptAnalyzer],
|
|
9
|
+
["javascript", javascriptAnalyzer],
|
|
10
|
+
["python", pythonTreeSitterAnalyzer],
|
|
11
|
+
["go", goTreeSitterAnalyzer],
|
|
12
|
+
["rust", rustTreeSitterAnalyzer],
|
|
13
|
+
["java", javaTreeSitterAnalyzer]
|
|
14
|
+
]);
|
|
15
|
+
export function analyzerFor(language) {
|
|
16
|
+
return analyzers.get(language) ?? fallbackAnalyzer;
|
|
17
|
+
}
|
|
18
|
+
export function listAnalyzers() {
|
|
19
|
+
return [...analyzers.values(), fallbackAnalyzer];
|
|
20
|
+
}
|
|
21
|
+
export function analyzeFileWithRegistry(input) {
|
|
22
|
+
return analyzerFor(input.file.language).analyzeFile(input);
|
|
23
|
+
}
|