c-next 0.1.70 → 0.1.72

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 (205) hide show
  1. package/package.json +1 -1
  2. package/src/lib/__tests__/parseCHeader.mocked.test.ts +69 -54
  3. package/src/lib/parseCHeader.ts +56 -23
  4. package/src/lib/parseWithSymbols.ts +195 -53
  5. package/src/transpiler/Transpiler.ts +180 -63
  6. package/src/transpiler/logic/analysis/FunctionCallAnalyzer.ts +1 -2
  7. package/src/transpiler/logic/analysis/InitializationAnalyzer.ts +1 -2
  8. package/src/transpiler/logic/analysis/PassByValueAnalyzer.ts +51 -2
  9. package/src/transpiler/logic/analysis/__tests__/FunctionCallAnalyzer.test.ts +18 -12
  10. package/src/transpiler/logic/analysis/__tests__/InitializationAnalyzer.test.ts +9 -9
  11. package/src/transpiler/logic/analysis/__tests__/runAnalyzers.test.ts +5 -5
  12. package/src/transpiler/logic/symbols/SymbolTable.ts +729 -265
  13. package/src/transpiler/logic/symbols/SymbolUtils.ts +2 -2
  14. package/src/transpiler/logic/symbols/__tests__/SymbolTable.test.ts +415 -751
  15. package/src/transpiler/logic/symbols/c/__tests__/CResolver.integration.test.ts +573 -0
  16. package/src/transpiler/logic/symbols/c/__tests__/testHelpers.ts +20 -0
  17. package/src/transpiler/logic/symbols/c/collectors/EnumCollector.ts +82 -0
  18. package/src/transpiler/logic/symbols/c/collectors/FunctionCollector.ts +106 -0
  19. package/src/transpiler/logic/symbols/c/collectors/StructCollector.ts +173 -0
  20. package/src/transpiler/logic/symbols/c/collectors/TypedefCollector.ts +35 -0
  21. package/src/transpiler/logic/symbols/c/collectors/VariableCollector.ts +80 -0
  22. package/src/transpiler/logic/symbols/c/index.ts +333 -0
  23. package/src/transpiler/logic/symbols/c/utils/DeclaratorUtils.ts +269 -0
  24. package/src/transpiler/logic/symbols/cnext/__tests__/BitmapCollector.test.ts +50 -11
  25. package/src/transpiler/logic/symbols/cnext/__tests__/CNextResolver.integration.test.ts +45 -34
  26. package/src/transpiler/logic/symbols/cnext/__tests__/EnumCollector.test.ts +30 -13
  27. package/src/transpiler/logic/symbols/cnext/__tests__/FunctionCollector.test.ts +279 -64
  28. package/src/transpiler/logic/symbols/cnext/__tests__/RegisterCollector.test.ts +60 -13
  29. package/src/transpiler/logic/symbols/cnext/__tests__/ScopeCollector.test.ts +40 -37
  30. package/src/transpiler/logic/symbols/cnext/__tests__/StructCollector.test.ts +131 -45
  31. package/src/transpiler/logic/symbols/cnext/__tests__/TSymbolInfoAdapter.test.ts +223 -139
  32. package/src/transpiler/logic/symbols/cnext/__tests__/VariableCollector.test.ts +79 -25
  33. package/src/transpiler/logic/symbols/cnext/__tests__/testUtils.ts +53 -0
  34. package/src/transpiler/logic/symbols/cnext/adapters/TSymbolInfoAdapter.ts +83 -43
  35. package/src/transpiler/logic/symbols/cnext/collectors/BitmapCollector.ts +14 -13
  36. package/src/transpiler/logic/symbols/cnext/collectors/EnumCollector.ts +11 -10
  37. package/src/transpiler/logic/symbols/cnext/collectors/FunctionCollector.ts +83 -34
  38. package/src/transpiler/logic/symbols/cnext/collectors/RegisterCollector.ts +22 -18
  39. package/src/transpiler/logic/symbols/cnext/collectors/ScopeCollector.ts +53 -35
  40. package/src/transpiler/logic/symbols/cnext/collectors/StructCollector.ts +30 -23
  41. package/src/transpiler/logic/symbols/cnext/collectors/VariableCollector.ts +18 -19
  42. package/src/transpiler/logic/symbols/cnext/index.ts +36 -14
  43. package/src/transpiler/logic/symbols/cnext/types/IScopeCollectorResult.ts +2 -2
  44. package/src/transpiler/logic/symbols/cnext/utils/SymbolNameUtils.ts +27 -0
  45. package/src/transpiler/logic/symbols/cpp/__tests__/CppResolver.integration.test.ts +270 -0
  46. package/src/transpiler/logic/symbols/cpp/__tests__/testHelpers.ts +20 -0
  47. package/src/transpiler/logic/symbols/cpp/collectors/ClassCollector.ts +317 -0
  48. package/src/transpiler/logic/symbols/cpp/collectors/EnumCollector.ts +71 -0
  49. package/src/transpiler/logic/symbols/cpp/collectors/FunctionCollector.ts +155 -0
  50. package/src/transpiler/logic/symbols/cpp/collectors/NamespaceCollector.ts +65 -0
  51. package/src/transpiler/logic/symbols/cpp/collectors/TypeAliasCollector.ts +46 -0
  52. package/src/transpiler/logic/symbols/cpp/collectors/VariableCollector.ts +54 -0
  53. package/src/transpiler/logic/symbols/cpp/index.ts +366 -0
  54. package/src/transpiler/logic/symbols/cpp/utils/DeclaratorUtils.ts +248 -0
  55. package/src/transpiler/logic/symbols/shared/IExtractedParameter.ts +18 -0
  56. package/src/transpiler/logic/symbols/shared/ParameterExtractorUtils.ts +73 -0
  57. package/src/transpiler/output/codegen/CodeGenerator.ts +268 -1674
  58. package/src/transpiler/output/codegen/__tests__/CodeGenerator.test.ts +7 -1
  59. package/src/transpiler/output/codegen/assignment/AssignmentClassifier.ts +2 -1
  60. package/src/transpiler/output/codegen/assignment/handlers/AssignmentHandlerUtils.ts +7 -1
  61. package/src/transpiler/output/codegen/assignment/handlers/BitmapHandlers.ts +6 -2
  62. package/src/transpiler/output/codegen/assignment/handlers/RegisterHandlers.ts +2 -1
  63. package/src/transpiler/output/codegen/generators/declarationGenerators/ScopeGenerator.ts +21 -8
  64. package/src/transpiler/output/codegen/generators/declarationGenerators/ScopedRegisterGenerator.ts +3 -2
  65. package/src/transpiler/output/codegen/generators/expressions/CallExprUtils.ts +9 -3
  66. package/src/transpiler/output/codegen/generators/expressions/__tests__/CallExprGenerator.test.ts +3 -4
  67. package/src/transpiler/output/codegen/generators/expressions/__tests__/CallExprUtils.test.ts +4 -8
  68. package/src/transpiler/output/codegen/helpers/ArgumentGenerator.ts +236 -0
  69. package/src/transpiler/output/codegen/helpers/CppConstructorHelper.ts +3 -3
  70. package/src/transpiler/output/codegen/helpers/FunctionContextManager.ts +435 -0
  71. package/src/transpiler/output/codegen/helpers/StringOperationsHelper.ts +203 -0
  72. package/src/transpiler/output/codegen/helpers/SymbolLookupHelper.ts +8 -12
  73. package/src/transpiler/output/codegen/helpers/TypeRegistrationEngine.ts +520 -0
  74. package/src/transpiler/output/codegen/helpers/VariableDeclHelper.ts +735 -0
  75. package/src/transpiler/output/codegen/helpers/VariableDeclarationFormatter.ts +1 -1
  76. package/src/transpiler/output/codegen/helpers/__tests__/ArgumentGenerator.test.ts +521 -0
  77. package/src/transpiler/output/codegen/helpers/__tests__/CppConstructorHelper.test.ts +4 -5
  78. package/src/transpiler/output/codegen/helpers/__tests__/FunctionContextManager.test.ts +983 -0
  79. package/src/transpiler/output/codegen/helpers/__tests__/StringOperationsHelper.test.ts +269 -0
  80. package/src/transpiler/output/codegen/helpers/__tests__/SymbolLookupHelper.test.ts +31 -32
  81. package/src/transpiler/output/codegen/helpers/__tests__/TypeRegistrationEngine.test.ts +186 -0
  82. package/src/transpiler/output/codegen/helpers/__tests__/VariableDeclHelper.test.ts +460 -0
  83. package/src/transpiler/output/codegen/helpers/types/IArgumentGeneratorCallbacks.ts +32 -0
  84. package/src/transpiler/output/codegen/resolution/EnumTypeResolver.ts +5 -1
  85. package/src/transpiler/output/codegen/types/IFunctionContextCallbacks.ts +12 -0
  86. package/src/transpiler/output/codegen/types/IVariableFormatInput.ts +1 -1
  87. package/src/transpiler/output/codegen/utils/QualifiedNameGenerator.ts +114 -0
  88. package/src/transpiler/output/codegen/utils/__tests__/QualifiedNameGenerator.test.ts +183 -0
  89. package/src/transpiler/output/headers/BaseHeaderGenerator.ts +4 -4
  90. package/src/transpiler/output/headers/ExternalTypeHeaderBuilder.ts +7 -7
  91. package/src/transpiler/output/headers/HeaderGenerator.ts +9 -7
  92. package/src/transpiler/output/headers/HeaderGeneratorUtils.ts +19 -20
  93. package/src/transpiler/output/headers/__tests__/BaseHeaderGenerator.test.ts +15 -18
  94. package/src/transpiler/output/headers/__tests__/CHeaderGenerator.test.ts +63 -64
  95. package/src/transpiler/output/headers/__tests__/CppHeaderGenerator.test.ts +36 -32
  96. package/src/transpiler/output/headers/__tests__/ExternalTypeHeaderBuilder.test.ts +26 -26
  97. package/src/transpiler/output/headers/__tests__/HeaderGenerator.test.ts +87 -59
  98. package/src/transpiler/output/headers/__tests__/HeaderGeneratorUtils.test.ts +57 -58
  99. package/src/transpiler/output/headers/adapters/HeaderSymbolAdapter.ts +222 -0
  100. package/src/transpiler/output/headers/adapters/__tests__/HeaderSymbolAdapter.test.ts +538 -0
  101. package/src/transpiler/output/headers/types/IGroupedSymbols.ts +8 -8
  102. package/src/transpiler/output/headers/types/IHeaderSymbol.ts +62 -0
  103. package/src/transpiler/state/CodeGenState.ts +20 -33
  104. package/src/transpiler/state/SymbolRegistry.ts +181 -0
  105. package/src/transpiler/{types → state}/TranspilerState.ts +1 -1
  106. package/src/transpiler/state/__tests__/CodeGenState.test.ts +67 -59
  107. package/src/transpiler/state/__tests__/SymbolRegistry.test.ts +249 -0
  108. package/src/transpiler/{types → state}/__tests__/TranspilerState.test.ts +1 -1
  109. package/src/transpiler/types/ICachedFileEntry.ts +1 -1
  110. package/src/transpiler/types/IConflict.ts +14 -0
  111. package/src/transpiler/types/IPipelineInput.ts +0 -3
  112. package/src/transpiler/types/ISerializedSymbol.ts +11 -0
  113. package/src/transpiler/types/TPrimitiveKind.ts +20 -0
  114. package/src/transpiler/types/TType.ts +103 -0
  115. package/src/transpiler/types/TVisibility.ts +6 -0
  116. package/src/transpiler/types/symbol-kinds/TSymbolKind.ts +10 -0
  117. package/src/transpiler/types/symbol-kinds/TSymbolKindC.ts +12 -0
  118. package/src/transpiler/types/symbol-kinds/TSymbolKindCNext.ts +16 -0
  119. package/src/transpiler/types/symbol-kinds/TSymbolKindCpp.ts +14 -0
  120. package/src/transpiler/types/symbols/IBaseSymbol.ts +31 -0
  121. package/src/transpiler/{logic/symbols/types → types/symbols}/IBitmapFieldInfo.ts +2 -2
  122. package/src/transpiler/types/symbols/IBitmapSymbol.ts +21 -0
  123. package/src/transpiler/{logic/symbols/types → types/symbols}/IEnumSymbol.ts +5 -6
  124. package/src/transpiler/types/symbols/IFieldInfo.ts +26 -0
  125. package/src/transpiler/types/symbols/IFunctionSymbol.ts +30 -0
  126. package/src/transpiler/types/symbols/IParameterInfo.ts +26 -0
  127. package/src/transpiler/{logic/symbols/types → types/symbols}/IRegisterMemberInfo.ts +4 -4
  128. package/src/transpiler/types/symbols/IRegisterSymbol.ts +18 -0
  129. package/src/transpiler/types/symbols/IScopeSymbol.ts +32 -0
  130. package/src/transpiler/{logic/symbols/types → types/symbols}/IStructFieldInfo.ts +2 -1
  131. package/src/transpiler/types/symbols/IStructSymbol.ts +15 -0
  132. package/src/transpiler/types/symbols/IVariableSymbol.ts +30 -0
  133. package/src/transpiler/types/symbols/SymbolGuards.ts +43 -0
  134. package/src/transpiler/types/symbols/TAnySymbol.ts +22 -0
  135. package/src/transpiler/types/symbols/TSymbol.ts +32 -0
  136. package/src/transpiler/types/symbols/__tests__/IBaseSymbol.test.ts +56 -0
  137. package/src/transpiler/types/symbols/__tests__/SymbolGuards.test.ts +57 -0
  138. package/src/transpiler/types/symbols/c/ICBaseSymbol.ts +28 -0
  139. package/src/transpiler/types/symbols/c/ICEnumMemberSymbol.ts +17 -0
  140. package/src/transpiler/types/symbols/c/ICEnumSymbol.ts +17 -0
  141. package/src/transpiler/types/symbols/c/ICFieldInfo.ts +16 -0
  142. package/src/transpiler/types/symbols/c/ICFunctionSymbol.ts +21 -0
  143. package/src/transpiler/types/symbols/c/ICParameterInfo.ts +19 -0
  144. package/src/transpiler/types/symbols/c/ICStructSymbol.ts +21 -0
  145. package/src/transpiler/types/symbols/c/ICTypedefSymbol.ts +14 -0
  146. package/src/transpiler/types/symbols/c/ICVariableSymbol.ts +26 -0
  147. package/src/transpiler/types/symbols/c/TCSymbol.ts +26 -0
  148. package/src/transpiler/types/symbols/cpp/ICppBaseSymbol.ts +31 -0
  149. package/src/transpiler/types/symbols/cpp/ICppClassSymbol.ts +15 -0
  150. package/src/transpiler/types/symbols/cpp/ICppEnumMemberSymbol.ts +14 -0
  151. package/src/transpiler/types/symbols/cpp/ICppEnumSymbol.ts +14 -0
  152. package/src/transpiler/types/symbols/cpp/ICppFieldInfo.ts +16 -0
  153. package/src/transpiler/types/symbols/cpp/ICppFunctionSymbol.ts +21 -0
  154. package/src/transpiler/types/symbols/cpp/ICppNamespaceSymbol.ts +11 -0
  155. package/src/transpiler/types/symbols/cpp/ICppParameterInfo.ts +19 -0
  156. package/src/transpiler/types/symbols/cpp/ICppStructSymbol.ts +16 -0
  157. package/src/transpiler/types/symbols/cpp/ICppTypeAliasSymbol.ts +14 -0
  158. package/src/transpiler/types/symbols/cpp/ICppVariableSymbol.ts +23 -0
  159. package/src/transpiler/types/symbols/cpp/TCppSymbol.ts +30 -0
  160. package/src/utils/CppNamespaceUtils.ts +3 -4
  161. package/src/utils/FunctionUtils.ts +92 -0
  162. package/src/utils/ParameterUtils.ts +55 -0
  163. package/src/utils/PrimitiveKindUtils.ts +33 -0
  164. package/src/utils/ScopeUtils.ts +105 -0
  165. package/src/utils/TTypeUtils.ts +159 -0
  166. package/src/utils/TypeResolver.ts +132 -0
  167. package/src/utils/__tests__/CppNamespaceUtils.test.ts +92 -99
  168. package/src/utils/__tests__/FunctionUtils.test.ts +284 -0
  169. package/src/utils/__tests__/ParameterUtils.test.ts +174 -0
  170. package/src/utils/__tests__/PrimitiveKindUtils.test.ts +59 -0
  171. package/src/utils/__tests__/ScopeUtils.test.ts +53 -0
  172. package/src/utils/__tests__/TTypeUtils.test.ts +245 -0
  173. package/src/utils/__tests__/TypeResolver.test.ts +332 -0
  174. package/src/utils/cache/CacheManager.ts +91 -50
  175. package/src/utils/cache/__tests__/CacheManager.test.ts +180 -114
  176. package/src/transpiler/logic/symbols/AutoConstUpdater.ts +0 -93
  177. package/src/transpiler/logic/symbols/CSymbolCollector.ts +0 -648
  178. package/src/transpiler/logic/symbols/CppSymbolCollector.ts +0 -874
  179. package/src/transpiler/logic/symbols/SymbolCollectorContext.ts +0 -68
  180. package/src/transpiler/logic/symbols/__tests__/AutoConstUpdater.test.ts +0 -418
  181. package/src/transpiler/logic/symbols/__tests__/CSymbolCollector.test.ts +0 -685
  182. package/src/transpiler/logic/symbols/__tests__/CppSymbolCollector.test.ts +0 -1146
  183. package/src/transpiler/logic/symbols/__tests__/SymbolCollectorContext.test.ts +0 -290
  184. package/src/transpiler/logic/symbols/__tests__/cTestHelpers.ts +0 -43
  185. package/src/transpiler/logic/symbols/__tests__/cppTestHelpers.ts +0 -40
  186. package/src/transpiler/logic/symbols/cnext/__tests__/TSymbolAdapter.test.ts +0 -595
  187. package/src/transpiler/logic/symbols/cnext/adapters/TSymbolAdapter.ts +0 -345
  188. package/src/transpiler/logic/symbols/types/IBaseSymbol.ts +0 -27
  189. package/src/transpiler/logic/symbols/types/IBitmapSymbol.ts +0 -23
  190. package/src/transpiler/logic/symbols/types/ICollectorContext.ts +0 -19
  191. package/src/transpiler/logic/symbols/types/IConflict.ts +0 -20
  192. package/src/transpiler/logic/symbols/types/IFieldInfo.ts +0 -18
  193. package/src/transpiler/logic/symbols/types/IFunctionSymbol.ts +0 -25
  194. package/src/transpiler/logic/symbols/types/IParameterInfo.ts +0 -24
  195. package/src/transpiler/logic/symbols/types/IRegisterSymbol.ts +0 -20
  196. package/src/transpiler/logic/symbols/types/IScopeSymbol.ts +0 -19
  197. package/src/transpiler/logic/symbols/types/IStructSymbol.ts +0 -16
  198. package/src/transpiler/logic/symbols/types/IVariableSymbol.ts +0 -30
  199. package/src/transpiler/logic/symbols/types/TSymbol.ts +0 -36
  200. package/src/transpiler/logic/symbols/types/__tests__/SymbolGuards.test.ts +0 -244
  201. package/src/transpiler/logic/symbols/types/typeGuards.ts +0 -44
  202. package/src/utils/types/ESymbolKind.ts +0 -19
  203. package/src/utils/types/ISymbol.ts +0 -64
  204. /package/src/transpiler/{types → constants}/BITMAP_BACKING_TYPE.ts +0 -0
  205. /package/src/transpiler/{types → constants}/BITMAP_SIZE.ts +0 -0
@@ -0,0 +1,983 @@
1
+ /**
2
+ * Unit tests for FunctionContextManager
3
+ *
4
+ * Issue #793: Tests for the extracted function context manager.
5
+ */
6
+
7
+ import { describe, it, expect, beforeEach, vi } from "vitest";
8
+ import FunctionContextManager from "../FunctionContextManager.js";
9
+ import IFunctionContextCallbacks from "../../types/IFunctionContextCallbacks.js";
10
+ import CodeGenState from "../../../../state/CodeGenState.js";
11
+
12
+ /**
13
+ * Helper to set up CodeGenState.symbols with minimal fields.
14
+ */
15
+ function setupSymbols(
16
+ overrides: {
17
+ knownEnums?: Set<string>;
18
+ knownBitmaps?: Set<string>;
19
+ bitmapBitWidth?: Map<string, number>;
20
+ } = {},
21
+ ): void {
22
+ CodeGenState.symbols = {
23
+ knownScopes: new Set(),
24
+ knownStructs: new Set(),
25
+ knownRegisters: new Set(),
26
+ knownEnums: overrides.knownEnums ?? new Set(),
27
+ knownBitmaps: overrides.knownBitmaps ?? new Set(),
28
+ scopeMembers: new Map(),
29
+ scopeMemberVisibility: new Map(),
30
+ structFields: new Map(),
31
+ structFieldArrays: new Map(),
32
+ structFieldDimensions: new Map(),
33
+ enumMembers: new Map(),
34
+ bitmapFields: new Map(),
35
+ bitmapBackingType: new Map(),
36
+ bitmapBitWidth: overrides.bitmapBitWidth ?? new Map(),
37
+ scopedRegisters: new Map(),
38
+ registerMemberAccess: new Map(),
39
+ registerMemberTypes: new Map(),
40
+ registerBaseAddresses: new Map(),
41
+ registerMemberOffsets: new Map(),
42
+ registerMemberCTypes: new Map(),
43
+ scopeVariableUsage: new Map(),
44
+ scopePrivateConstValues: new Map(),
45
+ functionReturnTypes: new Map(),
46
+ getSingleFunctionForVariable: () => null,
47
+ hasPublicSymbols: () => false,
48
+ };
49
+ }
50
+
51
+ /**
52
+ * Default callbacks for testing.
53
+ */
54
+ function createMockCallbacks(): IFunctionContextCallbacks {
55
+ return {
56
+ isStructType: vi.fn(() => false),
57
+ resolveQualifiedType: vi.fn((ids: string[]) => ids.join("_")),
58
+ };
59
+ }
60
+
61
+ /**
62
+ * Helper to create a mock parameter context.
63
+ */
64
+ function createMockParam(
65
+ name: string,
66
+ typeText: string,
67
+ options: {
68
+ isArray?: boolean;
69
+ isConst?: boolean;
70
+ isPrimitive?: boolean;
71
+ isUserType?: boolean;
72
+ isString?: boolean;
73
+ stringCapacity?: number;
74
+ } = {},
75
+ ): never {
76
+ const {
77
+ isArray,
78
+ isConst,
79
+ isPrimitive,
80
+ isUserType,
81
+ isString,
82
+ stringCapacity,
83
+ } = options;
84
+
85
+ return {
86
+ IDENTIFIER: () => ({ getText: () => name }),
87
+ arrayDimension: () => (isArray ? [{ expression: () => null }] : []),
88
+ constModifier: () => (isConst ? {} : null),
89
+ type: () => ({
90
+ getText: () => typeText,
91
+ primitiveType: () => (isPrimitive ? { getText: () => typeText } : null),
92
+ userType: () => (isUserType ? { getText: () => typeText } : null),
93
+ qualifiedType: () => null,
94
+ scopedType: () => null,
95
+ globalType: () => null,
96
+ stringType: () =>
97
+ isString
98
+ ? {
99
+ getText: () =>
100
+ stringCapacity ? `string<${stringCapacity}>` : "string",
101
+ INTEGER_LITERAL: () =>
102
+ stringCapacity
103
+ ? { getText: () => String(stringCapacity) }
104
+ : null,
105
+ }
106
+ : null,
107
+ arrayType: () => null,
108
+ }),
109
+ } as never;
110
+ }
111
+
112
+ /**
113
+ * Helper to create a mock function declaration context.
114
+ */
115
+ function createMockFunctionDecl(
116
+ name: string,
117
+ returnType: string,
118
+ params: never[] = [],
119
+ ): never {
120
+ return {
121
+ type: () => ({
122
+ getText: () => returnType,
123
+ }),
124
+ parameterList: () =>
125
+ params.length > 0
126
+ ? {
127
+ parameter: () => params,
128
+ }
129
+ : null,
130
+ } as never;
131
+ }
132
+
133
+ describe("FunctionContextManager", () => {
134
+ beforeEach(() => {
135
+ CodeGenState.reset();
136
+ setupSymbols();
137
+ });
138
+
139
+ describe("setupFunctionContext", () => {
140
+ it("sets current function name without scope", () => {
141
+ const callbacks = createMockCallbacks();
142
+ const ctx = createMockFunctionDecl("myFunc", "void");
143
+
144
+ FunctionContextManager.setupFunctionContext("myFunc", ctx, callbacks);
145
+
146
+ expect(CodeGenState.currentFunctionName).toBe("myFunc");
147
+ });
148
+
149
+ it("sets current function name with scope prefix", () => {
150
+ CodeGenState.currentScope = "MyScope";
151
+ const callbacks = createMockCallbacks();
152
+ const ctx = createMockFunctionDecl("myFunc", "void");
153
+
154
+ FunctionContextManager.setupFunctionContext("myFunc", ctx, callbacks);
155
+
156
+ expect(CodeGenState.currentFunctionName).toBe("MyScope_myFunc");
157
+ });
158
+
159
+ it("sets current function return type", () => {
160
+ const callbacks = createMockCallbacks();
161
+ const ctx = createMockFunctionDecl("myFunc", "u32");
162
+
163
+ FunctionContextManager.setupFunctionContext("myFunc", ctx, callbacks);
164
+
165
+ expect(CodeGenState.currentFunctionReturnType).toBe("u32");
166
+ });
167
+
168
+ it("sets inFunctionBody to true", () => {
169
+ const callbacks = createMockCallbacks();
170
+ const ctx = createMockFunctionDecl("myFunc", "void");
171
+
172
+ FunctionContextManager.setupFunctionContext("myFunc", ctx, callbacks);
173
+
174
+ expect(CodeGenState.inFunctionBody).toBe(true);
175
+ });
176
+
177
+ it("clears local variables", () => {
178
+ CodeGenState.localVariables.add("existingVar");
179
+ const callbacks = createMockCallbacks();
180
+ const ctx = createMockFunctionDecl("myFunc", "void");
181
+
182
+ FunctionContextManager.setupFunctionContext("myFunc", ctx, callbacks);
183
+
184
+ expect(CodeGenState.localVariables.size).toBe(0);
185
+ });
186
+
187
+ it("processes parameters when present", () => {
188
+ const callbacks = createMockCallbacks();
189
+ const params = [createMockParam("x", "u32", { isPrimitive: true })];
190
+ const ctx = createMockFunctionDecl("myFunc", "void", params);
191
+
192
+ FunctionContextManager.setupFunctionContext("myFunc", ctx, callbacks);
193
+
194
+ expect(CodeGenState.currentParameters.has("x")).toBe(true);
195
+ });
196
+ });
197
+
198
+ describe("cleanupFunctionContext", () => {
199
+ it("resets inFunctionBody to false", () => {
200
+ CodeGenState.inFunctionBody = true;
201
+
202
+ FunctionContextManager.cleanupFunctionContext();
203
+
204
+ expect(CodeGenState.inFunctionBody).toBe(false);
205
+ });
206
+
207
+ it("clears local variables", () => {
208
+ CodeGenState.localVariables.add("localVar");
209
+
210
+ FunctionContextManager.cleanupFunctionContext();
211
+
212
+ expect(CodeGenState.localVariables.size).toBe(0);
213
+ });
214
+
215
+ it("clears float bit shadows", () => {
216
+ CodeGenState.floatBitShadows.add("shadow1");
217
+
218
+ FunctionContextManager.cleanupFunctionContext();
219
+
220
+ expect(CodeGenState.floatBitShadows.size).toBe(0);
221
+ });
222
+
223
+ it("clears mainArgsName", () => {
224
+ CodeGenState.mainArgsName = "args";
225
+
226
+ FunctionContextManager.cleanupFunctionContext();
227
+
228
+ expect(CodeGenState.mainArgsName).toBeNull();
229
+ });
230
+
231
+ it("clears currentFunctionName", () => {
232
+ CodeGenState.currentFunctionName = "myFunc";
233
+
234
+ FunctionContextManager.cleanupFunctionContext();
235
+
236
+ expect(CodeGenState.currentFunctionName).toBeNull();
237
+ });
238
+
239
+ it("clears currentFunctionReturnType", () => {
240
+ CodeGenState.currentFunctionReturnType = "u32";
241
+
242
+ FunctionContextManager.cleanupFunctionContext();
243
+
244
+ expect(CodeGenState.currentFunctionReturnType).toBeNull();
245
+ });
246
+
247
+ it("clears parameters", () => {
248
+ CodeGenState.currentParameters.set("x", {
249
+ name: "x",
250
+ baseType: "u32",
251
+ isArray: false,
252
+ isStruct: false,
253
+ isConst: false,
254
+ isCallback: false,
255
+ isString: false,
256
+ });
257
+
258
+ FunctionContextManager.cleanupFunctionContext();
259
+
260
+ expect(CodeGenState.currentParameters.size).toBe(0);
261
+ });
262
+ });
263
+
264
+ describe("resolveReturnTypeAndParams", () => {
265
+ it("returns int for main with args", () => {
266
+ const params = [createMockParam("args", "u8", { isArray: true })];
267
+ const ctx = createMockFunctionDecl("main", "void", params);
268
+
269
+ const result = FunctionContextManager.resolveReturnTypeAndParams(
270
+ "main",
271
+ "void",
272
+ true,
273
+ ctx,
274
+ );
275
+
276
+ expect(result.actualReturnType).toBe("int");
277
+ expect(result.initialParams).toBe("int argc, char *argv[]");
278
+ expect(CodeGenState.mainArgsName).toBe("args");
279
+ });
280
+
281
+ it("returns int for main without args", () => {
282
+ const ctx = createMockFunctionDecl("main", "void");
283
+
284
+ const result = FunctionContextManager.resolveReturnTypeAndParams(
285
+ "main",
286
+ "void",
287
+ false,
288
+ ctx,
289
+ );
290
+
291
+ expect(result.actualReturnType).toBe("int");
292
+ expect(result.initialParams).toBe("");
293
+ });
294
+
295
+ it("preserves return type for non-main functions", () => {
296
+ const ctx = createMockFunctionDecl("myFunc", "u32");
297
+
298
+ const result = FunctionContextManager.resolveReturnTypeAndParams(
299
+ "myFunc",
300
+ "u32",
301
+ false,
302
+ ctx,
303
+ );
304
+
305
+ expect(result.actualReturnType).toBe("u32");
306
+ expect(result.initialParams).toBe("");
307
+ });
308
+ });
309
+
310
+ describe("processParameterList", () => {
311
+ it("clears existing parameters", () => {
312
+ CodeGenState.currentParameters.set("existing", {
313
+ name: "existing",
314
+ baseType: "u32",
315
+ isArray: false,
316
+ isStruct: false,
317
+ isConst: false,
318
+ isCallback: false,
319
+ isString: false,
320
+ });
321
+ const callbacks = createMockCallbacks();
322
+
323
+ FunctionContextManager.processParameterList(null, callbacks);
324
+
325
+ expect(CodeGenState.currentParameters.size).toBe(0);
326
+ });
327
+
328
+ it("processes multiple parameters", () => {
329
+ const callbacks = createMockCallbacks();
330
+ const params = {
331
+ parameter: () => [
332
+ createMockParam("x", "u32", { isPrimitive: true }),
333
+ createMockParam("y", "i32", { isPrimitive: true }),
334
+ ],
335
+ } as never;
336
+
337
+ FunctionContextManager.processParameterList(params, callbacks);
338
+
339
+ expect(CodeGenState.currentParameters.size).toBe(2);
340
+ expect(CodeGenState.currentParameters.has("x")).toBe(true);
341
+ expect(CodeGenState.currentParameters.has("y")).toBe(true);
342
+ });
343
+ });
344
+
345
+ describe("processParameter", () => {
346
+ it("registers primitive parameter", () => {
347
+ const callbacks = createMockCallbacks();
348
+ const param = createMockParam("x", "u32", { isPrimitive: true });
349
+
350
+ FunctionContextManager.processParameter(param, callbacks);
351
+
352
+ const paramInfo = CodeGenState.currentParameters.get("x");
353
+ expect(paramInfo).toBeDefined();
354
+ expect(paramInfo!.baseType).toBe("u32");
355
+ expect(paramInfo!.isArray).toBe(false);
356
+ expect(paramInfo!.isStruct).toBe(false);
357
+ });
358
+
359
+ it("registers array parameter", () => {
360
+ const callbacks = createMockCallbacks();
361
+ const param = createMockParam("arr", "u8", {
362
+ isPrimitive: true,
363
+ isArray: true,
364
+ });
365
+
366
+ FunctionContextManager.processParameter(param, callbacks);
367
+
368
+ const paramInfo = CodeGenState.currentParameters.get("arr");
369
+ expect(paramInfo).toBeDefined();
370
+ expect(paramInfo!.isArray).toBe(true);
371
+ });
372
+
373
+ it("registers const parameter", () => {
374
+ const callbacks = createMockCallbacks();
375
+ const param = createMockParam("x", "u32", {
376
+ isPrimitive: true,
377
+ isConst: true,
378
+ });
379
+
380
+ FunctionContextManager.processParameter(param, callbacks);
381
+
382
+ const paramInfo = CodeGenState.currentParameters.get("x");
383
+ expect(paramInfo).toBeDefined();
384
+ expect(paramInfo!.isConst).toBe(true);
385
+ });
386
+
387
+ it("registers struct parameter using callback", () => {
388
+ const callbacks = createMockCallbacks();
389
+ (callbacks.isStructType as ReturnType<typeof vi.fn>).mockReturnValue(
390
+ true,
391
+ );
392
+ const param = createMockParam("point", "Point", { isUserType: true });
393
+
394
+ FunctionContextManager.processParameter(param, callbacks);
395
+
396
+ const paramInfo = CodeGenState.currentParameters.get("point");
397
+ expect(paramInfo).toBeDefined();
398
+ expect(paramInfo!.isStruct).toBe(true);
399
+ expect(callbacks.isStructType).toHaveBeenCalledWith("Point");
400
+ });
401
+
402
+ it("registers string parameter", () => {
403
+ const callbacks = createMockCallbacks();
404
+ const param = createMockParam("name", "string<32>", {
405
+ isString: true,
406
+ stringCapacity: 32,
407
+ });
408
+
409
+ FunctionContextManager.processParameter(param, callbacks);
410
+
411
+ const paramInfo = CodeGenState.currentParameters.get("name");
412
+ expect(paramInfo).toBeDefined();
413
+ expect(paramInfo!.isString).toBe(true);
414
+ });
415
+ });
416
+
417
+ describe("resolveParameterTypeInfo", () => {
418
+ it("resolves primitive type", () => {
419
+ const callbacks = createMockCallbacks();
420
+ const typeCtx = {
421
+ primitiveType: () => ({ getText: () => "u32" }),
422
+ userType: () => null,
423
+ qualifiedType: () => null,
424
+ scopedType: () => null,
425
+ globalType: () => null,
426
+ stringType: () => null,
427
+ arrayType: () => null,
428
+ getText: () => "u32",
429
+ } as never;
430
+
431
+ const result = FunctionContextManager.resolveParameterTypeInfo(
432
+ typeCtx,
433
+ callbacks,
434
+ );
435
+
436
+ expect(result.typeName).toBe("u32");
437
+ expect(result.isStruct).toBe(false);
438
+ expect(result.isCallback).toBe(false);
439
+ expect(result.isString).toBe(false);
440
+ });
441
+
442
+ it("resolves user type and checks struct", () => {
443
+ const callbacks = createMockCallbacks();
444
+ (callbacks.isStructType as ReturnType<typeof vi.fn>).mockReturnValue(
445
+ true,
446
+ );
447
+ const typeCtx = {
448
+ primitiveType: () => null,
449
+ userType: () => ({ getText: () => "Point" }),
450
+ qualifiedType: () => null,
451
+ scopedType: () => null,
452
+ globalType: () => null,
453
+ stringType: () => null,
454
+ arrayType: () => null,
455
+ getText: () => "Point",
456
+ } as never;
457
+
458
+ const result = FunctionContextManager.resolveParameterTypeInfo(
459
+ typeCtx,
460
+ callbacks,
461
+ );
462
+
463
+ expect(result.typeName).toBe("Point");
464
+ expect(result.isStruct).toBe(true);
465
+ });
466
+
467
+ it("resolves qualified type using callback", () => {
468
+ const callbacks = createMockCallbacks();
469
+ const typeCtx = {
470
+ primitiveType: () => null,
471
+ userType: () => null,
472
+ qualifiedType: () => ({
473
+ IDENTIFIER: () => [
474
+ { getText: () => "Scope" },
475
+ { getText: () => "Type" },
476
+ ],
477
+ }),
478
+ scopedType: () => null,
479
+ globalType: () => null,
480
+ stringType: () => null,
481
+ arrayType: () => null,
482
+ getText: () => "Scope.Type",
483
+ } as never;
484
+
485
+ const result = FunctionContextManager.resolveParameterTypeInfo(
486
+ typeCtx,
487
+ callbacks,
488
+ );
489
+
490
+ expect(callbacks.resolveQualifiedType).toHaveBeenCalledWith([
491
+ "Scope",
492
+ "Type",
493
+ ]);
494
+ expect(result.typeName).toBe("Scope_Type");
495
+ });
496
+
497
+ it("resolves scoped type with current scope", () => {
498
+ CodeGenState.currentScope = "MyScope";
499
+ const callbacks = createMockCallbacks();
500
+ const typeCtx = {
501
+ primitiveType: () => null,
502
+ userType: () => null,
503
+ qualifiedType: () => null,
504
+ scopedType: () => ({
505
+ IDENTIFIER: () => ({ getText: () => "LocalType" }),
506
+ }),
507
+ globalType: () => null,
508
+ stringType: () => null,
509
+ arrayType: () => null,
510
+ getText: () => "this.LocalType",
511
+ } as never;
512
+
513
+ const result = FunctionContextManager.resolveParameterTypeInfo(
514
+ typeCtx,
515
+ callbacks,
516
+ );
517
+
518
+ expect(result.typeName).toBe("MyScope_LocalType");
519
+ });
520
+
521
+ it("resolves global type", () => {
522
+ const callbacks = createMockCallbacks();
523
+ const typeCtx = {
524
+ primitiveType: () => null,
525
+ userType: () => null,
526
+ qualifiedType: () => null,
527
+ scopedType: () => null,
528
+ globalType: () => ({
529
+ IDENTIFIER: () => ({ getText: () => "GlobalType" }),
530
+ }),
531
+ stringType: () => null,
532
+ arrayType: () => null,
533
+ getText: () => "global.GlobalType",
534
+ } as never;
535
+
536
+ const result = FunctionContextManager.resolveParameterTypeInfo(
537
+ typeCtx,
538
+ callbacks,
539
+ );
540
+
541
+ expect(result.typeName).toBe("GlobalType");
542
+ });
543
+
544
+ it("resolves string type", () => {
545
+ const callbacks = createMockCallbacks();
546
+ const typeCtx = {
547
+ primitiveType: () => null,
548
+ userType: () => null,
549
+ qualifiedType: () => null,
550
+ scopedType: () => null,
551
+ globalType: () => null,
552
+ stringType: () => ({
553
+ getText: () => "string<32>",
554
+ INTEGER_LITERAL: () => ({ getText: () => "32" }),
555
+ }),
556
+ arrayType: () => null,
557
+ getText: () => "string<32>",
558
+ } as never;
559
+
560
+ const result = FunctionContextManager.resolveParameterTypeInfo(
561
+ typeCtx,
562
+ callbacks,
563
+ );
564
+
565
+ expect(result.typeName).toBe("string");
566
+ expect(result.isString).toBe(true);
567
+ });
568
+
569
+ it("resolves array type with primitive base", () => {
570
+ const callbacks = createMockCallbacks();
571
+ const typeCtx = {
572
+ primitiveType: () => null,
573
+ userType: () => null,
574
+ qualifiedType: () => null,
575
+ scopedType: () => null,
576
+ globalType: () => null,
577
+ stringType: () => null,
578
+ arrayType: () => ({
579
+ primitiveType: () => ({ getText: () => "u8" }),
580
+ userType: () => null,
581
+ stringType: () => null,
582
+ }),
583
+ getText: () => "u8[10]",
584
+ } as never;
585
+
586
+ const result = FunctionContextManager.resolveParameterTypeInfo(
587
+ typeCtx,
588
+ callbacks,
589
+ );
590
+
591
+ expect(result.typeName).toBe("u8");
592
+ expect(result.isStruct).toBe(false);
593
+ });
594
+
595
+ it("resolves array type with user type base", () => {
596
+ const callbacks = createMockCallbacks();
597
+ (callbacks.isStructType as ReturnType<typeof vi.fn>).mockReturnValue(
598
+ true,
599
+ );
600
+ const typeCtx = {
601
+ primitiveType: () => null,
602
+ userType: () => null,
603
+ qualifiedType: () => null,
604
+ scopedType: () => null,
605
+ globalType: () => null,
606
+ stringType: () => null,
607
+ arrayType: () => ({
608
+ primitiveType: () => null,
609
+ userType: () => ({ getText: () => "Point" }),
610
+ stringType: () => null,
611
+ }),
612
+ getText: () => "Point[5]",
613
+ } as never;
614
+
615
+ const result = FunctionContextManager.resolveParameterTypeInfo(
616
+ typeCtx,
617
+ callbacks,
618
+ );
619
+
620
+ expect(result.typeName).toBe("Point");
621
+ expect(result.isStruct).toBe(true);
622
+ });
623
+
624
+ it("resolves array type with string base", () => {
625
+ const callbacks = createMockCallbacks();
626
+ const typeCtx = {
627
+ primitiveType: () => null,
628
+ userType: () => null,
629
+ qualifiedType: () => null,
630
+ scopedType: () => null,
631
+ globalType: () => null,
632
+ stringType: () => null,
633
+ arrayType: () => ({
634
+ primitiveType: () => null,
635
+ userType: () => null,
636
+ stringType: () => ({
637
+ getText: () => "string<32>",
638
+ }),
639
+ }),
640
+ getText: () => "string<32>[5]",
641
+ } as never;
642
+
643
+ const result = FunctionContextManager.resolveParameterTypeInfo(
644
+ typeCtx,
645
+ callbacks,
646
+ );
647
+
648
+ expect(result.typeName).toBe("string<32>");
649
+ expect(result.isString).toBe(true);
650
+ });
651
+
652
+ it("returns fallback for unknown type", () => {
653
+ const callbacks = createMockCallbacks();
654
+ const typeCtx = {
655
+ primitiveType: () => null,
656
+ userType: () => null,
657
+ qualifiedType: () => null,
658
+ scopedType: () => null,
659
+ globalType: () => null,
660
+ stringType: () => null,
661
+ arrayType: () => null,
662
+ getText: () => "SomeUnknownType",
663
+ } as never;
664
+
665
+ const result = FunctionContextManager.resolveParameterTypeInfo(
666
+ typeCtx,
667
+ callbacks,
668
+ );
669
+
670
+ expect(result.typeName).toBe("SomeUnknownType");
671
+ expect(result.isStruct).toBe(false);
672
+ expect(result.isCallback).toBe(false);
673
+ expect(result.isString).toBe(false);
674
+ });
675
+ });
676
+
677
+ describe("registerParameterType", () => {
678
+ it("registers parameter in type registry", () => {
679
+ const param = createMockParam("x", "u32", { isPrimitive: true });
680
+
681
+ FunctionContextManager.registerParameterType(
682
+ "x",
683
+ {
684
+ typeName: "u32",
685
+ isStruct: false,
686
+ isCallback: false,
687
+ isString: false,
688
+ },
689
+ param,
690
+ false,
691
+ false,
692
+ );
693
+
694
+ const typeInfo = CodeGenState.getVariableTypeInfo("x");
695
+ expect(typeInfo).toBeDefined();
696
+ expect(typeInfo!.baseType).toBe("u32");
697
+ expect(typeInfo!.isParameter).toBe(true);
698
+ });
699
+
700
+ it("registers enum parameter with enumTypeName", () => {
701
+ setupSymbols({ knownEnums: new Set(["Color"]) });
702
+ const param = createMockParam("color", "Color", { isUserType: true });
703
+
704
+ FunctionContextManager.registerParameterType(
705
+ "color",
706
+ {
707
+ typeName: "Color",
708
+ isStruct: false,
709
+ isCallback: false,
710
+ isString: false,
711
+ },
712
+ param,
713
+ false,
714
+ false,
715
+ );
716
+
717
+ const typeInfo = CodeGenState.getVariableTypeInfo("color");
718
+ expect(typeInfo).toBeDefined();
719
+ expect(typeInfo!.isEnum).toBe(true);
720
+ expect(typeInfo!.enumTypeName).toBe("Color");
721
+ });
722
+
723
+ it("registers bitmap parameter with bitWidth", () => {
724
+ setupSymbols({
725
+ knownBitmaps: new Set(["Flags"]),
726
+ bitmapBitWidth: new Map([["Flags", 8]]),
727
+ });
728
+ const param = createMockParam("flags", "Flags", { isUserType: true });
729
+
730
+ FunctionContextManager.registerParameterType(
731
+ "flags",
732
+ {
733
+ typeName: "Flags",
734
+ isStruct: false,
735
+ isCallback: false,
736
+ isString: false,
737
+ },
738
+ param,
739
+ false,
740
+ false,
741
+ );
742
+
743
+ const typeInfo = CodeGenState.getVariableTypeInfo("flags");
744
+ expect(typeInfo).toBeDefined();
745
+ expect(typeInfo!.isBitmap).toBe(true);
746
+ expect(typeInfo!.bitmapTypeName).toBe("Flags");
747
+ expect(typeInfo!.bitWidth).toBe(8);
748
+ });
749
+ });
750
+
751
+ describe("clearParameters", () => {
752
+ it("removes parameters from type registry", () => {
753
+ CodeGenState.currentParameters.set("x", {
754
+ name: "x",
755
+ baseType: "u32",
756
+ isArray: false,
757
+ isStruct: false,
758
+ isConst: false,
759
+ isCallback: false,
760
+ isString: false,
761
+ });
762
+ CodeGenState.setVariableTypeInfo("x", {
763
+ baseType: "u32",
764
+ bitWidth: 32,
765
+ isArray: false,
766
+ isConst: false,
767
+ isParameter: true,
768
+ });
769
+
770
+ FunctionContextManager.clearParameters();
771
+
772
+ expect(CodeGenState.getVariableTypeInfo("x")).toBeUndefined();
773
+ });
774
+
775
+ it("clears currentParameters map", () => {
776
+ CodeGenState.currentParameters.set("x", {
777
+ name: "x",
778
+ baseType: "u32",
779
+ isArray: false,
780
+ isStruct: false,
781
+ isConst: false,
782
+ isCallback: false,
783
+ isString: false,
784
+ });
785
+
786
+ FunctionContextManager.clearParameters();
787
+
788
+ expect(CodeGenState.currentParameters.size).toBe(0);
789
+ });
790
+
791
+ it("clears localArrays set", () => {
792
+ CodeGenState.localArrays.add("arr");
793
+
794
+ FunctionContextManager.clearParameters();
795
+
796
+ expect(CodeGenState.localArrays.size).toBe(0);
797
+ });
798
+ });
799
+
800
+ describe("enterFunctionBody", () => {
801
+ it("sets inFunctionBody to true", () => {
802
+ CodeGenState.inFunctionBody = false;
803
+
804
+ FunctionContextManager.enterFunctionBody();
805
+
806
+ expect(CodeGenState.inFunctionBody).toBe(true);
807
+ });
808
+
809
+ it("clears local variables", () => {
810
+ CodeGenState.localVariables.add("var");
811
+
812
+ FunctionContextManager.enterFunctionBody();
813
+
814
+ expect(CodeGenState.localVariables.size).toBe(0);
815
+ });
816
+
817
+ it("clears float bit shadows", () => {
818
+ CodeGenState.floatBitShadows.add("shadow");
819
+
820
+ FunctionContextManager.enterFunctionBody();
821
+
822
+ expect(CodeGenState.floatBitShadows.size).toBe(0);
823
+ });
824
+ });
825
+
826
+ describe("exitFunctionBody", () => {
827
+ it("sets inFunctionBody to false", () => {
828
+ CodeGenState.inFunctionBody = true;
829
+
830
+ FunctionContextManager.exitFunctionBody();
831
+
832
+ expect(CodeGenState.inFunctionBody).toBe(false);
833
+ });
834
+
835
+ it("clears mainArgsName", () => {
836
+ CodeGenState.mainArgsName = "args";
837
+
838
+ FunctionContextManager.exitFunctionBody();
839
+
840
+ expect(CodeGenState.mainArgsName).toBeNull();
841
+ });
842
+ });
843
+
844
+ describe("getStringCapacity", () => {
845
+ it("returns undefined for non-string types", () => {
846
+ const typeCtx = {
847
+ stringType: () => null,
848
+ arrayType: () => null,
849
+ } as never;
850
+
851
+ const result = FunctionContextManager.getStringCapacity(typeCtx, false);
852
+
853
+ expect(result).toBeUndefined();
854
+ });
855
+
856
+ it("extracts capacity from direct string type", () => {
857
+ const typeCtx = {
858
+ stringType: () => ({
859
+ INTEGER_LITERAL: () => ({ getText: () => "32" }),
860
+ }),
861
+ arrayType: () => null,
862
+ } as never;
863
+
864
+ const result = FunctionContextManager.getStringCapacity(typeCtx, true);
865
+
866
+ expect(result).toBe(32);
867
+ });
868
+
869
+ it("extracts capacity from array of strings", () => {
870
+ const typeCtx = {
871
+ stringType: () => null,
872
+ arrayType: () => ({
873
+ stringType: () => ({
874
+ INTEGER_LITERAL: () => ({ getText: () => "64" }),
875
+ }),
876
+ }),
877
+ } as never;
878
+
879
+ const result = FunctionContextManager.getStringCapacity(typeCtx, true);
880
+
881
+ expect(result).toBe(64);
882
+ });
883
+ });
884
+
885
+ describe("extractParamArrayDimensions", () => {
886
+ it("returns empty array for non-array parameters", () => {
887
+ const param = createMockParam("x", "u32", { isPrimitive: true });
888
+ const typeCtx = {
889
+ arrayType: () => null,
890
+ } as never;
891
+
892
+ const result = FunctionContextManager.extractParamArrayDimensions(
893
+ param,
894
+ typeCtx,
895
+ false,
896
+ );
897
+
898
+ expect(result).toEqual([]);
899
+ });
900
+
901
+ it("returns empty array when arrayType is null for array parameter", () => {
902
+ const param = {
903
+ arrayDimension: () => [],
904
+ } as never;
905
+ const typeCtx = {
906
+ arrayType: () => null,
907
+ } as never;
908
+
909
+ const result = FunctionContextManager.extractParamArrayDimensions(
910
+ param,
911
+ typeCtx,
912
+ true,
913
+ );
914
+
915
+ expect(result).toEqual([]);
916
+ });
917
+
918
+ it("parses C-Next style array dimensions from arrayType", () => {
919
+ const param = {
920
+ arrayDimension: () => [],
921
+ } as never;
922
+ const typeCtx = {
923
+ arrayType: () => ({
924
+ arrayTypeDimension: () => [
925
+ { expression: () => ({ getText: () => "10" }) },
926
+ { expression: () => ({ getText: () => "20" }) },
927
+ ],
928
+ }),
929
+ } as never;
930
+
931
+ const result = FunctionContextManager.extractParamArrayDimensions(
932
+ param,
933
+ typeCtx,
934
+ true,
935
+ );
936
+
937
+ expect(result).toEqual([10, 20]);
938
+ });
939
+
940
+ it("skips dimensions without expression", () => {
941
+ const param = {
942
+ arrayDimension: () => [],
943
+ } as never;
944
+ const typeCtx = {
945
+ arrayType: () => ({
946
+ arrayTypeDimension: () => [
947
+ { expression: () => ({ getText: () => "10" }) },
948
+ { expression: () => null },
949
+ ],
950
+ }),
951
+ } as never;
952
+
953
+ const result = FunctionContextManager.extractParamArrayDimensions(
954
+ param,
955
+ typeCtx,
956
+ true,
957
+ );
958
+
959
+ expect(result).toEqual([10]);
960
+ });
961
+
962
+ it("skips non-numeric dimension values", () => {
963
+ const param = {
964
+ arrayDimension: () => [],
965
+ } as never;
966
+ const typeCtx = {
967
+ arrayType: () => ({
968
+ arrayTypeDimension: () => [
969
+ { expression: () => ({ getText: () => "SIZE" }) },
970
+ ],
971
+ }),
972
+ } as never;
973
+
974
+ const result = FunctionContextManager.extractParamArrayDimensions(
975
+ param,
976
+ typeCtx,
977
+ true,
978
+ );
979
+
980
+ expect(result).toEqual([]);
981
+ });
982
+ });
983
+ });