gitnexus 1.3.11 → 1.4.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.
Files changed (91) hide show
  1. package/README.md +22 -2
  2. package/dist/cli/ai-context.d.ts +2 -1
  3. package/dist/cli/ai-context.js +15 -6
  4. package/dist/cli/analyze.d.ts +2 -0
  5. package/dist/cli/analyze.js +12 -2
  6. package/dist/cli/index.js +2 -0
  7. package/dist/cli/skill-gen.d.ts +26 -0
  8. package/dist/cli/skill-gen.js +549 -0
  9. package/dist/core/graph/types.d.ts +5 -2
  10. package/dist/core/ingestion/call-processor.d.ts +5 -5
  11. package/dist/core/ingestion/call-processor.js +173 -260
  12. package/dist/core/ingestion/constants.d.ts +16 -0
  13. package/dist/core/ingestion/constants.js +16 -0
  14. package/dist/core/ingestion/entry-point-scoring.d.ts +2 -1
  15. package/dist/core/ingestion/entry-point-scoring.js +81 -22
  16. package/dist/core/ingestion/export-detection.d.ts +18 -0
  17. package/dist/core/ingestion/export-detection.js +230 -0
  18. package/dist/core/ingestion/framework-detection.d.ts +5 -1
  19. package/dist/core/ingestion/framework-detection.js +39 -8
  20. package/dist/core/ingestion/heritage-processor.d.ts +13 -4
  21. package/dist/core/ingestion/heritage-processor.js +92 -28
  22. package/dist/core/ingestion/import-processor.d.ts +17 -19
  23. package/dist/core/ingestion/import-processor.js +170 -695
  24. package/dist/core/ingestion/language-config.d.ts +46 -0
  25. package/dist/core/ingestion/language-config.js +167 -0
  26. package/dist/core/ingestion/mro-processor.d.ts +45 -0
  27. package/dist/core/ingestion/mro-processor.js +369 -0
  28. package/dist/core/ingestion/named-binding-extraction.d.ts +61 -0
  29. package/dist/core/ingestion/named-binding-extraction.js +363 -0
  30. package/dist/core/ingestion/parsing-processor.d.ts +1 -10
  31. package/dist/core/ingestion/parsing-processor.js +41 -177
  32. package/dist/core/ingestion/pipeline.js +26 -24
  33. package/dist/core/ingestion/process-processor.js +2 -1
  34. package/dist/core/ingestion/resolvers/csharp.d.ts +22 -0
  35. package/dist/core/ingestion/resolvers/csharp.js +109 -0
  36. package/dist/core/ingestion/resolvers/go.d.ts +19 -0
  37. package/dist/core/ingestion/resolvers/go.js +42 -0
  38. package/dist/core/ingestion/resolvers/index.d.ts +16 -0
  39. package/dist/core/ingestion/resolvers/index.js +11 -0
  40. package/dist/core/ingestion/resolvers/jvm.d.ts +23 -0
  41. package/dist/core/ingestion/resolvers/jvm.js +87 -0
  42. package/dist/core/ingestion/resolvers/php.d.ts +15 -0
  43. package/dist/core/ingestion/resolvers/php.js +35 -0
  44. package/dist/core/ingestion/resolvers/rust.d.ts +15 -0
  45. package/dist/core/ingestion/resolvers/rust.js +73 -0
  46. package/dist/core/ingestion/resolvers/standard.d.ts +28 -0
  47. package/dist/core/ingestion/resolvers/standard.js +145 -0
  48. package/dist/core/ingestion/resolvers/utils.d.ts +33 -0
  49. package/dist/core/ingestion/resolvers/utils.js +120 -0
  50. package/dist/core/ingestion/symbol-resolver.d.ts +32 -0
  51. package/dist/core/ingestion/symbol-resolver.js +83 -0
  52. package/dist/core/ingestion/symbol-table.d.ts +12 -1
  53. package/dist/core/ingestion/symbol-table.js +19 -12
  54. package/dist/core/ingestion/tree-sitter-queries.d.ts +11 -11
  55. package/dist/core/ingestion/tree-sitter-queries.js +114 -9
  56. package/dist/core/ingestion/type-env.d.ts +27 -0
  57. package/dist/core/ingestion/type-env.js +86 -0
  58. package/dist/core/ingestion/type-extractors/c-cpp.d.ts +2 -0
  59. package/dist/core/ingestion/type-extractors/c-cpp.js +60 -0
  60. package/dist/core/ingestion/type-extractors/csharp.d.ts +2 -0
  61. package/dist/core/ingestion/type-extractors/csharp.js +89 -0
  62. package/dist/core/ingestion/type-extractors/go.d.ts +2 -0
  63. package/dist/core/ingestion/type-extractors/go.js +105 -0
  64. package/dist/core/ingestion/type-extractors/index.d.ts +21 -0
  65. package/dist/core/ingestion/type-extractors/index.js +29 -0
  66. package/dist/core/ingestion/type-extractors/jvm.d.ts +3 -0
  67. package/dist/core/ingestion/type-extractors/jvm.js +121 -0
  68. package/dist/core/ingestion/type-extractors/php.d.ts +2 -0
  69. package/dist/core/ingestion/type-extractors/php.js +31 -0
  70. package/dist/core/ingestion/type-extractors/python.d.ts +2 -0
  71. package/dist/core/ingestion/type-extractors/python.js +41 -0
  72. package/dist/core/ingestion/type-extractors/rust.d.ts +2 -0
  73. package/dist/core/ingestion/type-extractors/rust.js +39 -0
  74. package/dist/core/ingestion/type-extractors/shared.d.ts +17 -0
  75. package/dist/core/ingestion/type-extractors/shared.js +97 -0
  76. package/dist/core/ingestion/type-extractors/swift.d.ts +2 -0
  77. package/dist/core/ingestion/type-extractors/swift.js +43 -0
  78. package/dist/core/ingestion/type-extractors/types.d.ts +14 -0
  79. package/dist/core/ingestion/type-extractors/types.js +1 -0
  80. package/dist/core/ingestion/type-extractors/typescript.d.ts +2 -0
  81. package/dist/core/ingestion/type-extractors/typescript.js +46 -0
  82. package/dist/core/ingestion/utils.d.ts +67 -0
  83. package/dist/core/ingestion/utils.js +691 -4
  84. package/dist/core/ingestion/workers/parse-worker.d.ts +20 -3
  85. package/dist/core/ingestion/workers/parse-worker.js +84 -345
  86. package/dist/core/kuzu/csv-generator.js +19 -3
  87. package/dist/core/kuzu/kuzu-adapter.js +3 -0
  88. package/dist/core/kuzu/schema.d.ts +3 -3
  89. package/dist/core/kuzu/schema.js +16 -1
  90. package/dist/mcp/tools.js +12 -3
  91. package/package.json +1 -1
@@ -10,6 +10,7 @@
10
10
  * This module is language-agnostic - language-specific patterns are defined per language.
11
11
  */
12
12
  import { detectFrameworkFromPath } from './framework-detection.js';
13
+ import { SupportedLanguages } from '../../config/supported-languages.js';
13
14
  // ============================================================================
14
15
  // NAME PATTERNS - All 9 supported languages
15
16
  // ============================================================================
@@ -34,65 +35,112 @@ const ENTRY_POINT_PATTERNS = {
34
35
  /^emit[A-Z]/, // emitEvent
35
36
  ],
36
37
  // JavaScript/TypeScript
37
- 'javascript': [
38
+ [SupportedLanguages.JavaScript]: [
38
39
  /^use[A-Z]/, // React hooks (useEffect, etc.)
39
40
  ],
40
- 'typescript': [
41
+ [SupportedLanguages.TypeScript]: [
41
42
  /^use[A-Z]/, // React hooks
42
43
  ],
43
44
  // Python
44
- 'python': [
45
+ [SupportedLanguages.Python]: [
45
46
  /^app$/, // Flask/FastAPI app
46
47
  /^(get|post|put|delete|patch)_/i, // REST conventions
47
48
  /^api_/, // API functions
48
49
  /^view_/, // Django views
49
50
  ],
50
51
  // Java
51
- 'java': [
52
+ [SupportedLanguages.Java]: [
52
53
  /^do[A-Z]/, // doGet, doPost (Servlets)
53
54
  /^create[A-Z]/, // Factory patterns
54
55
  /^build[A-Z]/, // Builder patterns
55
56
  /Service$/, // UserService
56
57
  ],
57
58
  // C#
58
- 'csharp': [
59
- /^(Get|Post|Put|Delete)/, // ASP.NET conventions
59
+ [SupportedLanguages.CSharp]: [
60
+ /^(Get|Post|Put|Delete|Patch)/, // ASP.NET action methods
60
61
  /Action$/, // MVC actions
61
- /^On[A-Z]/, // Event handlers
62
+ /^On[A-Z]/, // Event handlers / Blazor lifecycle
62
63
  /Async$/, // Async entry points
64
+ /^Configure$/, // Startup.Configure
65
+ /^ConfigureServices$/, // Startup.ConfigureServices
66
+ /^Handle$/, // MediatR / generic handler
67
+ /^Execute$/, // Command pattern
68
+ /^Invoke$/, // Middleware Invoke
69
+ /^Map[A-Z]/, // Minimal API MapGet, MapPost
70
+ /Service$/, // Service classes
71
+ /^Seed/, // Database seeding
63
72
  ],
64
73
  // Go
65
- 'go': [
74
+ [SupportedLanguages.Go]: [
66
75
  /Handler$/, // http.Handler pattern
67
76
  /^Serve/, // ServeHTTP
68
77
  /^New[A-Z]/, // Constructor pattern (returns new instance)
69
78
  /^Make[A-Z]/, // Make functions
70
79
  ],
71
80
  // Rust
72
- 'rust': [
81
+ [SupportedLanguages.Rust]: [
73
82
  /^(get|post|put|delete)_handler$/i,
74
83
  /^handle_/, // handle_request
75
84
  /^new$/, // Constructor pattern
76
85
  /^run$/, // run entry point
77
86
  /^spawn/, // Async spawn
78
87
  ],
79
- // C - explicit main() boost (critical for C programs)
80
- 'c': [
88
+ // C - explicit main() boost plus common C entry point conventions
89
+ [SupportedLanguages.C]: [
81
90
  /^main$/, // THE entry point
82
- /^init_/, // Initialization functions
83
- /^start_/, // Start functions
84
- /^run_/, // Run functions
91
+ /^init_/, // init_server, init_client
92
+ /_init$/, // module_init, server_init
93
+ /^start_/, // start_server
94
+ /_start$/, // thread_start
95
+ /^run_/, // run_loop
96
+ /_run$/, // event_run
97
+ /^stop_/, // stop_server
98
+ /_stop$/, // service_stop
99
+ /^open_/, // open_connection
100
+ /_open$/, // file_open
101
+ /^close_/, // close_connection
102
+ /_close$/, // socket_close
103
+ /^create_/, // create_session
104
+ /_create$/, // object_create
105
+ /^destroy_/, // destroy_session
106
+ /_destroy$/, // object_destroy
107
+ /^handle_/, // handle_request
108
+ /_handler$/, // signal_handler
109
+ /_callback$/, // event_callback
110
+ /^cmd_/, // tmux: cmd_new_window, cmd_attach_session
111
+ /^server_/, // server_start, server_loop
112
+ /^client_/, // client_connect
113
+ /^session_/, // session_create
114
+ /^window_/, // window_resize (tmux)
115
+ /^key_/, // key_press
116
+ /^input_/, // input_parse
117
+ /^output_/, // output_write
118
+ /^notify_/, // notify_client
119
+ /^control_/, // control_start
85
120
  ],
86
- // C++ - same as C plus class patterns
87
- 'cpp': [
121
+ // C++ - same as C plus OOP/template patterns
122
+ [SupportedLanguages.CPlusPlus]: [
88
123
  /^main$/, // THE entry point
89
124
  /^init_/,
125
+ /_init$/,
90
126
  /^Create[A-Z]/, // Factory patterns
127
+ /^create_/,
91
128
  /^Run$/, // Run methods
129
+ /^run$/,
92
130
  /^Start$/, // Start methods
131
+ /^start$/,
132
+ /^handle_/,
133
+ /_handler$/,
134
+ /_callback$/,
135
+ /^OnEvent/, // Event callbacks
136
+ /^on_/,
137
+ /::Run$/, // Class::Run
138
+ /::Start$/, // Class::Start
139
+ /::Init$/, // Class::Init
140
+ /::Execute$/, // Class::Execute
93
141
  ],
94
142
  // Swift / iOS
95
- 'swift': [
143
+ [SupportedLanguages.Swift]: [
96
144
  /^viewDidLoad$/, // UIKit lifecycle
97
145
  /^viewWillAppear$/, // UIKit lifecycle
98
146
  /^viewDidAppear$/, // UIKit lifecycle
@@ -111,7 +159,7 @@ const ENTRY_POINT_PATTERNS = {
111
159
  /^makeBody$/, // SwiftUI ViewModifier
112
160
  ],
113
161
  // PHP / Laravel
114
- 'php': [
162
+ [SupportedLanguages.PHP]: [
115
163
  /Controller$/, // UserController (class name convention)
116
164
  /^handle$/, // Job::handle(), Listener::handle()
117
165
  /^execute$/, // Command::execute()
@@ -131,6 +179,14 @@ const ENTRY_POINT_PATTERNS = {
131
179
  /^delete$/, // Repository::delete()
132
180
  ],
133
181
  };
182
+ /** Pre-computed merged patterns (universal + language-specific) to avoid per-call array allocation. */
183
+ const MERGED_ENTRY_POINT_PATTERNS = {};
184
+ const UNIVERSAL_PATTERNS = ENTRY_POINT_PATTERNS['*'] || [];
185
+ for (const [lang, patterns] of Object.entries(ENTRY_POINT_PATTERNS)) {
186
+ if (lang === '*')
187
+ continue;
188
+ MERGED_ENTRY_POINT_PATTERNS[lang] = [...UNIVERSAL_PATTERNS, ...patterns];
189
+ }
134
190
  // ============================================================================
135
191
  // UTILITY PATTERNS - Functions that should be penalized
136
192
  // ============================================================================
@@ -196,9 +252,7 @@ export function calculateEntryPointScore(name, language, isExported, callerCount
196
252
  }
197
253
  else {
198
254
  // Check positive patterns
199
- const universalPatterns = ENTRY_POINT_PATTERNS['*'] || [];
200
- const langPatterns = ENTRY_POINT_PATTERNS[language] || [];
201
- const allPatterns = [...universalPatterns, ...langPatterns];
255
+ const allPatterns = MERGED_ENTRY_POINT_PATTERNS[language] || UNIVERSAL_PATTERNS;
202
256
  if (allPatterns.some(p => p.test(name))) {
203
257
  nameMultiplier = 1.5; // Bonus for matching entry point pattern
204
258
  reasons.push('entry-pattern');
@@ -253,8 +307,13 @@ export function isTestFile(filePath) {
253
307
  p.endsWith('test.swift') ||
254
308
  p.includes('uitests/') ||
255
309
  // C# test patterns
310
+ p.endsWith('tests.cs') ||
311
+ p.endsWith('test.cs') ||
256
312
  p.includes('.tests/') ||
257
- p.includes('tests.cs') ||
313
+ p.includes('.test/') ||
314
+ p.includes('.integrationtests/') ||
315
+ p.includes('.unittests/') ||
316
+ p.includes('/testproject/') ||
258
317
  // PHP/Laravel test patterns
259
318
  p.endsWith('test.php') ||
260
319
  p.endsWith('spec.php') ||
@@ -0,0 +1,18 @@
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 { SyntaxNode } from './utils.js';
10
+ import { SupportedLanguages } from '../../config/supported-languages.js';
11
+ /**
12
+ * Check if a tree-sitter node is exported/public in its language.
13
+ * @param node - The tree-sitter AST node
14
+ * @param name - The symbol name
15
+ * @param language - The programming language
16
+ * @returns true if the symbol is exported/public
17
+ */
18
+ export declare const isNodeExported: (node: SyntaxNode, name: string, language: SupportedLanguages) => boolean;
@@ -0,0 +1,230 @@
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
+ };
@@ -33,6 +33,9 @@ export declare const FRAMEWORK_AST_PATTERNS: {
33
33
  spring: string[];
34
34
  jaxrs: string[];
35
35
  aspnet: string[];
36
+ signalr: string[];
37
+ blazor: string[];
38
+ efcore: string[];
36
39
  'go-http': string[];
37
40
  laravel: string[];
38
41
  actix: string[];
@@ -42,9 +45,10 @@ export declare const FRAMEWORK_AST_PATTERNS: {
42
45
  swiftui: string[];
43
46
  combine: string[];
44
47
  };
48
+ import { SupportedLanguages } from '../../config/supported-languages.js';
45
49
  /**
46
50
  * Detect framework entry points from AST definition text (decorators/annotations/attributes).
47
51
  * Returns null if no known pattern is found.
48
52
  * Note: callers should slice definitionText to ~300 chars since annotations appear at the start.
49
53
  */
50
- export declare function detectFrameworkFromAST(language: string, definitionText: string): FrameworkHint | null;
54
+ export declare function detectFrameworkFromAST(language: SupportedLanguages, definitionText: string): FrameworkHint | null;
@@ -140,6 +140,29 @@ export function detectFrameworkFromPath(filePath) {
140
140
  if (p.endsWith('controller.cs')) {
141
141
  return { framework: 'aspnet', entryPointMultiplier: 3.0, reason: 'aspnet-controller-file' };
142
142
  }
143
+ // ASP.NET Services
144
+ if ((p.includes('/services/') || p.includes('/service/')) && p.endsWith('.cs')) {
145
+ return { framework: 'aspnet', entryPointMultiplier: 1.8, reason: 'aspnet-service' };
146
+ }
147
+ // ASP.NET Middleware
148
+ if (p.includes('/middleware/') && p.endsWith('.cs')) {
149
+ return { framework: 'aspnet', entryPointMultiplier: 2.5, reason: 'aspnet-middleware' };
150
+ }
151
+ // SignalR Hubs
152
+ if (p.includes('/hubs/') && p.endsWith('.cs')) {
153
+ return { framework: 'signalr', entryPointMultiplier: 2.5, reason: 'signalr-hub' };
154
+ }
155
+ if (p.endsWith('hub.cs')) {
156
+ return { framework: 'signalr', entryPointMultiplier: 2.5, reason: 'signalr-hub-file' };
157
+ }
158
+ // Minimal API / Program.cs / Startup.cs
159
+ if (p.endsWith('/program.cs') || p.endsWith('/startup.cs')) {
160
+ return { framework: 'aspnet', entryPointMultiplier: 3.0, reason: 'aspnet-entry' };
161
+ }
162
+ // Background services / Hosted services
163
+ if ((p.includes('/backgroundservices/') || p.includes('/hostedservices/')) && p.endsWith('.cs')) {
164
+ return { framework: 'aspnet', entryPointMultiplier: 2.0, reason: 'aspnet-background-service' };
165
+ }
143
166
  // Blazor pages
144
167
  if (p.includes('/pages/') && p.endsWith('.razor')) {
145
168
  return { framework: 'blazor', entryPointMultiplier: 2.5, reason: 'blazor-page' };
@@ -296,7 +319,11 @@ export const FRAMEWORK_AST_PATTERNS = {
296
319
  'spring': ['@RestController', '@Controller', '@GetMapping', '@PostMapping', '@RequestMapping'],
297
320
  'jaxrs': ['@Path', '@GET', '@POST', '@PUT', '@DELETE'],
298
321
  // C# attributes
299
- 'aspnet': ['[ApiController]', '[HttpGet]', '[HttpPost]', '[Route]'],
322
+ 'aspnet': ['[ApiController]', '[HttpGet]', '[HttpPost]', '[HttpPut]', '[HttpDelete]',
323
+ '[Route]', '[Authorize]', '[AllowAnonymous]'],
324
+ 'signalr': ['[HubMethodName]', ': Hub', ': Hub<'],
325
+ 'blazor': ['@page', '[Parameter]', '@inject'],
326
+ 'efcore': ['DbContext', 'DbSet<', 'OnModelCreating'],
300
327
  // Go patterns (function signatures)
301
328
  'go-http': ['http.Handler', 'http.HandlerFunc', 'ServeHTTP'],
302
329
  // PHP/Laravel
@@ -311,31 +338,35 @@ export const FRAMEWORK_AST_PATTERNS = {
311
338
  'swiftui': ['@main', 'WindowGroup', 'ContentView', '@StateObject', '@ObservedObject'],
312
339
  'combine': ['sink', 'assign', 'Publisher', 'Subscriber'],
313
340
  };
341
+ import { SupportedLanguages } from '../../config/supported-languages.js';
314
342
  const AST_FRAMEWORK_PATTERNS_BY_LANGUAGE = {
315
- javascript: [
343
+ [SupportedLanguages.JavaScript]: [
316
344
  { framework: 'nestjs', entryPointMultiplier: 3.2, reason: 'nestjs-decorator', patterns: FRAMEWORK_AST_PATTERNS.nestjs },
317
345
  ],
318
- typescript: [
346
+ [SupportedLanguages.TypeScript]: [
319
347
  { framework: 'nestjs', entryPointMultiplier: 3.2, reason: 'nestjs-decorator', patterns: FRAMEWORK_AST_PATTERNS.nestjs },
320
348
  ],
321
- python: [
349
+ [SupportedLanguages.Python]: [
322
350
  { framework: 'fastapi', entryPointMultiplier: 3.0, reason: 'fastapi-decorator', patterns: FRAMEWORK_AST_PATTERNS.fastapi },
323
351
  { framework: 'flask', entryPointMultiplier: 2.8, reason: 'flask-decorator', patterns: FRAMEWORK_AST_PATTERNS.flask },
324
352
  ],
325
- java: [
353
+ [SupportedLanguages.Java]: [
326
354
  { framework: 'spring', entryPointMultiplier: 3.2, reason: 'spring-annotation', patterns: FRAMEWORK_AST_PATTERNS.spring },
327
355
  { framework: 'jaxrs', entryPointMultiplier: 3.0, reason: 'jaxrs-annotation', patterns: FRAMEWORK_AST_PATTERNS.jaxrs },
328
356
  ],
329
- kotlin: [
357
+ [SupportedLanguages.Kotlin]: [
330
358
  { framework: 'spring-kotlin', entryPointMultiplier: 3.2, reason: 'spring-kotlin-annotation', patterns: FRAMEWORK_AST_PATTERNS.spring },
331
359
  { framework: 'jaxrs', entryPointMultiplier: 3.0, reason: 'jaxrs-annotation', patterns: FRAMEWORK_AST_PATTERNS.jaxrs },
332
360
  { framework: 'ktor', entryPointMultiplier: 2.8, reason: 'ktor-routing', patterns: ['routing', 'embeddedServer', 'Application.module'] },
333
361
  { framework: 'android-kotlin', entryPointMultiplier: 2.5, reason: 'android-annotation', patterns: ['@AndroidEntryPoint', 'AppCompatActivity', 'Fragment('] },
334
362
  ],
335
- csharp: [
363
+ [SupportedLanguages.CSharp]: [
336
364
  { framework: 'aspnet', entryPointMultiplier: 3.2, reason: 'aspnet-attribute', patterns: FRAMEWORK_AST_PATTERNS.aspnet },
365
+ { framework: 'signalr', entryPointMultiplier: 2.8, reason: 'signalr-attribute', patterns: FRAMEWORK_AST_PATTERNS.signalr },
366
+ { framework: 'blazor', entryPointMultiplier: 2.5, reason: 'blazor-attribute', patterns: FRAMEWORK_AST_PATTERNS.blazor },
367
+ { framework: 'efcore', entryPointMultiplier: 2.0, reason: 'efcore-pattern', patterns: FRAMEWORK_AST_PATTERNS.efcore },
337
368
  ],
338
- php: [
369
+ [SupportedLanguages.PHP]: [
339
370
  { framework: 'laravel', entryPointMultiplier: 3.0, reason: 'php-route-attribute', patterns: FRAMEWORK_AST_PATTERNS.laravel },
340
371
  ],
341
372
  };
@@ -2,19 +2,28 @@
2
2
  * Heritage Processor
3
3
  *
4
4
  * Extracts class inheritance relationships:
5
- * - EXTENDS: Class extends another Class (TS, JS, Python)
6
- * - IMPLEMENTS: Class implements an Interface (TS only)
5
+ * - EXTENDS: Class extends another Class (TS, JS, Python, C#, C++)
6
+ * - IMPLEMENTS: Class implements an Interface (TS, C#, Java, Kotlin, PHP)
7
+ *
8
+ * Languages like C# use a single `base_list` for both class and interface parents.
9
+ * We resolve the correct edge type by checking the symbol table: if the parent is
10
+ * registered as an Interface, we emit IMPLEMENTS; otherwise EXTENDS. For unresolved
11
+ * external symbols, the fallback heuristic is language-gated:
12
+ * - C# / Java: apply the `I[A-Z]` naming convention (e.g. IDisposable → IMPLEMENTS)
13
+ * - Swift: default to IMPLEMENTS (protocol conformance is more common than class inheritance)
14
+ * - All other languages: default to EXTENDS
7
15
  */
8
16
  import { KnowledgeGraph } from '../graph/types.js';
9
17
  import { ASTCache } from './ast-cache.js';
10
18
  import { SymbolTable } from './symbol-table.js';
11
19
  import type { ExtractedHeritage } from './workers/parse-worker.js';
20
+ import type { ImportMap, PackageMap } from './import-processor.js';
12
21
  export declare const processHeritage: (graph: KnowledgeGraph, files: {
13
22
  path: string;
14
23
  content: string;
15
- }[], astCache: ASTCache, symbolTable: SymbolTable, onProgress?: (current: number, total: number) => void) => Promise<void>;
24
+ }[], astCache: ASTCache, symbolTable: SymbolTable, importMap: ImportMap, packageMap?: PackageMap, onProgress?: (current: number, total: number) => void) => Promise<void>;
16
25
  /**
17
26
  * Fast path: resolve pre-extracted heritage from workers.
18
27
  * No AST parsing — workers already extracted className + parentName + kind.
19
28
  */
20
- export declare const processHeritageFromExtracted: (graph: KnowledgeGraph, extractedHeritage: ExtractedHeritage[], symbolTable: SymbolTable, onProgress?: (current: number, total: number) => void) => Promise<void>;
29
+ export declare const processHeritageFromExtracted: (graph: KnowledgeGraph, extractedHeritage: ExtractedHeritage[], symbolTable: SymbolTable, importMap: ImportMap, packageMap?: PackageMap, onProgress?: (current: number, total: number) => void) => Promise<void>;