Repository navigation
Render compile-time constant values in C# and C++ emitters - #48
Merged
Merged
Conversation
Renders the values of constants whose values are known at compile time: - C#: const fields and enum members now show their value (e.g. public const string DefaultName = "default", public const SampleStatus Active = 0), via a new FormatConstantValue helper that formats Mono.Cecil's folded field.Constant (string escaping, char escaping including control characters, lowercase bool, numeric literals, enum underlying values). - C++: CppField gains a nullable Value populated only for constexpr fields whose initializer is a simple literal (int/float/char/bool/string) or a leading unary +/- directly over such a literal (e.g. -5). Compound or computed expressions (e.g. 2 * 21) and named-constant references are deliberately left unrendered to avoid an incorrect/partial evaluator. Rendered in both the gradual-disclosure and single-file C++ emitters. - VHDL already rendered constant values; left unchanged. Includes updated design and verification docs, reqstream requirement updates, user guide updates, and new fixture/regression tests (C# NUL-char escaping, C++ negative-literal and bool/char constexpr fields, computed- expression non-folding guard, and CppField.Value construction tests). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Contributor
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Unresolved C# escaping and C++ parsing/coverage issues remain, along with traceability gaps.
Review effort: Lite
Findings: 3
Open (5)
Add floating-point literal parser regression coverage · New Reject nested unary operators in literal formatter · New Escape remaining control characters in string literals · New Link negative constexpr unary test in requirement traceability · New Add const-char NUL escaping test to requirement traceability · New
What changed in this PR
Adds compile-time constant rendering for C# and C++ API documentation emitters, with parser/model updates, tests, and documentation traceability.
Changes:
- Formats C# constants and enum values.
- Extracts and renders simple C++
constexprliterals. - Adds fixtures, regression tests, and supporting documentation.
| File | Summary |
|---|---|
test/ApiMark.DotNet.Tests/DotNetEmitterTests.cs |
Tests C# constant rendering. |
test/ApiMark.DotNet.Tests/DocumentationCoverageCheckerTests.cs |
Updates coverage expectations. |
test/ApiMark.DotNet.Fixtures/SampleEnum.cs |
Adds enum constant fixtures. |
test/ApiMark.DotNet.Fixtures/SampleClass.cs |
Adds C# constant fixtures. |
test/ApiMark.Cpp.Tests/CppEmitterSingleFileTests.cs |
Tests single-file rendering. |
test/ApiMark.Cpp.Tests/CppEmitterGradualDisclosureTests.cs |
Tests gradual rendering. |
test/ApiMark.Cpp.Tests/CppAstModelTests.cs |
Tests CppField.Value. |
test/ApiMark.Cpp.Tests/ClangAstParserTests.cs |
Tests C++ literal extraction. |
test/ApiMark.Cpp.Fixtures/include/fixtures/SampleClass.h |
Adds C++ constexpr fixtures. |
src/ApiMark.DotNet/DotNetEmitter.cs |
Formats C# constant values. |
src/ApiMark.Cpp/CppEmitterSingleFile.cs |
Renders values in single-file output. |
src/ApiMark.Cpp/CppEmitterGradualDisclosure.cs |
Renders values in gradual output. |
src/ApiMark.Cpp/CppAst/CppAstModel.cs |
Adds nullable field values. |
src/ApiMark.Cpp/CppAst/ClangAstParser.cs |
Extracts C++ literal values. |
docs/verification/api-mark-dot-net/dot-net-emitter.md |
Adds C# verification scenarios. |
docs/verification/api-mark-cpp/cpp-emitter-single-file.md |
Adds single-file scenarios. |
docs/verification/api-mark-cpp/cpp-emitter-gradual-disclosure.md |
Adds gradual scenarios. |
docs/verification/api-mark-cpp/cpp-ast-model.md |
Adds model scenarios. |
docs/verification/api-mark-cpp/clang-ast-parser.md |
Adds parser scenarios. |
docs/user_guide/dotnet.md |
Documents C# constant output. |
docs/user_guide/cpp.md |
Documents C++ constant output. |
docs/reqstream/api-mark-dot-net/dot-net-emitter.yaml |
Adds C# traceability. |
docs/reqstream/api-mark-cpp/cpp-emitter-single-file.yaml |
Adds single-file traceability. |
docs/reqstream/api-mark-cpp/cpp-emitter-gradual-disclosure.yaml |
Adds gradual traceability. |
docs/reqstream/api-mark-cpp/clang-ast-parser.yaml |
Adds parser traceability. |
docs/design/api-mark-dot-net/dot-net-emitter.md |
Documents formatting helpers. |
docs/design/api-mark-dot-net.md |
Updates .NET design documentation. |
docs/design/api-mark-cpp/cpp-emitter-single-file.md |
Documents single-file rendering. |
docs/design/api-mark-cpp/cpp-emitter-gradual-disclosure.md |
Documents gradual rendering. |
docs/design/api-mark-cpp/cpp-ast-model.md |
Documents CppField.Value. |
docs/design/api-mark-cpp/clang-ast-parser.md |
Documents literal extraction. |
docs/design/api-mark-cpp.md |
Updates C++ design documentation. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Fixes all 5 findings from the automated PR #48 review: - Medium: Add FloatingLiteral fixture/test coverage (ClangAstParser). New constexpr double field (Pi) in the C++ fixture, with a test asserting the display value matches clang's own decimal spelling. - Medium: Reject nested unary operators in the constexpr literal formatter. A doubly-negated literal such as - -5 previously reconstructed as the misleading --5 (reads as a C++ decrement); ExtractConstexprUnaryLiteralValue now rejects a UnaryOperator operand (via a new UnwrapPassThroughKind helper) and yields null instead. New constexpr field (DoubleNegated) and test cover the guard. - Medium: Escape all remaining control characters in C# string/char literals. EscapeStringLiteral and EscapeCharLiteral now share a new EscapeControlCharacter helper covering \a, \b, \f, \v (in addition to the existing \0, \n, \r, \t), with a \uXXXX fallback for any other non-printable control character (e.g. DEL/0x7f) so no raw control byte is ever embedded in generated documentation text. New direct unit tests on FormatConstantValue cover both the named-escape and Unicode-fallback paths without touching the compiled fixture assembly. - Low: Add the negative-literal regression test to the clang-ast-parser.yaml requirement's traceability list. - Low: Add the NUL-char regression test to the dot-net-emitter.yaml requirement's traceability list. Also updates design and verification documentation for both affected units to describe the new behavior, and adds the new floating-point and double-negation tests to the C++ requirement's traceability list for consistency. Verified: 344/344 .NET tests pass (net8/net9/net10); 191/191 C++ tests pass (net8/net9/net10, clang exercised, 0 skipped). fix.ps1 and lint.ps1 both clean. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Fixes the single Medium finding from the latest automated PR #48 review: EscapeControlCharacter only recognized DEL (0x7f) as an unnamed control character, so Unicode C1 controls (U+0080-U+009F, e.g. NEL U+0085) fell through to value.ToString() and were embedded raw, despite the documented guarantee that every non-printable control uses a \uXXXX escape. EscapeControlCharacter now falls back to char.IsControl(value) for its catch-all branch, covering the full Unicode control range (ASCII C0 controls, DEL, and C1 controls) instead of a hand-rolled range check. New FormatConstantValue test covers a C1 control character. Verified: 345/345 .NET tests pass (net8/net9/net10). fix.ps1 and lint.ps1 both clean. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This was referenced Oct 5, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.


Summary
Implements the feature request: render the values of constants whose values are known at compile time (primarily numbers and strings), across the languages ApiMark supports.
Review process
Testing
Out of scope / follow-up ideas