ILSpy showed the current location only implicitly in the tree selection and kept search in a separate docked pane. The omnibar, modelled on the Files community app and jiripolasek's EditorBar, puts an address-bar atop each decompiler document: a breadcrumb of the node (Assembly > Namespace > Type > Member) whose segments navigate and whose chevrons list child nodes, turning into a search box on typing that reuses the existing search engine. It coexists with the docked search pane and ships off by default behind the Options / Display 'Tab options' EnableOmnibar toggle, which applies live.
Assisted-by: Claude:claude-opus-4-8:Claude Code
CopyFSharpCoreDll built the ILSpy-tests path with hardcoded Windows backslashes
("..\\..\\..\\ILSpy-tests\\FSharp\\FSharp.Core.dll"). On non-Windows, '\' is a
normal filename character, so the whole string became a single bogus path,
File.Exists always returned false, and the FSharp ILPretty tests were silently
Assert.Ignore'd even when ILSpy-tests was checked out. Build the path from
Path.Combine segments instead so it resolves on every platform (same target:
three levels up from the ILPretty test-case directory).
Assisted-by: Claude:claude-opus-4-8:Claude Code
The Linux and macOS jobs were near-identical copies; their shared head
(checkout, SDK setup, version, restore, build, both test steps, test-log
upload) drifts the moment one is edited and the other is not. Collapse
them into a single platform-parameterized matrix job, and hoist the .NET
SDK version/quality and the staging directory to workflow-level env so an
SDK bump is a one-line change across all jobs.
The Windows job keeps its id (Build) so internal references stay stable,
but gains a display name to read as "Desktop (Windows)" alongside the
matrix "Desktop (linux)/(macos)" checks. Branch-protection required
checks must be repointed to the new check names.
Assisted-by: Claude:claude-opus-4-8:Claude Code
The decompiler test suite is platform-aware: on non-Windows,
Tester.SupportedOnCurrentPlatform keeps only the dotnet-hosted Roslyn
configs and [Platform("Win")] gates the fixtures that truly need
Windows (legacy csc, mcs, 32-bit, roundtrip), so running the suite on
the Linux and macOS jobs gives real coverage of the non-Windows
decompilation paths instead of leaving them untested. Both jobs now
also check out the ILSpy-tests submodule, because the TargetNet40
configs compile against its legacy reference assemblies even when the
compiled output is never executed.
Assisted-by: Claude:claude-fable-5:Claude Code
The first CI run on a macOS runner surfaced that these tests encoded
the Windows/Linux menu shape, while MainMenu.Attach intentionally
diverges on macOS: TranslateGesturesForMacOS rewrites Control to Meta
so shortcuts follow the Cmd-key convention, and PromoteHelpToMacAppMenu
moves the Help items into the application menu and drops the _Help
top-level. The tests now assert the macOS-correct expectations on
macOS, including that the Help content lands in the app menu rather
than vanishing.
Assisted-by: Claude:claude-fable-5:Claude Code
The macOS CI artifact is an unsigned zipped ILSpy.app; the signed
distribution channel is a dmg the release manager creates offline with
create-dmg.ps1 (codesign and notarization stay optional parameters, so
no signing secrets ever live in CI). Distribution via Homebrew uses a
tap repository holding only a cask file that points at the dmg attached
to the GitHub release; the cask template and per-release update steps
are documented next to the scripts.
Assisted-by: Claude:claude-fable-5:Claude Code
Two new jobs run alongside the Windows matrix: each builds the desktop
solution filter on its own OS, runs the headless UI tests there, and
packages Release self-contained bundles (zip/deb/rpm on Linux, zipped
ILSpy.app on macOS) via the BuildTools packaging scripts. Decompiler
tests, NuGet packing, and the Windows installers stay in the Windows
job, and neither new job checks out the ILSpy-tests submodule, since
that only feeds the decompiler tests. The Windows job is untouched so
existing required-status-check names keep working.
Assisted-by: Claude:claude-fable-5:Claude Code
With the move to Avalonia the app runs on Linux and macOS, so the
distribution tooling grows beyond Windows: publish.ps1 gains a
-Platform parameter (the default keeps the Windows behavior unchanged),
and new BuildTools scripts package the self-contained publish outputs
into a zip, deb, and rpm on Linux and a zipped ILSpy.app on macOS.
Nothing is signed at package time; signing happens offline on the
release manager machine. Info-ZIP zip is used instead of
Compress-Archive because the latter drops unix mode bits. deb/rpm are
built with dpkg-deb/rpmbuild directly (both preinstalled on GitHub
ubuntu runners) following sourcegit-scm/sourcegit's proven model,
including the libicu OR-chain in the deb control file and disabled
auto-requires for the self-contained rpm payload. Pre-release versions
map '-' to '~' so both package managers sort them before the release.
The macOS bundle's Info.plist now carries placeholders stamped at
package time; on Windows the spec/control/desktop files are kept LF via
.gitattributes because Linux tools consume them verbatim.
Assisted-by: Claude:claude-fable-5:Claude Code
On FIPS-mode systems the platform crypto provider refuses to create
SHA-1 instances (OpenSSL: error:03000098 invalid digest), so merely
displaying a strong-named assembly's identity failed. The public-key
token is a non-secret identity hash whose algorithm is fixed by
ECMA-335, so the two token sites now use dotnet/runtime's managed
Sha1ForNonSecretPurposes, vendored with its license header intact and
shielded from the repo formatter via generated_code in .editorconfig
so future upstream syncs diff cleanly. IncrementalHash was considered
and rejected: like SHA1.Create(), it resolves the digest through the
host crypto policy, and Roslyn's equivalent token code also relies on
the platform SHA-1, so it offers no precedent for FIPS safety.
Assisted-by: Claude:claude-fable-5:Claude Code
WPF revealed files through the shell COM API (SHOpenFolderAndSelectItems):
selecting several assemblies and choosing "Open Containing Folder" opened
one Explorer window per folder with all of that folder's files selected,
reusing a window already open at the location. The Avalonia port replaced
this with explorer.exe /select, invoked once per file, so revealing N
assemblies spawned N new windows and a single reveal never reused an
existing one.
Restore the shell-COM reveal on Windows behind the existing cross-platform
ShellHelper, grouping the selection by containing folder. macOS keeps a
single Finder "open -R" for the whole selection; Linux, lacking a portable
select-item hook, opens each distinct parent folder once instead of one
window per file. The folder grouping is a pure, unit-tested seam so the
behaviour is verified without launching the OS file manager.
The Windows COM portion is adapted from the pre-Avalonia ShellHelper; its
author's copyright notice is retained per its MIT license.
Assisted-by: Claude:claude-opus-4-8:Claude Code
LoadedAssembly caches one type system per TypeSystemOptions value, but
the consumers disagreed on which one to use: tree nodes and the
metadata navigator resolved through GetTypeSystemOrNull (a separate
default-options instance) and the search built its request with default
settings. Each module could therefore materialise several type systems,
and none of the display surfaces respected settings that change entity
shapes (nullability, tuples, extension methods, ...). WPF routed all of
these through GetTypeSystemWithCurrentOptionsOrNull.
Reintroduce that helper on top of CreateEffectiveDecompilerSettings and
use it in TypeTreeNode, AssemblyReferenceTreeNode, and the metadata
navigator; the search request now derives its settings the same way, so
all of them hit the same cached instance. NamespaceTreeNode.Decompile
enumerates through the type system matching the decompilation options
it was handed.
Assisted-by: Claude:claude-fable-5:Claude Code
The Avalonia port gave DecompilationOptions a parameterless constructor
that silently defaults to new DecompilerSettings(). Several paths picked
it up and decompiled with default settings where the WPF version used
the user's current options: tree member filtering (CSharpLanguage.
ShowMember), PDB generation, the single-file / project / solution Save
Code paths, and the DEBUG decompile-all commands.
Promote the live-snapshot logic that was private to DecompilerTabPage-
Model (settings clone + Display-option bridge + toolbar language
version) to SettingsService.CreateEffectiveDecompilerSettings and use
it at every entry point. Remove the parameterless DecompilationOptions
constructor and make SolutionWriter require settings, so reaching for
defaults is an explicit choice rather than a silent fallback - that
default is exactly what masked these regressions. Search deliberately
keeps default settings (it only needs a type system to materialise).
Assisted-by: Claude:claude-fable-5:Claude Code
These types were public through release/10.1; the Avalonia port had
dropped them to internal. Plugins build custom tree integrations on
top of the member tree nodes, so restore their 10.1 visibility.
NaturalStringComparer becomes public too, but keeps its static-class
shape.
Assisted-by: Claude:claude-fable-5:Claude Code
The global:: prefixes existed because the test project's namespace
ICSharpCode.ILSpy.Tests used to shadow the app's old top-level ILSpy
namespace. With the UI code back under ICSharpCode.ILSpy there is
nothing left to shadow, so plain fully qualified names resolve fine.
Assisted-by: Claude:claude-fable-5:Claude Code
The Avalonia port had placed the UI app in an ILSpy.* namespace tree,
while the csproj RootNamespace and every prior release (through 10.1)
use ICSharpCode.ILSpy.*. Restoring the historical namespace reduces the
public API diff against release/10.1 for plugin authors and removes the
shadowing that forced global:: qualifiers in the test project. The
Images class and AccessOverlayIcon enum move back into the root
namespace (as in 10.1), since an ICSharpCode.ILSpy.Images namespace
would shadow the Images class for all code inside ICSharpCode.ILSpy.
Assisted-by: Claude:claude-fable-5:Claude Code
Windows maps CON, PRN, AUX, NUL, COM1-9 and LPT1-9 to devices -- on many
builds even with an extension appended, so a type named Con made both
whole-project export and the save dialog fail with IOException '\\.\Con'.
CleanUpName only checked for reserved names after re-appending the file
extension, where they never match, and the save-dialog default-name
helpers did not check them at all. The escape appends the underscore to
the base name (con_.txt, not con.txt_) because device-name parsing
ignores everything after the first dot, and is applied per path segment
so reserved directory names produced by namespaces are covered too. The
ILSpy.Tests.Windows fixture verifies on a real Windows filesystem that
the escaped names are creatable.
Assisted-by: Claude:claude-fable-5:Claude Code
Reference links navigated on pointer-press, which meant a press-drag
over a link could never select its text -- the press fired navigation
and handled the event before a selection could start. Move navigation
to pointer-release and only follow the link when the pointer did not
drag past the click threshold, matching the WPF view's mouse-up
handling. A press-drag now selects link text like any other span.
Assisted-by: Claude:claude-fable-5:Claude Code
A Debug.Assert raised on a background decompile thread runs through
TraceInternal.Fail, which holds the global trace lock while invoking
the listener; the listener blocks on the UI thread to show the
assertion dialog. Meanwhile the UI thread, mid-navigation, runs a
layout pass whose virtualizing panel raises a binding error that
Avalonia logs via Trace.WriteLine -- which blocks acquiring that same
global trace lock. The two threads deadlock and the app freezes with
no dialog.
Mark the listener thread-safe and disable the global trace lock so
TraceInternal dispatches to it without serializing, removing the
contended lock between the asserting thread and the UI thread.
Assisted-by: Claude:claude-fable-5:Claude Code
Selecting text inside the popup closed it: the selection drag captures
the pointer, so sweeping past the popup edge fired the content's
PointerExited with IsPointerOver already false. The close veto now
covers pointer-over, keyboard-focus-within (so a finished selection
survives for Ctrl+C, as the WPF tooltip did), and pointer capture held
inside the popup; only a document change force-closes.
Assisted-by: Claude:claude-fable-5:Claude Code
Doc-comment crefs in hover tooltips rendered as link-styled but inert
text, and cref resolution was never wired up. Crefs now resolve against
the current tab's assembly list and navigate through the same
NavigateToReferenceEventArgs channel the analyzer uses; href links open
via the TopLevel launcher. Avalonia inlines are not input elements, so
links are hit-testable TextBlocks embedded via InlineUIContainer.
Interactive content also requires the popup to survive the pointer
travelling onto it: the editor's exit handler now tolerates the
overlay-popup enter/exit ordering via the distance corridor, and the
popup closes when the pointer leaves its own content instead.
Assisted-by: Claude:claude-fable-5:Claude Code
The hover documentation popup has been invisible since
X11PlatformOptions.OverlayPopups was enabled (c075c2bc8): popups are
hosted in an OverlayPopupHost, a ContentControl that resolves its
control theme through the Popup's logical parent. The popup was
constructed detached (valid for the native PopupRoot hosts used
before), so the host stayed template-less, never materialized its
child, and rendered as nothing. Declaring the popup in the view's
XAML gives the host a styling root.
Assisted-by: Claude:claude-fable-5:Claude Code
The WPF app showed the disassembled IL header when hovering a member
reference in IL view, and the opcode's XML documentation when hovering
an instruction. The Avalonia port lost both: ILLanguage fell back to
the base ambience one-liner and the opcode tooltip carried only the
name and encoding. Opcode docs additionally need a modern-.NET source:
the WPF code read the .NET Framework reference-assembly docs, which do
not exist on modern .NET, so MscorlibDocumentation now falls back to
the ref pack parallel to the hosting runtime.
Assisted-by: Claude:claude-fable-5:Claude Code
When the current language is not an IDebugStepProvider (e.g. the IL
disassembler), the Debug Steps pane kept displaying the previous
language's step tree, and its commands still triggered re-decompiles
with a step limit the language ignores. Detaching now clears the tree
and the view shows a "not available" note until a step-providing
language is selected again.
Assisted-by: Claude:claude-fable-5:Claude Code
Compilation uses the .NET builds of the Roslyn toolsets (tasks/netcore*,
bincore csc.dll/vbc.dll launched through the dotnet host). ilasm/ildasm
options use the '-' prefix, which all platforms accept. The dotnet-hosted
compilers have no implicit references or SDK path: net40 compiles pass
mscorlib explicitly, and vbc gets -sdkpath, _MYTYPE=Empty and
-vbruntime:Microsoft.VisualBasic.Core.dll (the facade in the ref packs is
not followed for runtime helpers). The TestRunner gets a self-contained
build for the host platform.
Configurations depending on Windows-only tools or runtimes (legacy
csc/vbc, Roslyn 1.x/2.x, mcs, Force32Bit, executing net40 binaries) are
filtered from the matrix off-Windows via Tester.SupportedOnCurrentPlatform
or gated with [Platform("Win")]. PdbGen comparisons normalize document
name separators, and Correctness/Async uses Console.IsInputRedirected
instead of the Windows-only Console.CapsLock.
Assisted-by: Claude:claude-fable-5:Claude Code
Hosts without a .NET Framework installation (e.g. Linux and macOS) have
no GAC; the only system-wide assembly store there is the shared-framework
directory of the runtime executing the decompiler, and
UniversalAssemblyResolver only consulted it through the version <= 4.0
legacy fallback. This made e.g. the type-forwards of a netstandard facade
(pointing to a versioned System.Runtime) unresolvable, which left
well-known types like Nullable<T> without a definition and among other
things misaligned nullability decoding (Nullable<T> occupies no slot in
the nullable metadata, so it must be recognized).
On Windows nothing the GAC answered changes; the new fallback only adds
resolutions that previously failed outright.
Assisted-by: Claude:claude-fable-5:Claude Code
Captures the compiler-matrix model, the test kinds and their pipelines,
how to add tests per kind, the #if/preprocessor-symbol comparison rules,
and the probe-a-construct-across-all-compilers workflow, so this no
longer has to be reverse-engineered from the runners.
Assisted-by: Claude:claude-fable-5:Claude Code
The decompiled view only offered navigation on member names; finding
what an override actually overrides required opening the analyzer.
Attaching a reference to the modifier token gives the same
go-to-definition affordance Visual Studio has on 'override'. The
reference resolves via InheritanceHelper.GetBaseMember, so it targets
the nearest overridden member and degrades to plain text when the base
member cannot be resolved.
Assisted-by: Claude:claude-fable-5:Claude Code
Two failure modes that both showed the user the "no" cursor with no
other feedback:
1. ResolveDropTarget returned null when e.Source had no
SharpTreeViewItem ancestor, so Explorer drops landing in the gap
beneath the last row (or onto an empty list) never reached
SharpTreeNode.InternalDrop.
2. The middle 50% of a row produces a DropPlace.Inside target on the
row's own node. Most concrete SharpTreeNodes inherit the base CanDrop
(returns false), so a literal "drop a .dll onto an assembly row"
refused even though AssemblyListTreeNode happily accepts that payload.
For (1), fall back to (Root, Children.Count, DropPlace.Inside) when no
row is hit. For (2), introduce PickAcceptingTarget which retries with
the empty-space (root) target when the initial CanDrop is false. Both
OnDragOver and OnDrop go through the same picker so the cursor and the
actual drop agree on the outcome. The retry skips when the initial
target already IS the root, so a real refusal still surfaces as "no".
The marker adorner stays hidden for empty-space drops because the
place is always Inside (Item is null for that case); the existing
DropPlace.Inside early return covers it.
DropTarget, DropPlace, and the two new helpers are internal-visible to
the ILSpy.Tests project for the unit tests that assert the fallback
chain.
Assisted-by: Claude:claude-opus-4-7[1m]:Claude Code
Frozen tabs each cache their own decompiled output, but the language
change handler only refreshed ActiveDecompilerTab — hard-wired to the
preview tab — and the display-setting refresh only reached the preview
tab's cached content model, so frozen (and floated) tabs kept showing
stale output until manually re-selected. The handler predates the
freeze feature, which introduced multiple sibling decompiler tabs
without widening it.
Both paths now iterate every decompiler tab across all document docks
(the walk CancelPendingOperationsAsync already used, extracted as
AllDecompilerTabs), and the language handler uses Redecompile instead
of the CurrentNode re-assignment hack.
Assisted-by: Claude:claude-fable-5[1m]:Claude Code
Three follow-ups so the WPF-era ILSpy.xml survives a load-save-load
cycle through the Avalonia host without losing data the user expected
to keep.
Preserve unknown children verbatim. LoadFromXml only interprets a
known set of element names (KnownChildren) and stashes everything
else; SaveToXml re-emits the stash after the known section. The
AvalonDock <DockLayout> blob the WPF host writes is incompatible with
the Avalonia Dock host and we don't want to interpret it, but blank-
ing it on save would discard a WPF user's saved layout the first
time they launched the Avalonia build. The same stash future-proofs
older builds against fields added in newer ones.
Emit the legacy on-disk shape on save. WindowBounds is written as a
CSV body "L,T,W,H" (the WPF Rect TypeConverter format) instead of
Left/Top/Width/Height attributes, and ActiveTreeViewPath <Node>
values are \xNNNN-hex-escaped on write. With both directions of the
conversion in this file a file written by the Avalonia build is
still readable by an older ILSpy 10.x install, and the diff against
a pre-existing ILSpy.xml stays small during the transition.
Wire SelectedSearchMode and ActiveAutoLoadedAssembly. The WPF host
persisted both: the search-pane mode picker so the user's last
choice survives restarts, and the file path of the auto-loaded
(dependency) assembly the saved tree-path lands in so the restore
can re-open it before walking. The Avalonia code read both into
properties that nothing wrote to. Now SearchPaneModel restores
SelectedSearchMode on construction and writes back on change via
SettingsService, and AssemblyTreeModel walks the selection's
ancestor chain to find the owning AssemblyTreeNode, stores its
LoadedAssembly.FileName when IsAutoLoaded, and re-opens that file
(when it still exists) before RestoreSelectedPathAsync.
Assisted-by: Claude:claude-opus-4-7[1m]:Claude Code
The new Avalonia SessionSettings reads WindowBounds as Left/Top/Width/Height
attributes and reads ActiveTreeViewPath node values raw, but ILSpy 10.x wrote
WindowBounds as a CSV element body ("L,T,W,H", the Rect TypeConverter format)
and \xNNNN-hex-escaped every non-letter-or-digit char in each Node value (so
"TomsToolbox.Wpf" round-tripped through XML as "TomsToolbox\x002EWpf"). On
first launch against an existing ILSpy.xml that means the saved window
position resets to the default and the selected tree node never restores --
the escaped path can't match a live node's ToString().
Accept the CSV body when the WindowBounds element has no attributes, and
decode \xNNNN escapes in tree-view node values. Both fall back through the
existing ParseDouble defaults if a piece is missing, so a corrupted entry
won't crash startup.
Lock the shape in with tests against the actual section the WPF host emits,
plus a forward-compat pair confirming LoadFromXml ignores unknown children
(DockLayout, SelectedSearchMode, ActiveAutoLoadedAssembly) and SaveToXml
never echoes them back -- the AvalonDock schema doesn't translate to the
Avalonia Dock host and would otherwise persist forever as dead state.
Assisted-by: Claude:claude-opus-4-7[1m]:Claude Code
WPF showed a row Offset column and decoded the Kind GUID into one cell
combining heap offset, friendly name, and raw GUID; the Avalonia table
only carried the bare heap offsets. Offset follows the GetRowOffset
convention every other table uses. Kind is plain text rather than a
hex column plus tooltip so the per-column filter matches the friendly
names.
Assisted-by: Claude:claude-fable-5[1m]:Claude Code
Selecting a row in the CustomDebugInformation table now previews its
Value blob beneath it, completing WPF row-details parity: state-machine
hoisted local scopes, compilation options, metadata references, and
tuple element names parse into typed sub-grid rows; source-link JSON
shows as text; everything else — unrecognized kinds, embedded source,
and malformed structured blobs — degrades to a hex dump, as in WPF.
The parser switches on the Kind GUID directly via KnownGuids; the
entry deliberately carries no decoded-kind state, leaving that to the
kind-column work that builds on this.
Assisted-by: Claude:claude-fable-5[1m]:Claude Code
WPF ILSpy used DataGrid row details in three places: the COFF and
Optional header views (flag-bit breakdown of the Characteristics /
DLL Characteristics words, permanently expanded) and the
CustomDebugInformation table (decoded Value blob, visible when
selected). The Avalonia port already carried the data — both header
nodes populate Entry.RowDetails and the column builder skips it — but
nothing displayed it.
ProDataGrid builds the row-details template once per details element
and recycles the built control across rows, swapping only the
DataContext, so a WPF-style template selector would go stale;
MetadataRowDetailsControl re-runs its content factory on every
DataContext change instead. Per-row initial visibility has no
SetDetailsVisibilityForItem equivalent and recycling resets
AreDetailsVisible, so the view re-derives it in LoadingRow. Row
activation now ignores gestures originating inside the details
presenter — selecting text in a details blob must not navigate away.
This lands the infrastructure plus the two header consumers; the
CustomDebugInformation details build on the EmbeddedSource decoding
work and follow with it. ConfigurePage on MetadataTableTreeNode is
the hook that consumer overrides.
Assisted-by: Claude:claude-fable-5[1m]:Claude Code
Clicking inside the open flags filter popup could act on the
DataGridColumnHeader underneath: unhandled press/release pairs bubbled
out of the popup into the header (which treats them as a sort click
and flashes its pressed visual), and on X11 overlay popups the
light-dismiss machinery could even re-target a click's press directly
at the header while the popup stayed open.
The filter UI is now hosted in a Flyout attached to the funnel icon
instead of a hand-rolled Popup parked in the header's panel. Avalonia
positions Popup as the low-level primitive and recommends Flyout for
attached pickers: light dismiss, Escape-to-close, focus handling, and
theme-correct presenter chrome come built in (the old hard-coded white
background was also wrong in dark mode). The flyout content swallows
unhandled wheel and press/release events, since its internal popup is
still logically parented to the funnel inside the header.
A headless end-to-end regression test drives a real DataGrid with
overlay popup hosts (the X11 OverlayPopups=true configuration the app
runs with) and raw input through the funnel and every visible flyout
control, asserting the header never sorts and never receives an
unhandled press or release.
Assisted-by: Claude:claude-fable-5[1m]:Claude Code
Opening a package from a feed previously meant downloading the .nupkg by
hand and using File > Open (#2313). The new File menu command searches any
public V3 feed (editable package-source list, persisted as an MRU in the
ILSpy settings), offers the latest 100 versions in a dropdown, and downloads
into the NuGet global packages folder so the cache is shared with every
other NuGet consumer on the machine and nothing is fetched twice. The cached
.nupkg is then opened exactly like the regular Open command. Feed access
sits behind INuGetFeedClient so the headless test suite covers search,
paging, version selection, download, cancellation, and error surfacing
without touching the network.
Assisted-by: Claude:claude-fable-5:Claude Code
When enabled, switch sections are ordered by their case label value
instead of by the underlying branch's IL offset. Default is false to
keep existing output unchanged. Useful when diffing decompiler output
across rebuilds of obfuscated assemblies, where IL block layout is
unstable but the case-to-value mapping is not.
Includes an ILPretty test that exercises a hand-written switch whose
table targets are placed at non-monotonic IL offsets (simulating
obfuscator block shuffling) and verifies the cases come out in
label-value order with the setting enabled. Also adds the
Resources.resx / Resources.Designer.cs entry so the WPF settings UI
shows a proper label instead of the raw key.
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* Fix anonymous-type lambda early-return emitting unresolvable cast
When a lambda's inferred return type contains an anonymous type and one
branch returns null, the decompiler emitted an explicit cast such as
`return (IEnumerable<<>f__AnonymousType0<int>>)null;`, which is invalid C#.
Skip the cast in IsPossibleLossOfTypeInformation for null literals whenever
the expected type contains an anonymous type:
null is implicitly convertible to any reference type, so no cast is needed,
and the anonymous type has no nameable form to cast to anyway.
Fixes#3751
ECMA-335 names the zero state of most mutually exclusive sub-ranges
(NotPublic, AutoLayout, Class, AnsiClass, PrivateScope, ReuseSlot, ...)
and the reflection enums declare those members, but the schema inferer
skipped zero-valued fields and synthesised a generic '(none)' entry
instead. Zero fits every mask, so the member is attributed to a group
by declaration order: ECMA-335 and the reflection enums declare each
mask directly followed by its members. Filter persistence stores
numeric values, so saved filters are unaffected by the label change.
Assisted-by: Claude:claude-fable-5[1m]:Claude Code
The schema inferer only walks the enum's declared fields, so the
ECMA-335 Forwarder bit (0x00200000, no member in
System.Reflection.TypeAttributes) was invisible to the per-column
flags filter even though the cell tooltip already shows it. An
explicit per-enum extras table appends it as an independent flag,
making forwarders filterable on the ExportedType table.
Assisted-by: Claude:claude-fable-5[1m]:Claude Code