gitnexus 1.4.1 → 1.4.6
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/README.md +215 -194
- package/dist/cli/ai-context.d.ts +2 -1
- package/dist/cli/ai-context.js +117 -90
- package/dist/cli/analyze.d.ts +2 -0
- package/dist/cli/analyze.js +57 -30
- package/dist/cli/augment.js +1 -1
- package/dist/cli/eval-server.d.ts +1 -1
- package/dist/cli/eval-server.js +14 -6
- package/dist/cli/index.js +18 -25
- package/dist/cli/lazy-action.d.ts +6 -0
- package/dist/cli/lazy-action.js +18 -0
- package/dist/cli/mcp.js +1 -1
- package/dist/cli/setup.js +42 -32
- package/dist/cli/skill-gen.d.ts +26 -0
- package/dist/cli/skill-gen.js +549 -0
- package/dist/cli/status.js +13 -4
- package/dist/cli/tool.d.ts +3 -2
- package/dist/cli/tool.js +48 -13
- package/dist/cli/wiki.js +2 -2
- package/dist/config/ignore-service.d.ts +25 -0
- package/dist/config/ignore-service.js +76 -0
- package/dist/config/supported-languages.d.ts +1 -0
- package/dist/config/supported-languages.js +1 -1
- package/dist/core/augmentation/engine.js +99 -72
- package/dist/core/embeddings/embedder.d.ts +1 -1
- package/dist/core/embeddings/embedder.js +1 -1
- package/dist/core/embeddings/embedding-pipeline.d.ts +3 -3
- package/dist/core/embeddings/embedding-pipeline.js +74 -47
- package/dist/core/embeddings/types.d.ts +1 -1
- package/dist/core/graph/types.d.ts +5 -2
- package/dist/core/ingestion/ast-cache.js +3 -2
- package/dist/core/ingestion/call-processor.d.ts +5 -7
- package/dist/core/ingestion/call-processor.js +430 -283
- package/dist/core/ingestion/call-routing.d.ts +53 -0
- package/dist/core/ingestion/call-routing.js +108 -0
- package/dist/core/ingestion/cluster-enricher.js +16 -16
- package/dist/core/ingestion/constants.d.ts +16 -0
- package/dist/core/ingestion/constants.js +16 -0
- package/dist/core/ingestion/entry-point-scoring.d.ts +2 -1
- package/dist/core/ingestion/entry-point-scoring.js +94 -24
- package/dist/core/ingestion/export-detection.d.ts +18 -0
- package/dist/core/ingestion/export-detection.js +231 -0
- package/dist/core/ingestion/filesystem-walker.js +4 -3
- package/dist/core/ingestion/framework-detection.d.ts +5 -1
- package/dist/core/ingestion/framework-detection.js +48 -8
- package/dist/core/ingestion/heritage-processor.d.ts +13 -5
- package/dist/core/ingestion/heritage-processor.js +109 -55
- package/dist/core/ingestion/import-processor.d.ts +16 -20
- package/dist/core/ingestion/import-processor.js +202 -696
- package/dist/core/ingestion/language-config.d.ts +46 -0
- package/dist/core/ingestion/language-config.js +167 -0
- package/dist/core/ingestion/mro-processor.d.ts +45 -0
- package/dist/core/ingestion/mro-processor.js +369 -0
- package/dist/core/ingestion/named-binding-extraction.d.ts +61 -0
- package/dist/core/ingestion/named-binding-extraction.js +363 -0
- package/dist/core/ingestion/parsing-processor.d.ts +3 -11
- package/dist/core/ingestion/parsing-processor.js +85 -181
- package/dist/core/ingestion/pipeline.d.ts +5 -1
- package/dist/core/ingestion/pipeline.js +192 -116
- package/dist/core/ingestion/process-processor.js +2 -1
- package/dist/core/ingestion/resolution-context.d.ts +53 -0
- package/dist/core/ingestion/resolution-context.js +132 -0
- package/dist/core/ingestion/resolvers/csharp.d.ts +22 -0
- package/dist/core/ingestion/resolvers/csharp.js +109 -0
- package/dist/core/ingestion/resolvers/go.d.ts +19 -0
- package/dist/core/ingestion/resolvers/go.js +42 -0
- package/dist/core/ingestion/resolvers/index.d.ts +18 -0
- package/dist/core/ingestion/resolvers/index.js +13 -0
- package/dist/core/ingestion/resolvers/jvm.d.ts +23 -0
- package/dist/core/ingestion/resolvers/jvm.js +87 -0
- package/dist/core/ingestion/resolvers/php.d.ts +15 -0
- package/dist/core/ingestion/resolvers/php.js +35 -0
- package/dist/core/ingestion/resolvers/python.d.ts +19 -0
- package/dist/core/ingestion/resolvers/python.js +52 -0
- package/dist/core/ingestion/resolvers/ruby.d.ts +12 -0
- package/dist/core/ingestion/resolvers/ruby.js +15 -0
- package/dist/core/ingestion/resolvers/rust.d.ts +15 -0
- package/dist/core/ingestion/resolvers/rust.js +73 -0
- package/dist/core/ingestion/resolvers/standard.d.ts +28 -0
- package/dist/core/ingestion/resolvers/standard.js +123 -0
- package/dist/core/ingestion/resolvers/utils.d.ts +33 -0
- package/dist/core/ingestion/resolvers/utils.js +122 -0
- package/dist/core/ingestion/symbol-table.d.ts +21 -1
- package/dist/core/ingestion/symbol-table.js +40 -12
- package/dist/core/ingestion/tree-sitter-queries.d.ts +12 -11
- package/dist/core/ingestion/tree-sitter-queries.js +642 -485
- package/dist/core/ingestion/type-env.d.ts +49 -0
- package/dist/core/ingestion/type-env.js +611 -0
- package/dist/core/ingestion/type-extractors/c-cpp.d.ts +2 -0
- package/dist/core/ingestion/type-extractors/c-cpp.js +385 -0
- package/dist/core/ingestion/type-extractors/csharp.d.ts +2 -0
- package/dist/core/ingestion/type-extractors/csharp.js +383 -0
- package/dist/core/ingestion/type-extractors/go.d.ts +2 -0
- package/dist/core/ingestion/type-extractors/go.js +467 -0
- package/dist/core/ingestion/type-extractors/index.d.ts +22 -0
- package/dist/core/ingestion/type-extractors/index.js +31 -0
- package/dist/core/ingestion/type-extractors/jvm.d.ts +3 -0
- package/dist/core/ingestion/type-extractors/jvm.js +681 -0
- package/dist/core/ingestion/type-extractors/php.d.ts +2 -0
- package/dist/core/ingestion/type-extractors/php.js +549 -0
- package/dist/core/ingestion/type-extractors/python.d.ts +2 -0
- package/dist/core/ingestion/type-extractors/python.js +406 -0
- package/dist/core/ingestion/type-extractors/ruby.d.ts +2 -0
- package/dist/core/ingestion/type-extractors/ruby.js +389 -0
- package/dist/core/ingestion/type-extractors/rust.d.ts +2 -0
- package/dist/core/ingestion/type-extractors/rust.js +449 -0
- package/dist/core/ingestion/type-extractors/shared.d.ts +133 -0
- package/dist/core/ingestion/type-extractors/shared.js +703 -0
- package/dist/core/ingestion/type-extractors/swift.d.ts +2 -0
- package/dist/core/ingestion/type-extractors/swift.js +137 -0
- package/dist/core/ingestion/type-extractors/types.d.ts +127 -0
- package/dist/core/ingestion/type-extractors/types.js +1 -0
- package/dist/core/ingestion/type-extractors/typescript.d.ts +2 -0
- package/dist/core/ingestion/type-extractors/typescript.js +494 -0
- package/dist/core/ingestion/utils.d.ts +98 -0
- package/dist/core/ingestion/utils.js +1064 -9
- package/dist/core/ingestion/workers/parse-worker.d.ts +38 -4
- package/dist/core/ingestion/workers/parse-worker.js +251 -359
- package/dist/core/ingestion/workers/worker-pool.js +8 -0
- package/dist/core/{kuzu → lbug}/csv-generator.d.ts +1 -1
- package/dist/core/{kuzu → lbug}/csv-generator.js +20 -4
- package/dist/core/{kuzu/kuzu-adapter.d.ts → lbug/lbug-adapter.d.ts} +19 -19
- package/dist/core/{kuzu/kuzu-adapter.js → lbug/lbug-adapter.js} +82 -82
- package/dist/core/{kuzu → lbug}/schema.d.ts +4 -4
- package/dist/core/{kuzu → lbug}/schema.js +304 -289
- package/dist/core/search/bm25-index.d.ts +4 -4
- package/dist/core/search/bm25-index.js +17 -16
- package/dist/core/search/hybrid-search.d.ts +2 -2
- package/dist/core/search/hybrid-search.js +9 -9
- package/dist/core/tree-sitter/parser-loader.js +9 -2
- package/dist/core/wiki/generator.d.ts +4 -52
- package/dist/core/wiki/generator.js +53 -552
- package/dist/core/wiki/graph-queries.d.ts +4 -46
- package/dist/core/wiki/graph-queries.js +103 -282
- package/dist/core/wiki/html-viewer.js +192 -192
- package/dist/core/wiki/llm-client.js +11 -73
- package/dist/core/wiki/prompts.d.ts +8 -52
- package/dist/core/wiki/prompts.js +86 -200
- package/dist/mcp/compatible-stdio-transport.d.ts +25 -0
- package/dist/mcp/compatible-stdio-transport.js +200 -0
- package/dist/mcp/core/{kuzu-adapter.d.ts → lbug-adapter.d.ts} +7 -9
- package/dist/mcp/core/{kuzu-adapter.js → lbug-adapter.js} +77 -79
- package/dist/mcp/local/local-backend.d.ts +7 -6
- package/dist/mcp/local/local-backend.js +176 -147
- package/dist/mcp/resources.js +42 -42
- package/dist/mcp/server.js +18 -19
- package/dist/mcp/tools.js +103 -104
- package/dist/server/api.js +12 -12
- package/dist/server/mcp-http.d.ts +1 -1
- package/dist/server/mcp-http.js +1 -1
- package/dist/storage/repo-manager.d.ts +20 -2
- package/dist/storage/repo-manager.js +55 -1
- package/dist/types/pipeline.d.ts +1 -1
- package/hooks/claude/gitnexus-hook.cjs +238 -155
- package/hooks/claude/pre-tool-use.sh +79 -79
- package/hooks/claude/session-start.sh +42 -42
- package/package.json +99 -96
- package/scripts/patch-tree-sitter-swift.cjs +74 -74
- package/skills/gitnexus-cli.md +82 -82
- package/skills/gitnexus-debugging.md +89 -89
- package/skills/gitnexus-exploring.md +78 -78
- package/skills/gitnexus-guide.md +64 -64
- package/skills/gitnexus-impact-analysis.md +97 -97
- package/skills/gitnexus-pr-review.md +163 -163
- package/skills/gitnexus-refactoring.md +121 -121
- package/vendor/leiden/index.cjs +355 -355
- package/vendor/leiden/utils.cjs +392 -392
- package/dist/core/wiki/diagrams.d.ts +0 -27
- package/dist/core/wiki/diagrams.js +0 -163
|
@@ -1,179 +1,15 @@
|
|
|
1
1
|
import Parser from 'tree-sitter';
|
|
2
|
-
import { loadParser, loadLanguage } from '../tree-sitter/parser-loader.js';
|
|
2
|
+
import { loadParser, loadLanguage, isLanguageAvailable } from '../tree-sitter/parser-loader.js';
|
|
3
3
|
import { LANGUAGE_QUERIES } from './tree-sitter-queries.js';
|
|
4
4
|
import { generateId } from '../../lib/utils.js';
|
|
5
|
-
import {
|
|
5
|
+
import { getLanguageFromFilename, yieldToEventLoop, getDefinitionNodeFromCaptures, findEnclosingClassId, extractMethodSignature } from './utils.js';
|
|
6
|
+
import { isNodeExported } from './export-detection.js';
|
|
6
7
|
import { detectFrameworkFromAST } from './framework-detection.js';
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
'definition.struct',
|
|
13
|
-
'definition.enum',
|
|
14
|
-
'definition.namespace',
|
|
15
|
-
'definition.module',
|
|
16
|
-
'definition.trait',
|
|
17
|
-
'definition.impl',
|
|
18
|
-
'definition.type',
|
|
19
|
-
'definition.const',
|
|
20
|
-
'definition.static',
|
|
21
|
-
'definition.typedef',
|
|
22
|
-
'definition.macro',
|
|
23
|
-
'definition.union',
|
|
24
|
-
'definition.property',
|
|
25
|
-
'definition.record',
|
|
26
|
-
'definition.delegate',
|
|
27
|
-
'definition.annotation',
|
|
28
|
-
'definition.constructor',
|
|
29
|
-
'definition.template',
|
|
30
|
-
];
|
|
31
|
-
const getDefinitionNodeFromCaptures = (captureMap) => {
|
|
32
|
-
for (const key of DEFINITION_CAPTURE_KEYS) {
|
|
33
|
-
if (captureMap[key])
|
|
34
|
-
return captureMap[key];
|
|
35
|
-
}
|
|
36
|
-
return null;
|
|
37
|
-
};
|
|
38
|
-
// ============================================================================
|
|
39
|
-
// EXPORT DETECTION - Language-specific visibility detection
|
|
40
|
-
// ============================================================================
|
|
41
|
-
/**
|
|
42
|
-
* Check if a symbol (function, class, etc.) is exported/public
|
|
43
|
-
* Handles all 9 supported languages with explicit logic
|
|
44
|
-
*
|
|
45
|
-
* @param node - The AST node for the symbol name
|
|
46
|
-
* @param name - The symbol name
|
|
47
|
-
* @param language - The programming language
|
|
48
|
-
* @returns true if the symbol is exported/public
|
|
49
|
-
*/
|
|
50
|
-
export const isNodeExported = (node, name, language) => {
|
|
51
|
-
let current = node;
|
|
52
|
-
switch (language) {
|
|
53
|
-
// JavaScript/TypeScript: Check for export keyword in ancestors
|
|
54
|
-
case 'javascript':
|
|
55
|
-
case 'typescript':
|
|
56
|
-
while (current) {
|
|
57
|
-
const type = current.type;
|
|
58
|
-
if (type === 'export_statement' ||
|
|
59
|
-
type === 'export_specifier' ||
|
|
60
|
-
type === 'lexical_declaration' && current.parent?.type === 'export_statement') {
|
|
61
|
-
return true;
|
|
62
|
-
}
|
|
63
|
-
// Also check if text starts with 'export '
|
|
64
|
-
if (current.text?.startsWith('export ')) {
|
|
65
|
-
return true;
|
|
66
|
-
}
|
|
67
|
-
current = current.parent;
|
|
68
|
-
}
|
|
69
|
-
return false;
|
|
70
|
-
// Python: Public if no leading underscore (convention)
|
|
71
|
-
case 'python':
|
|
72
|
-
return !name.startsWith('_');
|
|
73
|
-
// Java: Check for 'public' modifier
|
|
74
|
-
// In tree-sitter Java, modifiers are siblings of the name node, not parents
|
|
75
|
-
case 'java':
|
|
76
|
-
while (current) {
|
|
77
|
-
// Check if this node or any sibling is a 'modifiers' node containing 'public'
|
|
78
|
-
if (current.parent) {
|
|
79
|
-
const parent = current.parent;
|
|
80
|
-
// Check all children of the parent for modifiers
|
|
81
|
-
for (let i = 0; i < parent.childCount; i++) {
|
|
82
|
-
const child = parent.child(i);
|
|
83
|
-
if (child?.type === 'modifiers' && child.text?.includes('public')) {
|
|
84
|
-
return true;
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
// Also check if the parent's text starts with 'public' (fallback)
|
|
88
|
-
if (parent.type === 'method_declaration' || parent.type === 'constructor_declaration') {
|
|
89
|
-
if (parent.text?.trimStart().startsWith('public')) {
|
|
90
|
-
return true;
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
current = current.parent;
|
|
95
|
-
}
|
|
96
|
-
return false;
|
|
97
|
-
// C#: Check for 'public' modifier in ancestors
|
|
98
|
-
case 'csharp':
|
|
99
|
-
while (current) {
|
|
100
|
-
if (current.type === 'modifier' || current.type === 'modifiers') {
|
|
101
|
-
if (current.text?.includes('public'))
|
|
102
|
-
return true;
|
|
103
|
-
}
|
|
104
|
-
current = current.parent;
|
|
105
|
-
}
|
|
106
|
-
return false;
|
|
107
|
-
// Go: Uppercase first letter = exported
|
|
108
|
-
case 'go':
|
|
109
|
-
if (name.length === 0)
|
|
110
|
-
return false;
|
|
111
|
-
const first = name[0];
|
|
112
|
-
// Must be uppercase letter (not a number or symbol)
|
|
113
|
-
return first === first.toUpperCase() && first !== first.toLowerCase();
|
|
114
|
-
// Rust: Check for 'pub' visibility modifier
|
|
115
|
-
case 'rust':
|
|
116
|
-
while (current) {
|
|
117
|
-
if (current.type === 'visibility_modifier') {
|
|
118
|
-
if (current.text?.includes('pub'))
|
|
119
|
-
return true;
|
|
120
|
-
}
|
|
121
|
-
current = current.parent;
|
|
122
|
-
}
|
|
123
|
-
return false;
|
|
124
|
-
// Kotlin: Default visibility is public (unlike Java)
|
|
125
|
-
// visibility_modifier is inside modifiers, a sibling of the name node within the declaration
|
|
126
|
-
case 'kotlin':
|
|
127
|
-
while (current) {
|
|
128
|
-
if (current.parent) {
|
|
129
|
-
const visMod = findSiblingChild(current.parent, 'modifiers', 'visibility_modifier');
|
|
130
|
-
if (visMod) {
|
|
131
|
-
const text = visMod.text;
|
|
132
|
-
if (text === 'private' || text === 'internal' || text === 'protected')
|
|
133
|
-
return false;
|
|
134
|
-
if (text === 'public')
|
|
135
|
-
return true;
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
current = current.parent;
|
|
139
|
-
}
|
|
140
|
-
// No visibility modifier = public (Kotlin default)
|
|
141
|
-
return true;
|
|
142
|
-
// C/C++: No native export concept at language level
|
|
143
|
-
// Entry points will be detected via name patterns (main, etc.)
|
|
144
|
-
case 'c':
|
|
145
|
-
case 'cpp':
|
|
146
|
-
return false;
|
|
147
|
-
// Swift: Check for 'public' or 'open' access modifiers
|
|
148
|
-
case 'swift':
|
|
149
|
-
while (current) {
|
|
150
|
-
if (current.type === 'modifiers' || current.type === 'visibility_modifier') {
|
|
151
|
-
const text = current.text || '';
|
|
152
|
-
if (text.includes('public') || text.includes('open'))
|
|
153
|
-
return true;
|
|
154
|
-
}
|
|
155
|
-
current = current.parent;
|
|
156
|
-
}
|
|
157
|
-
return false;
|
|
158
|
-
// PHP: Check for visibility modifier or top-level scope
|
|
159
|
-
case 'php':
|
|
160
|
-
while (current) {
|
|
161
|
-
if (current.type === 'class_declaration' ||
|
|
162
|
-
current.type === 'interface_declaration' ||
|
|
163
|
-
current.type === 'trait_declaration' ||
|
|
164
|
-
current.type === 'enum_declaration') {
|
|
165
|
-
return true;
|
|
166
|
-
}
|
|
167
|
-
if (current.type === 'visibility_modifier') {
|
|
168
|
-
return current.text === 'public';
|
|
169
|
-
}
|
|
170
|
-
current = current.parent;
|
|
171
|
-
}
|
|
172
|
-
return true; // Top-level functions are globally accessible
|
|
173
|
-
default:
|
|
174
|
-
return false;
|
|
175
|
-
}
|
|
176
|
-
};
|
|
8
|
+
import { typeConfigs } from './type-extractors/index.js';
|
|
9
|
+
import { getTreeSitterBufferSize, TREE_SITTER_MAX_BUFFER } from './constants.js';
|
|
10
|
+
// isNodeExported imported from ./export-detection.js (shared module)
|
|
11
|
+
// Re-export for backward compatibility with any external consumers
|
|
12
|
+
export { isNodeExported } from './export-detection.js';
|
|
177
13
|
// ============================================================================
|
|
178
14
|
// Worker-based parallel parsing
|
|
179
15
|
// ============================================================================
|
|
@@ -186,7 +22,7 @@ const processParsingWithWorkers = async (graph, files, symbolTable, astCache, wo
|
|
|
186
22
|
parseableFiles.push({ path: file.path, content: file.content });
|
|
187
23
|
}
|
|
188
24
|
if (parseableFiles.length === 0)
|
|
189
|
-
return { imports: [], calls: [], heritage: [], routes: [] };
|
|
25
|
+
return { imports: [], calls: [], heritage: [], routes: [], constructorBindings: [] };
|
|
190
26
|
const total = files.length;
|
|
191
27
|
// Dispatch to worker pool — pool handles splitting into chunks and sub-batching
|
|
192
28
|
const chunkResults = await workerPool.dispatch(parseableFiles, (filesProcessed) => {
|
|
@@ -197,6 +33,7 @@ const processParsingWithWorkers = async (graph, files, symbolTable, astCache, wo
|
|
|
197
33
|
const allCalls = [];
|
|
198
34
|
const allHeritage = [];
|
|
199
35
|
const allRoutes = [];
|
|
36
|
+
const allConstructorBindings = [];
|
|
200
37
|
for (const result of chunkResults) {
|
|
201
38
|
for (const node of result.nodes) {
|
|
202
39
|
graph.addNode({
|
|
@@ -209,16 +46,34 @@ const processParsingWithWorkers = async (graph, files, symbolTable, astCache, wo
|
|
|
209
46
|
graph.addRelationship(rel);
|
|
210
47
|
}
|
|
211
48
|
for (const sym of result.symbols) {
|
|
212
|
-
symbolTable.add(sym.filePath, sym.name, sym.nodeId, sym.type
|
|
49
|
+
symbolTable.add(sym.filePath, sym.name, sym.nodeId, sym.type, {
|
|
50
|
+
parameterCount: sym.parameterCount,
|
|
51
|
+
returnType: sym.returnType,
|
|
52
|
+
ownerId: sym.ownerId,
|
|
53
|
+
});
|
|
213
54
|
}
|
|
214
55
|
allImports.push(...result.imports);
|
|
215
56
|
allCalls.push(...result.calls);
|
|
216
57
|
allHeritage.push(...result.heritage);
|
|
217
58
|
allRoutes.push(...result.routes);
|
|
59
|
+
allConstructorBindings.push(...result.constructorBindings);
|
|
60
|
+
}
|
|
61
|
+
// Merge and log skipped languages from workers
|
|
62
|
+
const skippedLanguages = new Map();
|
|
63
|
+
for (const result of chunkResults) {
|
|
64
|
+
for (const [lang, count] of Object.entries(result.skippedLanguages)) {
|
|
65
|
+
skippedLanguages.set(lang, (skippedLanguages.get(lang) || 0) + count);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
if (skippedLanguages.size > 0) {
|
|
69
|
+
const summary = Array.from(skippedLanguages.entries())
|
|
70
|
+
.map(([lang, count]) => `${lang}: ${count}`)
|
|
71
|
+
.join(', ');
|
|
72
|
+
console.warn(` Skipped unsupported languages: ${summary}`);
|
|
218
73
|
}
|
|
219
74
|
// Final progress
|
|
220
75
|
onFileProgress?.(total, total, 'done');
|
|
221
|
-
return { imports: allImports, calls: allCalls, heritage: allHeritage, routes: allRoutes };
|
|
76
|
+
return { imports: allImports, calls: allCalls, heritage: allHeritage, routes: allRoutes, constructorBindings: allConstructorBindings };
|
|
222
77
|
};
|
|
223
78
|
// ============================================================================
|
|
224
79
|
// Sequential fallback (original implementation)
|
|
@@ -226,6 +81,7 @@ const processParsingWithWorkers = async (graph, files, symbolTable, astCache, wo
|
|
|
226
81
|
const processParsingSequential = async (graph, files, symbolTable, astCache, onFileProgress) => {
|
|
227
82
|
const parser = await loadParser();
|
|
228
83
|
const total = files.length;
|
|
84
|
+
const skippedLanguages = new Map();
|
|
229
85
|
for (let i = 0; i < files.length; i++) {
|
|
230
86
|
const file = files[i];
|
|
231
87
|
onFileProgress?.(i + 1, total, file.path);
|
|
@@ -234,18 +90,23 @@ const processParsingSequential = async (graph, files, symbolTable, astCache, onF
|
|
|
234
90
|
const language = getLanguageFromFilename(file.path);
|
|
235
91
|
if (!language)
|
|
236
92
|
continue;
|
|
237
|
-
// Skip
|
|
238
|
-
if (
|
|
93
|
+
// Skip unsupported languages (e.g. Swift when tree-sitter-swift not installed)
|
|
94
|
+
if (!isLanguageAvailable(language)) {
|
|
95
|
+
skippedLanguages.set(language, (skippedLanguages.get(language) || 0) + 1);
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
// Skip files larger than the max tree-sitter buffer (32 MB)
|
|
99
|
+
if (file.content.length > TREE_SITTER_MAX_BUFFER)
|
|
239
100
|
continue;
|
|
240
101
|
try {
|
|
241
102
|
await loadLanguage(language, file.path);
|
|
242
103
|
}
|
|
243
104
|
catch {
|
|
244
|
-
continue; // parser unavailable —
|
|
105
|
+
continue; // parser unavailable — safety net
|
|
245
106
|
}
|
|
246
107
|
let tree;
|
|
247
108
|
try {
|
|
248
|
-
tree = parser.parse(file.content, undefined, { bufferSize:
|
|
109
|
+
tree = parser.parse(file.content, undefined, { bufferSize: getTreeSitterBufferSize(file.content.length) });
|
|
249
110
|
}
|
|
250
111
|
catch (parseError) {
|
|
251
112
|
console.warn(`Skipping unparseable file: ${file.path}`);
|
|
@@ -330,11 +191,25 @@ const processParsingSequential = async (graph, files, symbolTable, astCache, onF
|
|
|
330
191
|
nodeLabel = 'Template';
|
|
331
192
|
const definitionNodeForRange = getDefinitionNodeFromCaptures(captureMap);
|
|
332
193
|
const startLine = definitionNodeForRange ? definitionNodeForRange.startPosition.row : (nameNode ? nameNode.startPosition.row : 0);
|
|
333
|
-
const nodeId = generateId(nodeLabel, `${file.path}:${nodeName}
|
|
194
|
+
const nodeId = generateId(nodeLabel, `${file.path}:${nodeName}`);
|
|
334
195
|
const definitionNode = getDefinitionNodeFromCaptures(captureMap);
|
|
335
196
|
const frameworkHint = definitionNode
|
|
336
197
|
? detectFrameworkFromAST(language, (definitionNode.text || '').slice(0, 300))
|
|
337
198
|
: null;
|
|
199
|
+
// Extract method signature for Method/Constructor nodes
|
|
200
|
+
const methodSig = (nodeLabel === 'Function' || nodeLabel === 'Method' || nodeLabel === 'Constructor')
|
|
201
|
+
? extractMethodSignature(definitionNode)
|
|
202
|
+
: undefined;
|
|
203
|
+
// Language-specific return type fallback (e.g. Ruby YARD @return [Type])
|
|
204
|
+
// Also upgrades uninformative AST types like PHP `array` with PHPDoc `@return User[]`
|
|
205
|
+
if (methodSig && (!methodSig.returnType || methodSig.returnType === 'array' || methodSig.returnType === 'iterable') && definitionNode) {
|
|
206
|
+
const tc = typeConfigs[language];
|
|
207
|
+
if (tc?.extractReturnType) {
|
|
208
|
+
const docReturn = tc.extractReturnType(definitionNode);
|
|
209
|
+
if (docReturn)
|
|
210
|
+
methodSig.returnType = docReturn;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
338
213
|
const node = {
|
|
339
214
|
id: nodeId,
|
|
340
215
|
label: nodeLabel,
|
|
@@ -349,10 +224,22 @@ const processParsingSequential = async (graph, files, symbolTable, astCache, onF
|
|
|
349
224
|
astFrameworkMultiplier: frameworkHint.entryPointMultiplier,
|
|
350
225
|
astFrameworkReason: frameworkHint.reason,
|
|
351
226
|
} : {}),
|
|
227
|
+
...(methodSig ? {
|
|
228
|
+
parameterCount: methodSig.parameterCount,
|
|
229
|
+
returnType: methodSig.returnType,
|
|
230
|
+
} : {}),
|
|
352
231
|
},
|
|
353
232
|
};
|
|
354
233
|
graph.addNode(node);
|
|
355
|
-
|
|
234
|
+
// Compute enclosing class for Method/Constructor/Property/Function — used for both ownerId and HAS_METHOD
|
|
235
|
+
// Function is included because Kotlin/Rust/Python capture class methods as Function nodes
|
|
236
|
+
const needsOwner = nodeLabel === 'Method' || nodeLabel === 'Constructor' || nodeLabel === 'Property' || nodeLabel === 'Function';
|
|
237
|
+
const enclosingClassId = needsOwner ? findEnclosingClassId(nameNode || definitionNodeForRange, file.path) : null;
|
|
238
|
+
symbolTable.add(file.path, nodeName, nodeId, nodeLabel, {
|
|
239
|
+
parameterCount: methodSig?.parameterCount,
|
|
240
|
+
returnType: methodSig?.returnType,
|
|
241
|
+
ownerId: enclosingClassId ?? undefined,
|
|
242
|
+
});
|
|
356
243
|
const fileId = generateId('File', file.path);
|
|
357
244
|
const relId = generateId('DEFINES', `${fileId}->${nodeId}`);
|
|
358
245
|
const relationship = {
|
|
@@ -364,8 +251,25 @@ const processParsingSequential = async (graph, files, symbolTable, astCache, onF
|
|
|
364
251
|
reason: '',
|
|
365
252
|
};
|
|
366
253
|
graph.addRelationship(relationship);
|
|
254
|
+
// ── HAS_METHOD: link method/constructor/property to enclosing class ──
|
|
255
|
+
if (enclosingClassId) {
|
|
256
|
+
graph.addRelationship({
|
|
257
|
+
id: generateId('HAS_METHOD', `${enclosingClassId}->${nodeId}`),
|
|
258
|
+
sourceId: enclosingClassId,
|
|
259
|
+
targetId: nodeId,
|
|
260
|
+
type: 'HAS_METHOD',
|
|
261
|
+
confidence: 1.0,
|
|
262
|
+
reason: '',
|
|
263
|
+
});
|
|
264
|
+
}
|
|
367
265
|
});
|
|
368
266
|
}
|
|
267
|
+
if (skippedLanguages.size > 0) {
|
|
268
|
+
const summary = Array.from(skippedLanguages.entries())
|
|
269
|
+
.map(([lang, count]) => `${lang}: ${count}`)
|
|
270
|
+
.join(', ');
|
|
271
|
+
console.warn(` Skipped unsupported languages: ${summary}`);
|
|
272
|
+
}
|
|
369
273
|
};
|
|
370
274
|
// ============================================================================
|
|
371
275
|
// Public API
|
|
@@ -1,2 +1,6 @@
|
|
|
1
1
|
import { PipelineProgress, PipelineResult } from '../../types/pipeline.js';
|
|
2
|
-
export
|
|
2
|
+
export interface PipelineOptions {
|
|
3
|
+
/** Skip MRO, community detection, and process extraction for faster test runs. */
|
|
4
|
+
skipGraphPhases?: boolean;
|
|
5
|
+
}
|
|
6
|
+
export declare const runPipelineFromRepo: (repoPath: string, onProgress: (progress: PipelineProgress) => void, options?: PipelineOptions) => Promise<PipelineResult>;
|