Browse Source

Show hover tooltips for local variables

Local variable references are emitted as reference segments (via
WriteLocalReference), but their reference object is an ILVariable, which
BuildHoverContent could not resolve to an IEntity - so hovering a local
showed nothing. Render the declared type (syntax-highlighted, via a new
Language.GetRichText(IType) overload) with the name and whether it is a
parameter or a local, directly from the ILVariable.

Assisted-by: Claude:claude-fable-5:Claude Code
pull/3907/head
Siegfried Pammer 2 months ago committed by Siegfried Pammer
parent
commit
749caad637
  1. 11
      ILSpy/Languages/CSharpLanguage.cs
  2. 6
      ILSpy/Languages/Language.cs
  3. 8
      ILSpy/TextView/DecompilerTextView.axaml.cs

11
ILSpy/Languages/CSharpLanguage.cs

@ -288,6 +288,17 @@ namespace ICSharpCode.ILSpy.Languages @@ -288,6 +288,17 @@ namespace ICSharpCode.ILSpy.Languages
return new RichText(text, model);
}
public override RichText GetRichText(IType type)
{
ArgumentNullException.ThrowIfNull(type);
var output = new StringWriter();
var decoratedWriter = new TextWriterTokenWriter(output);
var writer = new CSharpHighlightingTokenWriter(TokenWriter.InsertRequiredSpaces(decoratedWriter), locatable: decoratedWriter);
var astBuilder = new TypeSystemAstBuilder { AlwaysUseShortTypeNames = true };
astBuilder.ConvertType(type).AcceptVisitor(new CSharpOutputVisitor(writer, FormattingOptionsFactory.CreateAllman()));
return new RichText(output.ToString(), writer.HighlightingModel);
}
static void EmboldenTypeNames(string text, RichTextModel model)
{
var highlighting = HighlightingManager.Instance.GetDefinition("C#");

6
ILSpy/Languages/Language.cs

@ -188,6 +188,12 @@ namespace ICSharpCode.ILSpy.Languages @@ -188,6 +188,12 @@ namespace ICSharpCode.ILSpy.Languages
public virtual RichText GetRichText(IEntity entity, ConversionFlags conversionFlags, bool boldTypeNames = false)
=> new(EntityToString(entity, conversionFlags));
/// <summary>
/// Renders a bare type (e.g. a local variable's type, or <c>dynamic</c>) as rich text for a hover.
/// </summary>
public virtual RichText GetRichText(IType type)
=> new(TypeToString(type));
public virtual void DecompileType(ITypeDefinition type, ITextOutput output, DecompilationOptions options)
{
WriteCommentLine(output, TypeToString(type));

8
ILSpy/TextView/DecompilerTextView.axaml.cs

@ -1471,6 +1471,14 @@ namespace ICSharpCode.ILSpy.TextView @@ -1471,6 +1471,14 @@ namespace ICSharpCode.ILSpy.TextView
internal HoverContent? BuildHoverContent(DecompilerTabPageModel model, ReferenceSegment segment)
{
var language = model.Language;
if (segment.Reference is Decompiler.IL.ILVariable variable && language != null)
{
// Local variables have no metadata symbol, so render the declared type and name directly.
string kind = variable.Kind == Decompiler.IL.VariableKind.Parameter ? "parameter" : "local variable";
var localRenderer = CreateTooltipRenderer();
localRenderer.AddSignatureBlock(new RichText($"({kind}) ") + language.GetRichText(variable.Type) + new RichText($" {variable.Name}"));
return new HoverContent(localRenderer.CreateView(), IsRich: true);
}
var resolved = ResolveEntity(model, segment.Reference);
switch (resolved)
{

Loading…
Cancel
Save