Nest manifest resources into namespace directories (fixes #3717)#3735
Nest manifest resources into namespace directories (fixes #3717)#3735OpenSourcereR-dev wants to merge 1 commit into
Conversation
Three changes to WholeProjectDecompiler.cs so that 'ilspycmd -p' (and WholeProjectDecompiler in general) places manifest resources inside the namespace directory that matches their dotted prefix, instead of leaving them flat at the project root. Before: 'Be.Windows.Forms.HexBox.bmp' written as a flat file next to a directory 'Be.Windows.Forms/' (which contains the matching HexBox.cs etc). After: 'Be.Windows.Forms.HexBox.bmp' written as 'Be/Windows/Forms/HexBox.bmp' (with --nested-directories) or 'Be.Windows.Forms/HexBox.bmp' (default flat- dotted dirs), alongside the matching HexBox.cs. The csproj's LogicalName attribute is unchanged, so the produced .resources manifest entry name is identical to the original input -- no runtime behavior changes. 1. DecompileProject: pre-populate 'directories' with the namespace folders of all types BEFORE calling WriteResourceFilesInProject. The original code cleared 'directories' on entry then ran resource-writing first while 'directories' was still empty, then ran code-file writing (which is what populates 'directories'). As a result GetFileNameForResource's match loop couldn't ever find an existing namespace directory and emitted every resource flat at the project root. The pre-pass also physically creates each directory (CreateDirectory) so subsequent code-file writes find them already there (the existing 'directories.Add returned true -> CreateDirectory' branch in WriteCodeFilesInProject is a no-op when the directory is already in the set). 2. GetFileNameForResource: when the input has no path separators (the common case for dotted manifest resource names) split on '.' keeping the file extension on the last segment, and try matching the prefix against BOTH slash-joined and dot-joined directory entries -- handles both UseNestedDirectoriesForNamespaces=true and the default false. 3. WriteResourceToFile and the flat-resource branch in WriteResourceFilesInProject: create the chosen directory on disk before opening the FileStream, since resources are written before code-files and the namespace directory the resource was placed in may not exist yet (when the pre-pass added the dotted-namespace dir but the resource's destination needs a different layout, e.g. slash-joined when --nested-directories is set).
|
Can you please mention in your PR description if you used AI? This is definitely AI-generated. |
|
Also I think this needs a setting on WholeProjectDecompiler |
Hi. AI-Assisted (Claude Opus 4.7). Fully reviewed and tested by me. Why?
Can add it if you want me to. :-) |
|
So you no longer need this? It's not like we don't accept AI contributions, it's just that we want the author to disclose whether they used AI and to what extent. It's only about disclosure. |
@siegfriedpammer I already have it implemented and working beautifully on my local build,
Still can do that if you want me to, just say the word :-) p.s.
Honestly, just let a good enough model go through that long pile of open issues and it will help you get most if not all of them resolved in no time. AI helps us being extra productive. I know you don't object, saw you use Claude too. :-) |
That's actually what I have planned for the near future :) Altough, I don't really like code review, but now's the time the industriy changes, so improving that skill is certainly valuable. |
Yes, please do it. :) |
Fixes #3717.
When decompiling an assembly as a project, manifest resources with dot-separated names (e.g.
MyApp.images.CopyHS.png) were emitted flat in the project root next to the namespace directory containing the matching.csfiles. This PR places them inside that directory.The csproj's
<EmbeddedResource ... LogicalName="..." />value is unchanged, so the produced manifest resource name is byte-identical to before.Changes (all in
WholeProjectDecompiler.cs)DecompileProject: pre-populatedirectorieswith the namespace folders of all top-level types before callingWriteResourceFilesInProject. Resources are written before code files, sodirectorieswas always empty during the resource walk andGetFileNameForResource's prefix-match loop never matched anything.GetFileNameForResource: when input has no path separators, split on.(keeping the extension on the last segment) and match against both slash- and dot-joined directory entries.WriteResourceToFile+ flat-resource branch: create the chosen directory before opening theFileStream.Testing
Verified on a ~3 MB assembly with 19 embedded resources: all 19 are now placed inside the matching namespace directory. Existing
WholeProjectDecompilerTestsunaffected (it mocksWriteResourceFilesInProject). Happy to add a regression test if you'd like.