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,333 @@
1
+ /**
2
+ * CResolver - Orchestrates C symbol collection using composable collectors.
3
+ *
4
+ * This resolver collects symbols from C header parse trees and returns
5
+ * typed TCSymbol[] discriminated unions.
6
+ */
7
+
8
+ /* eslint-disable @typescript-eslint/no-explicit-any */
9
+
10
+ import type {
11
+ CompilationUnitContext,
12
+ DeclarationContext,
13
+ DeclarationSpecifiersContext,
14
+ DeclarationSpecifierContext,
15
+ } from "../../parser/c/grammar/CParser";
16
+ import type TCSymbol from "../../../types/symbols/c/TCSymbol";
17
+ import SymbolTable from "../SymbolTable";
18
+ import DeclaratorUtils from "./utils/DeclaratorUtils";
19
+ import StructCollector from "./collectors/StructCollector";
20
+ import EnumCollector from "./collectors/EnumCollector";
21
+ import FunctionCollector from "./collectors/FunctionCollector";
22
+ import TypedefCollector from "./collectors/TypedefCollector";
23
+ import VariableCollector from "./collectors/VariableCollector";
24
+
25
+ /**
26
+ * Result of resolving C symbols.
27
+ */
28
+ interface ICResolverResult {
29
+ /** Collected symbols */
30
+ readonly symbols: TCSymbol[];
31
+
32
+ /** Warnings generated during collection */
33
+ readonly warnings: string[];
34
+ }
35
+
36
+ /**
37
+ * Internal context for declaration processing.
38
+ */
39
+ interface IDeclarationContext {
40
+ readonly sourceFile: string;
41
+ readonly line: number;
42
+ readonly isTypedef: boolean;
43
+ readonly isExtern: boolean;
44
+ readonly symbols: TCSymbol[];
45
+ }
46
+
47
+ class CResolver {
48
+ /**
49
+ * Resolve all symbols from a C compilation unit.
50
+ *
51
+ * @param tree The parsed compilation unit context
52
+ * @param sourceFile Source file path
53
+ * @param symbolTable Optional symbol table for field tracking
54
+ */
55
+ static resolve(
56
+ tree: CompilationUnitContext,
57
+ sourceFile: string,
58
+ symbolTable?: SymbolTable | null,
59
+ ): ICResolverResult {
60
+ const symbols: TCSymbol[] = [];
61
+ const warnings: string[] = [];
62
+
63
+ const translationUnit = tree.translationUnit();
64
+ if (!translationUnit) {
65
+ return { symbols, warnings };
66
+ }
67
+
68
+ for (const extDecl of translationUnit.externalDeclaration()) {
69
+ // Function definition
70
+ const funcDef = extDecl.functionDefinition();
71
+ if (funcDef) {
72
+ const funcSymbol = FunctionCollector.collectFromDefinition(
73
+ funcDef,
74
+ sourceFile,
75
+ );
76
+ if (funcSymbol) {
77
+ symbols.push(funcSymbol);
78
+ }
79
+ continue;
80
+ }
81
+
82
+ // Declaration (typedef, struct, variable, function prototype)
83
+ const decl = extDecl.declaration();
84
+ if (decl) {
85
+ CResolver.collectDeclaration(
86
+ decl,
87
+ sourceFile,
88
+ symbolTable ?? null,
89
+ symbols,
90
+ warnings,
91
+ );
92
+ }
93
+ }
94
+
95
+ return { symbols, warnings };
96
+ }
97
+
98
+ /**
99
+ * Collect symbols from a declaration.
100
+ */
101
+ private static collectDeclaration(
102
+ decl: DeclarationContext,
103
+ sourceFile: string,
104
+ symbolTable: SymbolTable | null,
105
+ symbols: TCSymbol[],
106
+ warnings: string[],
107
+ ): void {
108
+ const declSpecs = decl.declarationSpecifiers();
109
+ if (!declSpecs) return;
110
+
111
+ const line = decl.start?.line ?? 0;
112
+
113
+ // Check for storage class specifiers
114
+ const isTypedef = DeclaratorUtils.hasStorageClass(declSpecs, "typedef");
115
+ const isExtern = DeclaratorUtils.hasStorageClass(declSpecs, "extern");
116
+
117
+ // Check for struct/union
118
+ const structSpec = DeclaratorUtils.findStructOrUnionSpecifier(declSpecs);
119
+ if (structSpec) {
120
+ // For typedef struct, extract the typedef name from declarationSpecifiers
121
+ const typedefName = isTypedef
122
+ ? DeclaratorUtils.extractTypedefNameFromSpecs(declSpecs)
123
+ : undefined;
124
+
125
+ const structSymbol = StructCollector.collect(
126
+ structSpec,
127
+ sourceFile,
128
+ line,
129
+ symbolTable,
130
+ typedefName,
131
+ isTypedef,
132
+ warnings,
133
+ );
134
+ if (structSymbol) {
135
+ symbols.push(structSymbol);
136
+ }
137
+ }
138
+
139
+ // Check for enum
140
+ const enumSpec = DeclaratorUtils.findEnumSpecifier(declSpecs);
141
+ if (enumSpec) {
142
+ const enumResult = EnumCollector.collect(enumSpec, sourceFile, line);
143
+ if (enumResult) {
144
+ symbols.push(enumResult.enum);
145
+ // Also add enum member symbols
146
+ for (const member of enumResult.members) {
147
+ symbols.push(member);
148
+ }
149
+ }
150
+ }
151
+
152
+ // Collect declarators (variables, function prototypes, typedefs)
153
+ const ctx: IDeclarationContext = {
154
+ sourceFile,
155
+ line,
156
+ isTypedef,
157
+ isExtern,
158
+ symbols,
159
+ };
160
+
161
+ const initDeclList = decl.initDeclaratorList();
162
+ if (initDeclList) {
163
+ const baseType = DeclaratorUtils.extractTypeFromDeclSpecs(declSpecs);
164
+ CResolver.collectInitDeclaratorList(initDeclList, baseType, ctx);
165
+ } else {
166
+ // Handle case where identifier is parsed as typedefName in declarationSpecifiers
167
+ CResolver.collectFromDeclSpecsTypedefName(
168
+ declSpecs,
169
+ structSpec,
170
+ enumSpec,
171
+ ctx,
172
+ );
173
+ }
174
+ }
175
+
176
+ /**
177
+ * Collect symbols from init declarator list.
178
+ */
179
+ private static collectInitDeclaratorList(
180
+ initDeclList: any,
181
+ baseType: string,
182
+ ctx: IDeclarationContext,
183
+ ): void {
184
+ for (const initDecl of initDeclList.initDeclarator()) {
185
+ const declarator = initDecl.declarator();
186
+ if (!declarator) continue;
187
+
188
+ const name = DeclaratorUtils.extractDeclaratorName(declarator);
189
+ if (!name) continue;
190
+
191
+ // Check if this is a function declaration (has parameter list)
192
+ const isFunction = DeclaratorUtils.declaratorIsFunction(declarator);
193
+
194
+ if (ctx.isTypedef) {
195
+ ctx.symbols.push(
196
+ TypedefCollector.collect(name, baseType, ctx.sourceFile, ctx.line),
197
+ );
198
+ } else if (isFunction) {
199
+ ctx.symbols.push(
200
+ FunctionCollector.collectFromDeclaration(
201
+ name,
202
+ baseType,
203
+ declarator,
204
+ ctx.sourceFile,
205
+ ctx.line,
206
+ ctx.isExtern,
207
+ ),
208
+ );
209
+ } else {
210
+ ctx.symbols.push(
211
+ VariableCollector.collect(
212
+ name,
213
+ baseType,
214
+ declarator,
215
+ ctx.sourceFile,
216
+ ctx.line,
217
+ ctx.isExtern,
218
+ ),
219
+ );
220
+ }
221
+ }
222
+ }
223
+
224
+ /**
225
+ * Collect symbols when identifier appears as typedefName in declarationSpecifiers.
226
+ * This handles the C grammar ambiguity where variable names can be parsed as typedef names.
227
+ */
228
+ private static collectFromDeclSpecsTypedefName(
229
+ declSpecs: DeclarationSpecifiersContext,
230
+ structSpec: any,
231
+ enumSpec: any,
232
+ ctx: IDeclarationContext,
233
+ ): void {
234
+ const specs = declSpecs.declarationSpecifier();
235
+ const { name: lastTypedefName, index: lastTypedefIndex } =
236
+ CResolver.findLastTypedefName(specs);
237
+
238
+ if (!lastTypedefName || lastTypedefIndex < 0) return;
239
+
240
+ // Skip duplicates for non-typedef declarations
241
+ if (
242
+ !ctx.isTypedef &&
243
+ CResolver.shouldSkipDuplicateTypedefName(
244
+ lastTypedefName,
245
+ structSpec,
246
+ enumSpec,
247
+ )
248
+ ) {
249
+ return;
250
+ }
251
+
252
+ const baseType = CResolver.buildBaseTypeFromSpecs(specs, lastTypedefIndex);
253
+
254
+ if (ctx.isTypedef) {
255
+ ctx.symbols.push(
256
+ TypedefCollector.collect(
257
+ lastTypedefName,
258
+ baseType,
259
+ ctx.sourceFile,
260
+ ctx.line,
261
+ ),
262
+ );
263
+ } else {
264
+ ctx.symbols.push(
265
+ VariableCollector.collectFromDeclSpecs(
266
+ lastTypedefName,
267
+ baseType,
268
+ ctx.sourceFile,
269
+ ctx.line,
270
+ ctx.isExtern,
271
+ ),
272
+ );
273
+ }
274
+ }
275
+
276
+ /**
277
+ * Find the last typedefName in declaration specifiers.
278
+ */
279
+ private static findLastTypedefName(specs: DeclarationSpecifierContext[]): {
280
+ name: string | undefined;
281
+ index: number;
282
+ } {
283
+ let name: string | undefined;
284
+ let index = -1;
285
+
286
+ for (let i = 0; i < specs.length; i++) {
287
+ const typeSpec = specs[i].typeSpecifier();
288
+ const typedefName = typeSpec?.typedefName?.();
289
+ if (typedefName) {
290
+ name = typedefName.getText();
291
+ index = i;
292
+ }
293
+ }
294
+
295
+ return { name, index };
296
+ }
297
+
298
+ /**
299
+ * Check if typedef name should be skipped to avoid duplicates.
300
+ */
301
+ private static shouldSkipDuplicateTypedefName(
302
+ typedefName: string,
303
+ structSpec: any,
304
+ enumSpec: any,
305
+ ): boolean {
306
+ const structName = structSpec?.Identifier?.()?.getText();
307
+ if (structName === typedefName) return true;
308
+
309
+ const enumName = enumSpec?.Identifier?.()?.getText();
310
+ if (enumName === typedefName) return true;
311
+
312
+ return false;
313
+ }
314
+
315
+ /**
316
+ * Build base type string from specifiers before the typedef name.
317
+ */
318
+ private static buildBaseTypeFromSpecs(
319
+ specs: DeclarationSpecifierContext[],
320
+ endIndex: number,
321
+ ): string {
322
+ const typeParts: string[] = [];
323
+ for (let i = 0; i < endIndex; i++) {
324
+ const typeSpec = specs[i].typeSpecifier();
325
+ if (typeSpec) {
326
+ typeParts.push(typeSpec.getText());
327
+ }
328
+ }
329
+ return typeParts.join(" ") || "int";
330
+ }
331
+ }
332
+
333
+ export default CResolver;
@@ -0,0 +1,269 @@
1
+ /**
2
+ * DeclaratorUtils - Shared utilities for extracting information from C declarators.
3
+ *
4
+ * Provides methods for extracting names, types, parameters, and array dimensions
5
+ * from C parse tree declarator contexts.
6
+ */
7
+
8
+ /* eslint-disable @typescript-eslint/no-explicit-any */
9
+
10
+ import type {
11
+ DeclarationSpecifiersContext,
12
+ StructOrUnionSpecifierContext,
13
+ EnumSpecifierContext,
14
+ } from "../../../parser/c/grammar/CParser";
15
+ import SymbolUtils from "../../SymbolUtils";
16
+ import IExtractedParameter from "../../shared/IExtractedParameter";
17
+ import ParameterExtractorUtils from "../../shared/ParameterExtractorUtils";
18
+
19
+ class DeclaratorUtils {
20
+ /**
21
+ * Extract name from a declarator context.
22
+ */
23
+ static extractDeclaratorName(declarator: any): string | null {
24
+ const directDecl = declarator.directDeclarator?.();
25
+ if (!directDecl) return null;
26
+
27
+ return DeclaratorUtils.extractDirectDeclaratorName(directDecl);
28
+ }
29
+
30
+ /**
31
+ * Extract identifier from directDeclarator, handling arrays and function pointers.
32
+ * The C grammar has recursive directDeclarator for arrays: `directDeclarator '[' ... ']'`
33
+ * so `buf[8]` is parsed as directDeclarator('[', directDeclarator('buf'), ']')
34
+ */
35
+ static extractDirectDeclaratorName(directDecl: any): string | null {
36
+ // Check for identifier (base case)
37
+ const identifier = directDecl.Identifier?.();
38
+ if (identifier) {
39
+ return identifier.getText();
40
+ }
41
+
42
+ // Nested declarator in parentheses: '(' declarator ')'
43
+ const nestedDecl = directDecl.declarator?.();
44
+ if (nestedDecl) {
45
+ return DeclaratorUtils.extractDeclaratorName(nestedDecl);
46
+ }
47
+
48
+ // Nested directDeclarator for arrays/functions
49
+ // Grammar: directDeclarator '[' ... ']' or directDeclarator '(' ... ')'
50
+ const nestedDirectDecl = directDecl.directDeclarator?.();
51
+ if (nestedDirectDecl) {
52
+ return DeclaratorUtils.extractDirectDeclaratorName(nestedDirectDecl);
53
+ }
54
+
55
+ return null;
56
+ }
57
+
58
+ /**
59
+ * Check if a declarator represents a function.
60
+ */
61
+ static declaratorIsFunction(declarator: any): boolean {
62
+ const directDecl = declarator.directDeclarator?.();
63
+ if (!directDecl) return false;
64
+
65
+ // Check for parameter type list (function with params) or empty parens
66
+ // The C grammar: directDeclarator '(' parameterTypeList ')' | directDeclarator '(' identifierList? ')'
67
+ if (directDecl.parameterTypeList?.() !== null) return true;
68
+
69
+ // Check for LeftParen token - indicates function declarator even with empty params
70
+ if (directDecl.LeftParen?.()) return true;
71
+
72
+ return false;
73
+ }
74
+
75
+ /**
76
+ * Extract function parameters from a declarator.
77
+ */
78
+ static extractFunctionParameters(declarator: any): IExtractedParameter[] {
79
+ const directDecl = declarator.directDeclarator?.();
80
+ if (!directDecl) return [];
81
+
82
+ const paramTypeList = directDecl.parameterTypeList?.();
83
+ if (!paramTypeList) return [];
84
+
85
+ const paramList = paramTypeList.parameterList?.();
86
+ if (!paramList) return [];
87
+
88
+ return ParameterExtractorUtils.processParameterList(
89
+ paramList,
90
+ DeclaratorUtils.extractParameterInfo,
91
+ );
92
+ }
93
+
94
+ /**
95
+ * Extract parameter info from a single parameter declaration.
96
+ */
97
+ static extractParameterInfo(paramDecl: any): IExtractedParameter | null {
98
+ const declSpecs = paramDecl.declarationSpecifiers?.();
99
+ if (!declSpecs) return null;
100
+
101
+ const baseType = DeclaratorUtils.extractTypeFromDeclSpecs(declSpecs);
102
+ const isConst = declSpecs.getText().includes("const");
103
+
104
+ // Check for pointer and array in declarator
105
+ const declarator = paramDecl.declarator?.();
106
+ let isPointer = false;
107
+ let isArray = false;
108
+
109
+ if (declarator) {
110
+ isPointer = Boolean(declarator.pointer?.());
111
+ const directDecl = declarator.directDeclarator?.();
112
+ if (directDecl) {
113
+ const text = directDecl.getText();
114
+ isArray = text.includes("[") && text.includes("]");
115
+ }
116
+ }
117
+
118
+ return ParameterExtractorUtils.buildParameterInfo(
119
+ declarator,
120
+ baseType,
121
+ isConst,
122
+ isPointer,
123
+ isArray,
124
+ DeclaratorUtils.extractDeclaratorName,
125
+ );
126
+ }
127
+
128
+ /**
129
+ * Extract array dimensions from a declarator.
130
+ */
131
+ static extractArrayDimensions(declarator: any): number[] {
132
+ const directDecl = declarator.directDeclarator?.();
133
+ if (!directDecl) return [];
134
+
135
+ // Use shared utility for regex-based extraction
136
+ return SymbolUtils.parseArrayDimensions(directDecl.getText());
137
+ }
138
+
139
+ /**
140
+ * Extract type string from declaration specifiers.
141
+ */
142
+ static extractTypeFromDeclSpecs(
143
+ declSpecs: DeclarationSpecifiersContext,
144
+ ): string {
145
+ const parts: string[] = [];
146
+
147
+ for (const spec of declSpecs.declarationSpecifier()) {
148
+ const typeSpec = spec.typeSpecifier();
149
+ if (typeSpec) {
150
+ parts.push(typeSpec.getText());
151
+ }
152
+ }
153
+
154
+ return parts.join(" ") || "int";
155
+ }
156
+
157
+ /**
158
+ * Check if declaration specifiers contain a specific storage class.
159
+ */
160
+ static hasStorageClass(
161
+ declSpecs: DeclarationSpecifiersContext,
162
+ storage: string,
163
+ ): boolean {
164
+ for (const spec of declSpecs.declarationSpecifier()) {
165
+ const storageSpec = spec.storageClassSpecifier();
166
+ if (storageSpec?.getText() === storage) {
167
+ return true;
168
+ }
169
+ }
170
+ return false;
171
+ }
172
+
173
+ /**
174
+ * Find struct or union specifier in declaration specifiers.
175
+ */
176
+ static findStructOrUnionSpecifier(
177
+ declSpecs: DeclarationSpecifiersContext,
178
+ ): StructOrUnionSpecifierContext | null {
179
+ for (const spec of declSpecs.declarationSpecifier()) {
180
+ const typeSpec = spec.typeSpecifier();
181
+ if (typeSpec) {
182
+ const structSpec = typeSpec.structOrUnionSpecifier?.();
183
+ if (structSpec) {
184
+ return structSpec;
185
+ }
186
+ }
187
+ }
188
+ return null;
189
+ }
190
+
191
+ /**
192
+ * Find enum specifier in declaration specifiers.
193
+ */
194
+ static findEnumSpecifier(
195
+ declSpecs: DeclarationSpecifiersContext,
196
+ ): EnumSpecifierContext | null {
197
+ for (const spec of declSpecs.declarationSpecifier()) {
198
+ const typeSpec = spec.typeSpecifier();
199
+ if (typeSpec) {
200
+ const enumSpec = typeSpec.enumSpecifier?.();
201
+ if (enumSpec) {
202
+ return enumSpec;
203
+ }
204
+ }
205
+ }
206
+ return null;
207
+ }
208
+
209
+ /**
210
+ * Extract type from specifierQualifierList (for struct fields).
211
+ * For struct/union field types, extract just the identifier (e.g., "InnerConfig")
212
+ * not the concatenated text ("structInnerConfig").
213
+ */
214
+ static extractTypeFromSpecQualList(specQualList: any): string {
215
+ const parts: string[] = [];
216
+
217
+ // Traverse the specifierQualifierList
218
+ let current = specQualList;
219
+ while (current) {
220
+ const typeSpec = current.typeSpecifier?.();
221
+ if (typeSpec) {
222
+ // Check for struct/union specifier - need to extract just the identifier
223
+ const structSpec = typeSpec.structOrUnionSpecifier?.();
224
+ if (structSpec) {
225
+ const identifier = structSpec.Identifier?.();
226
+ if (identifier) {
227
+ // Use just the struct/union name, not "structName" concatenated
228
+ parts.push(identifier.getText());
229
+ } else {
230
+ // Anonymous struct - use full text
231
+ parts.push(typeSpec.getText());
232
+ }
233
+ } else {
234
+ parts.push(typeSpec.getText());
235
+ }
236
+ }
237
+
238
+ const typeQual = current.typeQualifier?.();
239
+ if (typeQual) {
240
+ parts.push(typeQual.getText());
241
+ }
242
+
243
+ current = current.specifierQualifierList?.();
244
+ }
245
+
246
+ return parts.join(" ") || "int";
247
+ }
248
+
249
+ /**
250
+ * Extract typedef name from declaration specifiers.
251
+ * For "typedef struct { ... } AppConfig;", this returns "AppConfig".
252
+ */
253
+ static extractTypedefNameFromSpecs(
254
+ declSpecs: DeclarationSpecifiersContext,
255
+ ): string | undefined {
256
+ for (const spec of declSpecs.declarationSpecifier()) {
257
+ const typeSpec = spec.typeSpecifier();
258
+ if (typeSpec) {
259
+ const typeName = typeSpec.typedefName?.();
260
+ if (typeName) {
261
+ return typeName.getText();
262
+ }
263
+ }
264
+ }
265
+ return undefined;
266
+ }
267
+ }
268
+
269
+ export default DeclaratorUtils;