Resolving a metadata file to its assembly node learned to descend into packages,
but three sibling lookups kept their own scan of the root's direct children, so
a token reference, a metadata:// link and a LoadedAssembly reference still
resolved to nothing inside a package. One of them sat behind a guard whose
result was never used, which returned early for exactly the case it was meant to
serve. Routing all of them through the one lookup fixes them together.
Namespaces were matched by comparing a full name against a node label, which is
only ever equal in flat mode: with nested namespace nodes the label is the last
segment, and the empty-name test matched the first child rather than the global
namespace node. The assembly node already indexes its namespaces by full name.
The descent itself no longer sweeps the package depth-first. Expanding a folder
resolves and extracts every .dll it holds, so the path is taken from the
package's folder graph, which costs no tree node and reads no entry.
Assisted-by: Claude:claude-opus-5[1m]:Claude Code
Searching a package resolves its entries by file name against a case-insensitive
cache, which is right for an assembly reference but wrong for an archive entry:
two entries differing only in case are two files, and they collapsed onto one
LoadedAssembly, so one was searched twice and the other never. Keying the cache
by the entry itself separates them, and the entry's package-relative path
becomes the assembly's file name, which is what tells the copies of one assembly
in a multi-target package apart wherever a search result shows a location.
Cancellation was only checked between top-level list entries, so a walk the user
had already replaced by typing another character kept extracting package entries
alongside the run they were waiting for. The omnibar had no way to end its run at
all: its view model is per document tab and nothing cancelled it when the tab
went away.
Assisted-by: Claude:claude-opus-5[1m]:Claude Code
Resolving a type to its tree node scanned every descendant of the root, which
means every namespace node of every assembly - all of them built eagerly - to
find the one assembly node it needed. A package child records the bundle it
came from, so that chain leads straight to the single top-level node worth
descending into, and only that package's folders are searched from there.
The two sibling lookups only ever considered the root's direct children, so
neither resolved anything inside a package at all. Sharing one helper fixes
them along the way, and it expands package folders on the descent because
search surfaces package contents whether or not the tree was ever opened
there.
Assisted-by: Claude:claude-opus-5[1m]: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
DecompileAsEnumerableTest exercises the full path: open mscorlib, navigate
to Enumerable.AsEnumerable, render the decompilation, verify text and
verify the row centred in the assembly tree. Writing it surfaced two
pre-existing bugs the manual smoke-test missed:
- Hold AssemblyListManager on AssemblyTreeModel and mirror its
AssemblyLists collection so the toolbar combo can bind to it.
- New ActiveListName ([ObservableProperty]); OnActiveListNameChanged
loads the named list via the manager and rebuilds Root.
- The "seed initial assemblies if empty" fallback now only triggers
for the (Default) list, so switching to an empty user list doesn't
auto-populate it.
- MainToolBar AssemblyListComboBox bound to AssemblyLists /
ActiveListName (TwoWay).
Assisted-by: Claude:claude-opus-4-7:Claude Code
Adds the assembly tree pane (DataGrid-based, ProDataGrid hierarchical
rows), the SharpTreeNode-derived node type skeletons it consumes, the
empty MainToolBar placeholder, the ILSpySettings file-path provider
wiring in App.axaml.cs, and the AssemblyTreeModel.Initialize() hook in
the MainWindow code-behind.
Assisted-by: Claude:claude-opus-4-7:Claude Code
- Use custom test runner for correctness tests.
- Use .NET 6.0 framework for all Roslyn compiler tests.
- Disabled tests involving new string interpolation patterns.