diff --git a/src/SharpIDE.Godot/Features/CodeEditor/CustomSyntaxHighlighter.cs b/src/SharpIDE.Godot/Features/CodeEditor/CustomSyntaxHighlighter.cs index df8f8b4..ddccc75 100644 --- a/src/SharpIDE.Godot/Features/CodeEditor/CustomSyntaxHighlighter.cs +++ b/src/SharpIDE.Godot/Features/CodeEditor/CustomSyntaxHighlighter.cs @@ -260,6 +260,7 @@ public partial class CustomHighlighter : SyntaxHighlighter "type parameter name" => CachedColors.ClassGreen, "delegate name" => CachedColors.ClassGreen, "event name" => CachedColors.White, + "label name" => CachedColors.White, // Punctuation & operators "operator" => CachedColors.White, diff --git a/src/SharpIDE.Godot/Features/CodeEditor/SharpIdeCodeEdit_SymbolHover.cs b/src/SharpIDE.Godot/Features/CodeEditor/SharpIdeCodeEdit_SymbolHover.cs index baaba95..f57976e 100644 --- a/src/SharpIDE.Godot/Features/CodeEditor/SharpIdeCodeEdit_SymbolHover.cs +++ b/src/SharpIDE.Godot/Features/CodeEditor/SharpIdeCodeEdit_SymbolHover.cs @@ -146,15 +146,21 @@ public partial class SharpIdeCodeEdit diagnosticPanel?.AddThemeStyleboxOverride(ThemeStringNames.Panel, styleBox); diagnosticPanel?.AddChild(diagnosticNode); - var symbolInfoNode = roslynSymbol switch { IMethodSymbol methodSymbol => SymbolInfoComponents.GetMethodSymbolInfo(methodSymbol), INamedTypeSymbol namedTypeSymbol => SymbolInfoComponents.GetNamedTypeSymbolInfo(namedTypeSymbol), IPropertySymbol propertySymbol => SymbolInfoComponents.GetPropertySymbolInfo(propertySymbol), + IFieldSymbol { ContainingType.TypeKind: TypeKind.Enum } fieldSymbol => SymbolInfoComponents.GetEnumValueSymbolInfo(fieldSymbol), IFieldSymbol fieldSymbol => SymbolInfoComponents.GetFieldSymbolInfo(fieldSymbol), IParameterSymbol parameterSymbol => SymbolInfoComponents.GetParameterSymbolInfo(parameterSymbol), ILocalSymbol localSymbol => SymbolInfoComponents.GetLocalVariableSymbolInfo(localSymbol), + INamespaceSymbol namespaceSymbol => SymbolInfoComponents.GetNamespaceSymbolInfo(namespaceSymbol), + ITypeParameterSymbol typeParameterSymbol => SymbolInfoComponents.GetTypeParameterSymbolInfo(typeParameterSymbol), + IDynamicTypeSymbol dynamicTypeSymbol => SymbolInfoComponents.GetDynamicTypeSymbolInfo(dynamicTypeSymbol), + IEventSymbol eventSymbol => SymbolInfoComponents.GetEventSymbolInfo(eventSymbol), + IDiscardSymbol discardSymbol => SymbolInfoComponents.GetDiscardSymbolInfo(discardSymbol), + ILabelSymbol labelSymbol => SymbolInfoComponents.GetLabelSymbolInfo(labelSymbol), _ => SymbolInfoComponents.GetUnknownTooltip(roslynSymbol) }; symbolInfoNode.FitContent = true; diff --git a/src/SharpIDE.Godot/Features/CodeEditor/SymbolTooltips/Common.cs b/src/SharpIDE.Godot/Features/CodeEditor/SymbolTooltips/Common.cs index 495f02d..2571381 100644 --- a/src/SharpIDE.Godot/Features/CodeEditor/SymbolTooltips/Common.cs +++ b/src/SharpIDE.Godot/Features/CodeEditor/SymbolTooltips/Common.cs @@ -49,6 +49,17 @@ public static partial class SymbolInfoComponents label.Pop(); } + private static void AddSealedModifier(this RichTextLabel label, ISymbol symbol) + { + if (symbol.IsSealed) + { + label.PushColor(CachedColors.KeywordBlue); + label.AddText("sealed"); + label.Pop(); + label.AddText(" "); + } + } + private static void AddOverrideModifier(this RichTextLabel label, ISymbol methodSymbol) { if (methodSymbol.IsOverride) @@ -97,16 +108,37 @@ public static partial class SymbolInfoComponents { if (symbol.ContainingNamespace is null || symbol.ContainingNamespace.IsGlobalNamespace) return; // might be wrong label.Newline(); - if (symbol.ContainingType is null) - { - label.AddText("in namespace "); - } - else - { - label.AddText("in class "); - } - var namespaces = symbol.ContainingNamespace.ToDisplayString().Split('.'); + label.AddText("in "); + label.AddText(GetNamedTypeSymbolTypeName(symbol.ContainingType)); // e.g. 'class' or 'namespace' + label.AddText(" "); label.PushMeta("TODO", RichTextLabel.MetaUnderline.OnHover); + label.AddNamespace(symbol.ContainingNamespace); + + if (symbol.ContainingType is not null) + { + label.AddText("."); + label.AddType(symbol.ContainingType); + } + label.Pop(); // meta + } + + private static string GetNamedTypeSymbolTypeName(INamedTypeSymbol? symbol) => symbol?.TypeKind switch + { + TypeKind.Class when symbol.IsRecord => "record", + TypeKind.Class => "class", + TypeKind.Delegate => "delegate", + TypeKind.Enum => "enum", + TypeKind.Interface => "interface", + TypeKind.Struct when symbol.IsRecord => "record struct", + TypeKind.Struct => "struct", + null => "namespace", + _ => symbol.TypeKind.ToString().ToLowerInvariant() + }; + + private static void AddNamespace(this RichTextLabel label, INamespaceSymbol symbol) + { + var namespaces = symbol.ToDisplayString().Split('.'); + foreach (var (index, ns) in namespaces.Index()) { label.PushColor(CachedColors.KeywordBlue); @@ -114,14 +146,6 @@ public static partial class SymbolInfoComponents label.Pop(); 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.Pop(); // meta } private static void AddAttribute(this RichTextLabel label, AttributeData attribute, bool newLines) @@ -358,6 +382,7 @@ public static partial class SymbolInfoComponents INamedTypeSymbol namedTypeSymbol => label.AddNamedType(namedTypeSymbol), ITypeParameterSymbol typeParameterSymbol => label.AddTypeParameter(typeParameterSymbol), IArrayTypeSymbol arrayTypeSymbol => label.AddArrayType(arrayTypeSymbol), + IDynamicTypeSymbol dynamicTypeSymbol => label.AddDynamicType(dynamicTypeSymbol), _ => label.AddUnknownType(symbol) }; } @@ -380,7 +405,7 @@ public static partial class SymbolInfoComponents private static RichTextLabel AddSpecialType(this RichTextLabel label, ITypeSymbol symbol) { - label.PushColor(CachedColors.KeywordBlue); + label.PushColor(symbol.GetSymbolColourByType()); label.AddText(symbol.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat)); label.Pop(); return label; @@ -423,13 +448,34 @@ public static partial class SymbolInfoComponents label.Pop(); return label; } + + private static RichTextLabel AddDynamicType(this RichTextLabel label, IDynamicTypeSymbol symbol) + { + label.PushColor(CachedColors.KeywordBlue); + label.AddText(symbol.Name); + label.Pop(); + return label; + } // TODO: handle arrays etc, where there are multiple colours in one type private static Color GetSymbolColourByType(this ITypeSymbol symbol) { Color colour = symbol switch { - {SpecialType: not SpecialType.None} => CachedColors.KeywordBlue, + {SpecialType: not SpecialType.None} => symbol.SpecialType switch + { + SpecialType.System_Collections_IEnumerable => CachedColors.InterfaceGreen, + SpecialType.System_Collections_Generic_IEnumerable_T => CachedColors.InterfaceGreen, + SpecialType.System_Collections_Generic_IList_T => CachedColors.InterfaceGreen, + SpecialType.System_Collections_Generic_ICollection_T => CachedColors.InterfaceGreen, + SpecialType.System_Collections_IEnumerator => CachedColors.InterfaceGreen, + SpecialType.System_Collections_Generic_IEnumerator_T => CachedColors.InterfaceGreen, + SpecialType.System_Collections_Generic_IReadOnlyList_T => CachedColors.InterfaceGreen, + SpecialType.System_Collections_Generic_IReadOnlyCollection_T => CachedColors.InterfaceGreen, + SpecialType.System_IDisposable => CachedColors.InterfaceGreen, + SpecialType.System_IAsyncResult => CachedColors.InterfaceGreen, + _ => CachedColors.KeywordBlue + }, INamedTypeSymbol namedTypeSymbol => namedTypeSymbol.TypeKind switch { TypeKind.Class => CachedColors.ClassGreen, @@ -437,6 +483,7 @@ public static partial class SymbolInfoComponents TypeKind.Struct => CachedColors.ClassGreen, TypeKind.Enum => CachedColors.InterfaceGreen, TypeKind.Delegate => CachedColors.ClassGreen, + TypeKind.Dynamic => CachedColors.KeywordBlue, _ => CachedColors.Orange }, _ => CachedColors.Orange diff --git a/src/SharpIDE.Godot/Features/CodeEditor/SymbolTooltips/DiscardTooltip.cs b/src/SharpIDE.Godot/Features/CodeEditor/SymbolTooltips/DiscardTooltip.cs new file mode 100644 index 0000000..23a7d95 --- /dev/null +++ b/src/SharpIDE.Godot/Features/CodeEditor/SymbolTooltips/DiscardTooltip.cs @@ -0,0 +1,29 @@ +using Godot; + +using Microsoft.CodeAnalysis; + +namespace SharpIDE.Godot.Features.CodeEditor; + +public static partial class SymbolInfoComponents +{ + public static RichTextLabel GetDiscardSymbolInfo(IDiscardSymbol symbol) + { + var label = new RichTextLabel(); + label.PushColor(CachedColors.White); + label.PushFont(MonospaceFont); + label.AddText("discard "); + label.AddType(symbol.Type); + label.AddText(" "); + label.AddDiscard(symbol); + label.Pop(); + label.Pop(); + return label; + } + + private static void AddDiscard(this RichTextLabel label, IDiscardSymbol _) + { + label.PushColor(CachedColors.VariableBlue); + label.AddText("_"); + label.Pop(); + } +} \ No newline at end of file diff --git a/src/SharpIDE.Godot/Features/CodeEditor/SymbolTooltips/DynamicTypeTooltip.cs b/src/SharpIDE.Godot/Features/CodeEditor/SymbolTooltips/DynamicTypeTooltip.cs new file mode 100644 index 0000000..41a6461 --- /dev/null +++ b/src/SharpIDE.Godot/Features/CodeEditor/SymbolTooltips/DynamicTypeTooltip.cs @@ -0,0 +1,21 @@ +using Godot; + +using Microsoft.CodeAnalysis; + +namespace SharpIDE.Godot.Features.CodeEditor; + +public static partial class SymbolInfoComponents +{ + public static RichTextLabel GetDynamicTypeSymbolInfo(IDynamicTypeSymbol symbol) + { + var label = new RichTextLabel(); + label.PushColor(CachedColors.White); + label.PushFont(MonospaceFont); + label.PushColor(CachedColors.KeywordBlue); + label.AddText(symbol.ToDisplayString()); + label.Pop(); + label.Pop(); + label.Pop(); + return label; + } +} \ No newline at end of file diff --git a/src/SharpIDE.Godot/Features/CodeEditor/SymbolTooltips/EnumValueTooltip.cs b/src/SharpIDE.Godot/Features/CodeEditor/SymbolTooltips/EnumValueTooltip.cs new file mode 100644 index 0000000..712e7ff --- /dev/null +++ b/src/SharpIDE.Godot/Features/CodeEditor/SymbolTooltips/EnumValueTooltip.cs @@ -0,0 +1,35 @@ +using Godot; + +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Shared.Extensions; + +namespace SharpIDE.Godot.Features.CodeEditor; + +public static partial class SymbolInfoComponents +{ + public static RichTextLabel GetEnumValueSymbolInfo(IFieldSymbol symbol) + { + if (symbol is { ContainingType.TypeKind: not TypeKind.Enum }) + { + throw new ArgumentException("The containing type of the symbol must be an enum type.", nameof(symbol)); + } + + var label = new RichTextLabel(); + label.PushColor(CachedColors.White); + label.PushFont(MonospaceFont); + label.AddAttributes(symbol); + label.AddFieldName(symbol); + label.AddText(" = "); + label.PushColor(CachedColors.NumberGreen); + label.AddText($"{symbol.ConstantValue}"); + label.Pop(); + label.AddText(";"); + label.AddContainingNamespaceAndClass(symbol); + label.Newline(); + label.Pop(); + label.AddDocs(symbol); + + label.Pop(); + return label; + } +} \ No newline at end of file diff --git a/src/SharpIDE.Godot/Features/CodeEditor/SymbolTooltips/EventTooltip.cs b/src/SharpIDE.Godot/Features/CodeEditor/SymbolTooltips/EventTooltip.cs new file mode 100644 index 0000000..554a525 --- /dev/null +++ b/src/SharpIDE.Godot/Features/CodeEditor/SymbolTooltips/EventTooltip.cs @@ -0,0 +1,59 @@ +using Godot; + +using Microsoft.CodeAnalysis; + +namespace SharpIDE.Godot.Features.CodeEditor; + +public static partial class SymbolInfoComponents +{ + public static RichTextLabel GetEventSymbolInfo(IEventSymbol symbol) + { + var label = new RichTextLabel(); + label.PushColor(CachedColors.White); + label.PushFont(MonospaceFont); + label.AddAccessibilityModifier(symbol); + label.AddEventKeyword(symbol); + label.AddEventTypeName(symbol); + label.AddEventName(symbol); + label.AddEventMethods(symbol); + label.AddContainingNamespaceAndClass(symbol); + label.Newline(); + label.Pop(); + label.AddDocs(symbol); + label.Pop(); + return label; + } + + private static void AddEventKeyword(this RichTextLabel label, IEventSymbol symbol) + { + label.PushColor(CachedColors.KeywordBlue); + label.AddText("event "); + label.Pop(); + } + + private static void AddEventTypeName(this RichTextLabel label, IEventSymbol symbol) + { + label.AddType(symbol.Type); + label.AddText(" "); + } + + private static void AddEventName(this RichTextLabel label, IEventSymbol symbol) + { + label.PushColor(CachedColors.White); + label.AddText(symbol.Name); + label.Pop(); + } + + private static void AddEventMethods(this RichTextLabel label, IEventSymbol symbol) + { + label.AddText(" { "); + label.PushColor(CachedColors.KeywordBlue); + label.AddText("add"); + label.Pop(); + label.AddText("; "); + label.PushColor(CachedColors.KeywordBlue); + label.AddText("remove"); + label.Pop(); + label.AddText("; }"); + } +} \ No newline at end of file diff --git a/src/SharpIDE.Godot/Features/CodeEditor/SymbolTooltips/FieldTooltip.cs b/src/SharpIDE.Godot/Features/CodeEditor/SymbolTooltips/FieldTooltip.cs index 3e19d95..d71584c 100644 --- a/src/SharpIDE.Godot/Features/CodeEditor/SymbolTooltips/FieldTooltip.cs +++ b/src/SharpIDE.Godot/Features/CodeEditor/SymbolTooltips/FieldTooltip.cs @@ -17,6 +17,7 @@ public static partial class SymbolInfoComponents label.AddVirtualModifier(symbol); label.AddAbstractModifier(symbol); label.AddOverrideModifier(symbol); + label.AddRequiredModifier(symbol); label.AddFieldTypeName(symbol); label.AddFieldName(symbol); label.AddText(";"); @@ -51,6 +52,17 @@ public static partial class SymbolInfoComponents label.AddText(" "); } } + + private static void AddRequiredModifier(this RichTextLabel label, IFieldSymbol symbol) + { + if (symbol.IsRequired) + { + label.PushColor(CachedColors.KeywordBlue); + label.AddText("required"); + label.Pop(); + label.AddText(" "); + } + } private static void AddFieldTypeName(this RichTextLabel label, IFieldSymbol fieldSymbol) { diff --git a/src/SharpIDE.Godot/Features/CodeEditor/SymbolTooltips/LabelTooltip.cs b/src/SharpIDE.Godot/Features/CodeEditor/SymbolTooltips/LabelTooltip.cs new file mode 100644 index 0000000..9bb5c79 --- /dev/null +++ b/src/SharpIDE.Godot/Features/CodeEditor/SymbolTooltips/LabelTooltip.cs @@ -0,0 +1,27 @@ +using Godot; + +using Microsoft.CodeAnalysis; + +namespace SharpIDE.Godot.Features.CodeEditor; + +public static partial class SymbolInfoComponents +{ + public static RichTextLabel GetLabelSymbolInfo(ILabelSymbol symbol) + { + var label = new RichTextLabel(); + label.PushColor(CachedColors.White); + label.PushFont(MonospaceFont); + label.AddText("label "); + label.AddLabelName(symbol); + label.Pop(); + label.Pop(); + return label; + } + + private static void AddLabelName(this RichTextLabel label, ILabelSymbol symbol) + { + label.PushColor(CachedColors.White); + label.AddText(symbol.Name); + label.Pop(); + } +} \ No newline at end of file diff --git a/src/SharpIDE.Godot/Features/CodeEditor/SymbolTooltips/LocalVariableTooltip.cs b/src/SharpIDE.Godot/Features/CodeEditor/SymbolTooltips/LocalVariableTooltip.cs index 859a48c..5d9d57d 100644 --- a/src/SharpIDE.Godot/Features/CodeEditor/SymbolTooltips/LocalVariableTooltip.cs +++ b/src/SharpIDE.Godot/Features/CodeEditor/SymbolTooltips/LocalVariableTooltip.cs @@ -35,7 +35,7 @@ public static partial class SymbolInfoComponents private static void AddLocalVariableName(this RichTextLabel label, ILocalSymbol symbol) { - label.PushColor(CachedColors.White); + label.PushColor(CachedColors.VariableBlue); label.AddText(symbol.Name); label.Pop(); } diff --git a/src/SharpIDE.Godot/Features/CodeEditor/SymbolTooltips/MethodTooltip.cs b/src/SharpIDE.Godot/Features/CodeEditor/SymbolTooltips/MethodTooltip.cs index 9b7b6b2..ff22ba0 100644 --- a/src/SharpIDE.Godot/Features/CodeEditor/SymbolTooltips/MethodTooltip.cs +++ b/src/SharpIDE.Godot/Features/CodeEditor/SymbolTooltips/MethodTooltip.cs @@ -1,5 +1,7 @@ using Godot; using Microsoft.CodeAnalysis; +using System.Collections.Immutable; +using System.Runtime.CompilerServices; namespace SharpIDE.Godot.Features.CodeEditor; @@ -15,6 +17,7 @@ public static partial class SymbolInfoComponents label.AddMethodStaticModifier(methodSymbol); label.AddVirtualModifier(methodSymbol); label.AddAbstractModifier(methodSymbol); + label.AddSealedModifier(methodSymbol); label.AddOverrideModifier(methodSymbol); label.AddMethodAsyncModifier(methodSymbol); label.AddMethodReturnType(methodSymbol); @@ -24,6 +27,7 @@ public static partial class SymbolInfoComponents label.AddText("("); label.AddParameters(methodSymbol); label.AddText(")"); + label.AddTypeParameterConstraints(methodSymbol.TypeParameters); label.AddContainingNamespaceAndClass(methodSymbol); label.Newline(); label.AddTypeParameterArguments(methodSymbol); @@ -221,4 +225,89 @@ public static partial class SymbolInfoComponents } } } -} \ No newline at end of file + + private static void AddTypeParameterConstraints(this RichTextLabel label, ImmutableArray typeParameters) + { + foreach (var typeParameter in typeParameters) + { + var hasConstraints = typeParameter.HasReferenceTypeConstraint || typeParameter.HasValueTypeConstraint || typeParameter.HasUnmanagedTypeConstraint || typeParameter.HasNotNullConstraint || typeParameter.HasConstructorConstraint || typeParameter.AllowsRefLikeType || typeParameter.ConstraintTypes.Length > 0; + if (hasConstraints is false) continue; + + label.AddText(" "); + label.PushColor(CachedColors.KeywordBlue); + label.AddText("where"); + label.Pop(); + label.AddText(" "); + label.AddTypeParameter(typeParameter); + label.AddText(" : "); + var firstConstraintAdded = false; + + if (typeParameter.HasReferenceTypeConstraint) + { + label.PushColor(CachedColors.KeywordBlue); + label.AddText("class"); + label.Pop(); + } + + if (typeParameter.HasValueTypeConstraint) + { + MaybeAddComma(); + label.PushColor(CachedColors.KeywordBlue); + label.AddText("struct"); + label.Pop(); + } + + if (typeParameter.HasUnmanagedTypeConstraint) + { + MaybeAddComma(); + label.PushColor(CachedColors.KeywordBlue); + label.AddText("unmanaged"); + label.Pop(); + } + + if (typeParameter.HasNotNullConstraint) + { + MaybeAddComma(); + label.PushColor(CachedColors.KeywordBlue); + label.AddText("notnull"); + label.Pop(); + } + + foreach (var typeParameterConstraintType in typeParameter.ConstraintTypes) + { + MaybeAddComma(); + label.AddType(typeParameterConstraintType); + } + + if (typeParameter.HasConstructorConstraint) + { + MaybeAddComma(); + label.PushColor(CachedColors.KeywordBlue); + label.AddText("new"); + label.Pop(); + label.AddText("()"); + } + + if (typeParameter.AllowsRefLikeType) + { + MaybeAddComma(); + label.PushColor(CachedColors.KeywordBlue); + label.AddText("allows ref struct"); + label.Pop(); + } + continue; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + void MaybeAddComma() + { + if (firstConstraintAdded is false) + { + firstConstraintAdded = true; + } + else + { + label.AddText(", "); + } + } + } + } +} diff --git a/src/SharpIDE.Godot/Features/CodeEditor/SymbolTooltips/NamedTypeTooltip.cs b/src/SharpIDE.Godot/Features/CodeEditor/SymbolTooltips/NamedTypeTooltip.cs index ea4dd25..eef3c3a 100644 --- a/src/SharpIDE.Godot/Features/CodeEditor/SymbolTooltips/NamedTypeTooltip.cs +++ b/src/SharpIDE.Godot/Features/CodeEditor/SymbolTooltips/NamedTypeTooltip.cs @@ -12,6 +12,8 @@ public static partial class SymbolInfoComponents label.PushFont(MonospaceFont); label.AddAttributes(symbol); label.AddAccessibilityModifier(symbol); + label.AddSealedModifier(symbol); + label.AddReadonlyModifier(symbol); label.AddStaticModifier(symbol); label.AddVirtualModifier(symbol); label.AddAbstractModifier(symbol); @@ -19,6 +21,7 @@ public static partial class SymbolInfoComponents label.AddNamedTypeSymbolType(symbol); label.AddNamedTypeSymbolName(symbol); label.AddInheritedTypes(symbol); + label.AddTypeParameterConstraints(symbol.TypeParameters); label.AddContainingNamespaceAndClass(symbol); label.AddContainingPackage(symbol); label.Newline(); @@ -37,15 +40,7 @@ public static partial class SymbolInfoComponents private static void AddNamedTypeSymbolType(this RichTextLabel label, INamedTypeSymbol symbol) { label.PushColor(CachedColors.KeywordBlue); - switch (symbol.TypeKind) - { - case TypeKind.Class: label.AddText("class"); break; - case TypeKind.Struct: label.AddText("struct"); break; - case TypeKind.Interface: label.AddText("interface"); break; - case TypeKind.Enum: label.AddText("enum"); break; - case TypeKind.Delegate: label.AddText("delegate"); break; - default: label.AddText(symbol.TypeKind.ToString().ToLowerInvariant()); break; - } + label.AddText(GetNamedTypeSymbolTypeName(symbol)); label.Pop(); label.AddText(" "); } @@ -90,4 +85,15 @@ public static partial class SymbolInfoComponents label.Pop(); } } + + private static void AddReadonlyModifier(this RichTextLabel label, INamedTypeSymbol symbol) + { + if (symbol.IsReadOnly) + { + label.PushColor(CachedColors.KeywordBlue); + label.AddText("readonly"); + label.Pop(); + label.AddText(" "); + } + } } \ No newline at end of file diff --git a/src/SharpIDE.Godot/Features/CodeEditor/SymbolTooltips/NamespaceTooltip.cs b/src/SharpIDE.Godot/Features/CodeEditor/SymbolTooltips/NamespaceTooltip.cs new file mode 100644 index 0000000..8684a23 --- /dev/null +++ b/src/SharpIDE.Godot/Features/CodeEditor/SymbolTooltips/NamespaceTooltip.cs @@ -0,0 +1,23 @@ +using Godot; + +using Microsoft.CodeAnalysis; + +namespace SharpIDE.Godot.Features.CodeEditor; + +public static partial class SymbolInfoComponents +{ + public static RichTextLabel GetNamespaceSymbolInfo(INamespaceSymbol symbol) + { + var label = new RichTextLabel(); + label.PushColor(CachedColors.White); + label.PushFont(MonospaceFont); + label.PushColor(CachedColors.KeywordBlue); + label.AddText("namespace"); + label.Pop(); // color + label.AddText(" "); + label.AddNamespace(symbol); + label.Pop(); // font + label.Pop(); // color + return label; + } +} \ No newline at end of file diff --git a/src/SharpIDE.Godot/Features/CodeEditor/SymbolTooltips/PropertyTooltip.cs b/src/SharpIDE.Godot/Features/CodeEditor/SymbolTooltips/PropertyTooltip.cs index 7e21b34..6930e12 100644 --- a/src/SharpIDE.Godot/Features/CodeEditor/SymbolTooltips/PropertyTooltip.cs +++ b/src/SharpIDE.Godot/Features/CodeEditor/SymbolTooltips/PropertyTooltip.cs @@ -17,6 +17,7 @@ public partial class SymbolInfoComponents label.AddVirtualModifier(symbol); label.AddAbstractModifier(symbol); label.AddOverrideModifier(symbol); + label.AddRequiredModifier(symbol); label.AddPropertyTypeName(symbol); label.AddPropertyName(symbol); label.AddGetSetAccessors(symbol); @@ -40,6 +41,17 @@ public partial class SymbolInfoComponents label.AddText(" "); } } + + private static void AddRequiredModifier(this RichTextLabel label, IPropertySymbol symbol) + { + if (symbol.IsRequired) + { + label.PushColor(CachedColors.KeywordBlue); + label.AddText("required"); + label.Pop(); + label.AddText(" "); + } + } private static void AddPropertyTypeName(this RichTextLabel label, IPropertySymbol symbol) { diff --git a/src/SharpIDE.Godot/Features/CodeEditor/SymbolTooltips/TypeParameterTooltip.cs b/src/SharpIDE.Godot/Features/CodeEditor/SymbolTooltips/TypeParameterTooltip.cs new file mode 100644 index 0000000..14209d0 --- /dev/null +++ b/src/SharpIDE.Godot/Features/CodeEditor/SymbolTooltips/TypeParameterTooltip.cs @@ -0,0 +1,40 @@ +using Godot; +using Microsoft.CodeAnalysis; + +namespace SharpIDE.Godot.Features.CodeEditor; + +public static partial class SymbolInfoComponents +{ + public static RichTextLabel GetTypeParameterSymbolInfo(ITypeParameterSymbol symbol) + { + var label = new RichTextLabel(); + label.PushColor(CachedColors.White); + label.PushFont(MonospaceFont); + label.AddTypeParameter(symbol); + label.AddText(" in "); + + if (symbol.DeclaringMethod is { } declaringMethod) + { + label.AddDeclaringMethod(declaringMethod); + } + else + { + label.AddType(symbol.ContainingType); + label.AddTypeParameterConstraints(symbol.ContainingType.TypeParameters); + } + + label.Pop(); + label.Pop(); + return label; + + } + + private static void AddDeclaringMethod(this RichTextLabel label, IMethodSymbol symbol) + { + label.AddType(symbol.ContainingType); + label.AddText("."); + label.AddMethodName(symbol); + label.AddTypeParameters(symbol); + label.AddTypeParameterConstraints(symbol.TypeParameters); + } +} \ No newline at end of file