Skip to content

Pin ImGui.App's Resources.resx manifest name, and guard every .resx against drift - #429

Merged
matt-edmondson merged 3 commits into
mainfrom
claude/nice-davinci-58mhlm
Sep 21, 2026
Merged

matt-edmondson merged 3 commits into
mainfrom
claude/nice-davinci-58mhlm

Conversation

@matt-edmondson

Copy link
Copy Markdown
Contributor

Fixes #421

What was wrong

ImGui.App/Resources/Resources.resx had no <LogicalName> on its EmbeddedResource item, so its manifest name was derived from RootNamespace — which ktsu.Sdk computes from AuthorsNamespace/ProjectNamespace — while Resources.Designer.cs looks the name up from a string literal baked in when it was last generated. Nothing keeps the two in step, and when they drift the first lookup throws MissingManifestResourceException at run time rather than failing the build.

That drift already happened once, in examples/ImGuiAppDemo, and was fixed in 08d9b60 by pinning the name. Here the blast radius is larger: this resx holds NerdFont and NotoEmoji, so a break lands on font and emoji loading in every consuming application.

What changed

  • ImGui.App/ImGui.App.csproj — pins <LogicalName>ktsu.ImGui.App.Resources.Resources.resources</LogicalName>, the name the designer already looks up, with the same explanatory comment the demo carries.

  • tests/ImGui.App.Tests/EmbeddedResourceManifestNameTests.cs — new. Rather than fixing this one file and leaving the class open (as the triage comment on the issue suggested checking), it walks every .resx in the repository and requires that each one:

    1. has an explicit EmbeddedResource item carrying a LogicalName;
    2. has a LogicalName equal to the name its sibling *.Designer.cs passes to ResourceManager;

    plus two runtime assertions against the built library: the shipped assembly really embeds ResourceManager.BaseName + ".resources", and NerdFont/NotoEmoji both decode to non-empty fonts.

The repository currently has exactly two .resx files (this one and the demo's), so after this change the class is closed, and a third one added without a pin fails the test.

Verification

The pinned value is what MSBuild already produced, so nothing about the built assembly changes today — obj/**/ktsu.ImGui.App.Resources.Resources.resources is identical before and after, on net8.0 and net10.0 alike. The point is that a future RootNamespace change now fails a test instead of a consumer's font loading.

  • New tests fail without the csproj change (EveryResxInTheRepository_PinsItsLogicalName reports ImGui.App/Resources/Resources.resx has no LogicalName in ImGui.App.csproj) and pass with it — confirmed by reverting the one-line pin and re-running.
  • Full tests/ImGui.App.Tests suite: 442/442 passing on Linux.
  • dotnet build ImGui.App/ImGui.App.csproj -c Release clean across net10.0;net9.0;net8.0, 0 warnings.

🤖 Generated with Claude Code

https://claude.ai/code/session_01EGcveAXKn6XZnHU2G9jrro


Generated by Claude Code

… .resx

ImGui.App/Resources/Resources.resx had no LogicalName, so its manifest name
was derived from RootNamespace, which ktsu.Sdk computes from AuthorsNamespace
and ProjectNamespace, while Resources.Designer.cs looks the name up from a
string literal baked in when it was last generated. The two can drift apart
silently; the first lookup then throws MissingManifestResourceException at run
time. That already happened once in examples/ImGuiAppDemo (08d9b60), and here
it would take NerdFont and NotoEmoji down in every consuming application.

Pin the name the designer already looks up, mirroring the demo fix, and add
EmbeddedResourceManifestNameTests so the class is closed rather than fixed one
file at a time: it walks every .resx in the repository, requires an explicit
EmbeddedResource item with a LogicalName, requires that LogicalName to match
the name its designer looks up, and checks the shipped assembly really embeds
it and that both fonts decode.

The pinned value is what the build already produced, so the assembly is
byte-for-byte unchanged today; the point is that a future RootNamespace change
now fails a test instead of a consumer's font loading.

Fixes #421

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EGcveAXKn6XZnHU2G9jrro
Comment thread tests/ImGui.App.Tests/EmbeddedResourceManifestNameTests.cs Fixed
Comment thread tests/ImGui.App.Tests/EmbeddedResourceManifestNameTests.cs Fixed
matt-edmondson and others added 2 commits September 21, 2026 05:31
…mbine

Code quality flagged both Path.Combine calls in
EmbeddedResourceManifestNameTests for silently dropping their earlier
argument when the later one is rooted.

The repository-root walk joins a constant filename, so Path.Join says what it
means. The item-spec resolution genuinely has two cases — MSBuild reads a spec
relative to the project unless it is already rooted — so branch on
Path.IsPathRooted and resolve each one explicitly. Behaviour for the relative
specs both projects actually use is unchanged.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EGcveAXKn6XZnHU2G9jrro
…lePath

Test on macos-latest failed both source-scanning tests with "Could not locate
the repository root". CI builds with deterministic source paths, which
rewrites CallerFilePath to /_/tests/ImGui.App.Tests/..., so the walk had
nothing on disk to climb. Reproduced locally with
-p:ContinuousIntegrationBuild=true, which fails identically.

Walk up from AppContext.BaseDirectory instead: the binaries live under
tests/<project>/bin/<configuration>/<tfm>, inside the checkout either way.
CallerFilePath stays as a fallback for a run whose output was moved out of
the repository.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EGcveAXKn6XZnHU2G9jrro
@sonarqubecloud

Copy link
Copy Markdown

@matt-edmondson
matt-edmondson merged commit f376472 into main Sep 21, 2026
14 checks passed
@matt-edmondson
matt-edmondson deleted the claude/nice-davinci-58mhlm branch September 21, 2026 08:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ImGui.App's embedded Resources.resx lacks the LogicalName pin that fixed the identical bug in ImGuiAppDemo

1 participant