Fix #633: Overrides analysis and this/base keyword navigation - #3918
Merged
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
Adds the remaining pieces of issue #633 by introducing an “Overrides” analyzer (the upward base-class direction complementing “Overridden By”/“Implements”) and by improving keyword navigation so this/base primary expressions link to their respective types, matching IDE go-to-definition behavior.
Changes:
- Added a new built-in analyzer (
MemberOverridesAnalyzer) that walks the override chain upward viaInheritanceHelper.GetBaseMember, stopping atnew virtualshadow boundaries. - Updated
TextTokenWriter.WriteKeywordsothis/baseprimary expressions emit type references (in addition to existing constructor-initializer andoverride-modifier linking). - Added NUnit tests covering the new analyzer behavior and keyword reference behaviors.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| ILSpy.Tests/TextView/KeywordReferenceTests.cs | New tests pin this/base primary-expression type references and override modifier member reference. |
| ILSpy.Tests/Analyzers/Library/MemberOverridesAnalyzerTests.cs | New tests validate when “Overrides” shows and what base members it returns (including shadowing boundary). |
| ICSharpCode.ILSpyX/Analyzers/Builtin/MemberOverridesAnalyzer.cs | New analyzer implementation yielding overridden base-class members for override members. |
| ICSharpCode.Decompiler/Output/TextTokenWriter.cs | Emits references for this/base primary expressions to their resolved types. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
The analyzer panel could only walk downward (Overridden By, Implemented By); finding what a member overrides required manually climbing base types. The upward interface direction already exists as the Implements analysis, so this adds the missing base-class direction as its dual. The analyzer walks the override chain member by member via InheritanceHelper.GetBaseMember instead of collecting all signature-equal base members, so it stops at 'new virtual' shadow boundaries, which hide any further base members from overriding. No assembly-scope scan is needed; the walk is a direct type-system lookup. Assisted-by: Claude:claude-fable-5:Claude Code
The override modifier already navigates to the overridden member and constructor initializers link this/base to the invoked constructor, but the primary expressions carried no reference at all. Matching IDE go-to-definition behavior, 'this' now references the current type and 'base' the base type; both directions are added together deliberately, linking only 'base' would make the two keywords behave inconsistently. Assisted-by: Claude:claude-fable-5:Claude Code
siegfriedpammer
force-pushed
the
feature-633-overrides-analyzer
branch
from
July 27, 2026 14:36
86c55b2 to
ec72701
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #633.
Two commits, covering the remaining parts of the issue:
1. "Overrides" analyzer — the dual of "Overridden By": for an override method/property/event/indexer, the analyzer panel now shows the base members it overrides. The upward interface direction already exists as the "Implements" analysis, so this adds only the base-class direction. The analyzer walks the override chain member by member via
InheritanceHelper.GetBaseMemberinstead of collecting all signature-equal base members, so it stops atnew virtualshadow boundaries, which hide any further base members from overriding. No assembly-scope scan is needed; the walk is a direct type-system lookup. Tests mirror theMemberImplementsInterfaceAnalyzerTestspattern, including a shadowing case.2.
this/basekeyword navigation — as primary expressions,thisnow references the current type andbasethe base type, matching IDE go-to-definition behavior (both directions together deliberately; linking onlybasewould make the two keywords inconsistent). Theoverridemodifier already navigated to the overridden member and constructor initializers already linkedthis/baseto the invoked constructor; newKeywordReferenceTestspin all three behaviors.Of the issue's four points this delivers the analysis (1) and completes keyword navigation (2, 3); the last point (clicking a declaration selects the whole override chain in the tree) overlaps #819's target-picker idea and is intentionally left out.
Verified: ILSpy.Tests 1099 total / 0 failed / 3 skipped; decompiler suite 2544 total / 0 failed / 38 skipped; XPlat solution filter builds clean.
🤖 This PR was prepared by an AI agent (Claude Code) operated by @siegfriedpammer.