From 2145997190c77465a3229166643b39ca596e082e Mon Sep 17 00:00:00 2001 From: Matt Parker <61717342+MattParkerDev@users.noreply.github.com> Date: Sun, 12 Oct 2025 12:06:55 +1000 Subject: [PATCH] add named type symbol display --- .../Features/CodeEditor/SharpIdeCodeEdit.cs | 3 +- .../CodeEditor/SymbolInfoComponents.cs | 25 ++++-- .../SymbolTooltips/NamedTypeTooltip.cs | 85 +++++++++++++++++++ 3 files changed, 105 insertions(+), 8 deletions(-) create mode 100644 src/SharpIDE.Godot/Features/CodeEditor/SymbolTooltips/NamedTypeTooltip.cs diff --git a/src/SharpIDE.Godot/Features/CodeEditor/SharpIdeCodeEdit.cs b/src/SharpIDE.Godot/Features/CodeEditor/SharpIdeCodeEdit.cs index ba54752..ea09f27 100644 --- a/src/SharpIDE.Godot/Features/CodeEditor/SharpIdeCodeEdit.cs +++ b/src/SharpIDE.Godot/Features/CodeEditor/SharpIdeCodeEdit.cs @@ -127,10 +127,11 @@ public partial class SharpIdeCodeEdit : CodeEdit var symbolInfoNode = roslynSymbol switch { IMethodSymbol methodSymbol => SymbolInfoComponents.GetMethodSymbolInfo(methodSymbol), - INamedTypeSymbol namedTypeSymbol => new Control(), + INamedTypeSymbol namedTypeSymbol => SymbolInfoComponents.GetNamedTypeSymbolInfo(namedTypeSymbol), IPropertySymbol propertySymbol => SymbolInfoComponents.GetPropertySymbolInfo(propertySymbol), IFieldSymbol fieldSymbol => SymbolInfoComponents.GetFieldSymbolInfo(fieldSymbol), IParameterSymbol parameterSymbol => SymbolInfoComponents.GetParameterSymbolInfo(parameterSymbol), + //ILocalSymbol localSymbol => SymbolInfoComponents.GetLocalSymbolInfo(localSymbol), _ => new Control() }; popupPanel.AddChild(symbolInfoNode); diff --git a/src/SharpIDE.Godot/Features/CodeEditor/SymbolInfoComponents.cs b/src/SharpIDE.Godot/Features/CodeEditor/SymbolInfoComponents.cs index d0fc62c..c339402 100644 --- a/src/SharpIDE.Godot/Features/CodeEditor/SymbolInfoComponents.cs +++ b/src/SharpIDE.Godot/Features/CodeEditor/SymbolInfoComponents.cs @@ -264,21 +264,32 @@ public static partial class SymbolInfoComponents private static void AddContainingNamespaceAndClass(this RichTextLabel label, ISymbol symbol) { - if (symbol.ContainingNamespace is null || symbol.ContainingNamespace.IsGlobalNamespace) return; + if (symbol.ContainingNamespace is null || symbol.ContainingNamespace.IsGlobalNamespace) return; // might be wrong label.Newline(); - label.AddText("in class "); + if (symbol.ContainingType is null) + { + label.AddText("in namespace "); + } + else + { + label.AddText("in class "); + } var namespaces = symbol.ContainingNamespace.ToDisplayString().Split('.'); label.PushMeta("TODO", RichTextLabel.MetaUnderline.OnHover); - foreach (var ns in namespaces) + foreach (var (index, ns) in namespaces.Index()) { label.PushColor(CachedColors.KeywordBlue); label.AddText(ns); label.Pop(); - label.AddText("."); + if (index < namespaces.Length - 1) label.AddText("."); + } + if (symbol.ContainingType is not null) + { + label.AddText("."); + label.PushColor(CachedColors.ClassGreen); + label.AddText(symbol.ContainingType.Name); + label.Pop(); } - label.PushColor(CachedColors.ClassGreen); - label.AddText(symbol.ContainingType.Name); - label.Pop(); label.Pop(); // meta } diff --git a/src/SharpIDE.Godot/Features/CodeEditor/SymbolTooltips/NamedTypeTooltip.cs b/src/SharpIDE.Godot/Features/CodeEditor/SymbolTooltips/NamedTypeTooltip.cs new file mode 100644 index 0000000..ee96d80 --- /dev/null +++ b/src/SharpIDE.Godot/Features/CodeEditor/SymbolTooltips/NamedTypeTooltip.cs @@ -0,0 +1,85 @@ +using Godot; +using Microsoft.CodeAnalysis; + +namespace SharpIDE.Godot.Features.CodeEditor; + +public static partial class SymbolInfoComponents +{ + public static Control GetNamedTypeSymbolInfo(INamedTypeSymbol symbol) + { + var label = new RichTextLabel(); + label.FitContent = true; + label.AutowrapMode = TextServer.AutowrapMode.Off; + label.SetAnchorsPreset(Control.LayoutPreset.FullRect); + label.PushColor(CachedColors.White); + label.PushFont(MonospaceFont); + label.AddAttributes(symbol); + label.AddAccessibilityModifier(symbol); + label.AddStaticModifier(symbol); + label.AddVirtualModifier(symbol); + label.AddAbstractModifier(symbol); + label.AddOverrideModifier(symbol); + label.AddNamedTypeSymbolName(symbol); + label.AddInheritedTypes(symbol); + label.AddContainingNamespaceAndClass(symbol); + label.AddContainingPackage(symbol); + label.Newline(); + label.Pop(); // font + label.AddDocs(symbol); + + label.Pop(); + return label; + } + + private static void AddNamedTypeSymbolName(this RichTextLabel label, INamedTypeSymbol symbol) + { + label.PushColor(GetSymbolColourByType(symbol)); + label.AddText(symbol.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat)); + label.Pop(); + } + + private static void AddInheritedTypes(this RichTextLabel label, INamedTypeSymbol symbol) + { + if (symbol.BaseType is not null && symbol.BaseType.SpecialType != SpecialType.System_Object) + { + label.AddText(" : "); + label.PushColor(GetSymbolColourByType(symbol.BaseType)); + label.AddText(symbol.BaseType.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat)); + label.Pop(); + } + if (symbol.Interfaces.Length > 0) + { + if (symbol.BaseType is null || symbol.BaseType.SpecialType == SpecialType.System_Object) + { + label.AddText(" : "); + } + else + { + label.AddText(", "); + } + for (int i = 0; i < symbol.Interfaces.Length; i++) + { + var iface = symbol.Interfaces[i]; + label.PushColor(GetSymbolColourByType(iface)); + label.AddText(iface.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat)); + label.Pop(); + if (i < symbol.Interfaces.Length - 1) + { + label.AddText(", "); + } + } + } + } + + private static void AddContainingPackage(this RichTextLabel label, INamedTypeSymbol symbol) + { + var containingModule = symbol.ContainingModule; + if (containingModule is not null) + { + label.Newline(); + label.PushColor(CachedColors.White); + label.AddText($"from module {containingModule.Name}"); + label.Pop(); + } + } +} \ No newline at end of file