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
The WPF host attached a registry-driven context menu to the search list
(ContextMenuProvider.Add) and showed a tooltip on every result column;
the Avalonia port carried neither. Right-clicking a result now opens the
same menu the trees use -- the selected result's entity is handed to the
entries via TextViewContext.Reference, so Analyze and the scope-search
entries light up -- and the Location/Assembly cells regain their
full-text tooltips (the Name cell already showed the file path per
Fix#1263).
Assisted-by: Claude:claude-opus-4-8:Claude Code
The search panel rendered hits in a bare ListBox with no headers, so the only
ordering was the fixed fitness/name streaming order chosen at search time --
the user could not re-sort by Name, Location or Assembly. Replace the ListBox
with the app's standard sortable Avalonia DataGrid (mirroring OpenFromGacDialog
/ MetadataTablePage): three template columns that keep the per-field icons,
each with a SortMemberPath so clicking a header sorts by Name / Location /
Assembly. No initial column sort is applied, so the default fitness ranking is
preserved until the user clicks a header.
The code-behind is unchanged: ListBox and DataGrid share the
SelectingItemsControl surface, so the existing selection / activation /
keyboard / middle-click handlers port as-is (verified by the existing search
niceties tests now running against the DataGrid).
Assisted-by: Claude:claude-opus-4-8:Claude Code
Restores the result-navigation gestures the pane shipped with before the
port: Ctrl+T/M/S jump the picker to Type/Member/Constant, Down/Up arrow
hand focus between the search box and the result list, and Ctrl+Enter or a
middle-click open a result in a new document tab instead of reusing the
active one. New-tab activation routes through the existing
OpenNodeInNewTab so it matches the tree's open-in-new-tab behaviour.
Assisted-by: Claude:claude-opus-4-8:Claude Code
Search, Analyzer and Debug Steps cluttered the default layout. They now opt out via ExportToolPane.IsVisibleByDefault = false (which BuildToolDock finally honours), so a fresh launch shows just the assembly tree. Each pane keeps its home alignment and is materialised there on demand by ShowToolPane, so opening Search / Analyze surfaces it in the same place as before.
To audit what each UI test actually exercises, every step now snapshots the
live window to <TestFixtureName>/<TestName>_<NN>_<ShortDescription>.png: a
booted frame (emitted automatically by TestHarness.BootAsync), one after each
state-changing action, and one before each assertion. Flip ILSPY_TESTS_VISIBLE=1
to render the filmstrip; it lands under %TEMP%/ilspy-test-captures (overridable
via ILSPY_TEST_CAPTURES).
The step number and fixture/test name are derived automatically so inserting a
breakpoint never renumbers the rest. The identity is recorded up front from the
real ITest in an ITestAction hook rather than read live: NUnit's
TestContext.CurrentContext does not flow onto async continuations, so a capture
after an await would otherwise collide under the ad-hoc context. And when
rendering is off the whole call is a true no-op -- not even a dispatcher pump --
so instrumenting a test can never perturb the navigation/tab timing it asserts
on. Full headless suite stays green.
Nearly every headless UI test opened with the same four-line prologue
(resolve the shared MainWindow, show it, cast its DataContext, wait for the
assembly list), then repeated the corelib lookup, the EnsureLazyChildren +
Children.OfType<T>().Single() drill, the registry single-by-header lookups,
and the open-an-assembly-and-wait dance. The duplication made the intent of
each test hard to see and every signature tweak a suite-wide edit.
Collapse those into TestHarness (BootAsync, OpenAssemblyAsync, GetCommand,
GetEntry) and TreeNavigation extensions (FindCoreLib, GetChild<T>, Expand<T>),
then apply them across the suite. Net ~865 lines of boilerplate removed with
no change in behaviour; the full headless suite stays green.
DisplaySettings.SortResults was persisted but unused — RunningSearch hardcoded
ComparerByFitness. Now SearchPaneModel.RestartSearch reads the setting at
start-of-search and passes either ComparerByFitness (default) or ComparerByName
into RunningSearch. Capturing at start matches WPF — mid-run toggles only
affect the next search.
Assisted-by: Claude:claude-opus-4-7:Claude Code
The user reported that expanding an enum (System.DayOfWeek) with a search
term active showed only Base/Derived nodes — every FieldTreeNode child
hidden. This is NOT a recent regression. It traces back to commit
45461ddde, which made LanguageSettings.SearchTermMatches honour the
SearchTerm and wired SearchPaneModel to push its term into
LanguageSettings on every keystroke.
The pane's watermark advertises a prefix DSL that the parser didn't
implement — only inassembly: and innamespace: were honoured. Typing
"t:String" treated the whole thing as a literal keyword and matched
nothing useful.
Ctrl+E / Ctrl+Shift+F previously activated the pane but left
keyboard focus wherever it was — the user still had to click the
TextBox before typing. Add a FocusRequested event on SearchPaneModel
that the view subscribes to and pushes Focus() on the SearchInput
TextBox through Dispatcher.UIThread.Post (a tick lets the freshly-
active pane surface in the layout so .Focus() actually takes).
Assisted-by: Claude:claude-opus-4-7:Claude Code
SearchPaneModel gains an Activate(SearchResult) method that resolves
result.Reference through AssemblyTreeModel.FindTreeNode and moves the
assembly-tree selection there — exactly the WPF NavigateToReferenceEventArgs
flow, minus the message-bus indirection. SearchPane.axaml.cs wires
DoubleTapped + Enter on the results ListBox to call Activate.
Assisted-by: Claude:claude-opus-4-7:Claude Code
Flip LanguageSettings.SearchTerm from the always-empty placeholder
to a real ObservableProperty backing field, and replace the
always-true SearchTermMatches stub with a case-insensitive substring
contains. Empty term still matches everything (no filter active).
Assisted-by: Claude:claude-opus-4-7:Claude Code
Wire the search pane to the shared ICSharpCode.ILSpyX.Search engine.
Setting SearchTerm or SelectedSearchMode now cancels any in-flight
run and starts a fresh one; cleared term tears the run down.
Assisted-by: Claude:claude-opus-4-7:Claude Code
Replace the placeholder TextBlock with the real layout: a TextBox at
the top bound two-way to SearchPaneModel.SearchTerm (UpdateSourceTrigger
PropertyChanged so the orchestrator reacts on every keystroke once it
lands), a ComboBox bound to SearchModes / SelectedSearchMode, and a
ListBox that renders each SearchResult as three trimmed columns
(Name / Location / Assembly).
Assisted-by: Claude:claude-opus-4-7:Claude Code
Replace the SearchPaneModel stub with the real shape that the pane's
view, the background streaming orchestrator, and the LanguageSettings
filter cascade will all bind against.
Assisted-by: Claude:claude-opus-4-7:Claude Code