@duytransipher/gitnexus 1.4.6-sipher.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +73 -0
- package/README.md +261 -0
- package/dist/cli/ai-context.d.ts +23 -0
- package/dist/cli/ai-context.js +265 -0
- package/dist/cli/analyze.d.ts +12 -0
- package/dist/cli/analyze.js +345 -0
- package/dist/cli/augment.d.ts +13 -0
- package/dist/cli/augment.js +33 -0
- package/dist/cli/clean.d.ts +10 -0
- package/dist/cli/clean.js +60 -0
- package/dist/cli/eval-server.d.ts +37 -0
- package/dist/cli/eval-server.js +389 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.js +137 -0
- package/dist/cli/lazy-action.d.ts +6 -0
- package/dist/cli/lazy-action.js +18 -0
- package/dist/cli/list.d.ts +6 -0
- package/dist/cli/list.js +30 -0
- package/dist/cli/mcp.d.ts +8 -0
- package/dist/cli/mcp.js +36 -0
- package/dist/cli/serve.d.ts +4 -0
- package/dist/cli/serve.js +6 -0
- package/dist/cli/setup.d.ts +8 -0
- package/dist/cli/setup.js +367 -0
- package/dist/cli/sipher-patched.d.ts +2 -0
- package/dist/cli/sipher-patched.js +77 -0
- package/dist/cli/skill-gen.d.ts +26 -0
- package/dist/cli/skill-gen.js +549 -0
- package/dist/cli/status.d.ts +6 -0
- package/dist/cli/status.js +36 -0
- package/dist/cli/tool.d.ts +60 -0
- package/dist/cli/tool.js +180 -0
- package/dist/cli/wiki.d.ts +15 -0
- package/dist/cli/wiki.js +365 -0
- package/dist/config/ignore-service.d.ts +26 -0
- package/dist/config/ignore-service.js +284 -0
- package/dist/config/supported-languages.d.ts +15 -0
- package/dist/config/supported-languages.js +16 -0
- package/dist/core/augmentation/engine.d.ts +26 -0
- package/dist/core/augmentation/engine.js +240 -0
- package/dist/core/embeddings/embedder.d.ts +60 -0
- package/dist/core/embeddings/embedder.js +251 -0
- package/dist/core/embeddings/embedding-pipeline.d.ts +51 -0
- package/dist/core/embeddings/embedding-pipeline.js +356 -0
- package/dist/core/embeddings/index.d.ts +9 -0
- package/dist/core/embeddings/index.js +9 -0
- package/dist/core/embeddings/text-generator.d.ts +24 -0
- package/dist/core/embeddings/text-generator.js +182 -0
- package/dist/core/embeddings/types.d.ts +87 -0
- package/dist/core/embeddings/types.js +32 -0
- package/dist/core/graph/graph.d.ts +2 -0
- package/dist/core/graph/graph.js +66 -0
- package/dist/core/graph/types.d.ts +66 -0
- package/dist/core/graph/types.js +1 -0
- package/dist/core/ingestion/ast-cache.d.ts +11 -0
- package/dist/core/ingestion/ast-cache.js +35 -0
- package/dist/core/ingestion/call-processor.d.ts +23 -0
- package/dist/core/ingestion/call-processor.js +793 -0
- package/dist/core/ingestion/call-routing.d.ts +68 -0
- package/dist/core/ingestion/call-routing.js +129 -0
- package/dist/core/ingestion/cluster-enricher.d.ts +38 -0
- package/dist/core/ingestion/cluster-enricher.js +170 -0
- package/dist/core/ingestion/community-processor.d.ts +39 -0
- package/dist/core/ingestion/community-processor.js +312 -0
- package/dist/core/ingestion/constants.d.ts +16 -0
- package/dist/core/ingestion/constants.js +16 -0
- package/dist/core/ingestion/entry-point-scoring.d.ts +40 -0
- package/dist/core/ingestion/entry-point-scoring.js +353 -0
- package/dist/core/ingestion/export-detection.d.ts +18 -0
- package/dist/core/ingestion/export-detection.js +231 -0
- package/dist/core/ingestion/filesystem-walker.d.ts +28 -0
- package/dist/core/ingestion/filesystem-walker.js +81 -0
- package/dist/core/ingestion/framework-detection.d.ts +54 -0
- package/dist/core/ingestion/framework-detection.js +411 -0
- package/dist/core/ingestion/heritage-processor.d.ts +28 -0
- package/dist/core/ingestion/heritage-processor.js +251 -0
- package/dist/core/ingestion/import-processor.d.ts +34 -0
- package/dist/core/ingestion/import-processor.js +398 -0
- package/dist/core/ingestion/language-config.d.ts +46 -0
- package/dist/core/ingestion/language-config.js +167 -0
- package/dist/core/ingestion/mro-processor.d.ts +45 -0
- package/dist/core/ingestion/mro-processor.js +369 -0
- package/dist/core/ingestion/named-binding-extraction.d.ts +61 -0
- package/dist/core/ingestion/named-binding-extraction.js +363 -0
- package/dist/core/ingestion/parsing-processor.d.ts +19 -0
- package/dist/core/ingestion/parsing-processor.js +315 -0
- package/dist/core/ingestion/pipeline.d.ts +6 -0
- package/dist/core/ingestion/pipeline.js +401 -0
- package/dist/core/ingestion/process-processor.d.ts +51 -0
- package/dist/core/ingestion/process-processor.js +315 -0
- package/dist/core/ingestion/resolution-context.d.ts +53 -0
- package/dist/core/ingestion/resolution-context.js +132 -0
- package/dist/core/ingestion/resolvers/csharp.d.ts +22 -0
- package/dist/core/ingestion/resolvers/csharp.js +109 -0
- package/dist/core/ingestion/resolvers/go.d.ts +19 -0
- package/dist/core/ingestion/resolvers/go.js +42 -0
- package/dist/core/ingestion/resolvers/index.d.ts +18 -0
- package/dist/core/ingestion/resolvers/index.js +13 -0
- package/dist/core/ingestion/resolvers/jvm.d.ts +23 -0
- package/dist/core/ingestion/resolvers/jvm.js +87 -0
- package/dist/core/ingestion/resolvers/php.d.ts +15 -0
- package/dist/core/ingestion/resolvers/php.js +35 -0
- package/dist/core/ingestion/resolvers/python.d.ts +19 -0
- package/dist/core/ingestion/resolvers/python.js +52 -0
- package/dist/core/ingestion/resolvers/ruby.d.ts +12 -0
- package/dist/core/ingestion/resolvers/ruby.js +15 -0
- package/dist/core/ingestion/resolvers/rust.d.ts +15 -0
- package/dist/core/ingestion/resolvers/rust.js +73 -0
- package/dist/core/ingestion/resolvers/standard.d.ts +28 -0
- package/dist/core/ingestion/resolvers/standard.js +123 -0
- package/dist/core/ingestion/resolvers/utils.d.ts +33 -0
- package/dist/core/ingestion/resolvers/utils.js +122 -0
- package/dist/core/ingestion/structure-processor.d.ts +2 -0
- package/dist/core/ingestion/structure-processor.js +36 -0
- package/dist/core/ingestion/symbol-table.d.ts +63 -0
- package/dist/core/ingestion/symbol-table.js +85 -0
- package/dist/core/ingestion/tree-sitter-queries.d.ts +15 -0
- package/dist/core/ingestion/tree-sitter-queries.js +888 -0
- package/dist/core/ingestion/type-env.d.ts +49 -0
- package/dist/core/ingestion/type-env.js +613 -0
- package/dist/core/ingestion/type-extractors/c-cpp.d.ts +2 -0
- package/dist/core/ingestion/type-extractors/c-cpp.js +385 -0
- package/dist/core/ingestion/type-extractors/csharp.d.ts +2 -0
- package/dist/core/ingestion/type-extractors/csharp.js +383 -0
- package/dist/core/ingestion/type-extractors/go.d.ts +2 -0
- package/dist/core/ingestion/type-extractors/go.js +467 -0
- package/dist/core/ingestion/type-extractors/index.d.ts +22 -0
- package/dist/core/ingestion/type-extractors/index.js +31 -0
- package/dist/core/ingestion/type-extractors/jvm.d.ts +3 -0
- package/dist/core/ingestion/type-extractors/jvm.js +681 -0
- package/dist/core/ingestion/type-extractors/php.d.ts +2 -0
- package/dist/core/ingestion/type-extractors/php.js +549 -0
- package/dist/core/ingestion/type-extractors/python.d.ts +2 -0
- package/dist/core/ingestion/type-extractors/python.js +455 -0
- package/dist/core/ingestion/type-extractors/ruby.d.ts +2 -0
- package/dist/core/ingestion/type-extractors/ruby.js +389 -0
- package/dist/core/ingestion/type-extractors/rust.d.ts +2 -0
- package/dist/core/ingestion/type-extractors/rust.js +456 -0
- package/dist/core/ingestion/type-extractors/shared.d.ts +145 -0
- package/dist/core/ingestion/type-extractors/shared.js +810 -0
- package/dist/core/ingestion/type-extractors/swift.d.ts +2 -0
- package/dist/core/ingestion/type-extractors/swift.js +137 -0
- package/dist/core/ingestion/type-extractors/types.d.ts +127 -0
- package/dist/core/ingestion/type-extractors/types.js +1 -0
- package/dist/core/ingestion/type-extractors/typescript.d.ts +2 -0
- package/dist/core/ingestion/type-extractors/typescript.js +494 -0
- package/dist/core/ingestion/utils.d.ts +138 -0
- package/dist/core/ingestion/utils.js +1290 -0
- package/dist/core/ingestion/workers/parse-worker.d.ts +122 -0
- package/dist/core/ingestion/workers/parse-worker.js +1126 -0
- package/dist/core/ingestion/workers/worker-pool.d.ts +16 -0
- package/dist/core/ingestion/workers/worker-pool.js +128 -0
- package/dist/core/lbug/csv-generator.d.ts +33 -0
- package/dist/core/lbug/csv-generator.js +366 -0
- package/dist/core/lbug/lbug-adapter.d.ts +103 -0
- package/dist/core/lbug/lbug-adapter.js +769 -0
- package/dist/core/lbug/schema.d.ts +53 -0
- package/dist/core/lbug/schema.js +430 -0
- package/dist/core/search/bm25-index.d.ts +23 -0
- package/dist/core/search/bm25-index.js +96 -0
- package/dist/core/search/hybrid-search.d.ts +49 -0
- package/dist/core/search/hybrid-search.js +118 -0
- package/dist/core/tree-sitter/parser-loader.d.ts +5 -0
- package/dist/core/tree-sitter/parser-loader.js +63 -0
- package/dist/core/wiki/generator.d.ts +120 -0
- package/dist/core/wiki/generator.js +939 -0
- package/dist/core/wiki/graph-queries.d.ts +80 -0
- package/dist/core/wiki/graph-queries.js +238 -0
- package/dist/core/wiki/html-viewer.d.ts +10 -0
- package/dist/core/wiki/html-viewer.js +297 -0
- package/dist/core/wiki/llm-client.d.ts +43 -0
- package/dist/core/wiki/llm-client.js +186 -0
- package/dist/core/wiki/prompts.d.ts +53 -0
- package/dist/core/wiki/prompts.js +174 -0
- package/dist/lib/utils.d.ts +1 -0
- package/dist/lib/utils.js +3 -0
- package/dist/mcp/compatible-stdio-transport.d.ts +25 -0
- package/dist/mcp/compatible-stdio-transport.js +200 -0
- package/dist/mcp/core/embedder.d.ts +27 -0
- package/dist/mcp/core/embedder.js +108 -0
- package/dist/mcp/core/lbug-adapter.d.ts +57 -0
- package/dist/mcp/core/lbug-adapter.js +455 -0
- package/dist/mcp/local/local-backend.d.ts +181 -0
- package/dist/mcp/local/local-backend.js +1722 -0
- package/dist/mcp/resources.d.ts +31 -0
- package/dist/mcp/resources.js +411 -0
- package/dist/mcp/server.d.ts +23 -0
- package/dist/mcp/server.js +296 -0
- package/dist/mcp/staleness.d.ts +15 -0
- package/dist/mcp/staleness.js +29 -0
- package/dist/mcp/tools.d.ts +24 -0
- package/dist/mcp/tools.js +292 -0
- package/dist/server/api.d.ts +10 -0
- package/dist/server/api.js +344 -0
- package/dist/server/mcp-http.d.ts +13 -0
- package/dist/server/mcp-http.js +100 -0
- package/dist/storage/git.d.ts +6 -0
- package/dist/storage/git.js +35 -0
- package/dist/storage/repo-manager.d.ts +138 -0
- package/dist/storage/repo-manager.js +299 -0
- package/dist/types/pipeline.d.ts +32 -0
- package/dist/types/pipeline.js +18 -0
- package/dist/unreal/bridge.d.ts +4 -0
- package/dist/unreal/bridge.js +113 -0
- package/dist/unreal/config.d.ts +6 -0
- package/dist/unreal/config.js +55 -0
- package/dist/unreal/types.d.ts +105 -0
- package/dist/unreal/types.js +1 -0
- package/hooks/claude/gitnexus-hook.cjs +238 -0
- package/hooks/claude/pre-tool-use.sh +79 -0
- package/hooks/claude/session-start.sh +42 -0
- package/package.json +100 -0
- package/scripts/ensure-cli-executable.cjs +21 -0
- package/scripts/patch-tree-sitter-swift.cjs +74 -0
- package/scripts/setup-unreal-gitnexus.ps1 +191 -0
- package/skills/gitnexus-cli.md +82 -0
- package/skills/gitnexus-debugging.md +89 -0
- package/skills/gitnexus-exploring.md +78 -0
- package/skills/gitnexus-guide.md +64 -0
- package/skills/gitnexus-impact-analysis.md +97 -0
- package/skills/gitnexus-pr-review.md +163 -0
- package/skills/gitnexus-refactoring.md +121 -0
- package/vendor/leiden/index.cjs +355 -0
- package/vendor/leiden/utils.cjs +392 -0
|
@@ -0,0 +1,385 @@
|
|
|
1
|
+
import { extractSimpleTypeName, extractVarName, resolveIterableElementType, methodToTypeArgPosition } from './shared.js';
|
|
2
|
+
const DECLARATION_NODE_TYPES = new Set([
|
|
3
|
+
'declaration',
|
|
4
|
+
]);
|
|
5
|
+
/** C++: Type x = ...; Type* x; Type& x; */
|
|
6
|
+
const extractDeclaration = (node, env) => {
|
|
7
|
+
const typeNode = node.childForFieldName('type');
|
|
8
|
+
if (!typeNode)
|
|
9
|
+
return;
|
|
10
|
+
const typeName = extractSimpleTypeName(typeNode);
|
|
11
|
+
if (!typeName)
|
|
12
|
+
return;
|
|
13
|
+
const declarator = node.childForFieldName('declarator');
|
|
14
|
+
if (!declarator)
|
|
15
|
+
return;
|
|
16
|
+
// init_declarator: Type x = value
|
|
17
|
+
const nameNode = declarator.type === 'init_declarator'
|
|
18
|
+
? declarator.childForFieldName('declarator')
|
|
19
|
+
: declarator;
|
|
20
|
+
if (!nameNode)
|
|
21
|
+
return;
|
|
22
|
+
// Handle pointer/reference declarators
|
|
23
|
+
const finalName = nameNode.type === 'pointer_declarator' || nameNode.type === 'reference_declarator'
|
|
24
|
+
? nameNode.firstNamedChild
|
|
25
|
+
: nameNode;
|
|
26
|
+
if (!finalName)
|
|
27
|
+
return;
|
|
28
|
+
const varName = extractVarName(finalName);
|
|
29
|
+
if (varName)
|
|
30
|
+
env.set(varName, typeName);
|
|
31
|
+
};
|
|
32
|
+
/** C++: auto x = new User(); auto x = User(); */
|
|
33
|
+
const extractInitializer = (node, env, classNames) => {
|
|
34
|
+
const typeNode = node.childForFieldName('type');
|
|
35
|
+
if (!typeNode)
|
|
36
|
+
return;
|
|
37
|
+
// Only handle auto/placeholder — typed declarations are handled by extractDeclaration
|
|
38
|
+
const typeText = typeNode.text;
|
|
39
|
+
if (typeText !== 'auto' &&
|
|
40
|
+
typeText !== 'decltype(auto)' &&
|
|
41
|
+
typeNode.type !== 'placeholder_type_specifier')
|
|
42
|
+
return;
|
|
43
|
+
const declarator = node.childForFieldName('declarator');
|
|
44
|
+
if (!declarator)
|
|
45
|
+
return;
|
|
46
|
+
// Must be an init_declarator (i.e., has an initializer value)
|
|
47
|
+
if (declarator.type !== 'init_declarator')
|
|
48
|
+
return;
|
|
49
|
+
const value = declarator.childForFieldName('value');
|
|
50
|
+
if (!value)
|
|
51
|
+
return;
|
|
52
|
+
// Resolve the variable name, unwrapping pointer/reference declarators
|
|
53
|
+
const nameNode = declarator.childForFieldName('declarator');
|
|
54
|
+
if (!nameNode)
|
|
55
|
+
return;
|
|
56
|
+
const finalName = nameNode.type === 'pointer_declarator' || nameNode.type === 'reference_declarator'
|
|
57
|
+
? nameNode.firstNamedChild
|
|
58
|
+
: nameNode;
|
|
59
|
+
if (!finalName)
|
|
60
|
+
return;
|
|
61
|
+
const varName = extractVarName(finalName);
|
|
62
|
+
if (!varName)
|
|
63
|
+
return;
|
|
64
|
+
// auto x = new User() — new_expression
|
|
65
|
+
if (value.type === 'new_expression') {
|
|
66
|
+
const ctorType = value.childForFieldName('type');
|
|
67
|
+
if (ctorType) {
|
|
68
|
+
const typeName = extractSimpleTypeName(ctorType);
|
|
69
|
+
if (typeName)
|
|
70
|
+
env.set(varName, typeName);
|
|
71
|
+
}
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
// auto x = User() — call_expression where function is a type name
|
|
75
|
+
// tree-sitter-cpp may parse the constructor name as type_identifier or identifier.
|
|
76
|
+
// For plain identifiers, verify against known class names from the file's AST
|
|
77
|
+
// to distinguish constructor calls (User()) from function calls (getUser()).
|
|
78
|
+
if (value.type === 'call_expression') {
|
|
79
|
+
const func = value.childForFieldName('function');
|
|
80
|
+
if (!func)
|
|
81
|
+
return;
|
|
82
|
+
if (func.type === 'type_identifier') {
|
|
83
|
+
const typeName = func.text;
|
|
84
|
+
if (typeName)
|
|
85
|
+
env.set(varName, typeName);
|
|
86
|
+
}
|
|
87
|
+
else if (func.type === 'identifier') {
|
|
88
|
+
const text = func.text;
|
|
89
|
+
if (text && classNames.has(text))
|
|
90
|
+
env.set(varName, text);
|
|
91
|
+
}
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
// auto x = User{} — compound_literal_expression (brace initialization)
|
|
95
|
+
// AST: compound_literal_expression > type_identifier + initializer_list
|
|
96
|
+
if (value.type === 'compound_literal_expression') {
|
|
97
|
+
const typeId = value.firstNamedChild;
|
|
98
|
+
const typeName = typeId ? extractSimpleTypeName(typeId) : undefined;
|
|
99
|
+
if (typeName)
|
|
100
|
+
env.set(varName, typeName);
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
/** C/C++: parameter_declaration → type declarator */
|
|
104
|
+
const extractParameter = (node, env) => {
|
|
105
|
+
let nameNode = null;
|
|
106
|
+
let typeNode = null;
|
|
107
|
+
if (node.type === 'parameter_declaration') {
|
|
108
|
+
typeNode = node.childForFieldName('type');
|
|
109
|
+
const declarator = node.childForFieldName('declarator');
|
|
110
|
+
if (declarator) {
|
|
111
|
+
nameNode = declarator.type === 'pointer_declarator' || declarator.type === 'reference_declarator'
|
|
112
|
+
? declarator.firstNamedChild
|
|
113
|
+
: declarator;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
nameNode = node.childForFieldName('name') ?? node.childForFieldName('pattern');
|
|
118
|
+
typeNode = node.childForFieldName('type');
|
|
119
|
+
}
|
|
120
|
+
if (!nameNode || !typeNode)
|
|
121
|
+
return;
|
|
122
|
+
const varName = extractVarName(nameNode);
|
|
123
|
+
const typeName = extractSimpleTypeName(typeNode);
|
|
124
|
+
if (varName && typeName)
|
|
125
|
+
env.set(varName, typeName);
|
|
126
|
+
};
|
|
127
|
+
/** C/C++: auto x = User() where function is an identifier (not type_identifier) */
|
|
128
|
+
const scanConstructorBinding = (node) => {
|
|
129
|
+
if (node.type !== 'declaration')
|
|
130
|
+
return undefined;
|
|
131
|
+
const typeNode = node.childForFieldName('type');
|
|
132
|
+
if (!typeNode)
|
|
133
|
+
return undefined;
|
|
134
|
+
const typeText = typeNode.text;
|
|
135
|
+
if (typeText !== 'auto' && typeText !== 'decltype(auto)' && typeNode.type !== 'placeholder_type_specifier')
|
|
136
|
+
return undefined;
|
|
137
|
+
const declarator = node.childForFieldName('declarator');
|
|
138
|
+
if (!declarator || declarator.type !== 'init_declarator')
|
|
139
|
+
return undefined;
|
|
140
|
+
const value = declarator.childForFieldName('value');
|
|
141
|
+
if (!value || value.type !== 'call_expression')
|
|
142
|
+
return undefined;
|
|
143
|
+
const func = value.childForFieldName('function');
|
|
144
|
+
if (!func)
|
|
145
|
+
return undefined;
|
|
146
|
+
if (func.type === 'qualified_identifier' || func.type === 'scoped_identifier') {
|
|
147
|
+
const last = func.lastNamedChild;
|
|
148
|
+
if (!last)
|
|
149
|
+
return undefined;
|
|
150
|
+
const nameNode = declarator.childForFieldName('declarator');
|
|
151
|
+
if (!nameNode)
|
|
152
|
+
return undefined;
|
|
153
|
+
const finalName = nameNode.type === 'pointer_declarator' || nameNode.type === 'reference_declarator'
|
|
154
|
+
? nameNode.firstNamedChild : nameNode;
|
|
155
|
+
if (!finalName)
|
|
156
|
+
return undefined;
|
|
157
|
+
return { varName: finalName.text, calleeName: last.text };
|
|
158
|
+
}
|
|
159
|
+
if (func.type !== 'identifier')
|
|
160
|
+
return undefined;
|
|
161
|
+
const nameNode = declarator.childForFieldName('declarator');
|
|
162
|
+
if (!nameNode)
|
|
163
|
+
return undefined;
|
|
164
|
+
const finalName = nameNode.type === 'pointer_declarator' || nameNode.type === 'reference_declarator'
|
|
165
|
+
? nameNode.firstNamedChild : nameNode;
|
|
166
|
+
if (!finalName)
|
|
167
|
+
return undefined;
|
|
168
|
+
const varName = finalName.text;
|
|
169
|
+
if (!varName)
|
|
170
|
+
return undefined;
|
|
171
|
+
return { varName, calleeName: func.text };
|
|
172
|
+
};
|
|
173
|
+
/** C++: auto alias = user → declaration with auto type + init_declarator where value is identifier */
|
|
174
|
+
const extractPendingAssignment = (node, scopeEnv) => {
|
|
175
|
+
if (node.type !== 'declaration')
|
|
176
|
+
return undefined;
|
|
177
|
+
const typeNode = node.childForFieldName('type');
|
|
178
|
+
if (!typeNode)
|
|
179
|
+
return undefined;
|
|
180
|
+
// Only handle auto — typed declarations already resolved by extractDeclaration
|
|
181
|
+
const typeText = typeNode.text;
|
|
182
|
+
if (typeText !== 'auto' && typeText !== 'decltype(auto)'
|
|
183
|
+
&& typeNode.type !== 'placeholder_type_specifier')
|
|
184
|
+
return undefined;
|
|
185
|
+
const declarator = node.childForFieldName('declarator');
|
|
186
|
+
if (!declarator || declarator.type !== 'init_declarator')
|
|
187
|
+
return undefined;
|
|
188
|
+
const value = declarator.childForFieldName('value');
|
|
189
|
+
if (!value || value.type !== 'identifier')
|
|
190
|
+
return undefined;
|
|
191
|
+
const nameNode = declarator.childForFieldName('declarator');
|
|
192
|
+
if (!nameNode)
|
|
193
|
+
return undefined;
|
|
194
|
+
const finalName = nameNode.type === 'pointer_declarator' || nameNode.type === 'reference_declarator'
|
|
195
|
+
? nameNode.firstNamedChild : nameNode;
|
|
196
|
+
if (!finalName)
|
|
197
|
+
return undefined;
|
|
198
|
+
const lhs = extractVarName(finalName);
|
|
199
|
+
if (!lhs || scopeEnv.has(lhs))
|
|
200
|
+
return undefined;
|
|
201
|
+
return { kind: 'copy', lhs, rhs: value.text };
|
|
202
|
+
};
|
|
203
|
+
// --- For-loop Tier 1c ---
|
|
204
|
+
const FOR_LOOP_NODE_TYPES = new Set(['for_range_loop']);
|
|
205
|
+
/** Extract template type arguments from a C++ template_type node.
|
|
206
|
+
* C++ template_type uses template_argument_list (not type_arguments), and each
|
|
207
|
+
* argument is a type_descriptor with a 'type' field containing the type_specifier. */
|
|
208
|
+
const extractCppTemplateTypeArgs = (templateTypeNode) => {
|
|
209
|
+
const argsNode = templateTypeNode.childForFieldName('arguments');
|
|
210
|
+
if (!argsNode || argsNode.type !== 'template_argument_list')
|
|
211
|
+
return [];
|
|
212
|
+
const result = [];
|
|
213
|
+
for (let i = 0; i < argsNode.namedChildCount; i++) {
|
|
214
|
+
let argNode = argsNode.namedChild(i);
|
|
215
|
+
if (!argNode)
|
|
216
|
+
continue;
|
|
217
|
+
// type_descriptor wraps the actual type specifier in a 'type' field
|
|
218
|
+
if (argNode.type === 'type_descriptor') {
|
|
219
|
+
const inner = argNode.childForFieldName('type');
|
|
220
|
+
if (inner)
|
|
221
|
+
argNode = inner;
|
|
222
|
+
}
|
|
223
|
+
const name = extractSimpleTypeName(argNode);
|
|
224
|
+
if (name)
|
|
225
|
+
result.push(name);
|
|
226
|
+
}
|
|
227
|
+
return result;
|
|
228
|
+
};
|
|
229
|
+
/** Extract element type from a C++ type annotation AST node.
|
|
230
|
+
* Handles: template_type (vector<User>, map<string, User>),
|
|
231
|
+
* pointer/reference types (User*, User&). */
|
|
232
|
+
const extractCppElementTypeFromTypeNode = (typeNode, pos = 'last', depth = 0) => {
|
|
233
|
+
if (depth > 50)
|
|
234
|
+
return undefined;
|
|
235
|
+
// template_type: vector<User>, map<string, User> — extract type arg based on position
|
|
236
|
+
if (typeNode.type === 'template_type') {
|
|
237
|
+
const args = extractCppTemplateTypeArgs(typeNode);
|
|
238
|
+
if (args.length >= 1)
|
|
239
|
+
return pos === 'first' ? args[0] : args[args.length - 1];
|
|
240
|
+
}
|
|
241
|
+
// reference/pointer types: unwrap and recurse (vector<User>& → vector<User>)
|
|
242
|
+
if (typeNode.type === 'reference_type' || typeNode.type === 'pointer_type'
|
|
243
|
+
|| typeNode.type === 'type_descriptor') {
|
|
244
|
+
const inner = typeNode.lastNamedChild;
|
|
245
|
+
if (inner)
|
|
246
|
+
return extractCppElementTypeFromTypeNode(inner, pos, depth + 1);
|
|
247
|
+
}
|
|
248
|
+
// qualified/scoped types: std::vector<User> → unwrap to template_type child
|
|
249
|
+
if (typeNode.type === 'qualified_identifier' || typeNode.type === 'scoped_type_identifier') {
|
|
250
|
+
const inner = typeNode.lastNamedChild;
|
|
251
|
+
if (inner)
|
|
252
|
+
return extractCppElementTypeFromTypeNode(inner, pos, depth + 1);
|
|
253
|
+
}
|
|
254
|
+
return undefined;
|
|
255
|
+
};
|
|
256
|
+
/** Walk up from a for-range-loop to the enclosing function_definition and search parameters
|
|
257
|
+
* for one named `iterableName`. Returns the element type from its annotation. */
|
|
258
|
+
const findCppParamElementType = (iterableName, startNode, pos = 'last') => {
|
|
259
|
+
let current = startNode.parent;
|
|
260
|
+
while (current) {
|
|
261
|
+
if (current.type === 'function_definition') {
|
|
262
|
+
const declarator = current.childForFieldName('declarator');
|
|
263
|
+
// function_definition > declarator (function_declarator) > parameters (parameter_list)
|
|
264
|
+
const paramsNode = declarator?.childForFieldName('parameters');
|
|
265
|
+
if (paramsNode) {
|
|
266
|
+
for (let i = 0; i < paramsNode.namedChildCount; i++) {
|
|
267
|
+
const param = paramsNode.namedChild(i);
|
|
268
|
+
if (!param || param.type !== 'parameter_declaration')
|
|
269
|
+
continue;
|
|
270
|
+
const paramDeclarator = param.childForFieldName('declarator');
|
|
271
|
+
if (!paramDeclarator)
|
|
272
|
+
continue;
|
|
273
|
+
// Unwrap reference/pointer declarators: vector<User>& users → &users
|
|
274
|
+
let identNode = paramDeclarator;
|
|
275
|
+
if (identNode.type === 'reference_declarator' || identNode.type === 'pointer_declarator') {
|
|
276
|
+
identNode = identNode.firstNamedChild ?? identNode;
|
|
277
|
+
}
|
|
278
|
+
if (identNode.text !== iterableName)
|
|
279
|
+
continue;
|
|
280
|
+
const typeNode = param.childForFieldName('type');
|
|
281
|
+
if (typeNode)
|
|
282
|
+
return extractCppElementTypeFromTypeNode(typeNode, pos);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
break;
|
|
286
|
+
}
|
|
287
|
+
current = current.parent;
|
|
288
|
+
}
|
|
289
|
+
return undefined;
|
|
290
|
+
};
|
|
291
|
+
/** C++: for (auto& user : users) — extract loop variable binding.
|
|
292
|
+
* Handles explicit types (for (User& user : users)) and auto (for (auto& user : users)).
|
|
293
|
+
* For auto, resolves element type from the iterable's container type. */
|
|
294
|
+
const extractForLoopBinding = (node, { scopeEnv, declarationTypeNodes, scope }) => {
|
|
295
|
+
if (node.type !== 'for_range_loop')
|
|
296
|
+
return;
|
|
297
|
+
const typeNode = node.childForFieldName('type');
|
|
298
|
+
const declaratorNode = node.childForFieldName('declarator');
|
|
299
|
+
const rightNode = node.childForFieldName('right');
|
|
300
|
+
if (!typeNode || !declaratorNode || !rightNode)
|
|
301
|
+
return;
|
|
302
|
+
// Unwrap reference/pointer declarator to get the loop variable name
|
|
303
|
+
let nameNode = declaratorNode;
|
|
304
|
+
if (nameNode.type === 'reference_declarator' || nameNode.type === 'pointer_declarator') {
|
|
305
|
+
nameNode = nameNode.firstNamedChild ?? nameNode;
|
|
306
|
+
}
|
|
307
|
+
// Handle structured bindings: auto& [key, value] or auto [key, value]
|
|
308
|
+
// Bind the last identifier (value heuristic for [key, value] patterns)
|
|
309
|
+
let loopVarName;
|
|
310
|
+
if (nameNode.type === 'structured_binding_declarator') {
|
|
311
|
+
const lastChild = nameNode.lastNamedChild;
|
|
312
|
+
if (lastChild?.type === 'identifier') {
|
|
313
|
+
loopVarName = lastChild.text;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
else if (declaratorNode.type === 'structured_binding_declarator') {
|
|
317
|
+
const lastChild = declaratorNode.lastNamedChild;
|
|
318
|
+
if (lastChild?.type === 'identifier') {
|
|
319
|
+
loopVarName = lastChild.text;
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
const varName = loopVarName ?? extractVarName(nameNode);
|
|
323
|
+
if (!varName)
|
|
324
|
+
return;
|
|
325
|
+
// Check if the type is auto/placeholder — if not, use the explicit type directly
|
|
326
|
+
const isAuto = typeNode.type === 'placeholder_type_specifier'
|
|
327
|
+
|| typeNode.text === 'auto'
|
|
328
|
+
|| typeNode.text === 'const auto'
|
|
329
|
+
|| typeNode.text === 'decltype(auto)';
|
|
330
|
+
if (!isAuto) {
|
|
331
|
+
// Explicit type: for (User& user : users) — extract directly
|
|
332
|
+
const typeName = extractSimpleTypeName(typeNode);
|
|
333
|
+
if (typeName)
|
|
334
|
+
scopeEnv.set(varName, typeName);
|
|
335
|
+
return;
|
|
336
|
+
}
|
|
337
|
+
// auto/const auto/auto& — resolve from the iterable's container type
|
|
338
|
+
// Extract iterable name + optional method
|
|
339
|
+
let iterableName;
|
|
340
|
+
let methodName;
|
|
341
|
+
if (rightNode.type === 'identifier') {
|
|
342
|
+
iterableName = rightNode.text;
|
|
343
|
+
}
|
|
344
|
+
else if (rightNode.type === 'field_expression') {
|
|
345
|
+
const prop = rightNode.lastNamedChild;
|
|
346
|
+
if (prop)
|
|
347
|
+
iterableName = prop.text;
|
|
348
|
+
}
|
|
349
|
+
else if (rightNode.type === 'call_expression') {
|
|
350
|
+
// users.begin() is NOT used in range-for, but container.items() etc. might be
|
|
351
|
+
const fieldExpr = rightNode.childForFieldName('function');
|
|
352
|
+
if (fieldExpr?.type === 'field_expression') {
|
|
353
|
+
const obj = fieldExpr.firstNamedChild;
|
|
354
|
+
if (obj?.type === 'identifier')
|
|
355
|
+
iterableName = obj.text;
|
|
356
|
+
const field = fieldExpr.lastNamedChild;
|
|
357
|
+
if (field?.type === 'field_identifier')
|
|
358
|
+
methodName = field.text;
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
else if (rightNode.type === 'pointer_expression') {
|
|
362
|
+
// Dereference: for (auto& user : *ptr) → pointer_expression > identifier
|
|
363
|
+
// Only handles simple *identifier; *this->field and **ptr are not resolved.
|
|
364
|
+
const operand = rightNode.lastNamedChild;
|
|
365
|
+
if (operand?.type === 'identifier')
|
|
366
|
+
iterableName = operand.text;
|
|
367
|
+
}
|
|
368
|
+
if (!iterableName)
|
|
369
|
+
return;
|
|
370
|
+
const containerTypeName = scopeEnv.get(iterableName);
|
|
371
|
+
const typeArgPos = methodToTypeArgPosition(methodName, containerTypeName);
|
|
372
|
+
const elementType = resolveIterableElementType(iterableName, node, scopeEnv, declarationTypeNodes, scope, extractCppElementTypeFromTypeNode, findCppParamElementType, typeArgPos);
|
|
373
|
+
if (elementType)
|
|
374
|
+
scopeEnv.set(varName, elementType);
|
|
375
|
+
};
|
|
376
|
+
export const typeConfig = {
|
|
377
|
+
declarationNodeTypes: DECLARATION_NODE_TYPES,
|
|
378
|
+
forLoopNodeTypes: FOR_LOOP_NODE_TYPES,
|
|
379
|
+
extractDeclaration,
|
|
380
|
+
extractParameter,
|
|
381
|
+
extractInitializer,
|
|
382
|
+
scanConstructorBinding,
|
|
383
|
+
extractForLoopBinding,
|
|
384
|
+
extractPendingAssignment,
|
|
385
|
+
};
|