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
The tree node's text leads with the table's token-kind byte (e.g.
"02 TypeDef (1234)"), but the opened tab's title dropped it and showed
just "TypeDef (1234)". Lead the tab title with the same byte so the two
match.
Assisted-by: Claude:claude-opus-4-8:Claude Code
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.
The metadata page's KeyDown handler now mirrors the "Go to token"
context-menu entry: when Ctrl+G fires while focus is on a token-kind
DataGridCell (or, as a fallback, while one is hovered), dispatch the
same NavigateToCellRequested path as the hyperlink-style click. The
focus-resolution + dispatch logic lives behind an internal
TryNavigateToTokenInCell hook so tests can drive it without simulating
the keyboard event end-to-end.
Assisted-by: Claude:claude-opus-4-7:Claude Code
Adds MetadataTokenReference(MetadataFile, Handle). DockWorkspace
subscribes to a metadata page's NavigateToCellRequested when its
Content is attached; the click handler reads the row's MetadataFile
and the column's int token via reflection, walks to the matching
MetadataTableTreeNode under the assembly's Tables container (mapping
HandleKind → TableIndex by value), selects it, and seeds ScrollToRow
on the freshly-bound MetadataTablePageModel. The view's ApplyScrollTarget
already honours ScrollToRow by scrolling + selecting the row.
Assisted-by: Claude:claude-opus-4-7:Claude Code