c-next 0.2.10 → 0.2.12
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/dist/index.js +6228 -5365
- package/dist/index.js.map +3 -3
- package/grammar/C.g4 +8 -1
- package/package.json +3 -2
- package/src/transpiler/Transpiler.ts +16 -3
- package/src/transpiler/logic/parser/c/grammar/C.interp +15 -3
- package/src/transpiler/logic/parser/c/grammar/C.tokens +219 -207
- package/src/transpiler/logic/parser/c/grammar/CLexer.interp +21 -3
- package/src/transpiler/logic/parser/c/grammar/CLexer.tokens +219 -207
- package/src/transpiler/logic/parser/c/grammar/CLexer.ts +643 -606
- package/src/transpiler/logic/parser/c/grammar/CParser.ts +1076 -1038
- package/src/transpiler/logic/symbols/SymbolTable.ts +162 -34
- package/src/transpiler/logic/symbols/__tests__/SymbolTable.test.ts +122 -2
- package/src/transpiler/logic/symbols/c/__tests__/CResolver.integration.test.ts +3 -3
- package/src/transpiler/logic/symbols/c/__tests__/PointerTypedef.test.ts +47 -0
- package/src/transpiler/logic/symbols/c/collectors/StructCollector.ts +56 -43
- package/src/transpiler/logic/symbols/c/index.ts +25 -3
- package/src/transpiler/logic/symbols/c/utils/DeclaratorUtils.ts +17 -0
- package/src/transpiler/output/codegen/CodeGenerator.ts +18 -0
- package/src/transpiler/output/codegen/generators/IOrchestrator.ts +6 -0
- package/src/transpiler/output/codegen/generators/declarationGenerators/ScopeGenerator.ts +9 -3
- package/src/transpiler/output/codegen/generators/declarationGenerators/__tests__/ScopeGenerator.test.ts +2 -0
- package/src/transpiler/output/codegen/helpers/FunctionContextManager.ts +15 -3
- package/src/transpiler/output/codegen/helpers/ParameterInputAdapter.ts +14 -6
- package/src/transpiler/output/codegen/helpers/__tests__/ParameterInputAdapter.test.ts +1 -0
- package/src/transpiler/output/codegen/types/IFunctionContextCallbacks.ts +2 -0
- package/src/transpiler/state/CodeGenState.ts +9 -0
- package/src/transpiler/types/ICachedFileEntry.ts +6 -0
- package/src/utils/cache/CacheManager.ts +34 -13
- package/src/utils/cache/__tests__/CacheManager.test.ts +6 -4
|
@@ -179,14 +179,24 @@ class CResolver {
|
|
|
179
179
|
? CResolver.extractTypedefName(decl, declSpecs)
|
|
180
180
|
: undefined;
|
|
181
181
|
|
|
182
|
+
// Issue #957: Check if the typedef's declarator has a pointer prefix.
|
|
183
|
+
// For "typedef struct X *Y", Y is already a pointer type, NOT an opaque struct.
|
|
184
|
+
// Don't mark pointer typedefs as opaque.
|
|
185
|
+
const isPointerTypedef = ctx.isTypedef
|
|
186
|
+
? CResolver.isPointerTypedef(decl)
|
|
187
|
+
: false;
|
|
188
|
+
|
|
182
189
|
const structSymbol = StructCollector.collect(
|
|
183
190
|
structSpec,
|
|
184
191
|
ctx.sourceFile,
|
|
185
192
|
ctx.line,
|
|
186
193
|
symbolTable,
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
194
|
+
{
|
|
195
|
+
typedefName,
|
|
196
|
+
isTypedef: ctx.isTypedef,
|
|
197
|
+
warnings,
|
|
198
|
+
isPointerTypedef,
|
|
199
|
+
},
|
|
190
200
|
);
|
|
191
201
|
if (structSymbol) {
|
|
192
202
|
ctx.symbols.push(structSymbol);
|
|
@@ -209,6 +219,18 @@ class CResolver {
|
|
|
209
219
|
return DeclaratorUtils.extractTypedefNameFromSpecs(declSpecs);
|
|
210
220
|
}
|
|
211
221
|
|
|
222
|
+
/**
|
|
223
|
+
* Check if a typedef declaration has a pointer declarator.
|
|
224
|
+
* For "typedef struct X *Y", the declarator is "*Y" which has a pointer.
|
|
225
|
+
* Used for Issue #957 to distinguish pointer typedefs from opaque struct typedefs.
|
|
226
|
+
*/
|
|
227
|
+
private static isPointerTypedef(decl: DeclarationContext): boolean {
|
|
228
|
+
const initDeclList = decl.initDeclaratorList();
|
|
229
|
+
if (!initDeclList) return false;
|
|
230
|
+
|
|
231
|
+
return DeclaratorUtils.firstDeclaratorHasPointer(initDeclList);
|
|
232
|
+
}
|
|
233
|
+
|
|
212
234
|
/**
|
|
213
235
|
* Collect enum symbols from an enum specifier.
|
|
214
236
|
* Extracted to reduce cognitive complexity of collectDeclaration().
|
|
@@ -379,6 +379,23 @@ class DeclaratorUtils {
|
|
|
379
379
|
|
|
380
380
|
return DeclaratorUtils.extractDeclaratorName(firstDeclarator) ?? undefined;
|
|
381
381
|
}
|
|
382
|
+
|
|
383
|
+
/**
|
|
384
|
+
* Check if the first declarator in an init-declarator-list has a pointer.
|
|
385
|
+
* For "typedef struct X *handle_t;", the declarator is "*handle_t" which has a pointer.
|
|
386
|
+
* Used for Issue #957 to distinguish pointer typedefs from opaque struct typedefs.
|
|
387
|
+
*/
|
|
388
|
+
static firstDeclaratorHasPointer(
|
|
389
|
+
initDeclList: InitDeclaratorListContext,
|
|
390
|
+
): boolean {
|
|
391
|
+
const initDeclarators = initDeclList.initDeclarator?.();
|
|
392
|
+
if (!initDeclarators || initDeclarators.length === 0) return false;
|
|
393
|
+
|
|
394
|
+
const firstDeclarator = initDeclarators[0].declarator?.();
|
|
395
|
+
if (!firstDeclarator) return false;
|
|
396
|
+
|
|
397
|
+
return Boolean(firstDeclarator.pointer?.());
|
|
398
|
+
}
|
|
382
399
|
}
|
|
383
400
|
|
|
384
401
|
export default DeclaratorUtils;
|
|
@@ -1927,6 +1927,15 @@ export default class CodeGenerator implements IOrchestrator {
|
|
|
1927
1927
|
return CodeGenState.isOpaqueType(typeName);
|
|
1928
1928
|
}
|
|
1929
1929
|
|
|
1930
|
+
/**
|
|
1931
|
+
* Issue #958: Check if a type is an external typedef struct type.
|
|
1932
|
+
* Used for scope variables which should always be pointers for external struct types.
|
|
1933
|
+
* Part of IOrchestrator interface.
|
|
1934
|
+
*/
|
|
1935
|
+
isTypedefStructType(typeName: string): boolean {
|
|
1936
|
+
return CodeGenState.isTypedefStructType(typeName);
|
|
1937
|
+
}
|
|
1938
|
+
|
|
1930
1939
|
/**
|
|
1931
1940
|
* Issue #948: Mark a scope variable as having an opaque type.
|
|
1932
1941
|
* These variables are generated as pointers with NULL initialization.
|
|
@@ -3666,6 +3675,8 @@ export default class CodeGenerator implements IOrchestrator {
|
|
|
3666
3675
|
isStructType: (typeName: string) => this.isStructType(typeName),
|
|
3667
3676
|
resolveQualifiedType: (identifiers: string[]) =>
|
|
3668
3677
|
this.resolveQualifiedType(identifiers),
|
|
3678
|
+
isTypedefStructType: (t: string) =>
|
|
3679
|
+
CodeGenState.symbolTable?.isTypedefStructType(t) ?? false,
|
|
3669
3680
|
};
|
|
3670
3681
|
}
|
|
3671
3682
|
|
|
@@ -3757,6 +3768,8 @@ export default class CodeGenerator implements IOrchestrator {
|
|
|
3757
3768
|
isCallbackCompatible,
|
|
3758
3769
|
forcePassByReference,
|
|
3759
3770
|
forceConst,
|
|
3771
|
+
isTypedefStructType: (t) =>
|
|
3772
|
+
CodeGenState.symbolTable?.isTypedefStructType(t) ?? false,
|
|
3760
3773
|
});
|
|
3761
3774
|
|
|
3762
3775
|
// Use shared builder with C/C++ mode
|
|
@@ -3883,6 +3896,11 @@ export default class CodeGenerator implements IOrchestrator {
|
|
|
3883
3896
|
): string {
|
|
3884
3897
|
const type = this.generateType(ctx.type());
|
|
3885
3898
|
|
|
3899
|
+
// Issue #958: C-header typedef struct types always need pointer semantics
|
|
3900
|
+
if (CodeGenState.symbolTable?.isTypedefStructType(type)) {
|
|
3901
|
+
return `${type}*`;
|
|
3902
|
+
}
|
|
3903
|
+
|
|
3886
3904
|
if (!ctx.expression()) {
|
|
3887
3905
|
return type;
|
|
3888
3906
|
}
|
|
@@ -399,6 +399,12 @@ interface IOrchestrator {
|
|
|
399
399
|
*/
|
|
400
400
|
isOpaqueType(typeName: string): boolean;
|
|
401
401
|
|
|
402
|
+
/**
|
|
403
|
+
* Issue #958: Check if a type is an external typedef struct type.
|
|
404
|
+
* Used for scope variables which should always be pointers for external struct types.
|
|
405
|
+
*/
|
|
406
|
+
isTypedefStructType(typeName: string): boolean;
|
|
407
|
+
|
|
402
408
|
/**
|
|
403
409
|
* Mark a scope variable as having an opaque type.
|
|
404
410
|
* These variables are generated as pointers with NULL initialization.
|
|
@@ -191,10 +191,15 @@ function generateRegularVariable(
|
|
|
191
191
|
const fullName = QualifiedNameGenerator.forMember(scopeName, varName);
|
|
192
192
|
|
|
193
193
|
// Issue #948: Check if this is an opaque (forward-declared) struct type
|
|
194
|
-
//
|
|
194
|
+
// Issue #958: Also check for external typedef struct types (complete definitions)
|
|
195
|
+
// Both opaque and external typedef struct types must be declared as pointers
|
|
195
196
|
const isOpaque = orchestrator.isOpaqueType(type);
|
|
196
|
-
|
|
197
|
+
const isExternalStruct = orchestrator.isTypedefStructType(type);
|
|
198
|
+
if (isOpaque || isExternalStruct) {
|
|
197
199
|
type = `${type}*`;
|
|
200
|
+
// Mark as "opaque" scope variable so CallExprGenerator knows this is already
|
|
201
|
+
// a pointer and doesn't add '&' when passing to functions. The name is historical
|
|
202
|
+
// but the tracking applies to any scope variable declared as a pointer type.
|
|
198
203
|
orchestrator.markOpaqueScopeVariable(fullName);
|
|
199
204
|
}
|
|
200
205
|
|
|
@@ -218,7 +223,8 @@ function generateRegularVariable(
|
|
|
218
223
|
decl += ArrayDimensionUtils.generateStringCapacityDim(varDecl.type());
|
|
219
224
|
|
|
220
225
|
// Issue #948: Opaque types use NULL initialization instead of {0}
|
|
221
|
-
|
|
226
|
+
// Issue #958: External typedef struct types also use NULL initialization
|
|
227
|
+
if (isOpaque || isExternalStruct) {
|
|
222
228
|
decl += " = NULL";
|
|
223
229
|
} else {
|
|
224
230
|
decl += generateInitializer(varDecl, isArray, orchestrator);
|
|
@@ -468,6 +468,8 @@ function createMockOrchestrator(
|
|
|
468
468
|
tryEvaluateConstant: vi.fn(() => undefined),
|
|
469
469
|
// Issue #948: Opaque type helpers
|
|
470
470
|
isOpaqueType: vi.fn(() => false),
|
|
471
|
+
// Issue #958: Typedef struct type helper
|
|
472
|
+
isTypedefStructType: vi.fn(() => false),
|
|
471
473
|
markOpaqueScopeVariable: vi.fn(),
|
|
472
474
|
...overrides,
|
|
473
475
|
} as unknown as IOrchestrator;
|
|
@@ -160,19 +160,27 @@ class FunctionContextManager {
|
|
|
160
160
|
const isCallbackPointerParam =
|
|
161
161
|
callbackTypedefInfo?.shouldBePointer ?? false;
|
|
162
162
|
|
|
163
|
+
// Issue #958: Check if type is a typedef'd struct from C headers
|
|
164
|
+
const isTypedefStruct =
|
|
165
|
+
callbacks.isTypedefStructType?.(typeInfo.typeName) ?? false;
|
|
166
|
+
|
|
163
167
|
// Determine isStruct: for callback-compatible params, both typedef AND type info matter
|
|
164
168
|
// - If typedef says pointer AND it's actually a struct, use -> access (isStruct=true)
|
|
165
169
|
// - If typedef says pointer BUT it's a primitive (like u8), don't treat as struct
|
|
166
170
|
// (primitives use forcePointerSemantics for dereference instead)
|
|
171
|
+
// Issue #958: C-header typedef struct types are always treated as struct (pointer semantics)
|
|
167
172
|
const isStruct = callbackTypedefInfo
|
|
168
173
|
? isCallbackPointerParam && typeInfo.isStruct
|
|
169
|
-
: typeInfo.isStruct;
|
|
174
|
+
: typeInfo.isStruct || isTypedefStruct;
|
|
170
175
|
|
|
171
176
|
// Issue #895: Primitive types that become pointers need dereferencing when used as values
|
|
172
177
|
// e.g., "u8 buf" becoming "uint8_t* buf" requires "*buf" when accessing the value
|
|
173
178
|
const isCallbackPointerPrimitive =
|
|
174
179
|
isCallbackPointerParam && !typeInfo.isStruct && !isArray;
|
|
175
180
|
|
|
181
|
+
// Issue #958: typedef struct params need pointer semantics (like callback pointer params)
|
|
182
|
+
const forcePointerSemantics = isCallbackPointerParam || isTypedefStruct;
|
|
183
|
+
|
|
176
184
|
// Register in currentParameters
|
|
177
185
|
const paramInfo = {
|
|
178
186
|
name,
|
|
@@ -183,8 +191,8 @@ class FunctionContextManager {
|
|
|
183
191
|
isCallback: typeInfo.isCallback,
|
|
184
192
|
isString: typeInfo.isString,
|
|
185
193
|
isCallbackPointerPrimitive,
|
|
186
|
-
// Issue #895:
|
|
187
|
-
forcePointerSemantics
|
|
194
|
+
// Issue #895/#958: Force pointer semantics for callback-compatible and typedef struct params
|
|
195
|
+
forcePointerSemantics,
|
|
188
196
|
};
|
|
189
197
|
CodeGenState.currentParameters.set(name, paramInfo);
|
|
190
198
|
|
|
@@ -195,6 +203,7 @@ class FunctionContextManager {
|
|
|
195
203
|
param,
|
|
196
204
|
isArray,
|
|
197
205
|
isConst,
|
|
206
|
+
isTypedefStruct,
|
|
198
207
|
);
|
|
199
208
|
}
|
|
200
209
|
|
|
@@ -320,6 +329,7 @@ class FunctionContextManager {
|
|
|
320
329
|
param: Parser.ParameterContext,
|
|
321
330
|
isArray: boolean,
|
|
322
331
|
isConst: boolean,
|
|
332
|
+
isTypedefStruct = false,
|
|
323
333
|
): void {
|
|
324
334
|
const { typeName, isString } = typeInfo;
|
|
325
335
|
const typeCtx = param.type();
|
|
@@ -358,6 +368,8 @@ class FunctionContextManager {
|
|
|
358
368
|
isString,
|
|
359
369
|
stringCapacity,
|
|
360
370
|
isParameter: true,
|
|
371
|
+
// Issue #958: typedef struct params are already pointers — prevent &arg in call sites
|
|
372
|
+
...(isTypedefStruct && { isPointer: true }),
|
|
361
373
|
};
|
|
362
374
|
CodeGenState.setVariableTypeInfo(name, registeredType);
|
|
363
375
|
}
|
|
@@ -52,6 +52,9 @@ interface IFromASTDeps {
|
|
|
52
52
|
*/
|
|
53
53
|
forcePassByReference?: boolean;
|
|
54
54
|
|
|
55
|
+
/** Issue #958: Check if a type name is a typedef'd struct from C headers */
|
|
56
|
+
isTypedefStructType: (typeName: string) => boolean;
|
|
57
|
+
|
|
55
58
|
/**
|
|
56
59
|
* Issue #895: Force const qualifier from callback typedef signature.
|
|
57
60
|
* When the C typedef has `const T*`, this preserves const on the generated param.
|
|
@@ -137,15 +140,19 @@ class ParameterInputAdapter {
|
|
|
137
140
|
// Determine classification for non-array, non-string types
|
|
138
141
|
const isKnownStruct = deps.isKnownStruct(typeName);
|
|
139
142
|
const isKnownPrimitive = !!deps.typeMap[typeName];
|
|
143
|
+
// Issue #958: C-header typedef struct types need pointer semantics
|
|
144
|
+
const isTypedefStruct = deps.isTypedefStructType(typeName);
|
|
140
145
|
// Issue #895: Don't add auto-const for callback-compatible functions
|
|
141
146
|
// because it would change the signature and break typedef compatibility
|
|
142
147
|
const isAutoConst =
|
|
143
148
|
!deps.isCallbackCompatible && !deps.isModified && !isConst;
|
|
144
149
|
|
|
145
|
-
// Issue #895:
|
|
146
|
-
// when the typedef signature requires a pointer (e.g., opaque types)
|
|
150
|
+
// Issue #895/#958: Force pass-by-reference for callback or typedef struct types
|
|
147
151
|
const isPassByReference =
|
|
148
|
-
deps.forcePassByReference ||
|
|
152
|
+
deps.forcePassByReference ||
|
|
153
|
+
isKnownStruct ||
|
|
154
|
+
isKnownPrimitive ||
|
|
155
|
+
isTypedefStruct;
|
|
149
156
|
|
|
150
157
|
return {
|
|
151
158
|
name,
|
|
@@ -158,9 +165,10 @@ class ParameterInputAdapter {
|
|
|
158
165
|
isString: false,
|
|
159
166
|
isPassByValue: deps.isPassByValue,
|
|
160
167
|
isPassByReference,
|
|
161
|
-
// Issue #895: Force pointer syntax in C++ mode for callback-compatible
|
|
162
|
-
//
|
|
163
|
-
forcePointerSyntax:
|
|
168
|
+
// Issue #895/#958: Force pointer syntax in C++ mode for callback-compatible
|
|
169
|
+
// and typedef struct params (C types expect pointers, not C++ references)
|
|
170
|
+
forcePointerSyntax:
|
|
171
|
+
deps.forcePassByReference || isTypedefStruct || undefined,
|
|
164
172
|
// Issue #895: Preserve const from callback typedef signature
|
|
165
173
|
forceConst: deps.forceConst,
|
|
166
174
|
};
|
|
@@ -7,6 +7,8 @@ interface IFunctionContextCallbacks {
|
|
|
7
7
|
isStructType: (typeName: string) => boolean;
|
|
8
8
|
/** Resolve qualified type identifiers to a type name */
|
|
9
9
|
resolveQualifiedType: (identifiers: string[]) => string;
|
|
10
|
+
/** Issue #958: Check if a type name is a typedef'd struct from C headers */
|
|
11
|
+
isTypedefStructType?: (typeName: string) => boolean;
|
|
10
12
|
}
|
|
11
13
|
|
|
12
14
|
export default IFunctionContextCallbacks;
|
|
@@ -528,6 +528,15 @@ export default class CodeGenState {
|
|
|
528
528
|
return this.symbols?.opaqueTypes.has(typeName) ?? false;
|
|
529
529
|
}
|
|
530
530
|
|
|
531
|
+
/**
|
|
532
|
+
* Issue #958: Check if a type name is an external typedef struct type.
|
|
533
|
+
* External typedef struct types should use pointer semantics for scope variables.
|
|
534
|
+
* Unlike isOpaqueType, this returns true for both forward-declared and complete structs.
|
|
535
|
+
*/
|
|
536
|
+
static isTypedefStructType(typeName: string): boolean {
|
|
537
|
+
return this.symbolTable?.isTypedefStructType(typeName) ?? false;
|
|
538
|
+
}
|
|
539
|
+
|
|
531
540
|
/**
|
|
532
541
|
* Get type info for a variable.
|
|
533
542
|
* Checks local typeRegistry first, then falls back to SymbolTable
|
|
@@ -20,6 +20,12 @@ interface ICachedFileEntry {
|
|
|
20
20
|
enumBitWidth?: Record<string, number>;
|
|
21
21
|
/** Issue #948: Opaque types (forward-declared struct types) */
|
|
22
22
|
opaqueTypes?: string[];
|
|
23
|
+
/** Issue #958: Typedef struct types with source files ([typeName, sourceFile] pairs) */
|
|
24
|
+
typedefStructTypes?: Array<[string, string]>;
|
|
25
|
+
/** Issue #958: Struct tag → typedef name aliases ([structTag, typedefName] pairs) */
|
|
26
|
+
structTagAliases?: Array<[string, string]>;
|
|
27
|
+
/** Issue #958: Struct tags that have full definitions (bodies) */
|
|
28
|
+
structTagsWithBodies?: string[];
|
|
23
29
|
}
|
|
24
30
|
|
|
25
31
|
export default ICachedFileEntry;
|
|
@@ -32,7 +32,7 @@ import ESourceLanguage from "../types/ESourceLanguage";
|
|
|
32
32
|
const defaultFs = NodeFileSystem.instance;
|
|
33
33
|
|
|
34
34
|
/** Current cache format version - increment when serialization format changes */
|
|
35
|
-
const CACHE_VERSION =
|
|
35
|
+
const CACHE_VERSION = 7; // Issue #958: Add structTagAliases, structTagsWithBodies to cache
|
|
36
36
|
|
|
37
37
|
const TRANSPILER_VERSION = packageJson.version;
|
|
38
38
|
|
|
@@ -135,6 +135,9 @@ class CacheManager {
|
|
|
135
135
|
needsStructKeyword: string[];
|
|
136
136
|
enumBitWidth: Map<string, number>;
|
|
137
137
|
opaqueTypes: string[];
|
|
138
|
+
typedefStructTypes: Array<[string, string]>;
|
|
139
|
+
structTagAliases: Array<[string, string]>;
|
|
140
|
+
structTagsWithBodies: string[];
|
|
138
141
|
} | null {
|
|
139
142
|
if (!this.cache) return null;
|
|
140
143
|
|
|
@@ -175,6 +178,9 @@ class CacheManager {
|
|
|
175
178
|
needsStructKeyword: cachedEntry.needsStructKeyword ?? [],
|
|
176
179
|
enumBitWidth,
|
|
177
180
|
opaqueTypes: cachedEntry.opaqueTypes ?? [],
|
|
181
|
+
typedefStructTypes: cachedEntry.typedefStructTypes ?? [],
|
|
182
|
+
structTagAliases: cachedEntry.structTagAliases ?? [],
|
|
183
|
+
structTagsWithBodies: cachedEntry.structTagsWithBodies ?? [],
|
|
178
184
|
};
|
|
179
185
|
}
|
|
180
186
|
|
|
@@ -186,9 +192,14 @@ class CacheManager {
|
|
|
186
192
|
filePath: string,
|
|
187
193
|
symbols: ISerializedSymbol[],
|
|
188
194
|
structFields: Map<string, Map<string, IStructFieldInfo>>,
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
195
|
+
options?: {
|
|
196
|
+
needsStructKeyword?: string[];
|
|
197
|
+
enumBitWidth?: Map<string, number>;
|
|
198
|
+
opaqueTypes?: string[];
|
|
199
|
+
typedefStructTypes?: Array<[string, string]>;
|
|
200
|
+
structTagAliases?: Array<[string, string]>;
|
|
201
|
+
structTagsWithBodies?: string[];
|
|
202
|
+
},
|
|
192
203
|
): void {
|
|
193
204
|
if (!this.cache) return;
|
|
194
205
|
|
|
@@ -218,8 +229,8 @@ class CacheManager {
|
|
|
218
229
|
|
|
219
230
|
// Issue #208: Convert enum bit widths from Map to plain object
|
|
220
231
|
const serializedEnumBitWidth: Record<string, number> = {};
|
|
221
|
-
if (enumBitWidth) {
|
|
222
|
-
for (const [enumName, width] of enumBitWidth) {
|
|
232
|
+
if (options?.enumBitWidth) {
|
|
233
|
+
for (const [enumName, width] of options.enumBitWidth) {
|
|
223
234
|
serializedEnumBitWidth[enumName] = width;
|
|
224
235
|
}
|
|
225
236
|
}
|
|
@@ -230,9 +241,12 @@ class CacheManager {
|
|
|
230
241
|
cacheKey,
|
|
231
242
|
symbols: serializedSymbols,
|
|
232
243
|
structFields: serializedFields,
|
|
233
|
-
needsStructKeyword,
|
|
244
|
+
needsStructKeyword: options?.needsStructKeyword,
|
|
234
245
|
enumBitWidth: serializedEnumBitWidth,
|
|
235
|
-
opaqueTypes,
|
|
246
|
+
opaqueTypes: options?.opaqueTypes,
|
|
247
|
+
typedefStructTypes: options?.typedefStructTypes,
|
|
248
|
+
structTagAliases: options?.structTagAliases,
|
|
249
|
+
structTagsWithBodies: options?.structTagsWithBodies,
|
|
236
250
|
};
|
|
237
251
|
|
|
238
252
|
this.cache.setKey(filePath, entry);
|
|
@@ -273,15 +287,22 @@ class CacheManager {
|
|
|
273
287
|
// Issue #948: Extract opaque types (forward-declared structs)
|
|
274
288
|
const opaqueTypes = symbolTable.getAllOpaqueTypes();
|
|
275
289
|
|
|
290
|
+
// Issue #958: Extract typedef struct types (all typedef'd structs)
|
|
291
|
+
const typedefStructTypes = symbolTable.getAllTypedefStructTypes();
|
|
292
|
+
|
|
293
|
+
// Issue #958: Extract struct tag aliases and body tracking
|
|
294
|
+
const structTagAliases = symbolTable.getAllStructTagAliases();
|
|
295
|
+
const structTagsWithBodies = symbolTable.getAllStructTagsWithBodies();
|
|
296
|
+
|
|
276
297
|
// Delegate to existing setSymbols method
|
|
277
|
-
this.setSymbols(
|
|
278
|
-
filePath,
|
|
279
|
-
symbols,
|
|
280
|
-
structFields,
|
|
298
|
+
this.setSymbols(filePath, symbols, structFields, {
|
|
281
299
|
needsStructKeyword,
|
|
282
300
|
enumBitWidth,
|
|
283
301
|
opaqueTypes,
|
|
284
|
-
|
|
302
|
+
typedefStructTypes,
|
|
303
|
+
structTagAliases,
|
|
304
|
+
structTagsWithBodies,
|
|
305
|
+
});
|
|
285
306
|
}
|
|
286
307
|
|
|
287
308
|
/**
|
|
@@ -361,7 +361,9 @@ describe("CacheManager", () => {
|
|
|
361
361
|
const testFile = join(testDir, "test.h");
|
|
362
362
|
writeFileSync(testFile, "// test");
|
|
363
363
|
|
|
364
|
-
cacheManager.setSymbols(testFile, [], new Map(),
|
|
364
|
+
cacheManager.setSymbols(testFile, [], new Map(), {
|
|
365
|
+
needsStructKeyword: ["Point", "Rectangle"],
|
|
366
|
+
});
|
|
365
367
|
|
|
366
368
|
const cached = cacheManager.getSymbols(testFile);
|
|
367
369
|
expect(cached!.needsStructKeyword).toEqual(["Point", "Rectangle"]);
|
|
@@ -391,7 +393,7 @@ describe("CacheManager", () => {
|
|
|
391
393
|
enumBitWidth.set("Status", 8);
|
|
392
394
|
enumBitWidth.set("Mode", 16);
|
|
393
395
|
|
|
394
|
-
cacheManager.setSymbols(testFile, [], new Map(),
|
|
396
|
+
cacheManager.setSymbols(testFile, [], new Map(), { enumBitWidth });
|
|
395
397
|
|
|
396
398
|
const cached = cacheManager.getSymbols(testFile);
|
|
397
399
|
expect(cached!.enumBitWidth.get("Status")).toBe(8);
|
|
@@ -405,7 +407,7 @@ describe("CacheManager", () => {
|
|
|
405
407
|
const enumBitWidth = new Map<string, number>();
|
|
406
408
|
enumBitWidth.set("Priority", 32);
|
|
407
409
|
|
|
408
|
-
cacheManager.setSymbols(testFile, [], new Map(),
|
|
410
|
+
cacheManager.setSymbols(testFile, [], new Map(), { enumBitWidth });
|
|
409
411
|
await cacheManager.flush();
|
|
410
412
|
|
|
411
413
|
// Reload
|
|
@@ -1492,7 +1494,7 @@ describe("CacheManager", () => {
|
|
|
1492
1494
|
const content = mockFs.getWrittenContent("/project/.cnx/config.json");
|
|
1493
1495
|
expect(content).toBeDefined();
|
|
1494
1496
|
const newConfig = JSON.parse(content!);
|
|
1495
|
-
expect(newConfig.version).toBe(
|
|
1497
|
+
expect(newConfig.version).toBe(7); // Current CACHE_VERSION (Issue #958 structTagAliases, structTagsWithBodies)
|
|
1496
1498
|
});
|
|
1497
1499
|
|
|
1498
1500
|
it("should not cache files that do not exist in IFileSystem", async () => {
|