gitnexus 1.4.0 → 1.4.1
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 +194 -214
- package/dist/cli/ai-context.d.ts +1 -2
- package/dist/cli/ai-context.js +90 -117
- package/dist/cli/analyze.d.ts +0 -2
- package/dist/cli/analyze.js +2 -20
- package/dist/cli/index.js +25 -17
- package/dist/cli/setup.js +19 -17
- package/dist/core/augmentation/engine.js +20 -20
- package/dist/core/embeddings/embedding-pipeline.js +26 -26
- package/dist/core/graph/types.d.ts +2 -5
- package/dist/core/ingestion/ast-cache.js +2 -3
- package/dist/core/ingestion/call-processor.d.ts +5 -5
- package/dist/core/ingestion/call-processor.js +258 -173
- package/dist/core/ingestion/cluster-enricher.js +16 -16
- package/dist/core/ingestion/entry-point-scoring.d.ts +1 -2
- package/dist/core/ingestion/entry-point-scoring.js +22 -81
- package/dist/core/ingestion/framework-detection.d.ts +1 -5
- package/dist/core/ingestion/framework-detection.js +8 -39
- package/dist/core/ingestion/heritage-processor.d.ts +4 -13
- package/dist/core/ingestion/heritage-processor.js +28 -92
- package/dist/core/ingestion/import-processor.d.ts +19 -17
- package/dist/core/ingestion/import-processor.js +695 -170
- package/dist/core/ingestion/parsing-processor.d.ts +10 -1
- package/dist/core/ingestion/parsing-processor.js +177 -41
- package/dist/core/ingestion/pipeline.js +26 -49
- package/dist/core/ingestion/process-processor.js +1 -2
- package/dist/core/ingestion/symbol-table.d.ts +1 -12
- package/dist/core/ingestion/symbol-table.js +12 -19
- package/dist/core/ingestion/tree-sitter-queries.d.ts +11 -11
- package/dist/core/ingestion/tree-sitter-queries.js +485 -590
- package/dist/core/ingestion/utils.d.ts +0 -67
- package/dist/core/ingestion/utils.js +9 -692
- package/dist/core/ingestion/workers/parse-worker.d.ts +3 -20
- package/dist/core/ingestion/workers/parse-worker.js +345 -84
- package/dist/core/ingestion/workers/worker-pool.js +0 -8
- package/dist/core/kuzu/csv-generator.js +3 -19
- package/dist/core/kuzu/kuzu-adapter.js +19 -14
- package/dist/core/kuzu/schema.d.ts +3 -3
- package/dist/core/kuzu/schema.js +288 -303
- package/dist/core/search/bm25-index.js +6 -7
- package/dist/core/search/hybrid-search.js +3 -3
- package/dist/core/wiki/diagrams.d.ts +27 -0
- package/dist/core/wiki/diagrams.js +163 -0
- package/dist/core/wiki/generator.d.ts +50 -2
- package/dist/core/wiki/generator.js +548 -49
- package/dist/core/wiki/graph-queries.d.ts +42 -0
- package/dist/core/wiki/graph-queries.js +276 -97
- package/dist/core/wiki/html-viewer.js +192 -192
- package/dist/core/wiki/llm-client.js +73 -11
- package/dist/core/wiki/prompts.d.ts +52 -8
- package/dist/core/wiki/prompts.js +200 -86
- package/dist/mcp/core/kuzu-adapter.d.ts +3 -1
- package/dist/mcp/core/kuzu-adapter.js +44 -13
- package/dist/mcp/local/local-backend.js +128 -128
- package/dist/mcp/resources.js +42 -42
- package/dist/mcp/server.js +19 -18
- package/dist/mcp/tools.js +104 -103
- package/hooks/claude/gitnexus-hook.cjs +155 -238
- package/hooks/claude/pre-tool-use.sh +79 -79
- package/hooks/claude/session-start.sh +42 -42
- package/package.json +96 -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/cli/lazy-action.d.ts +0 -6
- package/dist/cli/lazy-action.js +0 -18
- package/dist/cli/skill-gen.d.ts +0 -26
- package/dist/cli/skill-gen.js +0 -549
- package/dist/core/ingestion/constants.d.ts +0 -16
- package/dist/core/ingestion/constants.js +0 -16
- package/dist/core/ingestion/export-detection.d.ts +0 -18
- package/dist/core/ingestion/export-detection.js +0 -230
- package/dist/core/ingestion/language-config.d.ts +0 -46
- package/dist/core/ingestion/language-config.js +0 -167
- package/dist/core/ingestion/mro-processor.d.ts +0 -45
- package/dist/core/ingestion/mro-processor.js +0 -369
- package/dist/core/ingestion/named-binding-extraction.d.ts +0 -61
- package/dist/core/ingestion/named-binding-extraction.js +0 -363
- package/dist/core/ingestion/resolvers/csharp.d.ts +0 -22
- package/dist/core/ingestion/resolvers/csharp.js +0 -109
- package/dist/core/ingestion/resolvers/go.d.ts +0 -19
- package/dist/core/ingestion/resolvers/go.js +0 -42
- package/dist/core/ingestion/resolvers/index.d.ts +0 -16
- package/dist/core/ingestion/resolvers/index.js +0 -11
- package/dist/core/ingestion/resolvers/jvm.d.ts +0 -23
- package/dist/core/ingestion/resolvers/jvm.js +0 -87
- package/dist/core/ingestion/resolvers/php.d.ts +0 -15
- package/dist/core/ingestion/resolvers/php.js +0 -35
- package/dist/core/ingestion/resolvers/rust.d.ts +0 -15
- package/dist/core/ingestion/resolvers/rust.js +0 -73
- package/dist/core/ingestion/resolvers/standard.d.ts +0 -28
- package/dist/core/ingestion/resolvers/standard.js +0 -145
- package/dist/core/ingestion/resolvers/utils.d.ts +0 -33
- package/dist/core/ingestion/resolvers/utils.js +0 -120
- package/dist/core/ingestion/symbol-resolver.d.ts +0 -32
- package/dist/core/ingestion/symbol-resolver.js +0 -83
- package/dist/core/ingestion/type-env.d.ts +0 -27
- package/dist/core/ingestion/type-env.js +0 -86
- package/dist/core/ingestion/type-extractors/c-cpp.d.ts +0 -2
- package/dist/core/ingestion/type-extractors/c-cpp.js +0 -60
- package/dist/core/ingestion/type-extractors/csharp.d.ts +0 -2
- package/dist/core/ingestion/type-extractors/csharp.js +0 -89
- package/dist/core/ingestion/type-extractors/go.d.ts +0 -2
- package/dist/core/ingestion/type-extractors/go.js +0 -105
- package/dist/core/ingestion/type-extractors/index.d.ts +0 -21
- package/dist/core/ingestion/type-extractors/index.js +0 -29
- package/dist/core/ingestion/type-extractors/jvm.d.ts +0 -3
- package/dist/core/ingestion/type-extractors/jvm.js +0 -121
- package/dist/core/ingestion/type-extractors/php.d.ts +0 -2
- package/dist/core/ingestion/type-extractors/php.js +0 -31
- package/dist/core/ingestion/type-extractors/python.d.ts +0 -2
- package/dist/core/ingestion/type-extractors/python.js +0 -41
- package/dist/core/ingestion/type-extractors/rust.d.ts +0 -2
- package/dist/core/ingestion/type-extractors/rust.js +0 -39
- package/dist/core/ingestion/type-extractors/shared.d.ts +0 -17
- package/dist/core/ingestion/type-extractors/shared.js +0 -97
- package/dist/core/ingestion/type-extractors/swift.d.ts +0 -2
- package/dist/core/ingestion/type-extractors/swift.js +0 -43
- package/dist/core/ingestion/type-extractors/types.d.ts +0 -14
- package/dist/core/ingestion/type-extractors/types.js +0 -1
- package/dist/core/ingestion/type-extractors/typescript.d.ts +0 -2
- package/dist/core/ingestion/type-extractors/typescript.js +0 -46
- package/dist/mcp/compatible-stdio-transport.d.ts +0 -25
- package/dist/mcp/compatible-stdio-transport.js +0 -200
|
@@ -1,230 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Export Detection
|
|
3
|
-
*
|
|
4
|
-
* Determines whether a symbol (function, class, etc.) is exported/public
|
|
5
|
-
* in its language. This is a pure function — safe for use in worker threads.
|
|
6
|
-
*
|
|
7
|
-
* Shared between parse-worker.ts (worker pool) and parsing-processor.ts (sequential fallback).
|
|
8
|
-
*/
|
|
9
|
-
import { findSiblingChild } from './utils.js';
|
|
10
|
-
import { SupportedLanguages } from '../../config/supported-languages.js';
|
|
11
|
-
// ============================================================================
|
|
12
|
-
// Per-language export checkers
|
|
13
|
-
// ============================================================================
|
|
14
|
-
/** JS/TS: walk ancestors looking for export_statement or export_specifier. */
|
|
15
|
-
const tsExportChecker = (node, _name) => {
|
|
16
|
-
let current = node;
|
|
17
|
-
while (current) {
|
|
18
|
-
const type = current.type;
|
|
19
|
-
if (type === 'export_statement' ||
|
|
20
|
-
type === 'export_specifier' ||
|
|
21
|
-
(type === 'lexical_declaration' && current.parent?.type === 'export_statement')) {
|
|
22
|
-
return true;
|
|
23
|
-
}
|
|
24
|
-
// Fallback: check if node text starts with 'export ' for edge cases
|
|
25
|
-
if (current.text?.startsWith('export ')) {
|
|
26
|
-
return true;
|
|
27
|
-
}
|
|
28
|
-
current = current.parent;
|
|
29
|
-
}
|
|
30
|
-
return false;
|
|
31
|
-
};
|
|
32
|
-
/** Python: public if no leading underscore (convention). */
|
|
33
|
-
const pythonExportChecker = (_node, name) => !name.startsWith('_');
|
|
34
|
-
/** Java: check for 'public' modifier — modifiers are siblings of the name node, not parents. */
|
|
35
|
-
const javaExportChecker = (node, _name) => {
|
|
36
|
-
let current = node;
|
|
37
|
-
while (current) {
|
|
38
|
-
if (current.parent) {
|
|
39
|
-
const parent = current.parent;
|
|
40
|
-
for (let i = 0; i < parent.childCount; i++) {
|
|
41
|
-
const child = parent.child(i);
|
|
42
|
-
if (child?.type === 'modifiers' && child.text?.includes('public')) {
|
|
43
|
-
return true;
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
if (parent.type === 'method_declaration' || parent.type === 'constructor_declaration') {
|
|
47
|
-
if (parent.text?.trimStart().startsWith('public')) {
|
|
48
|
-
return true;
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
current = current.parent;
|
|
53
|
-
}
|
|
54
|
-
return false;
|
|
55
|
-
};
|
|
56
|
-
/** C# declaration node types for sibling modifier scanning. */
|
|
57
|
-
const CSHARP_DECL_TYPES = new Set([
|
|
58
|
-
'method_declaration', 'local_function_statement', 'constructor_declaration',
|
|
59
|
-
'class_declaration', 'interface_declaration', 'struct_declaration',
|
|
60
|
-
'enum_declaration', 'record_declaration', 'record_struct_declaration',
|
|
61
|
-
'record_class_declaration', 'delegate_declaration',
|
|
62
|
-
'property_declaration', 'field_declaration', 'event_declaration',
|
|
63
|
-
'namespace_declaration', 'file_scoped_namespace_declaration',
|
|
64
|
-
]);
|
|
65
|
-
/**
|
|
66
|
-
* C#: modifier nodes are SIBLINGS of the name node inside the declaration.
|
|
67
|
-
* Walk up to the declaration node, then scan its direct children.
|
|
68
|
-
*/
|
|
69
|
-
const csharpExportChecker = (node, _name) => {
|
|
70
|
-
let current = node;
|
|
71
|
-
while (current) {
|
|
72
|
-
if (CSHARP_DECL_TYPES.has(current.type)) {
|
|
73
|
-
for (let i = 0; i < current.childCount; i++) {
|
|
74
|
-
const child = current.child(i);
|
|
75
|
-
if (child?.type === 'modifier' && child.text === 'public')
|
|
76
|
-
return true;
|
|
77
|
-
}
|
|
78
|
-
return false;
|
|
79
|
-
}
|
|
80
|
-
current = current.parent;
|
|
81
|
-
}
|
|
82
|
-
return false;
|
|
83
|
-
};
|
|
84
|
-
/** Go: uppercase first letter = exported. */
|
|
85
|
-
const goExportChecker = (_node, name) => {
|
|
86
|
-
if (name.length === 0)
|
|
87
|
-
return false;
|
|
88
|
-
const first = name[0];
|
|
89
|
-
return first === first.toUpperCase() && first !== first.toLowerCase();
|
|
90
|
-
};
|
|
91
|
-
/** Rust declaration node types for sibling visibility_modifier scanning. */
|
|
92
|
-
const RUST_DECL_TYPES = new Set([
|
|
93
|
-
'function_item', 'struct_item', 'enum_item', 'trait_item', 'impl_item',
|
|
94
|
-
'union_item', 'type_item', 'const_item', 'static_item', 'mod_item',
|
|
95
|
-
'use_declaration', 'associated_type', 'function_signature_item',
|
|
96
|
-
]);
|
|
97
|
-
/**
|
|
98
|
-
* Rust: visibility_modifier is a SIBLING of the name node within the declaration node
|
|
99
|
-
* (function_item, struct_item, etc.), not a parent. Walk up to the declaration node,
|
|
100
|
-
* then scan its direct children.
|
|
101
|
-
*/
|
|
102
|
-
const rustExportChecker = (node, _name) => {
|
|
103
|
-
let current = node;
|
|
104
|
-
while (current) {
|
|
105
|
-
if (RUST_DECL_TYPES.has(current.type)) {
|
|
106
|
-
for (let i = 0; i < current.childCount; i++) {
|
|
107
|
-
const child = current.child(i);
|
|
108
|
-
if (child?.type === 'visibility_modifier' && child.text?.startsWith('pub'))
|
|
109
|
-
return true;
|
|
110
|
-
}
|
|
111
|
-
return false;
|
|
112
|
-
}
|
|
113
|
-
current = current.parent;
|
|
114
|
-
}
|
|
115
|
-
return false;
|
|
116
|
-
};
|
|
117
|
-
/**
|
|
118
|
-
* Kotlin: default visibility is public (unlike Java).
|
|
119
|
-
* visibility_modifier is inside modifiers, a sibling of the name node within the declaration.
|
|
120
|
-
*/
|
|
121
|
-
const kotlinExportChecker = (node, _name) => {
|
|
122
|
-
let current = node;
|
|
123
|
-
while (current) {
|
|
124
|
-
if (current.parent) {
|
|
125
|
-
const visMod = findSiblingChild(current.parent, 'modifiers', 'visibility_modifier');
|
|
126
|
-
if (visMod) {
|
|
127
|
-
const text = visMod.text;
|
|
128
|
-
if (text === 'private' || text === 'internal' || text === 'protected')
|
|
129
|
-
return false;
|
|
130
|
-
if (text === 'public')
|
|
131
|
-
return true;
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
current = current.parent;
|
|
135
|
-
}
|
|
136
|
-
// No visibility modifier = public (Kotlin default)
|
|
137
|
-
return true;
|
|
138
|
-
};
|
|
139
|
-
/**
|
|
140
|
-
* C/C++: functions without 'static' storage class have external linkage by default,
|
|
141
|
-
* making them globally accessible (equivalent to exported). Only functions explicitly
|
|
142
|
-
* marked 'static' are file-scoped (not exported). C++ anonymous namespaces
|
|
143
|
-
* (namespace { ... }) also give internal linkage.
|
|
144
|
-
*/
|
|
145
|
-
const cCppExportChecker = (node, _name) => {
|
|
146
|
-
let cur = node;
|
|
147
|
-
while (cur) {
|
|
148
|
-
if (cur.type === 'function_definition' || cur.type === 'declaration') {
|
|
149
|
-
// Check for 'static' storage class specifier as a direct child node.
|
|
150
|
-
// This avoids reading the full function text (which can be very large).
|
|
151
|
-
for (let i = 0; i < cur.childCount; i++) {
|
|
152
|
-
const child = cur.child(i);
|
|
153
|
-
if (child?.type === 'storage_class_specifier' && child.text === 'static')
|
|
154
|
-
return false;
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
// C++ anonymous namespace: namespace_definition with no name child = internal linkage
|
|
158
|
-
if (cur.type === 'namespace_definition') {
|
|
159
|
-
const hasName = cur.childForFieldName?.('name');
|
|
160
|
-
if (!hasName)
|
|
161
|
-
return false;
|
|
162
|
-
}
|
|
163
|
-
cur = cur.parent;
|
|
164
|
-
}
|
|
165
|
-
return true; // Top-level C/C++ functions default to external linkage
|
|
166
|
-
};
|
|
167
|
-
/** PHP: check for visibility modifier or top-level scope. */
|
|
168
|
-
const phpExportChecker = (node, _name) => {
|
|
169
|
-
let current = node;
|
|
170
|
-
while (current) {
|
|
171
|
-
if (current.type === 'class_declaration' ||
|
|
172
|
-
current.type === 'interface_declaration' ||
|
|
173
|
-
current.type === 'trait_declaration' ||
|
|
174
|
-
current.type === 'enum_declaration') {
|
|
175
|
-
return true;
|
|
176
|
-
}
|
|
177
|
-
if (current.type === 'visibility_modifier') {
|
|
178
|
-
return current.text === 'public';
|
|
179
|
-
}
|
|
180
|
-
current = current.parent;
|
|
181
|
-
}
|
|
182
|
-
// Top-level functions are globally accessible
|
|
183
|
-
return true;
|
|
184
|
-
};
|
|
185
|
-
/** Swift: check for 'public' or 'open' access modifiers. */
|
|
186
|
-
const swiftExportChecker = (node, _name) => {
|
|
187
|
-
let current = node;
|
|
188
|
-
while (current) {
|
|
189
|
-
if (current.type === 'modifiers' || current.type === 'visibility_modifier') {
|
|
190
|
-
const text = current.text || '';
|
|
191
|
-
if (text.includes('public') || text.includes('open'))
|
|
192
|
-
return true;
|
|
193
|
-
}
|
|
194
|
-
current = current.parent;
|
|
195
|
-
}
|
|
196
|
-
return false;
|
|
197
|
-
};
|
|
198
|
-
// ============================================================================
|
|
199
|
-
// Exhaustive dispatch table — satisfies enforces all SupportedLanguages are covered
|
|
200
|
-
// ============================================================================
|
|
201
|
-
const exportCheckers = {
|
|
202
|
-
[SupportedLanguages.JavaScript]: tsExportChecker,
|
|
203
|
-
[SupportedLanguages.TypeScript]: tsExportChecker,
|
|
204
|
-
[SupportedLanguages.Python]: pythonExportChecker,
|
|
205
|
-
[SupportedLanguages.Java]: javaExportChecker,
|
|
206
|
-
[SupportedLanguages.CSharp]: csharpExportChecker,
|
|
207
|
-
[SupportedLanguages.Go]: goExportChecker,
|
|
208
|
-
[SupportedLanguages.Rust]: rustExportChecker,
|
|
209
|
-
[SupportedLanguages.Kotlin]: kotlinExportChecker,
|
|
210
|
-
[SupportedLanguages.C]: cCppExportChecker,
|
|
211
|
-
[SupportedLanguages.CPlusPlus]: cCppExportChecker,
|
|
212
|
-
[SupportedLanguages.PHP]: phpExportChecker,
|
|
213
|
-
[SupportedLanguages.Swift]: swiftExportChecker,
|
|
214
|
-
};
|
|
215
|
-
// ============================================================================
|
|
216
|
-
// Public API
|
|
217
|
-
// ============================================================================
|
|
218
|
-
/**
|
|
219
|
-
* Check if a tree-sitter node is exported/public in its language.
|
|
220
|
-
* @param node - The tree-sitter AST node
|
|
221
|
-
* @param name - The symbol name
|
|
222
|
-
* @param language - The programming language
|
|
223
|
-
* @returns true if the symbol is exported/public
|
|
224
|
-
*/
|
|
225
|
-
export const isNodeExported = (node, name, language) => {
|
|
226
|
-
const checker = exportCheckers[language];
|
|
227
|
-
if (!checker)
|
|
228
|
-
return false;
|
|
229
|
-
return checker(node, name);
|
|
230
|
-
};
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
/** TypeScript path alias config parsed from tsconfig.json */
|
|
2
|
-
export interface TsconfigPaths {
|
|
3
|
-
/** Map of alias prefix -> target prefix (e.g., "@/" -> "src/") */
|
|
4
|
-
aliases: Map<string, string>;
|
|
5
|
-
/** Base URL for path resolution (relative to repo root) */
|
|
6
|
-
baseUrl: string;
|
|
7
|
-
}
|
|
8
|
-
/** Go module config parsed from go.mod */
|
|
9
|
-
export interface GoModuleConfig {
|
|
10
|
-
/** Module path (e.g., "github.com/user/repo") */
|
|
11
|
-
modulePath: string;
|
|
12
|
-
}
|
|
13
|
-
/** PHP Composer PSR-4 autoload config */
|
|
14
|
-
export interface ComposerConfig {
|
|
15
|
-
/** Map of namespace prefix -> directory (e.g., "App\\" -> "app/") */
|
|
16
|
-
psr4: Map<string, string>;
|
|
17
|
-
}
|
|
18
|
-
/** C# project config parsed from .csproj files */
|
|
19
|
-
export interface CSharpProjectConfig {
|
|
20
|
-
/** Root namespace from <RootNamespace> or assembly name (default: project directory name) */
|
|
21
|
-
rootNamespace: string;
|
|
22
|
-
/** Directory containing the .csproj file */
|
|
23
|
-
projectDir: string;
|
|
24
|
-
}
|
|
25
|
-
/** Swift Package Manager module config */
|
|
26
|
-
export interface SwiftPackageConfig {
|
|
27
|
-
/** Map of target name -> source directory path (e.g., "SiuperModel" -> "Package/Sources/SiuperModel") */
|
|
28
|
-
targets: Map<string, string>;
|
|
29
|
-
}
|
|
30
|
-
/**
|
|
31
|
-
* Parse tsconfig.json to extract path aliases.
|
|
32
|
-
* Tries tsconfig.json, tsconfig.app.json, tsconfig.base.json in order.
|
|
33
|
-
*/
|
|
34
|
-
export declare function loadTsconfigPaths(repoRoot: string): Promise<TsconfigPaths | null>;
|
|
35
|
-
/**
|
|
36
|
-
* Parse go.mod to extract module path.
|
|
37
|
-
*/
|
|
38
|
-
export declare function loadGoModulePath(repoRoot: string): Promise<GoModuleConfig | null>;
|
|
39
|
-
/** Parse composer.json to extract PSR-4 autoload mappings (including autoload-dev). */
|
|
40
|
-
export declare function loadComposerConfig(repoRoot: string): Promise<ComposerConfig | null>;
|
|
41
|
-
/**
|
|
42
|
-
* Parse .csproj files to extract RootNamespace.
|
|
43
|
-
* Scans the repo root for .csproj files and returns configs for each.
|
|
44
|
-
*/
|
|
45
|
-
export declare function loadCSharpProjectConfig(repoRoot: string): Promise<CSharpProjectConfig[]>;
|
|
46
|
-
export declare function loadSwiftPackageConfig(repoRoot: string): Promise<SwiftPackageConfig | null>;
|
|
@@ -1,167 +0,0 @@
|
|
|
1
|
-
import fs from 'fs/promises';
|
|
2
|
-
import path from 'path';
|
|
3
|
-
const isDev = process.env.NODE_ENV === 'development';
|
|
4
|
-
// ============================================================================
|
|
5
|
-
// LANGUAGE-SPECIFIC CONFIG LOADERS
|
|
6
|
-
// ============================================================================
|
|
7
|
-
/**
|
|
8
|
-
* Parse tsconfig.json to extract path aliases.
|
|
9
|
-
* Tries tsconfig.json, tsconfig.app.json, tsconfig.base.json in order.
|
|
10
|
-
*/
|
|
11
|
-
export async function loadTsconfigPaths(repoRoot) {
|
|
12
|
-
const candidates = ['tsconfig.json', 'tsconfig.app.json', 'tsconfig.base.json'];
|
|
13
|
-
for (const filename of candidates) {
|
|
14
|
-
try {
|
|
15
|
-
const tsconfigPath = path.join(repoRoot, filename);
|
|
16
|
-
const raw = await fs.readFile(tsconfigPath, 'utf-8');
|
|
17
|
-
// Strip JSON comments (// and /* */ style) for robustness
|
|
18
|
-
const stripped = raw.replace(/\/\/.*$/gm, '').replace(/\/\*[\s\S]*?\*\//g, '');
|
|
19
|
-
const tsconfig = JSON.parse(stripped);
|
|
20
|
-
const compilerOptions = tsconfig.compilerOptions;
|
|
21
|
-
if (!compilerOptions?.paths)
|
|
22
|
-
continue;
|
|
23
|
-
const baseUrl = compilerOptions.baseUrl || '.';
|
|
24
|
-
const aliases = new Map();
|
|
25
|
-
for (const [pattern, targets] of Object.entries(compilerOptions.paths)) {
|
|
26
|
-
if (!Array.isArray(targets) || targets.length === 0)
|
|
27
|
-
continue;
|
|
28
|
-
const target = targets[0];
|
|
29
|
-
// Convert glob patterns: "@/*" -> "@/", "src/*" -> "src/"
|
|
30
|
-
const aliasPrefix = pattern.endsWith('/*') ? pattern.slice(0, -1) : pattern;
|
|
31
|
-
const targetPrefix = target.endsWith('/*') ? target.slice(0, -1) : target;
|
|
32
|
-
aliases.set(aliasPrefix, targetPrefix);
|
|
33
|
-
}
|
|
34
|
-
if (aliases.size > 0) {
|
|
35
|
-
if (isDev) {
|
|
36
|
-
console.log(`📦 Loaded ${aliases.size} path aliases from ${filename}`);
|
|
37
|
-
}
|
|
38
|
-
return { aliases, baseUrl };
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
catch {
|
|
42
|
-
// File doesn't exist or isn't valid JSON - try next
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
return null;
|
|
46
|
-
}
|
|
47
|
-
/**
|
|
48
|
-
* Parse go.mod to extract module path.
|
|
49
|
-
*/
|
|
50
|
-
export async function loadGoModulePath(repoRoot) {
|
|
51
|
-
try {
|
|
52
|
-
const goModPath = path.join(repoRoot, 'go.mod');
|
|
53
|
-
const content = await fs.readFile(goModPath, 'utf-8');
|
|
54
|
-
const match = content.match(/^module\s+(\S+)/m);
|
|
55
|
-
if (match) {
|
|
56
|
-
if (isDev) {
|
|
57
|
-
console.log(`📦 Loaded Go module path: ${match[1]}`);
|
|
58
|
-
}
|
|
59
|
-
return { modulePath: match[1] };
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
catch {
|
|
63
|
-
// No go.mod
|
|
64
|
-
}
|
|
65
|
-
return null;
|
|
66
|
-
}
|
|
67
|
-
/** Parse composer.json to extract PSR-4 autoload mappings (including autoload-dev). */
|
|
68
|
-
export async function loadComposerConfig(repoRoot) {
|
|
69
|
-
try {
|
|
70
|
-
const composerPath = path.join(repoRoot, 'composer.json');
|
|
71
|
-
const raw = await fs.readFile(composerPath, 'utf-8');
|
|
72
|
-
const composer = JSON.parse(raw);
|
|
73
|
-
const psr4Raw = composer.autoload?.['psr-4'] ?? {};
|
|
74
|
-
const psr4Dev = composer['autoload-dev']?.['psr-4'] ?? {};
|
|
75
|
-
const merged = { ...psr4Raw, ...psr4Dev };
|
|
76
|
-
const psr4 = new Map();
|
|
77
|
-
for (const [ns, dir] of Object.entries(merged)) {
|
|
78
|
-
const nsNorm = ns.replace(/\\+$/, '');
|
|
79
|
-
const dirNorm = dir.replace(/\\/g, '/').replace(/\/+$/, '');
|
|
80
|
-
psr4.set(nsNorm, dirNorm);
|
|
81
|
-
}
|
|
82
|
-
if (isDev) {
|
|
83
|
-
console.log(`📦 Loaded ${psr4.size} PSR-4 mappings from composer.json`);
|
|
84
|
-
}
|
|
85
|
-
return { psr4 };
|
|
86
|
-
}
|
|
87
|
-
catch {
|
|
88
|
-
return null;
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
/**
|
|
92
|
-
* Parse .csproj files to extract RootNamespace.
|
|
93
|
-
* Scans the repo root for .csproj files and returns configs for each.
|
|
94
|
-
*/
|
|
95
|
-
export async function loadCSharpProjectConfig(repoRoot) {
|
|
96
|
-
const configs = [];
|
|
97
|
-
// BFS scan for .csproj files up to 5 levels deep, cap at 100 dirs to avoid runaway scanning
|
|
98
|
-
const scanQueue = [{ dir: repoRoot, depth: 0 }];
|
|
99
|
-
const maxDepth = 5;
|
|
100
|
-
const maxDirs = 100;
|
|
101
|
-
let dirsScanned = 0;
|
|
102
|
-
while (scanQueue.length > 0 && dirsScanned < maxDirs) {
|
|
103
|
-
const { dir, depth } = scanQueue.shift();
|
|
104
|
-
dirsScanned++;
|
|
105
|
-
try {
|
|
106
|
-
const entries = await fs.readdir(dir, { withFileTypes: true });
|
|
107
|
-
for (const entry of entries) {
|
|
108
|
-
if (entry.isDirectory() && depth < maxDepth) {
|
|
109
|
-
// Skip common non-project directories
|
|
110
|
-
if (entry.name === 'node_modules' || entry.name === '.git' || entry.name === 'bin' || entry.name === 'obj')
|
|
111
|
-
continue;
|
|
112
|
-
scanQueue.push({ dir: path.join(dir, entry.name), depth: depth + 1 });
|
|
113
|
-
}
|
|
114
|
-
if (entry.isFile() && entry.name.endsWith('.csproj')) {
|
|
115
|
-
try {
|
|
116
|
-
const csprojPath = path.join(dir, entry.name);
|
|
117
|
-
const content = await fs.readFile(csprojPath, 'utf-8');
|
|
118
|
-
const nsMatch = content.match(/<RootNamespace>\s*([^<]+)\s*<\/RootNamespace>/);
|
|
119
|
-
const rootNamespace = nsMatch
|
|
120
|
-
? nsMatch[1].trim()
|
|
121
|
-
: entry.name.replace(/\.csproj$/, '');
|
|
122
|
-
const projectDir = path.relative(repoRoot, dir).replace(/\\/g, '/');
|
|
123
|
-
configs.push({ rootNamespace, projectDir });
|
|
124
|
-
if (isDev) {
|
|
125
|
-
console.log(`📦 Loaded C# project: ${entry.name} (namespace: ${rootNamespace}, dir: ${projectDir})`);
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
catch {
|
|
129
|
-
// Can't read .csproj
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
catch {
|
|
135
|
-
// Can't read directory
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
return configs;
|
|
139
|
-
}
|
|
140
|
-
export async function loadSwiftPackageConfig(repoRoot) {
|
|
141
|
-
// Swift imports are module-name based (e.g., `import SiuperModel`)
|
|
142
|
-
// SPM convention: Sources/<TargetName>/ or Package/Sources/<TargetName>/
|
|
143
|
-
// We scan for these directories to build a target map
|
|
144
|
-
const targets = new Map();
|
|
145
|
-
const sourceDirs = ['Sources', 'Package/Sources', 'src'];
|
|
146
|
-
for (const sourceDir of sourceDirs) {
|
|
147
|
-
try {
|
|
148
|
-
const fullPath = path.join(repoRoot, sourceDir);
|
|
149
|
-
const entries = await fs.readdir(fullPath, { withFileTypes: true });
|
|
150
|
-
for (const entry of entries) {
|
|
151
|
-
if (entry.isDirectory()) {
|
|
152
|
-
targets.set(entry.name, sourceDir + '/' + entry.name);
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
catch {
|
|
157
|
-
// Directory doesn't exist
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
if (targets.size > 0) {
|
|
161
|
-
if (isDev) {
|
|
162
|
-
console.log(`📦 Loaded ${targets.size} Swift package targets`);
|
|
163
|
-
}
|
|
164
|
-
return { targets };
|
|
165
|
-
}
|
|
166
|
-
return null;
|
|
167
|
-
}
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* MRO (Method Resolution Order) Processor
|
|
3
|
-
*
|
|
4
|
-
* Walks the inheritance DAG (EXTENDS/IMPLEMENTS edges), collects methods from
|
|
5
|
-
* each ancestor via HAS_METHOD edges, detects method-name collisions across
|
|
6
|
-
* parents, and applies language-specific resolution rules to emit OVERRIDES edges.
|
|
7
|
-
*
|
|
8
|
-
* Language-specific rules:
|
|
9
|
-
* - C++: leftmost base class in declaration order wins
|
|
10
|
-
* - C#/Java: class method wins over interface default; multiple interface
|
|
11
|
-
* methods with same name are ambiguous (null resolution)
|
|
12
|
-
* - Python: C3 linearization determines MRO; first in linearized order wins
|
|
13
|
-
* - Rust: no auto-resolution — requires qualified syntax, resolvedTo = null
|
|
14
|
-
* - Default: single inheritance — first definition wins
|
|
15
|
-
*
|
|
16
|
-
* OVERRIDES edge direction: Class → Method (not Method → Method).
|
|
17
|
-
* The source is the child class that inherits conflicting methods,
|
|
18
|
-
* the target is the winning ancestor method node.
|
|
19
|
-
* Cypher: MATCH (c:Class)-[r:CodeRelation {type: 'OVERRIDES'}]->(m:Method)
|
|
20
|
-
*/
|
|
21
|
-
import { KnowledgeGraph } from '../graph/types.js';
|
|
22
|
-
import { SupportedLanguages } from '../../config/supported-languages.js';
|
|
23
|
-
export interface MROEntry {
|
|
24
|
-
classId: string;
|
|
25
|
-
className: string;
|
|
26
|
-
language: SupportedLanguages;
|
|
27
|
-
mro: string[];
|
|
28
|
-
ambiguities: MethodAmbiguity[];
|
|
29
|
-
}
|
|
30
|
-
export interface MethodAmbiguity {
|
|
31
|
-
methodName: string;
|
|
32
|
-
definedIn: Array<{
|
|
33
|
-
classId: string;
|
|
34
|
-
className: string;
|
|
35
|
-
methodId: string;
|
|
36
|
-
}>;
|
|
37
|
-
resolvedTo: string | null;
|
|
38
|
-
reason: string;
|
|
39
|
-
}
|
|
40
|
-
export interface MROResult {
|
|
41
|
-
entries: MROEntry[];
|
|
42
|
-
overrideEdges: number;
|
|
43
|
-
ambiguityCount: number;
|
|
44
|
-
}
|
|
45
|
-
export declare function computeMRO(graph: KnowledgeGraph): MROResult;
|