gitnexus 1.4.8 → 1.4.10
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 +7 -0
- package/dist/cli/index-repo.d.ts +15 -0
- package/dist/cli/index-repo.js +115 -0
- package/dist/cli/index.js +11 -2
- package/dist/cli/setup.js +12 -9
- package/dist/cli/wiki.d.ts +4 -0
- package/dist/cli/wiki.js +174 -53
- package/dist/config/supported-languages.d.ts +7 -5
- package/dist/config/supported-languages.js +6 -4
- package/dist/core/graph/graph.js +9 -1
- package/dist/core/graph/types.d.ts +10 -2
- package/dist/core/ingestion/call-processor.d.ts +18 -1
- package/dist/core/ingestion/call-processor.js +297 -38
- package/dist/core/ingestion/call-routing.d.ts +3 -18
- package/dist/core/ingestion/call-routing.js +0 -19
- package/dist/core/ingestion/cobol/cobol-copy-expander.d.ts +57 -0
- package/dist/core/ingestion/cobol/cobol-copy-expander.js +385 -0
- package/dist/core/ingestion/cobol/cobol-preprocessor.d.ts +210 -0
- package/dist/core/ingestion/cobol/cobol-preprocessor.js +1509 -0
- package/dist/core/ingestion/cobol/jcl-parser.d.ts +68 -0
- package/dist/core/ingestion/cobol/jcl-parser.js +217 -0
- package/dist/core/ingestion/cobol/jcl-processor.d.ts +33 -0
- package/dist/core/ingestion/cobol/jcl-processor.js +229 -0
- package/dist/core/ingestion/cobol-processor.d.ts +54 -0
- package/dist/core/ingestion/cobol-processor.js +1186 -0
- package/dist/core/ingestion/entry-point-scoring.d.ts +17 -0
- package/dist/core/ingestion/entry-point-scoring.js +18 -4
- package/dist/core/ingestion/export-detection.d.ts +47 -8
- package/dist/core/ingestion/export-detection.js +29 -50
- package/dist/core/ingestion/field-extractor.d.ts +29 -0
- package/dist/core/ingestion/field-extractor.js +25 -0
- package/dist/core/ingestion/field-extractors/configs/c-cpp.d.ts +3 -0
- package/dist/core/ingestion/field-extractors/configs/c-cpp.js +108 -0
- package/dist/core/ingestion/field-extractors/configs/csharp.d.ts +8 -0
- package/dist/core/ingestion/field-extractors/configs/csharp.js +73 -0
- package/dist/core/ingestion/field-extractors/configs/dart.d.ts +8 -0
- package/dist/core/ingestion/field-extractors/configs/dart.js +76 -0
- package/dist/core/ingestion/field-extractors/configs/go.d.ts +11 -0
- package/dist/core/ingestion/field-extractors/configs/go.js +64 -0
- package/dist/core/ingestion/field-extractors/configs/helpers.d.ts +44 -0
- package/dist/core/ingestion/field-extractors/configs/helpers.js +134 -0
- package/dist/core/ingestion/field-extractors/configs/jvm.d.ts +3 -0
- package/dist/core/ingestion/field-extractors/configs/jvm.js +118 -0
- package/dist/core/ingestion/field-extractors/configs/php.d.ts +8 -0
- package/dist/core/ingestion/field-extractors/configs/php.js +67 -0
- package/dist/core/ingestion/field-extractors/configs/python.d.ts +12 -0
- package/dist/core/ingestion/field-extractors/configs/python.js +91 -0
- package/dist/core/ingestion/field-extractors/configs/ruby.d.ts +16 -0
- package/dist/core/ingestion/field-extractors/configs/ruby.js +75 -0
- package/dist/core/ingestion/field-extractors/configs/rust.d.ts +9 -0
- package/dist/core/ingestion/field-extractors/configs/rust.js +55 -0
- package/dist/core/ingestion/field-extractors/configs/swift.d.ts +8 -0
- package/dist/core/ingestion/field-extractors/configs/swift.js +63 -0
- package/dist/core/ingestion/field-extractors/configs/typescript-javascript.d.ts +3 -0
- package/dist/core/ingestion/field-extractors/configs/typescript-javascript.js +60 -0
- package/dist/core/ingestion/field-extractors/generic.d.ts +46 -0
- package/dist/core/ingestion/field-extractors/generic.js +111 -0
- package/dist/core/ingestion/field-extractors/typescript.d.ts +77 -0
- package/dist/core/ingestion/field-extractors/typescript.js +291 -0
- package/dist/core/ingestion/field-types.d.ts +59 -0
- package/dist/core/ingestion/field-types.js +2 -0
- package/dist/core/ingestion/framework-detection.d.ts +87 -0
- package/dist/core/ingestion/framework-detection.js +65 -2
- package/dist/core/ingestion/heritage-processor.js +15 -17
- package/dist/core/ingestion/import-processor.d.ts +9 -10
- package/dist/core/ingestion/import-processor.js +59 -14
- package/dist/core/ingestion/{resolvers → import-resolvers}/csharp.d.ts +6 -9
- package/dist/core/ingestion/{resolvers → import-resolvers}/csharp.js +20 -2
- package/dist/core/ingestion/import-resolvers/dart.d.ts +7 -0
- package/dist/core/ingestion/import-resolvers/dart.js +44 -0
- package/dist/core/ingestion/{resolvers → import-resolvers}/go.d.ts +4 -5
- package/dist/core/ingestion/{resolvers → import-resolvers}/go.js +17 -0
- package/dist/core/ingestion/{resolvers → import-resolvers}/jvm.d.ts +9 -1
- package/dist/core/ingestion/{resolvers → import-resolvers}/jvm.js +56 -0
- package/dist/core/ingestion/{resolvers → import-resolvers}/php.d.ts +6 -10
- package/dist/core/ingestion/{resolvers → import-resolvers}/php.js +7 -2
- package/dist/core/ingestion/{resolvers → import-resolvers}/python.d.ts +9 -3
- package/dist/core/ingestion/{resolvers → import-resolvers}/python.js +35 -3
- package/dist/core/ingestion/{resolvers → import-resolvers}/ruby.d.ts +5 -2
- package/dist/core/ingestion/{resolvers → import-resolvers}/ruby.js +7 -2
- package/dist/core/ingestion/{resolvers → import-resolvers}/rust.d.ts +5 -2
- package/dist/core/ingestion/{resolvers → import-resolvers}/rust.js +41 -2
- package/dist/core/ingestion/{resolvers → import-resolvers}/standard.d.ts +15 -7
- package/dist/core/ingestion/{resolvers → import-resolvers}/standard.js +22 -3
- package/dist/core/ingestion/import-resolvers/swift.d.ts +7 -0
- package/dist/core/ingestion/import-resolvers/swift.js +23 -0
- package/dist/core/ingestion/import-resolvers/types.d.ts +44 -0
- package/dist/core/ingestion/import-resolvers/types.js +6 -0
- package/dist/core/ingestion/{resolvers → import-resolvers}/utils.d.ts +0 -3
- package/dist/core/ingestion/{resolvers → import-resolvers}/utils.js +0 -9
- package/dist/core/ingestion/language-config.d.ts +4 -1
- package/dist/core/ingestion/language-provider.d.ts +121 -0
- package/dist/core/ingestion/language-provider.js +24 -0
- package/dist/core/ingestion/languages/c-cpp.d.ts +12 -0
- package/dist/core/ingestion/languages/c-cpp.js +71 -0
- package/dist/core/ingestion/languages/cobol.d.ts +1 -0
- package/dist/core/ingestion/languages/cobol.js +26 -0
- package/dist/core/ingestion/languages/csharp.d.ts +8 -0
- package/dist/core/ingestion/languages/csharp.js +49 -0
- package/dist/core/ingestion/languages/dart.d.ts +12 -0
- package/dist/core/ingestion/languages/dart.js +58 -0
- package/dist/core/ingestion/languages/go.d.ts +11 -0
- package/dist/core/ingestion/languages/go.js +28 -0
- package/dist/core/ingestion/languages/index.d.ts +38 -0
- package/dist/core/ingestion/languages/index.js +63 -0
- package/dist/core/ingestion/languages/java.d.ts +9 -0
- package/dist/core/ingestion/languages/java.js +29 -0
- package/dist/core/ingestion/languages/kotlin.d.ts +9 -0
- package/dist/core/ingestion/languages/kotlin.js +53 -0
- package/dist/core/ingestion/languages/php.d.ts +8 -0
- package/dist/core/ingestion/languages/php.js +145 -0
- package/dist/core/ingestion/languages/python.d.ts +12 -0
- package/dist/core/ingestion/languages/python.js +39 -0
- package/dist/core/ingestion/languages/ruby.d.ts +9 -0
- package/dist/core/ingestion/languages/ruby.js +44 -0
- package/dist/core/ingestion/languages/rust.d.ts +12 -0
- package/dist/core/ingestion/languages/rust.js +44 -0
- package/dist/core/ingestion/languages/swift.d.ts +12 -0
- package/dist/core/ingestion/languages/swift.js +133 -0
- package/dist/core/ingestion/languages/typescript.d.ts +10 -0
- package/dist/core/ingestion/languages/typescript.js +60 -0
- package/dist/core/ingestion/mro-processor.js +14 -15
- package/dist/core/ingestion/{named-binding-extraction.d.ts → named-binding-processor.d.ts} +0 -9
- package/dist/core/ingestion/named-binding-processor.js +42 -0
- package/dist/core/ingestion/named-bindings/csharp.d.ts +3 -0
- package/dist/core/ingestion/named-bindings/csharp.js +37 -0
- package/dist/core/ingestion/named-bindings/java.d.ts +3 -0
- package/dist/core/ingestion/named-bindings/java.js +29 -0
- package/dist/core/ingestion/named-bindings/kotlin.d.ts +3 -0
- package/dist/core/ingestion/named-bindings/kotlin.js +36 -0
- package/dist/core/ingestion/named-bindings/php.d.ts +3 -0
- package/dist/core/ingestion/named-bindings/php.js +61 -0
- package/dist/core/ingestion/named-bindings/python.d.ts +3 -0
- package/dist/core/ingestion/named-bindings/python.js +49 -0
- package/dist/core/ingestion/named-bindings/rust.d.ts +3 -0
- package/dist/core/ingestion/named-bindings/rust.js +64 -0
- package/dist/core/ingestion/named-bindings/types.d.ts +16 -0
- package/dist/core/ingestion/named-bindings/types.js +6 -0
- package/dist/core/ingestion/named-bindings/typescript.d.ts +3 -0
- package/dist/core/ingestion/named-bindings/typescript.js +58 -0
- package/dist/core/ingestion/parsing-processor.d.ts +5 -1
- package/dist/core/ingestion/parsing-processor.js +115 -16
- package/dist/core/ingestion/pipeline.js +925 -424
- package/dist/core/ingestion/resolution-context.js +1 -1
- package/dist/core/ingestion/route-extractors/expo.d.ts +1 -0
- package/dist/core/ingestion/route-extractors/expo.js +36 -0
- package/dist/core/ingestion/route-extractors/middleware.d.ts +47 -0
- package/dist/core/ingestion/route-extractors/middleware.js +143 -0
- package/dist/core/ingestion/route-extractors/nextjs.d.ts +3 -0
- package/dist/core/ingestion/route-extractors/nextjs.js +76 -0
- package/dist/core/ingestion/route-extractors/php.d.ts +7 -0
- package/dist/core/ingestion/route-extractors/php.js +21 -0
- package/dist/core/ingestion/route-extractors/response-shapes.d.ts +20 -0
- package/dist/core/ingestion/route-extractors/response-shapes.js +290 -0
- package/dist/core/ingestion/tree-sitter-queries.d.ts +8 -7
- package/dist/core/ingestion/tree-sitter-queries.js +231 -9
- package/dist/core/ingestion/type-env.d.ts +14 -17
- package/dist/core/ingestion/type-env.js +66 -14
- package/dist/core/ingestion/type-extractors/c-cpp.d.ts +1 -1
- package/dist/core/ingestion/type-extractors/csharp.js +1 -1
- package/dist/core/ingestion/type-extractors/dart.d.ts +15 -0
- package/dist/core/ingestion/type-extractors/dart.js +371 -0
- package/dist/core/ingestion/type-extractors/jvm.js +1 -1
- package/dist/core/ingestion/type-extractors/shared.d.ts +1 -13
- package/dist/core/ingestion/type-extractors/shared.js +9 -102
- package/dist/core/ingestion/type-extractors/swift.js +334 -4
- package/dist/core/ingestion/type-extractors/types.d.ts +3 -1
- package/dist/core/ingestion/{ast-helpers.d.ts → utils/ast-helpers.d.ts} +16 -13
- package/dist/core/ingestion/{ast-helpers.js → utils/ast-helpers.js} +111 -32
- package/dist/core/ingestion/{call-analysis.js → utils/call-analysis.js} +37 -0
- package/dist/core/ingestion/utils/event-loop.d.ts +5 -0
- package/dist/core/ingestion/utils/event-loop.js +5 -0
- package/dist/core/ingestion/utils/language-detection.d.ts +9 -0
- package/dist/core/ingestion/utils/language-detection.js +70 -0
- package/dist/core/ingestion/utils/verbose.d.ts +1 -0
- package/dist/core/ingestion/utils/verbose.js +7 -0
- package/dist/core/ingestion/workers/parse-worker.d.ts +43 -2
- package/dist/core/ingestion/workers/parse-worker.js +361 -150
- package/dist/core/lbug/csv-generator.js +34 -1
- package/dist/core/lbug/lbug-adapter.js +6 -0
- package/dist/core/lbug/schema.d.ts +5 -3
- package/dist/core/lbug/schema.js +39 -2
- package/dist/core/tree-sitter/parser-loader.js +7 -1
- package/dist/core/wiki/cursor-client.d.ts +31 -0
- package/dist/core/wiki/cursor-client.js +127 -0
- package/dist/core/wiki/generator.d.ts +28 -9
- package/dist/core/wiki/generator.js +115 -18
- package/dist/core/wiki/graph-queries.d.ts +4 -0
- package/dist/core/wiki/graph-queries.js +7 -1
- package/dist/core/wiki/llm-client.d.ts +2 -0
- package/dist/core/wiki/llm-client.js +8 -4
- package/dist/core/wiki/prompts.d.ts +3 -3
- package/dist/core/wiki/prompts.js +6 -0
- package/dist/mcp/core/lbug-adapter.d.ts +5 -0
- package/dist/mcp/core/lbug-adapter.js +11 -1
- package/dist/mcp/local/local-backend.d.ts +16 -5
- package/dist/mcp/local/local-backend.js +711 -74
- package/dist/mcp/tools.js +71 -2
- package/dist/storage/repo-manager.d.ts +3 -0
- package/package.json +14 -14
- package/dist/core/ingestion/import-resolution.d.ts +0 -101
- package/dist/core/ingestion/import-resolution.js +0 -251
- package/dist/core/ingestion/named-binding-extraction.js +0 -373
- package/dist/core/ingestion/resolvers/index.d.ts +0 -18
- package/dist/core/ingestion/resolvers/index.js +0 -13
- package/dist/core/ingestion/type-extractors/index.d.ts +0 -22
- package/dist/core/ingestion/type-extractors/index.js +0 -31
- package/dist/core/ingestion/utils.d.ts +0 -20
- package/dist/core/ingestion/utils.js +0 -242
- package/scripts/patch-tree-sitter-swift.cjs +0 -74
- /package/dist/core/ingestion/{call-analysis.d.ts → utils/call-analysis.d.ts} +0 -0
|
@@ -1,8 +1,12 @@
|
|
|
1
|
-
import { FUNCTION_NODE_TYPES, extractFunctionName, CLASS_CONTAINER_TYPES
|
|
2
|
-
import {
|
|
1
|
+
import { FUNCTION_NODE_TYPES, extractFunctionName, CLASS_CONTAINER_TYPES } from './utils/ast-helpers.js';
|
|
2
|
+
import { CALL_EXPRESSION_TYPES } from './utils/call-analysis.js';
|
|
3
|
+
import { TYPED_PARAMETER_TYPES } from './type-extractors/shared.js';
|
|
4
|
+
import { getProvider } from './languages/index.js';
|
|
3
5
|
import { extractSimpleTypeName, extractVarName, stripNullable, extractReturnTypeName } from './type-extractors/shared.js';
|
|
4
6
|
/** File-level scope key */
|
|
5
7
|
const FILE_SCOPE = '';
|
|
8
|
+
/** Shared empty map for files with no file-scope bindings. */
|
|
9
|
+
const EMPTY_FILE_SCOPE = new Map();
|
|
6
10
|
/** Fallback for languages where class names aren't in a 'name' field (e.g. Kotlin uses type_identifier). */
|
|
7
11
|
const findTypeIdentifierChild = (node) => {
|
|
8
12
|
for (let i = 0; i < node.childCount; i++) {
|
|
@@ -49,7 +53,7 @@ const fastStripNullable = (typeName) => {
|
|
|
49
53
|
: stripNullable(typeName);
|
|
50
54
|
};
|
|
51
55
|
/** Implementation of the lookup logic — shared between TypeEnvironment and the legacy export. */
|
|
52
|
-
const lookupInEnv = (env, varName, callNode, patternOverrides) => {
|
|
56
|
+
const lookupInEnv = (env, varName, callNode, patternOverrides, enclosingFunctionFinder) => {
|
|
53
57
|
// Self/this receiver: resolve to enclosing class name via AST walk
|
|
54
58
|
if (varName === 'self' || varName === 'this' || varName === '$this') {
|
|
55
59
|
return findEnclosingClassName(callNode);
|
|
@@ -60,7 +64,7 @@ const lookupInEnv = (env, varName, callNode, patternOverrides) => {
|
|
|
60
64
|
return findEnclosingParentClassName(callNode);
|
|
61
65
|
}
|
|
62
66
|
// Determine the enclosing function scope for the call
|
|
63
|
-
const scopeKey = findEnclosingScopeKey(callNode);
|
|
67
|
+
const scopeKey = findEnclosingScopeKey(callNode, enclosingFunctionFinder);
|
|
64
68
|
// Check position-indexed pattern overrides first (e.g., Kotlin when/is smart casts).
|
|
65
69
|
// These take priority over flat scopeEnv because they represent per-branch narrowing.
|
|
66
70
|
if (scopeKey && patternOverrides) {
|
|
@@ -88,21 +92,31 @@ const lookupInEnv = (env, varName, callNode, patternOverrides) => {
|
|
|
88
92
|
const raw = fileEnv?.get(varName);
|
|
89
93
|
return raw ? fastStripNullable(raw) : undefined;
|
|
90
94
|
};
|
|
95
|
+
/** Per-file memoization caches for expensive parent-walk functions.
|
|
96
|
+
* Cleared at the start of each buildTypeEnv call (one call per file). */
|
|
97
|
+
const enclosingClassNameCache = new Map();
|
|
98
|
+
const enclosingParentClassNameCache = new Map();
|
|
91
99
|
/**
|
|
92
100
|
* Walk up the AST from a node to find the enclosing class/module name.
|
|
93
101
|
* Used to resolve `self`/`this` receivers to their containing type.
|
|
102
|
+
* Memoized per-file: cache is cleared at buildTypeEnv entry.
|
|
94
103
|
*/
|
|
95
104
|
const findEnclosingClassName = (node) => {
|
|
105
|
+
if (enclosingClassNameCache.has(node))
|
|
106
|
+
return enclosingClassNameCache.get(node);
|
|
96
107
|
let current = node.parent;
|
|
97
108
|
while (current) {
|
|
98
109
|
if (CLASS_CONTAINER_TYPES.has(current.type)) {
|
|
99
110
|
const nameNode = current.childForFieldName('name')
|
|
100
111
|
?? findTypeIdentifierChild(current);
|
|
101
|
-
if (nameNode)
|
|
112
|
+
if (nameNode) {
|
|
113
|
+
enclosingClassNameCache.set(node, nameNode.text);
|
|
102
114
|
return nameNode.text;
|
|
115
|
+
}
|
|
103
116
|
}
|
|
104
117
|
current = current.parent;
|
|
105
118
|
}
|
|
119
|
+
enclosingClassNameCache.set(node, undefined);
|
|
106
120
|
return undefined;
|
|
107
121
|
};
|
|
108
122
|
/** Keywords that refer to the current instance across languages. */
|
|
@@ -138,13 +152,18 @@ const substituteThisReceiver = (item, node) => {
|
|
|
138
152
|
* - Swift: unnamed `inheritance_specifier` child → user_type → type_identifier
|
|
139
153
|
*/
|
|
140
154
|
const findEnclosingParentClassName = (node) => {
|
|
155
|
+
if (enclosingParentClassNameCache.has(node))
|
|
156
|
+
return enclosingParentClassNameCache.get(node);
|
|
141
157
|
let current = node.parent;
|
|
142
158
|
while (current) {
|
|
143
159
|
if (CLASS_CONTAINER_TYPES.has(current.type)) {
|
|
144
|
-
|
|
160
|
+
const result = extractParentClassFromNode(current);
|
|
161
|
+
enclosingParentClassNameCache.set(node, result);
|
|
162
|
+
return result;
|
|
145
163
|
}
|
|
146
164
|
current = current.parent;
|
|
147
165
|
}
|
|
166
|
+
enclosingParentClassNameCache.set(node, undefined);
|
|
148
167
|
return undefined;
|
|
149
168
|
};
|
|
150
169
|
/** Extract the parent/superclass name from a class declaration AST node. */
|
|
@@ -251,8 +270,12 @@ const extractParentClassFromNode = (classNode) => {
|
|
|
251
270
|
}
|
|
252
271
|
return undefined;
|
|
253
272
|
};
|
|
254
|
-
/** Find the enclosing function name for scope lookup.
|
|
255
|
-
|
|
273
|
+
/** Find the enclosing function name for scope lookup.
|
|
274
|
+
* When an `enclosingFunctionFinder` hook is provided (from the language provider),
|
|
275
|
+
* it is consulted for each ancestor before the default FUNCTION_NODE_TYPES check.
|
|
276
|
+
* This handles languages like Dart where the function body is a sibling of the
|
|
277
|
+
* signature instead of a child. */
|
|
278
|
+
const findEnclosingScopeKey = (node, enclosingFunctionFinder) => {
|
|
256
279
|
let current = node.parent;
|
|
257
280
|
while (current) {
|
|
258
281
|
if (FUNCTION_NODE_TYPES.has(current.type)) {
|
|
@@ -260,6 +283,15 @@ const findEnclosingScopeKey = (node) => {
|
|
|
260
283
|
if (funcName)
|
|
261
284
|
return `${funcName}@${current.startIndex}`;
|
|
262
285
|
}
|
|
286
|
+
// Language-specific hook (e.g., Dart function_body → sibling function_signature)
|
|
287
|
+
if (enclosingFunctionFinder) {
|
|
288
|
+
const result = enclosingFunctionFinder(current);
|
|
289
|
+
if (result) {
|
|
290
|
+
const sigNode = current.previousSibling;
|
|
291
|
+
const startIdx = sigNode?.startIndex ?? current.startIndex;
|
|
292
|
+
return `${result.funcName}@${startIdx}`;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
263
295
|
current = current.parent;
|
|
264
296
|
}
|
|
265
297
|
return undefined;
|
|
@@ -530,7 +562,10 @@ const resolveFixpointBindings = (pendingItems, env, returnTypeLookup, symbolTabl
|
|
|
530
562
|
let typeName;
|
|
531
563
|
switch (item.kind) {
|
|
532
564
|
case 'callResult':
|
|
533
|
-
|
|
565
|
+
// Phase 9: Prefer FQN lookup when available for higher precision
|
|
566
|
+
typeName = item.calleeFqn
|
|
567
|
+
? returnTypeLookup.lookupReturnType(item.calleeFqn)
|
|
568
|
+
: returnTypeLookup.lookupReturnType(item.callee);
|
|
534
569
|
break;
|
|
535
570
|
case 'copy':
|
|
536
571
|
typeName = scopeEnv.get(item.rhs) ?? env.get(FILE_SCOPE)?.get(item.rhs);
|
|
@@ -580,6 +615,9 @@ function seedImportedBindings(env, importedBindings) {
|
|
|
580
615
|
}
|
|
581
616
|
}
|
|
582
617
|
export const buildTypeEnv = (tree, language, options) => {
|
|
618
|
+
// Clear per-file memoization caches from the previous file.
|
|
619
|
+
enclosingClassNameCache.clear();
|
|
620
|
+
enclosingParentClassNameCache.clear();
|
|
583
621
|
const symbolTable = options?.symbolTable;
|
|
584
622
|
const parentMap = options?.parentMap;
|
|
585
623
|
const env = new Map();
|
|
@@ -590,7 +628,8 @@ export const buildTypeEnv = (tree, language, options) => {
|
|
|
590
628
|
const constructorTypeMap = new Map();
|
|
591
629
|
const localClassNames = new Set();
|
|
592
630
|
const classNames = createClassNameLookup(localClassNames, symbolTable);
|
|
593
|
-
const
|
|
631
|
+
const provider = getProvider(language);
|
|
632
|
+
const config = provider.typeConfig;
|
|
594
633
|
const bindings = [];
|
|
595
634
|
// Build ReturnTypeLookup: SymbolTable is authoritative when it has an unambiguous match.
|
|
596
635
|
// Cross-file importedReturnTypes are consulted ONLY when SymbolTable has 0 matches.
|
|
@@ -599,7 +638,7 @@ export const buildTypeEnv = (tree, language, options) => {
|
|
|
599
638
|
lookupReturnType(callee) {
|
|
600
639
|
// SymbolTable is authoritative when it has an unambiguous match
|
|
601
640
|
if (symbolTable) {
|
|
602
|
-
if (
|
|
641
|
+
if (provider.isBuiltInName(callee))
|
|
603
642
|
return undefined;
|
|
604
643
|
const callables = symbolTable.lookupFuzzyCallable(callee);
|
|
605
644
|
if (callables.length === 1) {
|
|
@@ -616,7 +655,7 @@ export const buildTypeEnv = (tree, language, options) => {
|
|
|
616
655
|
},
|
|
617
656
|
lookupRawReturnType(callee) {
|
|
618
657
|
if (symbolTable) {
|
|
619
|
-
if (
|
|
658
|
+
if (provider.isBuiltInName(callee))
|
|
620
659
|
return undefined;
|
|
621
660
|
const callables = symbolTable.lookupFuzzyCallable(callee);
|
|
622
661
|
if (callables.length === 1)
|
|
@@ -760,6 +799,18 @@ export const buildTypeEnv = (tree, language, options) => {
|
|
|
760
799
|
}
|
|
761
800
|
}
|
|
762
801
|
}
|
|
802
|
+
// Swift: property_declaration has type_annotation as a direct child (not a 'type' field).
|
|
803
|
+
// Extract the inner type node (array_type, user_type, etc.) for declarationTypeNodes.
|
|
804
|
+
if (!typeNode) {
|
|
805
|
+
for (let i = 0; i < node.namedChildCount; i++) {
|
|
806
|
+
const c = node.namedChild(i);
|
|
807
|
+
if (c?.type === 'type_annotation') {
|
|
808
|
+
// Use the inner type (array_type, user_type) rather than the annotation wrapper
|
|
809
|
+
typeNode = c.firstNamedChild ?? c;
|
|
810
|
+
break;
|
|
811
|
+
}
|
|
812
|
+
}
|
|
813
|
+
}
|
|
763
814
|
}
|
|
764
815
|
if (typeNode) {
|
|
765
816
|
const nameNode = node.childForFieldName('name')
|
|
@@ -982,9 +1033,10 @@ export const buildTypeEnv = (tree, language, options) => {
|
|
|
982
1033
|
}
|
|
983
1034
|
}
|
|
984
1035
|
return {
|
|
985
|
-
lookup: (varName, callNode) => lookupInEnv(env, varName, callNode, patternOverrides),
|
|
1036
|
+
lookup: (varName, callNode) => lookupInEnv(env, varName, callNode, patternOverrides, options?.enclosingFunctionFinder),
|
|
986
1037
|
constructorBindings: bindings,
|
|
987
|
-
env,
|
|
1038
|
+
fileScope: () => env.get(FILE_SCOPE) ?? EMPTY_FILE_SCOPE,
|
|
1039
|
+
allScopes: () => env,
|
|
988
1040
|
constructorTypeMap,
|
|
989
1041
|
};
|
|
990
1042
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { SyntaxNode } from '../utils.js';
|
|
1
|
+
import type { SyntaxNode } from '../utils/ast-helpers.js';
|
|
2
2
|
import type { LanguageTypeConfig } from './types.js';
|
|
3
3
|
/** Extract the first type name from a template_argument_list child.
|
|
4
4
|
* Unwraps type_descriptor wrappers common in tree-sitter-cpp ASTs.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import { findChild } from '../utils/ast-helpers.js';
|
|
1
2
|
import { extractSimpleTypeName, extractVarName, unwrapAwait, resolveIterableElementType, methodToTypeArgPosition, extractElementTypeFromString } from './shared.js';
|
|
2
|
-
import { findChild } from '../resolvers/utils.js';
|
|
3
3
|
/** Known container property accessors that operate on the container itself (e.g., dict.Keys, dict.Values) */
|
|
4
4
|
const KNOWN_CONTAINER_PROPS = new Set(['Keys', 'Values']);
|
|
5
5
|
const DECLARATION_NODE_TYPES = new Set([
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dart type extractor — full implementation following type-resolution-system.md.
|
|
3
|
+
*
|
|
4
|
+
* Tier 0: Explicit type annotations (User user = ...)
|
|
5
|
+
* Tier 0b: For-loop element types (for (var u in users))
|
|
6
|
+
* Tier 1: Constructor/initializer inference (var user = User())
|
|
7
|
+
* Tier 2: Assignment chain propagation (copy, fieldAccess, callResult, methodCallResult)
|
|
8
|
+
*
|
|
9
|
+
* Handles tree-sitter-dart's flat sibling AST structure:
|
|
10
|
+
* identifier + selector + selector (not nested call_expression).
|
|
11
|
+
*
|
|
12
|
+
* Credit: Type resolution approach adapted from @xFlaviews' PR #83.
|
|
13
|
+
*/
|
|
14
|
+
import type { LanguageTypeConfig } from './types.js';
|
|
15
|
+
export declare const typeConfig: LanguageTypeConfig;
|
|
@@ -0,0 +1,371 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dart type extractor — full implementation following type-resolution-system.md.
|
|
3
|
+
*
|
|
4
|
+
* Tier 0: Explicit type annotations (User user = ...)
|
|
5
|
+
* Tier 0b: For-loop element types (for (var u in users))
|
|
6
|
+
* Tier 1: Constructor/initializer inference (var user = User())
|
|
7
|
+
* Tier 2: Assignment chain propagation (copy, fieldAccess, callResult, methodCallResult)
|
|
8
|
+
*
|
|
9
|
+
* Handles tree-sitter-dart's flat sibling AST structure:
|
|
10
|
+
* identifier + selector + selector (not nested call_expression).
|
|
11
|
+
*
|
|
12
|
+
* Credit: Type resolution approach adapted from @xFlaviews' PR #83.
|
|
13
|
+
*/
|
|
14
|
+
import { extractSimpleTypeName, extractVarName, extractElementTypeFromString, resolveIterableElementType } from './shared.js';
|
|
15
|
+
import { findChild } from '../utils/ast-helpers.js';
|
|
16
|
+
// ── Node types ──────────────────────────────────────────────────────────
|
|
17
|
+
const DART_DECLARATION_NODE_TYPES = new Set([
|
|
18
|
+
'initialized_variable_definition',
|
|
19
|
+
'initialized_identifier',
|
|
20
|
+
]);
|
|
21
|
+
const DART_FOR_LOOP_NODE_TYPES = new Set([
|
|
22
|
+
'for_statement',
|
|
23
|
+
]);
|
|
24
|
+
function parseDartRHSChildren(children) {
|
|
25
|
+
let callee;
|
|
26
|
+
let member;
|
|
27
|
+
let hasCall = false;
|
|
28
|
+
for (const child of children) {
|
|
29
|
+
if (child.type === 'identifier' && !callee) {
|
|
30
|
+
callee = child.text;
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
if (child.type === 'selector') {
|
|
34
|
+
const uas = findChild(child, 'unconditional_assignable_selector')
|
|
35
|
+
?? findChild(child, 'conditional_assignable_selector');
|
|
36
|
+
if (uas) {
|
|
37
|
+
const id = findChild(uas, 'identifier');
|
|
38
|
+
if (id && !member)
|
|
39
|
+
member = id.text;
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
if (findChild(child, 'argument_part')) {
|
|
43
|
+
hasCall = true;
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return { callee, member, hasCall };
|
|
49
|
+
}
|
|
50
|
+
function parseDartRHS(node) {
|
|
51
|
+
const rhsChildren = [];
|
|
52
|
+
let foundEquals = false;
|
|
53
|
+
for (let i = 0; i < node.childCount; i++) {
|
|
54
|
+
const child = node.child(i);
|
|
55
|
+
if (!child)
|
|
56
|
+
continue;
|
|
57
|
+
if (!child.isNamed && child.text === '=') {
|
|
58
|
+
foundEquals = true;
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
if (foundEquals)
|
|
62
|
+
rhsChildren.push(child);
|
|
63
|
+
}
|
|
64
|
+
if (rhsChildren.length === 0)
|
|
65
|
+
return { hasCall: false, isAwait: false };
|
|
66
|
+
const first = rhsChildren[0];
|
|
67
|
+
if (first.type === 'unary_expression') {
|
|
68
|
+
const awaitExpr = findChild(first, 'await_expression');
|
|
69
|
+
if (awaitExpr) {
|
|
70
|
+
const innerChildren = [];
|
|
71
|
+
for (let i = 0; i < awaitExpr.namedChildCount; i++) {
|
|
72
|
+
const c = awaitExpr.namedChild(i);
|
|
73
|
+
if (c && c.type !== 'await')
|
|
74
|
+
innerChildren.push(c);
|
|
75
|
+
}
|
|
76
|
+
return { ...parseDartRHSChildren(innerChildren), isAwait: true };
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return { ...parseDartRHSChildren(rhsChildren), isAwait: false };
|
|
80
|
+
}
|
|
81
|
+
function hasDartTypeAnnotation(node) {
|
|
82
|
+
return !!(findChild(node, 'type_identifier') || findChild(node, 'nullable_type'));
|
|
83
|
+
}
|
|
84
|
+
// ── Tier 0: Explicit Type Annotations ───────────────────────────────────
|
|
85
|
+
const extractDartDeclaration = (node, env) => {
|
|
86
|
+
// initialized_identifier: comma-separated variable (String a, b, c) — type is on parent
|
|
87
|
+
if (node.type === 'initialized_identifier') {
|
|
88
|
+
const parent = node.parent;
|
|
89
|
+
if (!parent)
|
|
90
|
+
return;
|
|
91
|
+
let typeNode = findChild(parent, 'type_identifier');
|
|
92
|
+
if (!typeNode) {
|
|
93
|
+
const nullable = findChild(parent, 'nullable_type');
|
|
94
|
+
if (nullable)
|
|
95
|
+
typeNode = findChild(nullable, 'type_identifier');
|
|
96
|
+
}
|
|
97
|
+
if (!typeNode)
|
|
98
|
+
return;
|
|
99
|
+
const typeName = extractSimpleTypeName(typeNode);
|
|
100
|
+
if (!typeName || typeName === 'dynamic')
|
|
101
|
+
return;
|
|
102
|
+
const nameNode = findChild(node, 'identifier');
|
|
103
|
+
if (!nameNode)
|
|
104
|
+
return;
|
|
105
|
+
const varName = extractVarName(nameNode);
|
|
106
|
+
if (varName)
|
|
107
|
+
env.set(varName, typeName);
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
let typeNode = findChild(node, 'type_identifier');
|
|
111
|
+
if (!typeNode) {
|
|
112
|
+
const nullable = findChild(node, 'nullable_type');
|
|
113
|
+
if (nullable)
|
|
114
|
+
typeNode = findChild(nullable, 'type_identifier');
|
|
115
|
+
}
|
|
116
|
+
if (!typeNode)
|
|
117
|
+
return;
|
|
118
|
+
const typeName = extractSimpleTypeName(typeNode);
|
|
119
|
+
if (!typeName || typeName === 'dynamic')
|
|
120
|
+
return;
|
|
121
|
+
const nameNode = node.childForFieldName('name');
|
|
122
|
+
if (!nameNode)
|
|
123
|
+
return;
|
|
124
|
+
const varName = extractVarName(nameNode);
|
|
125
|
+
if (varName)
|
|
126
|
+
env.set(varName, typeName);
|
|
127
|
+
};
|
|
128
|
+
const extractDartParameter = (node, env) => {
|
|
129
|
+
let typeNode = findChild(node, 'type_identifier');
|
|
130
|
+
if (!typeNode) {
|
|
131
|
+
const nullable = findChild(node, 'nullable_type');
|
|
132
|
+
if (nullable)
|
|
133
|
+
typeNode = findChild(nullable, 'type_identifier');
|
|
134
|
+
}
|
|
135
|
+
if (!typeNode)
|
|
136
|
+
return;
|
|
137
|
+
const typeName = extractSimpleTypeName(typeNode);
|
|
138
|
+
if (!typeName || typeName === 'dynamic')
|
|
139
|
+
return;
|
|
140
|
+
const nameNode = node.childForFieldName('name');
|
|
141
|
+
if (!nameNode)
|
|
142
|
+
return;
|
|
143
|
+
const varName = extractVarName(nameNode);
|
|
144
|
+
if (varName)
|
|
145
|
+
env.set(varName, typeName);
|
|
146
|
+
};
|
|
147
|
+
// ── Tier 1: Constructor / Initializer Inference ─────────────────────────
|
|
148
|
+
const extractDartInitializer = (node, env, classNames) => {
|
|
149
|
+
if (node.type !== 'initialized_variable_definition')
|
|
150
|
+
return;
|
|
151
|
+
if (hasDartTypeAnnotation(node))
|
|
152
|
+
return;
|
|
153
|
+
const nameNode = node.childForFieldName('name');
|
|
154
|
+
if (!nameNode)
|
|
155
|
+
return;
|
|
156
|
+
const varName = extractVarName(nameNode);
|
|
157
|
+
if (!varName || env.has(varName))
|
|
158
|
+
return;
|
|
159
|
+
const rhs = parseDartRHS(node);
|
|
160
|
+
if (!rhs.callee || !rhs.hasCall)
|
|
161
|
+
return;
|
|
162
|
+
if (!rhs.member && classNames.has(rhs.callee)) {
|
|
163
|
+
env.set(varName, rhs.callee);
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
if (rhs.member && classNames.has(rhs.callee)) {
|
|
167
|
+
env.set(varName, rhs.callee);
|
|
168
|
+
}
|
|
169
|
+
};
|
|
170
|
+
// ── Constructor Binding Scan ────────────────────────────────────────────
|
|
171
|
+
const scanDartConstructorBinding = (node) => {
|
|
172
|
+
if (node.type !== 'initialized_variable_definition')
|
|
173
|
+
return undefined;
|
|
174
|
+
if (hasDartTypeAnnotation(node))
|
|
175
|
+
return undefined;
|
|
176
|
+
const nameNode = node.childForFieldName('name');
|
|
177
|
+
if (!nameNode)
|
|
178
|
+
return undefined;
|
|
179
|
+
const varName = nameNode.text;
|
|
180
|
+
if (!varName)
|
|
181
|
+
return undefined;
|
|
182
|
+
const rhs = parseDartRHS(node);
|
|
183
|
+
if (!rhs.callee)
|
|
184
|
+
return undefined;
|
|
185
|
+
if (rhs.hasCall && !rhs.member)
|
|
186
|
+
return { varName, calleeName: rhs.callee };
|
|
187
|
+
if (rhs.hasCall && rhs.member)
|
|
188
|
+
return { varName, calleeName: rhs.member };
|
|
189
|
+
return undefined;
|
|
190
|
+
};
|
|
191
|
+
// ── Virtual Dispatch ────────────────────────────────────────────────────
|
|
192
|
+
const detectDartConstructorType = (node, classNames) => {
|
|
193
|
+
if (node.type !== 'initialized_variable_definition')
|
|
194
|
+
return undefined;
|
|
195
|
+
const rhs = parseDartRHS(node);
|
|
196
|
+
if (!rhs.callee || !rhs.hasCall)
|
|
197
|
+
return undefined;
|
|
198
|
+
if (!rhs.member && classNames.has(rhs.callee))
|
|
199
|
+
return rhs.callee;
|
|
200
|
+
if (rhs.member && classNames.has(rhs.callee))
|
|
201
|
+
return rhs.callee;
|
|
202
|
+
return undefined;
|
|
203
|
+
};
|
|
204
|
+
// ── Literal Type Inference ──────────────────────────────────────────────
|
|
205
|
+
const inferDartLiteralType = (node) => {
|
|
206
|
+
switch (node.type) {
|
|
207
|
+
case 'decimal_integer_literal':
|
|
208
|
+
case 'hex_integer_literal':
|
|
209
|
+
return 'int';
|
|
210
|
+
case 'decimal_floating_point_literal':
|
|
211
|
+
return 'double';
|
|
212
|
+
case 'string_literal':
|
|
213
|
+
return 'String';
|
|
214
|
+
case 'true':
|
|
215
|
+
case 'false':
|
|
216
|
+
return 'bool';
|
|
217
|
+
case 'null_literal':
|
|
218
|
+
return 'null';
|
|
219
|
+
default:
|
|
220
|
+
return undefined;
|
|
221
|
+
}
|
|
222
|
+
};
|
|
223
|
+
// ── Tier 2: Assignment Chain Propagation ─────────────────────────────────
|
|
224
|
+
const extractDartPendingAssignment = (node, scopeEnv) => {
|
|
225
|
+
if (node.type !== 'initialized_variable_definition')
|
|
226
|
+
return undefined;
|
|
227
|
+
if (hasDartTypeAnnotation(node))
|
|
228
|
+
return undefined;
|
|
229
|
+
const nameNode = node.childForFieldName('name');
|
|
230
|
+
if (!nameNode)
|
|
231
|
+
return undefined;
|
|
232
|
+
const lhs = nameNode.text;
|
|
233
|
+
if (!lhs || scopeEnv.has(lhs))
|
|
234
|
+
return undefined;
|
|
235
|
+
const rhs = parseDartRHS(node);
|
|
236
|
+
if (!rhs.callee)
|
|
237
|
+
return undefined;
|
|
238
|
+
if (!rhs.hasCall && !rhs.member)
|
|
239
|
+
return { kind: 'copy', lhs, rhs: rhs.callee };
|
|
240
|
+
if (!rhs.hasCall && rhs.member)
|
|
241
|
+
return { kind: 'fieldAccess', lhs, receiver: rhs.callee, field: rhs.member };
|
|
242
|
+
if (rhs.hasCall && !rhs.member)
|
|
243
|
+
return { kind: 'callResult', lhs, callee: rhs.callee };
|
|
244
|
+
if (rhs.hasCall && rhs.member)
|
|
245
|
+
return { kind: 'methodCallResult', lhs, receiver: rhs.callee, method: rhs.member };
|
|
246
|
+
return undefined;
|
|
247
|
+
};
|
|
248
|
+
// ── For-Loop Element Type Resolution ────────────────────────────────────
|
|
249
|
+
function extractDartElementTypeFromTypeNode(typeNode) {
|
|
250
|
+
if (typeNode.type === 'type_identifier') {
|
|
251
|
+
const parent = typeNode.parent;
|
|
252
|
+
if (parent) {
|
|
253
|
+
const args = findChild(parent, 'type_arguments');
|
|
254
|
+
if (args && args.namedChildCount >= 1) {
|
|
255
|
+
const lastArg = args.namedChild(args.namedChildCount - 1);
|
|
256
|
+
if (lastArg)
|
|
257
|
+
return extractSimpleTypeName(lastArg);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
return undefined;
|
|
262
|
+
}
|
|
263
|
+
const extractDartForLoopBinding = (node, ctx) => {
|
|
264
|
+
if (node.type !== 'for_statement')
|
|
265
|
+
return;
|
|
266
|
+
const { scopeEnv, declarationTypeNodes, scope, returnTypeLookup } = ctx;
|
|
267
|
+
const loopParts = findChild(node, 'for_loop_parts');
|
|
268
|
+
if (!loopParts)
|
|
269
|
+
return;
|
|
270
|
+
const nameNode = loopParts.childForFieldName('name');
|
|
271
|
+
if (!nameNode)
|
|
272
|
+
return;
|
|
273
|
+
const loopVarName = nameNode.text;
|
|
274
|
+
if (!loopVarName)
|
|
275
|
+
return;
|
|
276
|
+
const typeNode = findChild(loopParts, 'type_identifier');
|
|
277
|
+
if (typeNode) {
|
|
278
|
+
const typeName = extractSimpleTypeName(typeNode);
|
|
279
|
+
if (typeName && !scopeEnv.has(loopVarName)) {
|
|
280
|
+
scopeEnv.set(loopVarName, typeName);
|
|
281
|
+
}
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
284
|
+
const iterableNode = loopParts.childForFieldName('value');
|
|
285
|
+
if (!iterableNode)
|
|
286
|
+
return;
|
|
287
|
+
let iterableName;
|
|
288
|
+
let callExprElementType;
|
|
289
|
+
if (iterableNode.type === 'identifier') {
|
|
290
|
+
iterableName = iterableNode.text;
|
|
291
|
+
}
|
|
292
|
+
else if (iterableNode.type === 'unary_expression') {
|
|
293
|
+
const awaitExpr = findChild(iterableNode, 'await_expression');
|
|
294
|
+
if (awaitExpr) {
|
|
295
|
+
const innerIdent = findChild(awaitExpr, 'identifier');
|
|
296
|
+
if (innerIdent)
|
|
297
|
+
iterableName = innerIdent.text;
|
|
298
|
+
}
|
|
299
|
+
if (!iterableName)
|
|
300
|
+
return;
|
|
301
|
+
}
|
|
302
|
+
if (iterableName) {
|
|
303
|
+
let hasCallSelector = false;
|
|
304
|
+
let memberName;
|
|
305
|
+
const selectorParent = iterableNode.type === 'unary_expression'
|
|
306
|
+
? findChild(iterableNode, 'await_expression')
|
|
307
|
+
: loopParts;
|
|
308
|
+
if (!selectorParent)
|
|
309
|
+
return;
|
|
310
|
+
let foundIterable = false;
|
|
311
|
+
for (let i = 0; i < selectorParent.childCount; i++) {
|
|
312
|
+
const child = selectorParent.child(i);
|
|
313
|
+
if (!child)
|
|
314
|
+
continue;
|
|
315
|
+
if (child.type === 'identifier' && child.text === iterableName) {
|
|
316
|
+
foundIterable = true;
|
|
317
|
+
continue;
|
|
318
|
+
}
|
|
319
|
+
if (child === iterableNode) {
|
|
320
|
+
foundIterable = true;
|
|
321
|
+
continue;
|
|
322
|
+
}
|
|
323
|
+
if (!foundIterable)
|
|
324
|
+
continue;
|
|
325
|
+
if (child.type === 'selector') {
|
|
326
|
+
const uas = findChild(child, 'unconditional_assignable_selector')
|
|
327
|
+
?? findChild(child, 'conditional_assignable_selector');
|
|
328
|
+
if (uas) {
|
|
329
|
+
const id = findChild(uas, 'identifier');
|
|
330
|
+
if (id)
|
|
331
|
+
memberName = id.text;
|
|
332
|
+
continue;
|
|
333
|
+
}
|
|
334
|
+
if (findChild(child, 'argument_part')) {
|
|
335
|
+
hasCallSelector = true;
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
if (hasCallSelector) {
|
|
340
|
+
const callee = memberName ?? iterableName;
|
|
341
|
+
const rawReturn = returnTypeLookup.lookupRawReturnType(callee);
|
|
342
|
+
if (rawReturn)
|
|
343
|
+
callExprElementType = extractElementTypeFromString(rawReturn);
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
if (!iterableName && !callExprElementType)
|
|
347
|
+
return;
|
|
348
|
+
let elementType;
|
|
349
|
+
if (callExprElementType) {
|
|
350
|
+
elementType = callExprElementType;
|
|
351
|
+
}
|
|
352
|
+
else if (iterableName) {
|
|
353
|
+
elementType = resolveIterableElementType(iterableName, node, scopeEnv, declarationTypeNodes, scope, extractDartElementTypeFromTypeNode);
|
|
354
|
+
}
|
|
355
|
+
if (elementType && !scopeEnv.has(loopVarName)) {
|
|
356
|
+
scopeEnv.set(loopVarName, elementType);
|
|
357
|
+
}
|
|
358
|
+
};
|
|
359
|
+
// ── Export ───────────────────────────────────────────────────────────────
|
|
360
|
+
export const typeConfig = {
|
|
361
|
+
declarationNodeTypes: DART_DECLARATION_NODE_TYPES,
|
|
362
|
+
forLoopNodeTypes: DART_FOR_LOOP_NODE_TYPES,
|
|
363
|
+
extractDeclaration: extractDartDeclaration,
|
|
364
|
+
extractParameter: extractDartParameter,
|
|
365
|
+
extractInitializer: extractDartInitializer,
|
|
366
|
+
scanConstructorBinding: scanDartConstructorBinding,
|
|
367
|
+
extractForLoopBinding: extractDartForLoopBinding,
|
|
368
|
+
extractPendingAssignment: extractDartPendingAssignment,
|
|
369
|
+
inferLiteralType: inferDartLiteralType,
|
|
370
|
+
detectConstructorType: detectDartConstructorType,
|
|
371
|
+
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import { findChild } from '../utils/ast-helpers.js';
|
|
1
2
|
import { extractSimpleTypeName, extractVarName, extractGenericTypeArgs, resolveIterableElementType, methodToTypeArgPosition, extractElementTypeFromString } from './shared.js';
|
|
2
|
-
import { findChild } from '../resolvers/utils.js';
|
|
3
3
|
// ── Java ──────────────────────────────────────────────────────────────────
|
|
4
4
|
const JAVA_DECLARATION_NODE_TYPES = new Set([
|
|
5
5
|
'local_variable_declaration',
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { SyntaxNode } from '../utils.js';
|
|
1
|
+
import type { SyntaxNode } from '../utils/ast-helpers.js';
|
|
2
2
|
/** Which type argument to extract from a multi-arg generic container.
|
|
3
3
|
* - 'first': key type (e.g., K from Map<K,V>) — used for .keys(), .keySet()
|
|
4
4
|
* - 'last': value type (e.g., V from Map<K,V>) — used for .values(), .items(), .iter() */
|
|
@@ -128,16 +128,4 @@ export declare const extractCalleeName: (callNode: SyntaxNode) => string | undef
|
|
|
128
128
|
*/
|
|
129
129
|
export declare function extractElementTypeFromString(typeStr: string, pos?: TypeArgPosition): string | undefined;
|
|
130
130
|
export declare const extractReturnTypeName: (raw: string, depth?: number) => string | undefined;
|
|
131
|
-
/**
|
|
132
|
-
* Extract the declared type of a property/field from its AST definition node.
|
|
133
|
-
* Handles cross-language patterns:
|
|
134
|
-
* - TypeScript: `name: Type` → type_annotation child
|
|
135
|
-
* - Java: `Type name` → type child on field_declaration
|
|
136
|
-
* - C#: `Type Name { get; set; }` → type child on property_declaration
|
|
137
|
-
* - Go: `Name Type` → type child on field_declaration
|
|
138
|
-
* - Kotlin: `var name: Type` → variable_declaration child with type field
|
|
139
|
-
*
|
|
140
|
-
* Returns the normalized type name, or undefined if no type can be extracted.
|
|
141
|
-
*/
|
|
142
|
-
export declare const extractPropertyDeclaredType: (definitionNode: SyntaxNode | null) => string | undefined;
|
|
143
131
|
export {};
|