Browse Source

Make synthesized dynamic members hover-only, not navigable

A member synthesized for a dynamic access has no metadata token, so the
navigation link it produced went nowhere. Emit it as a local-style
reference (WriteLocalReference) instead: the hover renderer still shows
the signature (it resolves any IEntity reference regardless of IsLocal),
but the identifier is no longer a navigation target, matching how local
variables are treated. The written text is unchanged.

Assisted-by: Claude:claude-fable-5:Claude Code
pull/3907/head
Siegfried Pammer 2 months ago committed by Siegfried Pammer
parent
commit
79a67fcee3
  1. 26
      ICSharpCode.Decompiler/Output/TextTokenWriter.cs

26
ICSharpCode.Decompiler/Output/TextTokenWriter.cs

@ -78,7 +78,16 @@ namespace ICSharpCode.Decompiler @@ -78,7 +78,16 @@ namespace ICSharpCode.Decompiler
output.WriteReference(t, name, false);
return;
case IMember m:
output.WriteReference(m, name, false);
if (IsDynamicMemberReference(nodeStack.Peek()))
{
// A member synthesized for a dynamic access: show its signature on hover, but do not
// make it a navigation target (there is no real member to jump to) - like a local.
output.WriteLocalReference(name, m);
}
else
{
output.WriteReference(m, name, false);
}
return;
}
@ -140,6 +149,21 @@ namespace ICSharpCode.Decompiler @@ -140,6 +149,21 @@ namespace ICSharpCode.Decompiler
return symbol;
}
/// <summary>
/// True if the member reference at this node was synthesized for a dynamic member access/invocation.
/// Such members carry a hover tooltip but must not be navigation targets, since they do not exist in
/// metadata.
/// </summary>
static bool IsDynamicMemberReference(AstNode node)
{
if (node.Annotation<ResolveResult>() is CSharp.Resolver.DynamicMemberResolveResult)
return true;
if (node.Slot?.Kind == Slots.TargetExpression && node.Parent is InvocationExpression
&& node.Parent.Annotation<ResolveResult>() is CSharp.Resolver.DynamicInvocationResolveResult)
return true;
return false;
}
object GetCurrentLocalReference()
{
AstNode node = nodeStack.Peek();

Loading…
Cancel
Save