c-next 0.2.16 → 0.2.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +18 -2
- package/dist/index.js +8897 -6260
- package/dist/index.js.map +4 -4
- package/grammar/CNext.g4 +12 -0
- package/package.json +4 -2
- package/src/transpiler/Transpiler.ts +376 -48
- package/src/transpiler/__tests__/DualCodePaths.test.ts +1 -1
- package/src/transpiler/__tests__/compileCommandsDiscovery.integration.test.ts +94 -0
- package/src/transpiler/__tests__/externalSymbolRecovery.integration.test.ts +215 -0
- package/src/transpiler/logic/__tests__/detectAssemblySyntax.test.ts +116 -0
- package/src/transpiler/logic/analysis/FunctionCallAnalyzer.ts +65 -10
- package/src/transpiler/logic/analysis/InitializationAnalyzer.ts +186 -14
- package/src/transpiler/logic/analysis/MixedTypeCategoryAnalyzer.ts +408 -0
- package/src/transpiler/logic/analysis/PassByValueAnalyzer.ts +16 -97
- package/src/transpiler/logic/analysis/ReturnPathAnalyzer.ts +171 -0
- package/src/transpiler/logic/analysis/SignedShiftAnalyzer.ts +124 -12
- package/src/transpiler/logic/analysis/__tests__/FunctionCallAnalyzer.test.ts +200 -0
- package/src/transpiler/logic/analysis/__tests__/InitializationAnalyzer.test.ts +386 -1
- package/src/transpiler/logic/analysis/__tests__/MixedTypeCategoryAnalyzer.test.ts +346 -0
- package/src/transpiler/logic/analysis/__tests__/ReturnPathAnalyzer.test.ts +232 -0
- package/src/transpiler/logic/analysis/__tests__/SignedShiftAnalyzer.test.ts +211 -0
- package/src/transpiler/logic/analysis/runAnalyzers.ts +23 -2
- package/src/transpiler/logic/analysis/types/IMixedTypeCategoryError.ts +17 -0
- package/src/transpiler/logic/analysis/types/IReturnPathError.ts +12 -0
- package/src/transpiler/logic/detectAssemblySyntax.ts +80 -0
- package/src/transpiler/logic/parser/grammar/CNext.interp +4 -1
- package/src/transpiler/logic/parser/grammar/CNext.tokens +169 -167
- package/src/transpiler/logic/parser/grammar/CNextLexer.interp +4 -1
- package/src/transpiler/logic/parser/grammar/CNextLexer.tokens +169 -167
- package/src/transpiler/logic/parser/grammar/CNextLexer.ts +545 -541
- package/src/transpiler/logic/parser/grammar/CNextListener.ts +11 -0
- package/src/transpiler/logic/parser/grammar/CNextParser.ts +1318 -1178
- package/src/transpiler/logic/parser/grammar/CNextVisitor.ts +7 -0
- package/src/transpiler/logic/preprocessor/CompileCommandsReader.ts +332 -0
- package/src/transpiler/logic/preprocessor/ExternalDeclarationOracle.ts +202 -0
- package/src/transpiler/logic/preprocessor/Preprocessor.ts +24 -6
- package/src/transpiler/logic/preprocessor/ToolchainDetector.ts +42 -1
- package/src/transpiler/logic/preprocessor/__tests__/CompileCommandsReader.test.ts +216 -0
- package/src/transpiler/logic/preprocessor/__tests__/ExternalDeclarationOracle.test.ts +153 -0
- package/src/transpiler/logic/preprocessor/__tests__/Preprocessor.test.ts +43 -18
- package/src/transpiler/logic/preprocessor/__tests__/ToolchainDetector.crossCompiler.test.ts +75 -0
- package/src/transpiler/logic/preprocessor/__tests__/fixtures/oracle/dependent.h +7 -0
- package/src/transpiler/logic/preprocessor/__tests__/fixtures/oracle/predecessor.h +5 -0
- package/src/transpiler/logic/preprocessor/types/ICompileCommandsResult.ts +14 -0
- package/src/transpiler/logic/preprocessor/types/IPreprocessOptions.ts +17 -0
- package/src/transpiler/logic/symbols/SymbolTable.ts +62 -2
- package/src/transpiler/logic/symbols/__tests__/SymbolTable.test.ts +55 -4
- package/src/transpiler/logic/symbols/cnext/collectors/VariableCollector.ts +15 -2
- package/src/transpiler/logic/symbols/cnext/utils/TypeUtils.ts +64 -50
- package/src/transpiler/output/MisraSuppressionUtils.ts +52 -0
- package/src/transpiler/output/__tests__/MisraSuppressionUtils.test.ts +67 -0
- package/src/transpiler/output/codegen/CodeGenerator.ts +196 -98
- package/src/transpiler/output/codegen/TypeResolver.ts +148 -0
- package/src/transpiler/output/codegen/TypeValidator.ts +179 -81
- package/src/transpiler/output/codegen/__tests__/CodeGenerator.coverage.test.ts +165 -17
- package/src/transpiler/output/codegen/__tests__/CodeGenerator.test.ts +163 -35
- package/src/transpiler/output/codegen/__tests__/TrackVariableTypeHelpers.test.ts +2 -2
- package/src/transpiler/output/codegen/__tests__/TypeResolver.test.ts +93 -0
- package/src/transpiler/output/codegen/__tests__/TypeValidator.alwaysTrueLoop.test.ts +91 -0
- package/src/transpiler/output/codegen/__tests__/TypeValidator.test.ts +97 -14
- package/src/transpiler/output/codegen/assignment/AssignmentClassifier.ts +13 -0
- package/src/transpiler/output/codegen/assignment/AssignmentKind.ts +1 -1
- package/src/transpiler/output/codegen/assignment/handlers/AccessPatternHandlers.ts +20 -12
- package/src/transpiler/output/codegen/assignment/handlers/ArrayHandlers.ts +424 -22
- package/src/transpiler/output/codegen/assignment/handlers/BitAccessHandlers.ts +31 -18
- package/src/transpiler/output/codegen/assignment/handlers/BitmapHandlers.ts +7 -8
- package/src/transpiler/output/codegen/assignment/handlers/RegisterHandlers.ts +6 -8
- package/src/transpiler/output/codegen/assignment/handlers/RegisterUtils.ts +12 -10
- package/src/transpiler/output/codegen/assignment/handlers/SimpleHandler.ts +3 -7
- package/src/transpiler/output/codegen/assignment/handlers/SpecialHandlers.ts +7 -9
- package/src/transpiler/output/codegen/assignment/handlers/StringHandlers.ts +12 -10
- package/src/transpiler/output/codegen/assignment/handlers/__tests__/ArrayHandlers.test.ts +479 -11
- package/src/transpiler/output/codegen/generators/IOrchestrator.ts +3 -0
- package/src/transpiler/output/codegen/generators/declarationGenerators/ScopeGenerator.ts +26 -7
- package/src/transpiler/output/codegen/generators/declarationGenerators/__tests__/ScopeGenerator.test.ts +86 -0
- package/src/transpiler/output/codegen/generators/expressions/BinaryExprGenerator.ts +43 -24
- package/src/transpiler/output/codegen/generators/expressions/CallExprGenerator.ts +76 -58
- package/src/transpiler/output/codegen/generators/expressions/ExpressionGenerator.ts +9 -2
- package/src/transpiler/output/codegen/generators/expressions/PostfixExpressionGenerator.ts +26 -13
- package/src/transpiler/output/codegen/generators/expressions/__tests__/CallExprGenerator.test.ts +44 -0
- package/src/transpiler/output/codegen/generators/expressions/__tests__/ExpressionGenerator.test.ts +82 -1
- package/src/transpiler/output/codegen/generators/expressions/__tests__/PostfixExpressionGenerator.test.ts +129 -1
- package/src/transpiler/output/codegen/generators/statements/ControlFlowGenerator.ts +64 -8
- package/src/transpiler/output/codegen/generators/statements/__tests__/ControlFlowGenerator.test.ts +8 -5
- package/src/transpiler/output/codegen/helpers/AssignmentExpectedTypeResolver.ts +30 -2
- package/src/transpiler/output/codegen/helpers/ParameterInputAdapter.ts +17 -3
- package/src/transpiler/output/codegen/helpers/ParameterSignatureBuilder.ts +17 -4
- package/src/transpiler/output/codegen/helpers/StringDeclHelper.ts +240 -42
- package/src/transpiler/output/codegen/helpers/SymbolLookupHelper.ts +0 -21
- package/src/transpiler/output/codegen/helpers/TypeGenerationHelper.ts +60 -39
- package/src/transpiler/output/codegen/helpers/TypeRegistrationEngine.ts +170 -36
- package/src/transpiler/output/codegen/helpers/VariableDeclHelper.ts +37 -39
- package/src/transpiler/output/codegen/helpers/__tests__/AssignmentExpectedTypeResolver.test.ts +19 -0
- package/src/transpiler/output/codegen/helpers/__tests__/ParameterInputAdapter.test.ts +117 -0
- package/src/transpiler/output/codegen/helpers/__tests__/ParameterSignatureBuilder.test.ts +94 -2
- package/src/transpiler/output/codegen/helpers/__tests__/StringDeclHelper.test.ts +322 -9
- package/src/transpiler/output/codegen/helpers/__tests__/SymbolLookupHelper.test.ts +0 -64
- package/src/transpiler/output/codegen/helpers/__tests__/TypeRegistrationEngine.test.ts +101 -0
- package/src/transpiler/output/codegen/helpers/__tests__/VariableDeclHelper.test.ts +29 -5
- package/src/transpiler/output/codegen/subscript/SubscriptClassifier.ts +30 -11
- package/src/transpiler/output/codegen/subscript/TSubscriptKind.ts +1 -1
- package/src/transpiler/output/codegen/subscript/__tests__/SubscriptClassifier.test.ts +38 -6
- package/src/transpiler/output/codegen/types/ICallbackTypeInfo.ts +2 -1
- package/src/transpiler/output/codegen/types/IParameterInput.ts +7 -0
- package/src/transpiler/output/headers/BaseHeaderGenerator.ts +8 -0
- package/src/transpiler/output/headers/HeaderGeneratorUtils.ts +140 -24
- package/src/transpiler/output/headers/__tests__/HeaderGeneratorUtils.test.ts +280 -0
- package/src/transpiler/output/headers/generators/IHeaderTypeInput.ts +13 -0
- package/src/transpiler/output/headers/generators/generateStructHeader.ts +48 -28
- package/src/transpiler/state/CodeGenState.ts +91 -22
- package/src/transpiler/state/__tests__/CodeGenState.test.ts +253 -11
- package/src/transpiler/types/ICachedFileEntry.ts +7 -0
- package/src/utils/LiteralUtils.ts +23 -0
- package/src/utils/__tests__/LiteralUtils.test.ts +101 -0
- package/src/utils/cache/CacheManager.ts +13 -2
- package/src/utils/cache/__tests__/CacheManager.test.ts +18 -1
- package/src/utils/constants/TypeConstants.ts +13 -0
- package/src/utils/types/IParameterSymbol.ts +1 -0
package/grammar/CNext.g4
CHANGED
|
@@ -217,6 +217,7 @@ statement
|
|
|
217
217
|
| whileStatement
|
|
218
218
|
| doWhileStatement
|
|
219
219
|
| forStatement
|
|
220
|
+
| foreverStatement // ADR-113: Infinite loops
|
|
220
221
|
| switchStatement
|
|
221
222
|
| returnStatement
|
|
222
223
|
| criticalStatement // ADR-050: Critical sections
|
|
@@ -283,6 +284,12 @@ forStatement
|
|
|
283
284
|
: 'for' '(' forInit? ';' expression? ';' forUpdate? ')' statement
|
|
284
285
|
;
|
|
285
286
|
|
|
287
|
+
// ADR-113: Infinite loop. Braces always required (no single-statement form),
|
|
288
|
+
// matching switch/scope/critical. Lowers to MISRA-compliant for(;;).
|
|
289
|
+
foreverStatement
|
|
290
|
+
: FOREVER block
|
|
291
|
+
;
|
|
292
|
+
|
|
286
293
|
// For loop init - uses versions without trailing semicolons
|
|
287
294
|
forInit
|
|
288
295
|
: forVarDecl
|
|
@@ -538,10 +545,14 @@ stringType
|
|
|
538
545
|
|
|
539
546
|
// C-Next style array type: dimensions in type position
|
|
540
547
|
// Supports: u8[8], u8[4][4], u8[] (unbounded), string<32>[5]
|
|
548
|
+
// Also supports scoped/qualified types: this.Type[4], Scope.Type[4], global.Type[4]
|
|
541
549
|
arrayType
|
|
542
550
|
: primitiveType arrayTypeDimension+
|
|
543
551
|
| userType arrayTypeDimension+
|
|
544
552
|
| stringType arrayTypeDimension+
|
|
553
|
+
| scopedType arrayTypeDimension+ // this.Type[4] - scoped type array
|
|
554
|
+
| qualifiedType arrayTypeDimension+ // Scope.Type[4] - qualified type array
|
|
555
|
+
| globalType arrayTypeDimension+ // global.Type[4] - global type array
|
|
545
556
|
;
|
|
546
557
|
|
|
547
558
|
arrayTypeDimension
|
|
@@ -638,6 +649,7 @@ ELSE : 'else';
|
|
|
638
649
|
WHILE : 'while';
|
|
639
650
|
DO : 'do'; // ADR-027: Do-while loops
|
|
640
651
|
FOR : 'for';
|
|
652
|
+
FOREVER : 'forever'; // ADR-113: Infinite loops
|
|
641
653
|
SWITCH : 'switch'; // ADR-025: Switch statements
|
|
642
654
|
CASE : 'case';
|
|
643
655
|
DEFAULT : 'default';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "c-next",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.18",
|
|
4
4
|
"description": "A safer C for embedded systems development. Transpiles to clean, readable C.",
|
|
5
5
|
"packageManager": "npm@11.9.0",
|
|
6
6
|
"type": "module",
|
|
@@ -23,7 +23,9 @@
|
|
|
23
23
|
"test:q": "tsx scripts/test.ts -q",
|
|
24
24
|
"test:update": "tsx scripts/test.ts --update",
|
|
25
25
|
"integration:transpile": "tsx scripts/test.ts --transpile-only",
|
|
26
|
-
"
|
|
26
|
+
"test:bugs": "tsx scripts/test.ts -- bugs",
|
|
27
|
+
"test:bugs:q": "tsx scripts/test.ts -- bugs -q",
|
|
28
|
+
"integration:bugs:transpile": "tsx scripts/test.ts -- bugs --transpile-only",
|
|
27
29
|
"analyze": "./scripts/static-analysis.sh",
|
|
28
30
|
"clean": "rm -rf dist src/transpiler/logic/parser/grammar src/transpiler/logic/parser/c/grammar src/transpiler/logic/parser/cpp/grammar",
|
|
29
31
|
"prettier:check": "prettier --check .",
|
|
@@ -36,6 +36,10 @@ import HeaderSymbolAdapter from "./output/headers/adapters/HeaderSymbolAdapter";
|
|
|
36
36
|
import IHeaderSymbol from "./output/headers/types/IHeaderSymbol";
|
|
37
37
|
import TSymbol from "./types/symbols/TSymbol";
|
|
38
38
|
import Preprocessor from "./logic/preprocessor/Preprocessor";
|
|
39
|
+
import ToolchainDetector from "./logic/preprocessor/ToolchainDetector";
|
|
40
|
+
import CompileCommandsReader from "./logic/preprocessor/CompileCommandsReader";
|
|
41
|
+
import IToolchain from "./logic/preprocessor/types/IToolchain";
|
|
42
|
+
import ICompileCommandsResult from "./logic/preprocessor/types/ICompileCommandsResult";
|
|
39
43
|
|
|
40
44
|
import FileDiscovery from "./data/FileDiscovery";
|
|
41
45
|
import EFileType from "./data/types/EFileType";
|
|
@@ -62,6 +66,8 @@ import ModificationAnalyzer from "./logic/analysis/ModificationAnalyzer";
|
|
|
62
66
|
import CacheManager from "../utils/cache/CacheManager";
|
|
63
67
|
import MapUtils from "../utils/MapUtils";
|
|
64
68
|
import detectCppSyntax from "./logic/detectCppSyntax";
|
|
69
|
+
import detectAssemblySyntax from "./logic/detectAssemblySyntax";
|
|
70
|
+
import ExternalDeclarationOracle from "./logic/preprocessor/ExternalDeclarationOracle";
|
|
65
71
|
import TransitiveEnumCollector from "./logic/symbols/TransitiveEnumCollector";
|
|
66
72
|
import TypedefParamParser from "./output/codegen/helpers/TypedefParamParser";
|
|
67
73
|
|
|
@@ -77,6 +83,13 @@ class Transpiler {
|
|
|
77
83
|
private readonly cacheManager: CacheManager | null;
|
|
78
84
|
/** Issue #211: Tracks if C++ output is needed (one-way flag, false → true only) */
|
|
79
85
|
private cppDetected: boolean;
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Set when any C header failed standalone preprocessing (fell back to raw
|
|
89
|
+
* text). Gates the ExternalDeclarationOracle recovery pass (Issue #985) so
|
|
90
|
+
* only projects with unresolvable framework headers pay its cost.
|
|
91
|
+
*/
|
|
92
|
+
private anyHeaderPreprocessFailed = false;
|
|
80
93
|
/** Issue #587: Encapsulated state for accumulated Maps/Sets */
|
|
81
94
|
private readonly state = new TranspilerState();
|
|
82
95
|
/**
|
|
@@ -112,7 +125,24 @@ class Transpiler {
|
|
|
112
125
|
// Issue #211: Initialize cppDetected from config (--cpp flag sets this)
|
|
113
126
|
this.cppDetected = this.config.cppRequired;
|
|
114
127
|
|
|
115
|
-
|
|
128
|
+
// Adopt the compiler's own view from the project's compile_commands.json, if
|
|
129
|
+
// present. Every build system (CMake, PlatformIO, Meson, Zephyr, bear-wrapped
|
|
130
|
+
// Make) emits this database; reading it — rather than mirroring framework
|
|
131
|
+
// include paths in cnext.config.json — lets cnext resolve external headers
|
|
132
|
+
// exactly as the compiler will, which is the same reason clangd reads it.
|
|
133
|
+
// The include paths + defines + compiler are the contract every build system
|
|
134
|
+
// converges on. (Issue #985 external-symbol recovery; unblocks ADR-062.)
|
|
135
|
+
const projectRoot = this.determineProjectRoot();
|
|
136
|
+
const compileDb = projectRoot
|
|
137
|
+
? CompileCommandsReader.load(join(projectRoot, "compile_commands.json"))
|
|
138
|
+
: null;
|
|
139
|
+
if (compileDb) {
|
|
140
|
+
this._applyCompileCommands(compileDb);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
this.preprocessor = new Preprocessor(
|
|
144
|
+
Transpiler._toolchainForCompileDb(compileDb),
|
|
145
|
+
);
|
|
116
146
|
this.codeGenerator = new CodeGenerator();
|
|
117
147
|
this.headerGenerator = new HeaderGenerator();
|
|
118
148
|
this.warnings = [];
|
|
@@ -128,13 +158,44 @@ class Transpiler {
|
|
|
128
158
|
this.fs,
|
|
129
159
|
);
|
|
130
160
|
|
|
131
|
-
// Initialize cache manager if caching is enabled and project root
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
161
|
+
// Initialize cache manager if caching is enabled and a project root was found.
|
|
162
|
+
this.cacheManager =
|
|
163
|
+
!this.config.noCache && projectRoot
|
|
164
|
+
? new CacheManager(projectRoot, this.fs)
|
|
165
|
+
: null;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Merge a discovered compile_commands.json into the effective config: union its
|
|
170
|
+
* include search paths into includeDirs (so both preprocessing and include-tree
|
|
171
|
+
* resolution see what the compiler sees) and merge its defines beneath the
|
|
172
|
+
* explicit CLI/config defines, which win on conflict.
|
|
173
|
+
*/
|
|
174
|
+
private _applyCompileCommands(db: ICompileCommandsResult): void {
|
|
175
|
+
const merged = [...this.config.includeDirs];
|
|
176
|
+
const seen = new Set(merged);
|
|
177
|
+
for (const path of db.includePaths) {
|
|
178
|
+
if (!seen.has(path)) {
|
|
179
|
+
seen.add(path);
|
|
180
|
+
merged.push(path);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
this.config.includeDirs = merged;
|
|
184
|
+
this.config.defines = { ...db.defines, ...this.config.defines };
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* The toolchain to preprocess with, given a discovered compile database. An
|
|
189
|
+
* explicit CNEXT_CROSS_COMPILER override always wins (deferred to Preprocessor's
|
|
190
|
+
* own detection); otherwise adopt the database's compiler if it resolves, else
|
|
191
|
+
* fall back to auto-detection.
|
|
192
|
+
*/
|
|
193
|
+
private static _toolchainForCompileDb(
|
|
194
|
+
db: ICompileCommandsResult | null,
|
|
195
|
+
): IToolchain | undefined {
|
|
196
|
+
if (process.env.CNEXT_CROSS_COMPILER) return undefined;
|
|
197
|
+
if (!db?.compiler) return undefined;
|
|
198
|
+
return ToolchainDetector.fromPath(db.compiler) ?? undefined;
|
|
138
199
|
}
|
|
139
200
|
|
|
140
201
|
// ===========================================================================
|
|
@@ -218,6 +279,16 @@ class Transpiler {
|
|
|
218
279
|
// Stage 2: Collect symbols from C/C++ headers and build analyzer context
|
|
219
280
|
// Issue #945: Now async for preprocessing support
|
|
220
281
|
await this._collectAllHeaderSymbols(input.headerFiles, result);
|
|
282
|
+
|
|
283
|
+
// Issue #985 recovery: when standalone header preprocessing missed framework
|
|
284
|
+
// symbols, recover their declared names via translation-unit preprocessing.
|
|
285
|
+
await this._collectExternalDeclarations(input);
|
|
286
|
+
|
|
287
|
+
// Snapshot external struct fields for InitializationAnalyzer AFTER recovery so
|
|
288
|
+
// structs that only become known through #985 recovery (their fields are added
|
|
289
|
+
// to symbolTable by _collectExternalDeclarations) are folded in and remain
|
|
290
|
+
// subject to init-completeness checking. Nothing consumes externalStructFields
|
|
291
|
+
// before Stage 5, so a single post-recovery build is sufficient.
|
|
221
292
|
CodeGenState.buildExternalStructFields();
|
|
222
293
|
|
|
223
294
|
// Stage 3: Collect symbols from C-Next files
|
|
@@ -628,13 +699,146 @@ class Transpiler {
|
|
|
628
699
|
headerFiles: IDiscoveredFile[],
|
|
629
700
|
result: ITranspilerResult,
|
|
630
701
|
): Promise<void> {
|
|
702
|
+
const precedingHeaders: string[] = [];
|
|
631
703
|
for (const file of headerFiles) {
|
|
704
|
+
let usable = false;
|
|
632
705
|
try {
|
|
633
|
-
await this.doCollectHeaderSymbols(file);
|
|
706
|
+
usable = await this.doCollectHeaderSymbols(file, precedingHeaders);
|
|
634
707
|
result.filesProcessed++;
|
|
635
708
|
} catch (err) {
|
|
636
709
|
this.warnings.push(`Failed to process header ${file.path}: ${err}`);
|
|
637
710
|
}
|
|
711
|
+
// Offer this header as macro context to headers processed after it, but
|
|
712
|
+
// only if it itself preprocessed cleanly — an unpreprocessable predecessor
|
|
713
|
+
// would otherwise make every dependent's -imacros retry fail.
|
|
714
|
+
if (usable) {
|
|
715
|
+
precedingHeaders.push(file.path);
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
/**
|
|
721
|
+
* Issue #985 recovery: recover the NAMES of framework functions / function-like
|
|
722
|
+
* macros that standalone header preprocessing missed, by preprocessing each
|
|
723
|
+
* .cnx's C includes as a translation unit (predecessors first — the way the
|
|
724
|
+
* real compiler does). Requires a toolchain that can preprocess the target's
|
|
725
|
+
* headers; for cross targets set CNEXT_CROSS_COMPILER. Gated on a preprocess
|
|
726
|
+
* failure so clean projects pay nothing.
|
|
727
|
+
*/
|
|
728
|
+
private async _collectExternalDeclarations(
|
|
729
|
+
input: IPipelineInput,
|
|
730
|
+
): Promise<void> {
|
|
731
|
+
if (!this.anyHeaderPreprocessFailed) return;
|
|
732
|
+
|
|
733
|
+
const directives = this._collectCIncludeDirectives(input);
|
|
734
|
+
if (directives.length === 0) return;
|
|
735
|
+
|
|
736
|
+
const recovery = await ExternalDeclarationOracle.recover(
|
|
737
|
+
directives,
|
|
738
|
+
this.preprocessor,
|
|
739
|
+
{ includePaths: this.config.includeDirs, defines: this.config.defines },
|
|
740
|
+
);
|
|
741
|
+
if (!recovery) return;
|
|
742
|
+
|
|
743
|
+
const cleanState = this._parseRecoveredSlices(recovery.perFileContent);
|
|
744
|
+
Transpiler._clearPhantomStructBodies(cleanState);
|
|
745
|
+
|
|
746
|
+
// Function-like macros have no declaration to parse; register their names for
|
|
747
|
+
// the undeclared-call check only (a by-value macro invocation is correct).
|
|
748
|
+
if (recovery.macroNames.size > 0) {
|
|
749
|
+
CodeGenState.symbolTable.addExternalDeclarationNames(recovery.macroNames);
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
/** Every C header the .cnx files include, deduped in first-seen source order. */
|
|
754
|
+
private _collectCIncludeDirectives(input: IPipelineInput): string[] {
|
|
755
|
+
const seen = new Set<string>();
|
|
756
|
+
const directives: string[] = [];
|
|
757
|
+
for (const file of input.cnextFiles) {
|
|
758
|
+
const source = file.source ?? this.readFileOrEmpty(file.path);
|
|
759
|
+
for (const directive of Transpiler.extractCIncludeDirectives(source)) {
|
|
760
|
+
if (!seen.has(directive)) {
|
|
761
|
+
seen.add(directive);
|
|
762
|
+
directives.push(directive);
|
|
763
|
+
}
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
return directives;
|
|
767
|
+
}
|
|
768
|
+
|
|
769
|
+
/**
|
|
770
|
+
* Parse each header's own preprocessed slice with the real header parser so
|
|
771
|
+
* recovered symbols carry FULL types — function signatures, typedefs, opaque
|
|
772
|
+
* structs — not just names. Each slice is macro-expanded (so e.g. FreeRTOS
|
|
773
|
+
* PRIVILEGED_FUNCTION is gone and vTaskDelay parses) yet small (no inlined
|
|
774
|
+
* tree, so ANTLR error-recovery doesn't drop declarations). Codegen needs
|
|
775
|
+
* these to pass structs by address (twai_driver_install(&cfg)) and treat
|
|
776
|
+
* opaque framework types as pointers (lv_obj_t -> lv_obj_t*).
|
|
777
|
+
*
|
|
778
|
+
* A second, isolated table is parsed in parallel and returned: it is clean of
|
|
779
|
+
* the normal pass's degraded-blob data, so it holds the AUTHORITATIVE
|
|
780
|
+
* opaque/struct-body truth. parseCHeader (main table) auto-detects C vs C++ and
|
|
781
|
+
* skips assembler; the isolated table uses the C parser directly (opaque struct
|
|
782
|
+
* typedefs are a C concern) and tolerates slices it cannot parse.
|
|
783
|
+
*/
|
|
784
|
+
private _parseRecoveredSlices(
|
|
785
|
+
perFileContent: Map<string, string>,
|
|
786
|
+
): SymbolTable {
|
|
787
|
+
const cleanState = new SymbolTable();
|
|
788
|
+
for (const [path, content] of perFileContent) {
|
|
789
|
+
try {
|
|
790
|
+
this.parseCHeader(content, path);
|
|
791
|
+
} catch {
|
|
792
|
+
// A slice that won't parse leaves the (already-collected) symbols as they
|
|
793
|
+
// were — skip it rather than fail the build.
|
|
794
|
+
}
|
|
795
|
+
const { tree } = HeaderParser.parseC(content);
|
|
796
|
+
if (!tree) continue;
|
|
797
|
+
try {
|
|
798
|
+
CResolver.resolve(tree, path, cleanState);
|
|
799
|
+
} catch {
|
|
800
|
+
/* isolated best-effort — only its opaque/body verdict is consulted */
|
|
801
|
+
}
|
|
802
|
+
}
|
|
803
|
+
return cleanState;
|
|
804
|
+
}
|
|
805
|
+
|
|
806
|
+
/**
|
|
807
|
+
* Undo PHANTOM struct bodies: when the normal pass parsed a header's huge
|
|
808
|
+
* preprocessed blob, ANTLR error-recovery could fabricate a `struct X { ... }`
|
|
809
|
+
* that was never really there (e.g. lvgl `struct _lv_obj_t`), which makes an
|
|
810
|
+
* opaque typedef look complete and defeats pointer codegen. The clean per-file
|
|
811
|
+
* re-parse (`cleanState`) is authoritative, so for every type it proves opaque,
|
|
812
|
+
* clear any body its tag does NOT actually have.
|
|
813
|
+
*/
|
|
814
|
+
private static _clearPhantomStructBodies(cleanState: SymbolTable): void {
|
|
815
|
+
const cleanBodies = new Set(cleanState.getAllStructTagsWithBodies());
|
|
816
|
+
for (const typedefName of cleanState.getAllOpaqueTypes()) {
|
|
817
|
+
if (!cleanState.isOpaqueType(typedefName)) continue;
|
|
818
|
+
const tag = CodeGenState.symbolTable.getStructTagForTypedef(typedefName);
|
|
819
|
+
if (tag && !cleanBodies.has(tag)) {
|
|
820
|
+
CodeGenState.symbolTable.clearStructTagHasBody(tag);
|
|
821
|
+
}
|
|
822
|
+
}
|
|
823
|
+
}
|
|
824
|
+
|
|
825
|
+
/** Extract C header include directives (`<...>` / `"..."`, non-.cnx) in order. */
|
|
826
|
+
private static extractCIncludeDirectives(source: string): string[] {
|
|
827
|
+
const directives: string[] = [];
|
|
828
|
+
const re = /^[ \t]*#include\s+([<"][^>"]+[>"])/gm;
|
|
829
|
+
for (const match of source.matchAll(re)) {
|
|
830
|
+
const spec = match[1];
|
|
831
|
+
if (/\.cnx[>"]$/.test(spec)) continue; // C-Next include, not a C header
|
|
832
|
+
directives.push(spec);
|
|
833
|
+
}
|
|
834
|
+
return directives;
|
|
835
|
+
}
|
|
836
|
+
|
|
837
|
+
private readFileOrEmpty(path: string): string {
|
|
838
|
+
try {
|
|
839
|
+
return this.fs.readFile(path);
|
|
840
|
+
} catch {
|
|
841
|
+
return "";
|
|
638
842
|
}
|
|
639
843
|
}
|
|
640
844
|
|
|
@@ -1058,18 +1262,25 @@ class Transpiler {
|
|
|
1058
1262
|
* Issue #945: Added preprocessing support for conditional compilation
|
|
1059
1263
|
* SonarCloud S3776: Refactored to use helper methods for reduced complexity.
|
|
1060
1264
|
*/
|
|
1061
|
-
private async doCollectHeaderSymbols(
|
|
1265
|
+
private async doCollectHeaderSymbols(
|
|
1266
|
+
file: IDiscoveredFile,
|
|
1267
|
+
precedingHeaders: readonly string[] = [],
|
|
1268
|
+
): Promise<boolean> {
|
|
1062
1269
|
// Track as processed (for cycle detection)
|
|
1063
1270
|
const absolutePath = resolve(file.path);
|
|
1064
1271
|
this.state.markHeaderProcessed(absolutePath);
|
|
1065
1272
|
|
|
1066
1273
|
// Check cache first
|
|
1067
|
-
|
|
1068
|
-
|
|
1274
|
+
const restored = this.tryRestoreFromCache(file);
|
|
1275
|
+
if (restored) {
|
|
1276
|
+
return restored.usable; // Cache hit - skip full parsing
|
|
1069
1277
|
}
|
|
1070
1278
|
|
|
1071
1279
|
// Issue #945: Preprocess header to evaluate #if/#ifdef directives
|
|
1072
|
-
const content = await this.getHeaderContent(
|
|
1280
|
+
const { content, usable } = await this.getHeaderContent(
|
|
1281
|
+
file,
|
|
1282
|
+
precedingHeaders,
|
|
1283
|
+
);
|
|
1073
1284
|
this.parseHeaderFile(file, content);
|
|
1074
1285
|
|
|
1075
1286
|
// Debug: Show symbols found
|
|
@@ -1078,27 +1289,34 @@ class Transpiler {
|
|
|
1078
1289
|
console.log(`[DEBUG] Found ${symbols.length} symbols in ${file.path}`);
|
|
1079
1290
|
}
|
|
1080
1291
|
|
|
1081
|
-
// Issue #590: Cache the results using simplified API
|
|
1292
|
+
// Issue #590: Cache the results using simplified API. Issue #985: record when
|
|
1293
|
+
// this header fell back to raw content so a warm-cache build re-runs recovery.
|
|
1082
1294
|
if (this.cacheManager) {
|
|
1083
1295
|
this.cacheManager.setSymbolsFromTable(
|
|
1084
1296
|
file.path,
|
|
1085
1297
|
CodeGenState.symbolTable,
|
|
1298
|
+
!usable,
|
|
1086
1299
|
);
|
|
1087
1300
|
}
|
|
1301
|
+
|
|
1302
|
+
return usable;
|
|
1088
1303
|
}
|
|
1089
1304
|
|
|
1090
1305
|
/**
|
|
1091
|
-
* Try to restore symbols from cache. Returns
|
|
1306
|
+
* Try to restore symbols from cache. Returns the restored header's usability
|
|
1307
|
+
* (whether it preprocessed cleanly) on a cache hit, or null on a miss.
|
|
1092
1308
|
* SonarCloud S3776: Extracted from doCollectHeaderSymbols().
|
|
1093
1309
|
*/
|
|
1094
|
-
private tryRestoreFromCache(
|
|
1310
|
+
private tryRestoreFromCache(
|
|
1311
|
+
file: IDiscoveredFile,
|
|
1312
|
+
): { usable: boolean } | null {
|
|
1095
1313
|
if (!this.cacheManager?.isValid(file.path)) {
|
|
1096
|
-
return
|
|
1314
|
+
return null;
|
|
1097
1315
|
}
|
|
1098
1316
|
|
|
1099
1317
|
const cached = this.cacheManager.getSymbols(file.path);
|
|
1100
1318
|
if (!cached) {
|
|
1101
|
-
return
|
|
1319
|
+
return null;
|
|
1102
1320
|
}
|
|
1103
1321
|
|
|
1104
1322
|
// Restore symbols, struct fields, needsStructKeyword, and enumBitWidth from cache
|
|
@@ -1127,7 +1345,15 @@ class Transpiler {
|
|
|
1127
1345
|
// Issue #211: Still check for C++ syntax even on cache hit
|
|
1128
1346
|
this.detectCppFromFileType(file);
|
|
1129
1347
|
|
|
1130
|
-
|
|
1348
|
+
// Issue #985: The cached symbols of a header that fell back to raw content
|
|
1349
|
+
// are degraded. Re-arm the recovery gate so a warm-cache build still runs
|
|
1350
|
+
// the external-declaration recovery pass and re-applies its corrections to
|
|
1351
|
+
// the in-memory symbol table (the cache itself holds the degraded symbols).
|
|
1352
|
+
if (cached.preprocessFailed) {
|
|
1353
|
+
this.anyHeaderPreprocessFailed = true;
|
|
1354
|
+
}
|
|
1355
|
+
|
|
1356
|
+
return { usable: !cached.preprocessFailed };
|
|
1131
1357
|
}
|
|
1132
1358
|
|
|
1133
1359
|
/**
|
|
@@ -1138,24 +1364,27 @@ class Transpiler {
|
|
|
1138
1364
|
* Preprocessing is needed when the file has conditional compilation patterns
|
|
1139
1365
|
* like #if MACRO != 0 that require expression evaluation.
|
|
1140
1366
|
*/
|
|
1141
|
-
private async getHeaderContent(
|
|
1367
|
+
private async getHeaderContent(
|
|
1368
|
+
file: IDiscoveredFile,
|
|
1369
|
+
precedingHeaders: readonly string[] = [],
|
|
1370
|
+
): Promise<{ content: string; usable: boolean }> {
|
|
1142
1371
|
const rawContent = this.fs.readFile(file.path);
|
|
1143
1372
|
|
|
1144
1373
|
// Check if preprocessing is disabled
|
|
1145
1374
|
if (this.config.preprocess === false) {
|
|
1146
|
-
return rawContent;
|
|
1375
|
+
return { content: rawContent, usable: true };
|
|
1147
1376
|
}
|
|
1148
1377
|
|
|
1149
1378
|
// Check if preprocessing is available
|
|
1150
1379
|
if (!this.preprocessor.isAvailable()) {
|
|
1151
|
-
return rawContent;
|
|
1380
|
+
return { content: rawContent, usable: true };
|
|
1152
1381
|
}
|
|
1153
1382
|
|
|
1154
1383
|
// Issue #945: Only preprocess if file has conditional compilation patterns
|
|
1155
1384
|
// that require expression evaluation (e.g., #if MACRO != 0, #if MACRO == 1)
|
|
1156
1385
|
// Simple #ifdef/#ifndef patterns are already handled by the parser
|
|
1157
1386
|
if (!this.needsConditionalPreprocessing(rawContent)) {
|
|
1158
|
-
return rawContent;
|
|
1387
|
+
return { content: rawContent, usable: true };
|
|
1159
1388
|
}
|
|
1160
1389
|
|
|
1161
1390
|
// Preprocess the header file
|
|
@@ -1166,14 +1395,34 @@ class Transpiler {
|
|
|
1166
1395
|
});
|
|
1167
1396
|
|
|
1168
1397
|
if (!result.success) {
|
|
1169
|
-
//
|
|
1398
|
+
// Some headers cannot be preprocessed standalone: they require a
|
|
1399
|
+
// predecessor to have run first (e.g. FreeRTOS task.h needs FreeRTOS.h to
|
|
1400
|
+
// define INC_FREERTOS_H and its attribute macros, and enforces this with
|
|
1401
|
+
// its own #error). Retry importing the macros of the headers collected
|
|
1402
|
+
// before this one (only those that themselves preprocessed cleanly, so one
|
|
1403
|
+
// unpreprocessable predecessor can't defeat the retry).
|
|
1404
|
+
if (precedingHeaders.length > 0) {
|
|
1405
|
+
const retry = await this.preprocessor.preprocess(file.path, {
|
|
1406
|
+
defines: this.config.defines,
|
|
1407
|
+
includePaths: this.config.includeDirs,
|
|
1408
|
+
keepLineDirectives: false,
|
|
1409
|
+
imacros: [...precedingHeaders],
|
|
1410
|
+
});
|
|
1411
|
+
if (retry.success) {
|
|
1412
|
+
return { content: retry.content, usable: true };
|
|
1413
|
+
}
|
|
1414
|
+
}
|
|
1415
|
+
// Fall back to raw content. Mark not-usable so this header is not offered
|
|
1416
|
+
// as macro context to headers processed after it, and flag that TU-level
|
|
1417
|
+
// external-declaration recovery is warranted (Issue #985).
|
|
1418
|
+
this.anyHeaderPreprocessFailed = true;
|
|
1170
1419
|
this.warnings.push(
|
|
1171
1420
|
`Preprocessing failed for ${file.path}: ${result.error}. Using raw content.`,
|
|
1172
1421
|
);
|
|
1173
|
-
return rawContent;
|
|
1422
|
+
return { content: rawContent, usable: false };
|
|
1174
1423
|
}
|
|
1175
1424
|
|
|
1176
|
-
return result.content;
|
|
1425
|
+
return { content: result.content, usable: true };
|
|
1177
1426
|
}
|
|
1178
1427
|
|
|
1179
1428
|
/**
|
|
@@ -1323,6 +1572,17 @@ class Transpiler {
|
|
|
1323
1572
|
* Uses heuristic detection to choose the appropriate parser
|
|
1324
1573
|
*/
|
|
1325
1574
|
private parseCHeader(content: string, filePath: string): void {
|
|
1575
|
+
// Assembler headers (e.g. xtensa coreasm.h, pulled in transitively by
|
|
1576
|
+
// FreeRTOS port headers) are not C. Parsing their `.macro` bodies as C
|
|
1577
|
+
// mis-collects instruction mnemonics like `loop` as C symbols that then
|
|
1578
|
+
// false-conflict with C-Next symbols of the same name. Skip them entirely.
|
|
1579
|
+
if (detectAssemblySyntax(content)) {
|
|
1580
|
+
if (this.config.debugMode) {
|
|
1581
|
+
console.log(`[DEBUG] Skipping assembler header: ${filePath}`);
|
|
1582
|
+
}
|
|
1583
|
+
return;
|
|
1584
|
+
}
|
|
1585
|
+
|
|
1326
1586
|
if (detectCppSyntax(content)) {
|
|
1327
1587
|
// Issue #211: C++ detected, set flag for .cpp output
|
|
1328
1588
|
this.cppDetected = true;
|
|
@@ -1410,8 +1670,15 @@ class Transpiler {
|
|
|
1410
1670
|
CodeGenState.symbolTable,
|
|
1411
1671
|
);
|
|
1412
1672
|
|
|
1673
|
+
// ADR-029: Convert callback types to header format
|
|
1674
|
+
const callbackTypesForHeader = this._buildCallbackTypesForHeader();
|
|
1675
|
+
|
|
1413
1676
|
const typeInputWithSymbolTable = typeInput
|
|
1414
|
-
? {
|
|
1677
|
+
? {
|
|
1678
|
+
...typeInput,
|
|
1679
|
+
symbolTable: CodeGenState.symbolTable,
|
|
1680
|
+
callbackTypes: callbackTypesForHeader,
|
|
1681
|
+
}
|
|
1415
1682
|
: undefined;
|
|
1416
1683
|
|
|
1417
1684
|
const unmodifiedParams = this.codeGenerator.getFunctionUnmodifiedParams();
|
|
@@ -1437,6 +1704,52 @@ class Transpiler {
|
|
|
1437
1704
|
);
|
|
1438
1705
|
}
|
|
1439
1706
|
|
|
1707
|
+
/**
|
|
1708
|
+
* ADR-029: Build callback types for header generation.
|
|
1709
|
+
* Only includes callbacks that are actually used as struct field types.
|
|
1710
|
+
* Converts CodeGenState.callbackTypes to the format expected by IHeaderTypeInput.
|
|
1711
|
+
*/
|
|
1712
|
+
private _buildCallbackTypesForHeader(): ReadonlyMap<
|
|
1713
|
+
string,
|
|
1714
|
+
{
|
|
1715
|
+
typedefName: string;
|
|
1716
|
+
returnType: string;
|
|
1717
|
+
parameters: ReadonlyArray<{ type: string; isStruct: boolean }>;
|
|
1718
|
+
}
|
|
1719
|
+
> {
|
|
1720
|
+
const result = new Map<
|
|
1721
|
+
string,
|
|
1722
|
+
{
|
|
1723
|
+
typedefName: string;
|
|
1724
|
+
returnType: string;
|
|
1725
|
+
parameters: ReadonlyArray<{ type: string; isStruct: boolean }>;
|
|
1726
|
+
}
|
|
1727
|
+
>();
|
|
1728
|
+
|
|
1729
|
+
// Collect callback function names that are actually used as struct field types
|
|
1730
|
+
const usedCallbackTypes = new Set<string>();
|
|
1731
|
+
for (const [, funcName] of CodeGenState.callbackFieldTypes) {
|
|
1732
|
+
usedCallbackTypes.add(funcName);
|
|
1733
|
+
}
|
|
1734
|
+
|
|
1735
|
+
// Only include callbacks that are used as struct field types
|
|
1736
|
+
for (const funcName of usedCallbackTypes) {
|
|
1737
|
+
const cbInfo = CodeGenState.callbackTypes.get(funcName);
|
|
1738
|
+
if (cbInfo) {
|
|
1739
|
+
result.set(funcName, {
|
|
1740
|
+
typedefName: cbInfo.typedefName,
|
|
1741
|
+
returnType: cbInfo.returnType,
|
|
1742
|
+
parameters: cbInfo.parameters.map((p) => ({
|
|
1743
|
+
type: p.type,
|
|
1744
|
+
isStruct: p.isStruct,
|
|
1745
|
+
})),
|
|
1746
|
+
});
|
|
1747
|
+
}
|
|
1748
|
+
}
|
|
1749
|
+
|
|
1750
|
+
return result;
|
|
1751
|
+
}
|
|
1752
|
+
|
|
1440
1753
|
/**
|
|
1441
1754
|
* Collect external enum sources from included C-Next files.
|
|
1442
1755
|
*/
|
|
@@ -1509,6 +1822,9 @@ class Transpiler {
|
|
|
1509
1822
|
|
|
1510
1823
|
// Issue #914: For callback-compatible functions, bake pointer/const overrides
|
|
1511
1824
|
// onto each parameter. Skip auto-const (matches CodeGenerator path).
|
|
1825
|
+
// Note: isOpaqueHandle is not set here because callback params get their
|
|
1826
|
+
// pointer/const semantics from the typedef signature via isCallbackPointer/
|
|
1827
|
+
// isCallbackConst, which take precedence over opaque handling in the builder.
|
|
1512
1828
|
if (callbackTypedefType) {
|
|
1513
1829
|
const updatedParams = TypedefParamParser.resolveCallbackParams(
|
|
1514
1830
|
headerSymbol.parameters,
|
|
@@ -1517,29 +1833,41 @@ class Transpiler {
|
|
|
1517
1833
|
return { ...headerSymbol, parameters: updatedParams };
|
|
1518
1834
|
}
|
|
1519
1835
|
|
|
1520
|
-
// Apply auto-const
|
|
1836
|
+
// Apply auto-const and resolve opaque type info for non-callback function parameters
|
|
1521
1837
|
const unmodified = unmodifiedParams.get(headerSymbol.name);
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1838
|
+
const updatedParams = headerSymbol.parameters.map((param) => {
|
|
1839
|
+
// Issue #995: Resolve opaque type info ONCE onto the symbol.
|
|
1840
|
+
// This is the single source of truth for both body (.c/.cpp) and header (.h/.hpp).
|
|
1841
|
+
const isOpaque = CodeGenState.isOpaqueType(param.type ?? "");
|
|
1842
|
+
|
|
1843
|
+
// ADR-006: Only non-array pointer params get auto-const.
|
|
1844
|
+
// Arrays are pass-by-reference and mutable by default - auto-const would
|
|
1845
|
+
// break compatibility with C APIs expecting mutable pointers (issue #986).
|
|
1846
|
+
// Note: isAutoConst may be set here, but ParameterSignatureBuilder will
|
|
1847
|
+
// suppress it for opaque handles (Issue #995) — single source of truth.
|
|
1848
|
+
const isPointerParam =
|
|
1849
|
+
!param.isConst &&
|
|
1850
|
+
!param.isArray &&
|
|
1851
|
+
param.type !== "f32" &&
|
|
1852
|
+
param.type !== "f64" &&
|
|
1853
|
+
param.type !== "ISR" &&
|
|
1854
|
+
!knownEnums.has(param.type ?? "");
|
|
1855
|
+
|
|
1856
|
+
const shouldAutoConst =
|
|
1857
|
+
unmodified && isPointerParam && unmodified.has(param.name);
|
|
1858
|
+
|
|
1859
|
+
// Return updated param with resolved flags
|
|
1860
|
+
if (shouldAutoConst || isOpaque) {
|
|
1861
|
+
return {
|
|
1862
|
+
...param,
|
|
1863
|
+
isAutoConst: shouldAutoConst || undefined,
|
|
1864
|
+
isOpaqueHandle: isOpaque || undefined,
|
|
1865
|
+
};
|
|
1866
|
+
}
|
|
1867
|
+
return param;
|
|
1868
|
+
});
|
|
1541
1869
|
|
|
1542
|
-
return headerSymbol;
|
|
1870
|
+
return { ...headerSymbol, parameters: updatedParams };
|
|
1543
1871
|
});
|
|
1544
1872
|
}
|
|
1545
1873
|
|