From cdf334cb856f533052afec28469295de75c86e59 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 1 May 2026 14:40:48 +0000 Subject: [PATCH 01/11] Add GotoDefinitionResultsWindow for multiple goto-definition results Agent-Logs-Url: https://github.com/X-Sharp/XSharpPublic/sessions/970d2592-55a2-44c5-bd37-c3fc9baa77f4 Co-authored-by: RobertvanderHulst <14240939+RobertvanderHulst@users.noreply.github.com> --- .../Commands/GotoDefinition.cs | 9 +- .../Commands/GotoDefinitionResultsWindow.xaml | 36 ++++++++ .../GotoDefinitionResultsWindow.xaml.cs | 86 +++++++++++++++++++ .../LanguageService/LanguageService.csproj | 8 ++ .../LanguageService2022.csproj | 8 ++ 5 files changed, 146 insertions(+), 1 deletion(-) create mode 100644 src/VisualStudio/LanguageService/Commands/GotoDefinitionResultsWindow.xaml create mode 100644 src/VisualStudio/LanguageService/Commands/GotoDefinitionResultsWindow.xaml.cs diff --git a/src/VisualStudio/LanguageService/Commands/GotoDefinition.cs b/src/VisualStudio/LanguageService/Commands/GotoDefinition.cs index f9601af87a..db873fc711 100644 --- a/src/VisualStudio/LanguageService/Commands/GotoDefinition.cs +++ b/src/VisualStudio/LanguageService/Commands/GotoDefinition.cs @@ -54,11 +54,18 @@ internal static void GotoDefn(ITextView TextView) var result = TextView.GetSymbolUnderCursor(out var state,out _, out _); // ThreadHelper.ThrowIfNotOnUIThread(); - if (result.Count > 0) + if (result.Count == 1) { Goto(result[0], TextView, state); return; } + if (result.Count > 1) + { + var window = new GotoDefinitionResultsWindow(result, TextView, state); + window.Owner = System.Windows.Application.Current?.MainWindow; + window.Show(); + return; + } } catch (Exception ex) { diff --git a/src/VisualStudio/LanguageService/Commands/GotoDefinitionResultsWindow.xaml b/src/VisualStudio/LanguageService/Commands/GotoDefinitionResultsWindow.xaml new file mode 100644 index 0000000000..5d17e4cadf --- /dev/null +++ b/src/VisualStudio/LanguageService/Commands/GotoDefinitionResultsWindow.xaml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + diff --git a/src/VisualStudio/LanguageService/Commands/GotoDefinitionResultsWindow.xaml.cs b/src/VisualStudio/LanguageService/Commands/GotoDefinitionResultsWindow.xaml.cs new file mode 100644 index 0000000000..38cb6a39e8 --- /dev/null +++ b/src/VisualStudio/LanguageService/Commands/GotoDefinitionResultsWindow.xaml.cs @@ -0,0 +1,86 @@ +// Copyright (c) XSharp B.V. All Rights Reserved. +// Licensed under the Apache License, Version 2.0. +// See License.txt in the project root for license information. +// +using Microsoft.VisualStudio.Text.Editor; +using System.Collections.Generic; +using System.Windows; +using System.Windows.Input; +using XSharpModel; + +namespace XSharp.LanguageService +{ + /// + /// Floating tool window shown when Goto Definition finds multiple locations. + /// Double-clicking an item (or pressing Enter) navigates to that location and closes the window. + /// + internal partial class GotoDefinitionResultsWindow : Window + { + private readonly ITextView _textView; + private readonly CompletionState _state; + + internal GotoDefinitionResultsWindow(IList results, ITextView textView, CompletionState state) + { + InitializeComponent(); + _textView = textView; + _state = state; + + var items = new List(); + foreach (var symbol in results) + { + items.Add(new GotoDefinitionResultItem(symbol)); + } + _listView.ItemsSource = items; + if (items.Count > 0) + _listView.SelectedIndex = 0; + } + + private void NavigateToSelected() + { + if (_listView.SelectedItem is GotoDefinitionResultItem item) + { + Close(); + XSharpGotoDefinition.Goto(item.Symbol, _textView, _state); + } + } + + private void OnItemDoubleClick(object sender, MouseButtonEventArgs e) + { + if (_listView.SelectedItem != null) + NavigateToSelected(); + } + + private void OnKeyDown(object sender, KeyEventArgs e) + { + if (e.Key == Key.Enter) + { + NavigateToSelected(); + e.Handled = true; + } + else if (e.Key == Key.Escape) + { + Close(); + e.Handled = true; + } + } + } + + /// + /// View-model item for a single Goto Definition result. + /// + internal sealed class GotoDefinitionResultItem + { + internal IXSymbol Symbol { get; } + internal string DisplayName { get; } + internal string Location { get; } + + internal GotoDefinitionResultItem(IXSymbol symbol) + { + Symbol = symbol; + DisplayName = symbol.Description; + if (string.IsNullOrEmpty(DisplayName)) + DisplayName = symbol.FullName; + Location = symbol.Location; + } + } +} diff --git a/src/VisualStudio/LanguageService/LanguageService.csproj b/src/VisualStudio/LanguageService/LanguageService.csproj index b79a58ae01..11f1eacde1 100644 --- a/src/VisualStudio/LanguageService/LanguageService.csproj +++ b/src/VisualStudio/LanguageService/LanguageService.csproj @@ -61,6 +61,10 @@ + + GotoDefinitionResultsWindow.xaml + Code + @@ -339,6 +343,10 @@ + + MSBuild:Compile + Designer + MSBuild:Compile Designer diff --git a/src/VisualStudio/LanguageService/LanguageService2022.csproj b/src/VisualStudio/LanguageService/LanguageService2022.csproj index 1e1c1767e3..6c5f8b3094 100644 --- a/src/VisualStudio/LanguageService/LanguageService2022.csproj +++ b/src/VisualStudio/LanguageService/LanguageService2022.csproj @@ -63,6 +63,10 @@ + + GotoDefinitionResultsWindow.xaml + Code + @@ -355,6 +359,10 @@ MSBuild:Compile Designer + + MSBuild:Compile + Designer + MSBuild:Compile Designer From 8a47749559182872e677b58082a4abe06453d4ad Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 1 May 2026 14:42:06 +0000 Subject: [PATCH 02/11] Fix review: use VS IVsUIShell for window owner and handle keys at window level Agent-Logs-Url: https://github.com/X-Sharp/XSharpPublic/sessions/970d2592-55a2-44c5-bd37-c3fc9baa77f4 Co-authored-by: RobertvanderHulst <14240939+RobertvanderHulst@users.noreply.github.com> --- .../Commands/GotoDefinitionResultsWindow.xaml | 3 +- .../GotoDefinitionResultsWindow.xaml.cs | 34 ++++++++++++++++++- 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/src/VisualStudio/LanguageService/Commands/GotoDefinitionResultsWindow.xaml b/src/VisualStudio/LanguageService/Commands/GotoDefinitionResultsWindow.xaml index 5d17e4cadf..79fbe4340c 100644 --- a/src/VisualStudio/LanguageService/Commands/GotoDefinitionResultsWindow.xaml +++ b/src/VisualStudio/LanguageService/Commands/GotoDefinitionResultsWindow.xaml @@ -16,8 +16,7 @@ + MouseDoubleClick="OnItemDoubleClick"> results, ITextView textView _listView.ItemsSource = items; if (items.Count > 0) _listView.SelectedIndex = 0; + + // Set the VS main window as the owner so the popup stays on top of the IDE + SetVsOwner(); + } + + private void SetVsOwner() + { + try + { + ThreadHelper.JoinableTaskFactory.Run(async () => + { + await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); + var vsUIShell = ServiceProvider.GlobalProvider.GetService(typeof(SVsUIShell)) as IVsUIShell; + if (vsUIShell != null) + { + vsUIShell.GetDialogOwnerHwnd(out IntPtr ownerHwnd); + if (ownerHwnd != IntPtr.Zero) + { + new WindowInteropHelper(this).Owner = ownerHwnd; + } + } + }); + } + catch (Exception) + { + // Fallback: no owner; window will still work + } } private void NavigateToSelected() @@ -50,7 +81,7 @@ private void OnItemDoubleClick(object sender, MouseButtonEventArgs e) NavigateToSelected(); } - private void OnKeyDown(object sender, KeyEventArgs e) + protected override void OnPreviewKeyDown(KeyEventArgs e) { if (e.Key == Key.Enter) { @@ -62,6 +93,7 @@ private void OnKeyDown(object sender, KeyEventArgs e) Close(); e.Handled = true; } + base.OnPreviewKeyDown(e); } } From 657be04ce24fe5dc5018c41dea98d91050907f40 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 1 May 2026 14:50:38 +0000 Subject: [PATCH 03/11] Use CVT VS.Services.GetUIShellAsync and toolkit:Themes.UseVsTheme on results window Agent-Logs-Url: https://github.com/X-Sharp/XSharpPublic/sessions/b57213ac-3397-4e6e-a075-bc0c6c065d5b Co-authored-by: RobertvanderHulst <14240939+RobertvanderHulst@users.noreply.github.com> --- .../Commands/GotoDefinitionResultsWindow.xaml | 2 ++ .../Commands/GotoDefinitionResultsWindow.xaml.cs | 5 ++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/VisualStudio/LanguageService/Commands/GotoDefinitionResultsWindow.xaml b/src/VisualStudio/LanguageService/Commands/GotoDefinitionResultsWindow.xaml index 79fbe4340c..0cb5eba492 100644 --- a/src/VisualStudio/LanguageService/Commands/GotoDefinitionResultsWindow.xaml +++ b/src/VisualStudio/LanguageService/Commands/GotoDefinitionResultsWindow.xaml @@ -1,6 +1,8 @@ { await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); - var vsUIShell = ServiceProvider.GlobalProvider.GetService(typeof(SVsUIShell)) as IVsUIShell; + var vsUIShell = await VS.Services.GetUIShellAsync(); if (vsUIShell != null) { vsUIShell.GetDialogOwnerHwnd(out IntPtr ownerHwnd); From a7203b0f5db2c2cfdb3dfe1034827e59fbb3a56e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 1 May 2026 14:51:35 +0000 Subject: [PATCH 04/11] Remove redundant window.Owner assignment; SetVsOwner handles HWND ownership Agent-Logs-Url: https://github.com/X-Sharp/XSharpPublic/sessions/b57213ac-3397-4e6e-a075-bc0c6c065d5b Co-authored-by: RobertvanderHulst <14240939+RobertvanderHulst@users.noreply.github.com> --- src/VisualStudio/LanguageService/Commands/GotoDefinition.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/VisualStudio/LanguageService/Commands/GotoDefinition.cs b/src/VisualStudio/LanguageService/Commands/GotoDefinition.cs index db873fc711..94e7431b2b 100644 --- a/src/VisualStudio/LanguageService/Commands/GotoDefinition.cs +++ b/src/VisualStudio/LanguageService/Commands/GotoDefinition.cs @@ -62,7 +62,6 @@ internal static void GotoDefn(ITextView TextView) if (result.Count > 1) { var window = new GotoDefinitionResultsWindow(result, TextView, state); - window.Owner = System.Windows.Application.Current?.MainWindow; window.Show(); return; } From 8d4b675ad652b7e6a5100160f5c773b8350590f5 Mon Sep 17 00:00:00 2001 From: Robert van der Hulst Date: Sat, 2 May 2026 11:58:22 +0200 Subject: [PATCH 05/11] Moved windows to common folder. Make sure multiple results are returned. Added methods to XProject that return multiple functions. --- .../Commands/GotoDefinition.cs | 10 +++++++- .../DocumentOutlineControl.cs | 0 .../DocumentOutlineControl.xaml | 0 .../GotoDefinitionResultsWindow.xaml | 4 +++ .../GotoDefinitionResultsWindow.xaml.cs | 5 +++- .../LanguageService2022.csproj | 10 ++++---- .../LanguageService/Lookup/XSharpLookup.cs | 25 ++++++++++++++----- .../ProjectSystem/XProject.prg | 17 ++++++++----- 8 files changed, 52 insertions(+), 19 deletions(-) rename src/VisualStudio/LanguageService/{DocumentOutline => Controls}/DocumentOutlineControl.cs (100%) rename src/VisualStudio/LanguageService/{DocumentOutline => Controls}/DocumentOutlineControl.xaml (100%) rename src/VisualStudio/LanguageService/{Commands => Controls}/GotoDefinitionResultsWindow.xaml (92%) rename src/VisualStudio/LanguageService/{Commands => Controls}/GotoDefinitionResultsWindow.xaml.cs (95%) diff --git a/src/VisualStudio/LanguageService/Commands/GotoDefinition.cs b/src/VisualStudio/LanguageService/Commands/GotoDefinition.cs index 94e7431b2b..fbdec2e884 100644 --- a/src/VisualStudio/LanguageService/Commands/GotoDefinition.cs +++ b/src/VisualStudio/LanguageService/Commands/GotoDefinition.cs @@ -154,7 +154,15 @@ private static XSourceEntity FindElementInFile(XFile file, XPETypeSymbol petype, { if (entity.Name == element.Name) { - return entity; + if (entity is IXMemberSymbol m1 && element is IXMemberSymbol m2) + { + if (m1.Prototype == m2.Prototype) + return entity; + } + else if (entity.FullName == element.FullName) + { + return entity; + } } } } diff --git a/src/VisualStudio/LanguageService/DocumentOutline/DocumentOutlineControl.cs b/src/VisualStudio/LanguageService/Controls/DocumentOutlineControl.cs similarity index 100% rename from src/VisualStudio/LanguageService/DocumentOutline/DocumentOutlineControl.cs rename to src/VisualStudio/LanguageService/Controls/DocumentOutlineControl.cs diff --git a/src/VisualStudio/LanguageService/DocumentOutline/DocumentOutlineControl.xaml b/src/VisualStudio/LanguageService/Controls/DocumentOutlineControl.xaml similarity index 100% rename from src/VisualStudio/LanguageService/DocumentOutline/DocumentOutlineControl.xaml rename to src/VisualStudio/LanguageService/Controls/DocumentOutlineControl.xaml diff --git a/src/VisualStudio/LanguageService/Commands/GotoDefinitionResultsWindow.xaml b/src/VisualStudio/LanguageService/Controls/GotoDefinitionResultsWindow.xaml similarity index 92% rename from src/VisualStudio/LanguageService/Commands/GotoDefinitionResultsWindow.xaml rename to src/VisualStudio/LanguageService/Controls/GotoDefinitionResultsWindow.xaml index 0cb5eba492..36b253f5d2 100644 --- a/src/VisualStudio/LanguageService/Commands/GotoDefinitionResultsWindow.xaml +++ b/src/VisualStudio/LanguageService/Controls/GotoDefinitionResultsWindow.xaml @@ -11,6 +11,10 @@ ResizeMode="CanResize" WindowStartupLocation="Manual"> + + + + diff --git a/src/VisualStudio/LanguageService/Commands/GotoDefinitionResultsWindow.xaml.cs b/src/VisualStudio/LanguageService/Controls/GotoDefinitionResultsWindow.xaml.cs similarity index 95% rename from src/VisualStudio/LanguageService/Commands/GotoDefinitionResultsWindow.xaml.cs rename to src/VisualStudio/LanguageService/Controls/GotoDefinitionResultsWindow.xaml.cs index 465effc770..3ab01f6156 100644 --- a/src/VisualStudio/LanguageService/Commands/GotoDefinitionResultsWindow.xaml.cs +++ b/src/VisualStudio/LanguageService/Controls/GotoDefinitionResultsWindow.xaml.cs @@ -3,6 +3,8 @@ // See License.txt in the project root for license information. // using Community.VisualStudio.Toolkit; + +using Microsoft.VisualStudio.Shell; using Microsoft.VisualStudio.Text.Editor; using System; using System.Collections.Generic; @@ -17,7 +19,7 @@ namespace XSharp.LanguageService /// Floating tool window shown when Goto Definition finds multiple locations. /// Double-clicking an item (or pressing Enter) navigates to that location and closes the window. /// - internal partial class GotoDefinitionResultsWindow : Window + partial class GotoDefinitionResultsWindow : Window { private readonly ITextView _textView; private readonly CompletionState _state; @@ -113,5 +115,6 @@ internal GotoDefinitionResultItem(IXSymbol symbol) DisplayName = symbol.FullName; Location = symbol.Location; } + public override string ToString() => DisplayName + " (" + Location + ")"; } } diff --git a/src/VisualStudio/LanguageService/LanguageService2022.csproj b/src/VisualStudio/LanguageService/LanguageService2022.csproj index 6c5f8b3094..318c015270 100644 --- a/src/VisualStudio/LanguageService/LanguageService2022.csproj +++ b/src/VisualStudio/LanguageService/LanguageService2022.csproj @@ -63,7 +63,7 @@ - + GotoDefinitionResultsWindow.xaml Code @@ -225,7 +225,7 @@ - + DocumentOutlineControl.xaml Code @@ -355,15 +355,15 @@ - DocumentOutline\VsThemeDictionary.xaml + Controls\VsThemeDictionary.xaml MSBuild:Compile Designer - + MSBuild:Compile Designer - + MSBuild:Compile Designer diff --git a/src/VisualStudio/LanguageService/Lookup/XSharpLookup.cs b/src/VisualStudio/LanguageService/Lookup/XSharpLookup.cs index 8ab4a49cb3..9dabb5e578 100644 --- a/src/VisualStudio/LanguageService/Lookup/XSharpLookup.cs +++ b/src/VisualStudio/LanguageService/Lookup/XSharpLookup.cs @@ -14,6 +14,7 @@ using XSharpModel; using XSharp.Settings; using XSharp.Support; +using System.Windows.Controls; namespace XSharp.LanguageService { internal static class XSharpLookup @@ -1140,10 +1141,22 @@ enum PPUDCType : byte if (result.Count == 0 && symbols.Count > 0) { result.Add(symbols.Pop()); - if (result[0] is IXMemberSymbol xmember && xmember.ParentType != null && xmember.ParentType.IsGeneric && symbols.Count > 0) + if (result[0] is IXMemberSymbol xmember) { - result.Clear(); - result.Add(AdjustGenericMember(xmember, symbols.Peek())); + if (xmember.ParentType != null && xmember.ParentType.IsGeneric && symbols.Count > 0) + { + result.Clear(); + result.Add(AdjustGenericMember(xmember, symbols.Peek())); + } + else + { + var overloads = xmember.GetOverloads(); + if (overloads.Length > 1) + { + result.Clear(); + result.AddRange(overloads); + } + } } } if (result.Count > 0 && result[0] is IXTypeSymbol xtype && state == CompletionState.Constructors) @@ -2004,10 +2017,10 @@ private static IList SearchFunction(XSharpSearchLocation locatio return result; } WriteOutputMessage($" SearchFunction {location.File.SourcePath}, '{name}' "); - IXMemberSymbol xMethod = location.File.Project.FindFunction(name); - if (xMethod != null) + var xMethods = location.File.Project.FindFunctions(name); + if (xMethods != null) { - result.Add(xMethod); + result.AddRange(xMethods); } else { diff --git a/src/VisualStudio/XSharpCodeModelXs/ProjectSystem/XProject.prg b/src/VisualStudio/XSharpCodeModelXs/ProjectSystem/XProject.prg index ace26e04f2..c6d2536c84 100644 --- a/src/VisualStudio/XSharpCodeModelXs/ProjectSystem/XProject.prg +++ b/src/VisualStudio/XSharpCodeModelXs/ProjectSystem/XProject.prg @@ -12,7 +12,7 @@ USING LanguageService.CodeAnalysis.XSharp USING System.Collections.Concurrent USING System.Reflection USING XSharp.Settings - +USING System.Linq #pragma options ("az", ON) NAMESPACE XSharpModel @@ -803,8 +803,10 @@ CLASS XProject SELF:LogTypeMessage(i"FindFunctionsLike {name}, found {result.Count} occurences") RETURN result - METHOD FindFunction(name AS STRING, lRecursive := TRUE AS LOGIC) AS IXMemberSymbol + var members := SELF:FindFunctions(name, lRecursive) + return members:FirstOrDefault() + METHOD FindFunctions(name AS STRING, lRecursive := TRUE AS LOGIC) AS IList // we look in the project references and assembly references // pass the list of ProjectIds and AssemblyIds to the database engine SELF:LogTypeMessage(ie"FindFunction {name} ") @@ -814,9 +816,9 @@ CLASS XProject projectIds := SELF:DependentProjectList ENDIF VAR result := XDatabase.FindFunction(name, projectIds) - VAR xmember := SELF:GetGlobalMember(result) - SELF:LogTypeMessage(ie"FindFunction {name}, result {iif (xmember != NULL, xmember.FullName, \"not found\")} ") - RETURN xmember + VAR xmembers := SELF:GetGlobalMembers(result) + SELF:LogTypeMessage(ie"FindFunction {name}, result {result:Count} ") + RETURN xmembers METHOD FindGlobalOrDefine(name AS STRING, lRecursive := TRUE AS LOGIC) AS IXMemberSymbol // we look in the project references and assembly references @@ -832,6 +834,9 @@ CLASS XProject RETURN xmember PRIVATE METHOD GetGlobalMember(result AS IList) AS IXMemberSymbol + var members := SELF:GetGlobalMembers(result) + return iif(members?:Count() > 0, members[0], NULL) + PRIVATE METHOD GetGlobalMembers(result AS IList) AS List IF result:Count > 0 // Get the source code and parse it into a member // we know that it will be of the globals class @@ -872,7 +877,7 @@ CLASS XProject ENDIF NEXT parentType:SetMembers(entities) - RETURN first + RETURN entities:ToList() ENDIF RETURN NULL From a8307e8bf360d851d4ad2007e45e863b5925fb9e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 2 May 2026 10:20:52 +0000 Subject: [PATCH 06/11] Replace ImageList glyphs with KnownMonikers in DocumentOutlineControl; use CrispImage for tree icons Agent-Logs-Url: https://github.com/X-Sharp/XSharpPublic/sessions/66420f9b-d1a6-4c04-8928-fc5f4ebe4705 Co-authored-by: RobertvanderHulst <14240939+RobertvanderHulst@users.noreply.github.com> --- .../Controls/DocumentOutlineControl.cs | 236 +++++++++++------- 1 file changed, 148 insertions(+), 88 deletions(-) diff --git a/src/VisualStudio/LanguageService/Controls/DocumentOutlineControl.cs b/src/VisualStudio/LanguageService/Controls/DocumentOutlineControl.cs index 581429b738..2f3985d1da 100644 --- a/src/VisualStudio/LanguageService/Controls/DocumentOutlineControl.cs +++ b/src/VisualStudio/LanguageService/Controls/DocumentOutlineControl.cs @@ -3,17 +3,13 @@ // See License.txt in the project root for license information. // using Community.VisualStudio.Toolkit; - +using Microsoft.VisualStudio.Imaging; +using Microsoft.VisualStudio.Imaging.Interop; using Microsoft.VisualStudio.Shell; - using System; using System.Collections.Generic; -using System.Data.Common; -using System.IO; using System.Windows; using System.Windows.Controls; -using System.Windows.Media; -using System.Windows.Media.Imaging; using Microsoft.VisualStudio.TextManager.Interop; using XSharpModel; @@ -33,33 +29,6 @@ sealed partial class DocumentOutlineControl : UserControl private bool _navigating; // reentrancy guard private bool _sortByName; // false = sort by document order (default) - // ----------------------------------------------------------------------- - // Image source cache: maps glyph index -> ImageSource - // ----------------------------------------------------------------------- - private static readonly Dictionary _glyphCache = new Dictionary(); - private static System.Windows.Forms.ImageList _imageList; - - static DocumentOutlineControl() - { - _imageList = new System.Windows.Forms.ImageList - { - ImageSize = new System.Drawing.Size(16, 16), - TransparentColor = System.Drawing.Color.FromArgb(255, 0, 255) - }; - try - { - Stream stream = typeof(Microsoft.VisualStudio.Package.LanguageService) - .Assembly - .GetManifestResourceStream("Resources.completionset.bmp"); - if (stream != null) - _imageList.Images.AddStrip(new System.Drawing.Bitmap(stream)); - } - catch (Exception) - { - // If images cannot be loaded the tree will still work without icons. - } - } - // ----------------------------------------------------------------------- // Construction // ----------------------------------------------------------------------- @@ -155,7 +124,7 @@ private OutlineTreeNode CreateNode(XSourceEntity entity) string label = entity.ComboPrototype; if (string.IsNullOrEmpty(label)) label = entity.Name; - return new OutlineTreeNode(entity, label, GetGlyphImage(entity.Glyph)); + return new OutlineTreeNode(entity, label, GetMoniker(entity.Kind, entity.Visibility)); } private void AddMemberNodes(OutlineTreeNode parentNode, XSourceTypeSymbol type) @@ -210,45 +179,149 @@ private static void FindBestNode(OutlineTreeNode node, int line, ref OutlineTree } // ----------------------------------------------------------------------- - // Glyph -> ImageSource conversion + // Kind + Visibility -> ImageMoniker mapping // ----------------------------------------------------------------------- - private static ImageSource GetGlyphImage(int glyphIndex) - { - if (_imageList == null || glyphIndex < 0 || glyphIndex >= _imageList.Images.Count) - return null; - - if (_glyphCache.TryGetValue(glyphIndex, out var cached)) - return cached; - var bmp = _imageList.Images[glyphIndex] as System.Drawing.Bitmap; - if (bmp == null) - return null; - - ImageSource source; - try + /// + /// Returns the from that best + /// represents the given entity and . + /// + private static ImageMoniker GetMoniker(Kind kind, Modifiers visibility) + { + switch (kind) { - var handle = bmp.GetHbitmap(); - try - { - source = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap( - handle, - IntPtr.Zero, - Int32Rect.Empty, - BitmapSizeOptions.FromEmptyOptions()); - source.Freeze(); - } - finally - { - NativeMethods.DeleteObject(handle); - } + case Kind.Class: + return VisibilityMoniker(visibility, + KnownMonikers.ClassPublic, KnownMonikers.ClassProtected, + KnownMonikers.ClassPrivate, KnownMonikers.ClassInternal); + + case Kind.Structure: + case Kind.VOStruct: + return VisibilityMoniker(visibility, + KnownMonikers.ValueTypePublic, KnownMonikers.ValueTypeProtected, + KnownMonikers.ValueTypePrivate, KnownMonikers.ValueTypeInternal); + + case Kind.Interface: + return VisibilityMoniker(visibility, + KnownMonikers.InterfacePublic, KnownMonikers.InterfaceProtected, + KnownMonikers.InterfacePrivate, KnownMonikers.InterfaceInternal); + + case Kind.Delegate: + return VisibilityMoniker(visibility, + KnownMonikers.DelegatePublic, KnownMonikers.DelegateProtected, + KnownMonikers.DelegatePrivate, KnownMonikers.DelegateInternal); + + case Kind.Enum: + return VisibilityMoniker(visibility, + KnownMonikers.EnumerationPublic, KnownMonikers.EnumerationProtected, + KnownMonikers.EnumerationPrivate, KnownMonikers.EnumerationInternal); + + case Kind.EnumMember: + return KnownMonikers.EnumerationItemPublic; + + case Kind.Constructor: + case Kind.Destructor: + case Kind.Method: + return VisibilityMoniker(visibility, + KnownMonikers.MethodPublic, KnownMonikers.MethodProtected, + KnownMonikers.MethodPrivate, KnownMonikers.MethodInternal); + + case Kind.Function: + case Kind.Procedure: + case Kind.LocalFunc: + case Kind.LocalProc: + // Global/module-level routines have no class visibility + return KnownMonikers.MethodPublic; + + case Kind.Access: + case Kind.Assign: + case Kind.Property: + return VisibilityMoniker(visibility, + KnownMonikers.PropertyPublic, KnownMonikers.PropertyProtected, + KnownMonikers.PropertyPrivate, KnownMonikers.PropertyInternal); + + case Kind.Event: + return VisibilityMoniker(visibility, + KnownMonikers.EventPublic, KnownMonikers.EventProtected, + KnownMonikers.EventPrivate, KnownMonikers.EventInternal); + + case Kind.Field: + case Kind.VOGlobal: + return VisibilityMoniker(visibility, + KnownMonikers.FieldPublic, KnownMonikers.FieldProtected, + KnownMonikers.FieldPrivate, KnownMonikers.FieldInternal); + + case Kind.Operator: + return KnownMonikers.Operator; + + case Kind.Namespace: + return KnownMonikers.Namespace; + + case Kind.Union: + return KnownMonikers.Union; + + case Kind.VODefine: + case Kind.Define: + case Kind.Undefine: + return VisibilityMoniker(visibility, + KnownMonikers.ConstantPublic, KnownMonikers.ConstantProtected, + KnownMonikers.ConstantPrivate, KnownMonikers.ConstantInternal); + + case Kind.Command: + case Kind.XCommand: + case Kind.YCommand: + case Kind.Translate: + case Kind.XTranslate: + case Kind.YTranslate: + return KnownMonikers.MacroPublic; + + case Kind.Include: + return KnownMonikers.Library; + + case Kind.Keyword: + return KnownMonikers.IntellisenseKeyword; + + case Kind.Attribute: + return KnownMonikers.Attribute; + + case Kind.TypeParameter: + return KnownMonikers.Type; + + case Kind.Local: + case Kind.Parameter: + case Kind.MemVar: + case Kind.DbField: + case Kind.Undeclared: + return KnownMonikers.LocalVariable; + + default: + return KnownMonikers.Item; } - catch (Exception) + } + + /// + /// Picks one of four visibility-specific monikers based on . + /// maps to the + /// because that is the closest visual equivalent available in the catalog. + /// Any other value (including and ) + /// returns . + /// + private static ImageMoniker VisibilityMoniker(Modifiers visibility, + ImageMoniker publicMoniker, ImageMoniker protectedMoniker, + ImageMoniker privateMoniker, ImageMoniker internalMoniker) + { + switch (visibility) { - return null; + case Modifiers.Protected: + case Modifiers.ProtectedInternal: + return protectedMoniker; + case Modifiers.Private: + return privateMoniker; + case Modifiers.Internal: + return internalMoniker; + default: + return publicMoniker; } - - _glyphCache[glyphIndex] = source; - return source; } // ----------------------------------------------------------------------- @@ -376,22 +449,19 @@ internal sealed class OutlineTreeNode : TreeViewItem { public XSourceEntity Entity { get; } - public OutlineTreeNode(XSourceEntity entity, string label, ImageSource icon) + public OutlineTreeNode(XSourceEntity entity, string label, ImageMoniker moniker) { Entity = entity; var panel = new StackPanel { Orientation = Orientation.Horizontal }; - if (icon != null) + panel.Children.Add(new CrispImage { - panel.Children.Add(new System.Windows.Controls.Image - { - Source = icon, - Width = 16, - Height = 16, - Margin = new Thickness(0, 0, 4, 0), - VerticalAlignment = VerticalAlignment.Center - }); - } + Moniker = moniker, + Width = 16, + Height = 16, + Margin = new Thickness(0, 0, 4, 0), + VerticalAlignment = VerticalAlignment.Center + }); panel.Children.Add(new TextBlock { Text = label, @@ -401,15 +471,5 @@ public OutlineTreeNode(XSourceEntity entity, string label, ImageSource icon) Header = panel; } } - - // --------------------------------------------------------------------------- - // P/Invoke helper for bitmap conversion - // --------------------------------------------------------------------------- - internal static class NativeMethods - { - [System.Runtime.InteropServices.DllImport("gdi32.dll")] - [return: System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.Bool)] - internal static extern bool DeleteObject(IntPtr hObject); - } } From 31d1d6f9ac8f45dd00a9955bee9f4776adad28a8 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 2 May 2026 10:37:05 +0000 Subject: [PATCH 07/11] Extract GetImageMoniker extension method; use it in DocumentOutlineControl and AnalysisClasses Agent-Logs-Url: https://github.com/X-Sharp/XSharpPublic/sessions/e07732be-3319-43f9-a8b3-753229c8a572 Co-authored-by: RobertvanderHulst <14240939+RobertvanderHulst@users.noreply.github.com> --- .../Controls/DocumentOutlineControl.cs | 149 +--------------- .../Controls/KindExtensions.cs | 160 ++++++++++++++++++ .../LanguageService/LanguageService.csproj | 1 + .../LanguageService2022.csproj | 1 + .../LanguageService/Lookup/AnalysisClasses.cs | 31 +--- 5 files changed, 164 insertions(+), 178 deletions(-) create mode 100644 src/VisualStudio/LanguageService/Controls/KindExtensions.cs diff --git a/src/VisualStudio/LanguageService/Controls/DocumentOutlineControl.cs b/src/VisualStudio/LanguageService/Controls/DocumentOutlineControl.cs index 2f3985d1da..54713d84b0 100644 --- a/src/VisualStudio/LanguageService/Controls/DocumentOutlineControl.cs +++ b/src/VisualStudio/LanguageService/Controls/DocumentOutlineControl.cs @@ -3,7 +3,6 @@ // See License.txt in the project root for license information. // using Community.VisualStudio.Toolkit; -using Microsoft.VisualStudio.Imaging; using Microsoft.VisualStudio.Imaging.Interop; using Microsoft.VisualStudio.Shell; using System; @@ -124,7 +123,7 @@ private OutlineTreeNode CreateNode(XSourceEntity entity) string label = entity.ComboPrototype; if (string.IsNullOrEmpty(label)) label = entity.Name; - return new OutlineTreeNode(entity, label, GetMoniker(entity.Kind, entity.Visibility)); + return new OutlineTreeNode(entity, label, entity.Kind.GetImageMoniker(entity.Visibility)); } private void AddMemberNodes(OutlineTreeNode parentNode, XSourceTypeSymbol type) @@ -178,152 +177,6 @@ private static void FindBestNode(OutlineTreeNode node, int line, ref OutlineTree FindBestNode(child, line, ref best, ref bestLength); } - // ----------------------------------------------------------------------- - // Kind + Visibility -> ImageMoniker mapping - // ----------------------------------------------------------------------- - - /// - /// Returns the from that best - /// represents the given entity and . - /// - private static ImageMoniker GetMoniker(Kind kind, Modifiers visibility) - { - switch (kind) - { - case Kind.Class: - return VisibilityMoniker(visibility, - KnownMonikers.ClassPublic, KnownMonikers.ClassProtected, - KnownMonikers.ClassPrivate, KnownMonikers.ClassInternal); - - case Kind.Structure: - case Kind.VOStruct: - return VisibilityMoniker(visibility, - KnownMonikers.ValueTypePublic, KnownMonikers.ValueTypeProtected, - KnownMonikers.ValueTypePrivate, KnownMonikers.ValueTypeInternal); - - case Kind.Interface: - return VisibilityMoniker(visibility, - KnownMonikers.InterfacePublic, KnownMonikers.InterfaceProtected, - KnownMonikers.InterfacePrivate, KnownMonikers.InterfaceInternal); - - case Kind.Delegate: - return VisibilityMoniker(visibility, - KnownMonikers.DelegatePublic, KnownMonikers.DelegateProtected, - KnownMonikers.DelegatePrivate, KnownMonikers.DelegateInternal); - - case Kind.Enum: - return VisibilityMoniker(visibility, - KnownMonikers.EnumerationPublic, KnownMonikers.EnumerationProtected, - KnownMonikers.EnumerationPrivate, KnownMonikers.EnumerationInternal); - - case Kind.EnumMember: - return KnownMonikers.EnumerationItemPublic; - - case Kind.Constructor: - case Kind.Destructor: - case Kind.Method: - return VisibilityMoniker(visibility, - KnownMonikers.MethodPublic, KnownMonikers.MethodProtected, - KnownMonikers.MethodPrivate, KnownMonikers.MethodInternal); - - case Kind.Function: - case Kind.Procedure: - case Kind.LocalFunc: - case Kind.LocalProc: - // Global/module-level routines have no class visibility - return KnownMonikers.MethodPublic; - - case Kind.Access: - case Kind.Assign: - case Kind.Property: - return VisibilityMoniker(visibility, - KnownMonikers.PropertyPublic, KnownMonikers.PropertyProtected, - KnownMonikers.PropertyPrivate, KnownMonikers.PropertyInternal); - - case Kind.Event: - return VisibilityMoniker(visibility, - KnownMonikers.EventPublic, KnownMonikers.EventProtected, - KnownMonikers.EventPrivate, KnownMonikers.EventInternal); - - case Kind.Field: - case Kind.VOGlobal: - return VisibilityMoniker(visibility, - KnownMonikers.FieldPublic, KnownMonikers.FieldProtected, - KnownMonikers.FieldPrivate, KnownMonikers.FieldInternal); - - case Kind.Operator: - return KnownMonikers.Operator; - - case Kind.Namespace: - return KnownMonikers.Namespace; - - case Kind.Union: - return KnownMonikers.Union; - - case Kind.VODefine: - case Kind.Define: - case Kind.Undefine: - return VisibilityMoniker(visibility, - KnownMonikers.ConstantPublic, KnownMonikers.ConstantProtected, - KnownMonikers.ConstantPrivate, KnownMonikers.ConstantInternal); - - case Kind.Command: - case Kind.XCommand: - case Kind.YCommand: - case Kind.Translate: - case Kind.XTranslate: - case Kind.YTranslate: - return KnownMonikers.MacroPublic; - - case Kind.Include: - return KnownMonikers.Library; - - case Kind.Keyword: - return KnownMonikers.IntellisenseKeyword; - - case Kind.Attribute: - return KnownMonikers.Attribute; - - case Kind.TypeParameter: - return KnownMonikers.Type; - - case Kind.Local: - case Kind.Parameter: - case Kind.MemVar: - case Kind.DbField: - case Kind.Undeclared: - return KnownMonikers.LocalVariable; - - default: - return KnownMonikers.Item; - } - } - - /// - /// Picks one of four visibility-specific monikers based on . - /// maps to the - /// because that is the closest visual equivalent available in the catalog. - /// Any other value (including and ) - /// returns . - /// - private static ImageMoniker VisibilityMoniker(Modifiers visibility, - ImageMoniker publicMoniker, ImageMoniker protectedMoniker, - ImageMoniker privateMoniker, ImageMoniker internalMoniker) - { - switch (visibility) - { - case Modifiers.Protected: - case Modifiers.ProtectedInternal: - return protectedMoniker; - case Modifiers.Private: - return privateMoniker; - case Modifiers.Internal: - return internalMoniker; - default: - return publicMoniker; - } - } - // ----------------------------------------------------------------------- // Event handlers // ----------------------------------------------------------------------- diff --git a/src/VisualStudio/LanguageService/Controls/KindExtensions.cs b/src/VisualStudio/LanguageService/Controls/KindExtensions.cs new file mode 100644 index 0000000000..5c9ec6375d --- /dev/null +++ b/src/VisualStudio/LanguageService/Controls/KindExtensions.cs @@ -0,0 +1,160 @@ +// Copyright (c) XSharp B.V. All Rights Reserved. +// Licensed under the Apache License, Version 2.0. +// See License.txt in the project root for license information. +// +using Microsoft.VisualStudio.Imaging; +using Microsoft.VisualStudio.Imaging.Interop; +using XSharpModel; + +namespace XSharp.LanguageService +{ + /// + /// Extension methods on that map an entity kind and visibility + /// to the appropriate from the VS catalog. + /// + internal static class KindExtensions + { + /// + /// Returns the from that best + /// represents the given and . + /// + internal static ImageMoniker GetImageMoniker(this Kind kind, Modifiers visibility) + { + switch (kind) + { + case Kind.Class: + return VisibilityMoniker(visibility, + KnownMonikers.ClassPublic, KnownMonikers.ClassProtected, + KnownMonikers.ClassPrivate, KnownMonikers.ClassInternal); + + case Kind.Structure: + case Kind.VOStruct: + return VisibilityMoniker(visibility, + KnownMonikers.ValueTypePublic, KnownMonikers.ValueTypeProtected, + KnownMonikers.ValueTypePrivate, KnownMonikers.ValueTypeInternal); + + case Kind.Interface: + return VisibilityMoniker(visibility, + KnownMonikers.InterfacePublic, KnownMonikers.InterfaceProtected, + KnownMonikers.InterfacePrivate, KnownMonikers.InterfaceInternal); + + case Kind.Delegate: + return VisibilityMoniker(visibility, + KnownMonikers.DelegatePublic, KnownMonikers.DelegateProtected, + KnownMonikers.DelegatePrivate, KnownMonikers.DelegateInternal); + + case Kind.Enum: + return VisibilityMoniker(visibility, + KnownMonikers.EnumerationPublic, KnownMonikers.EnumerationProtected, + KnownMonikers.EnumerationPrivate, KnownMonikers.EnumerationInternal); + + case Kind.EnumMember: + return KnownMonikers.EnumerationItemPublic; + + case Kind.Constructor: + case Kind.Destructor: + case Kind.Method: + return VisibilityMoniker(visibility, + KnownMonikers.MethodPublic, KnownMonikers.MethodProtected, + KnownMonikers.MethodPrivate, KnownMonikers.MethodInternal); + + case Kind.Function: + case Kind.Procedure: + case Kind.LocalFunc: + case Kind.LocalProc: + // Global/module-level routines have no class visibility + return KnownMonikers.MethodPublic; + + case Kind.Access: + case Kind.Assign: + case Kind.Property: + return VisibilityMoniker(visibility, + KnownMonikers.PropertyPublic, KnownMonikers.PropertyProtected, + KnownMonikers.PropertyPrivate, KnownMonikers.PropertyInternal); + + case Kind.Event: + return VisibilityMoniker(visibility, + KnownMonikers.EventPublic, KnownMonikers.EventProtected, + KnownMonikers.EventPrivate, KnownMonikers.EventInternal); + + case Kind.Field: + case Kind.VOGlobal: + return VisibilityMoniker(visibility, + KnownMonikers.FieldPublic, KnownMonikers.FieldProtected, + KnownMonikers.FieldPrivate, KnownMonikers.FieldInternal); + + case Kind.Operator: + return KnownMonikers.Operator; + + case Kind.Namespace: + case Kind.Using: + return KnownMonikers.Namespace; + + case Kind.Union: + return KnownMonikers.Union; + + case Kind.VODefine: + case Kind.Define: + case Kind.Undefine: + return VisibilityMoniker(visibility, + KnownMonikers.ConstantPublic, KnownMonikers.ConstantProtected, + KnownMonikers.ConstantPrivate, KnownMonikers.ConstantInternal); + + case Kind.Command: + case Kind.XCommand: + case Kind.YCommand: + case Kind.Translate: + case Kind.XTranslate: + case Kind.YTranslate: + return KnownMonikers.MacroPublic; + + case Kind.Include: + return KnownMonikers.Library; + + case Kind.Keyword: + return KnownMonikers.IntellisenseKeyword; + + case Kind.Attribute: + return KnownMonikers.Attribute; + + case Kind.TypeParameter: + return KnownMonikers.Type; + + case Kind.Local: + case Kind.Parameter: + case Kind.MemVar: + case Kind.DbField: + case Kind.Undeclared: + return KnownMonikers.LocalVariable; + + default: + return KnownMonikers.Item; + } + } + + /// + /// Picks one of four visibility-specific monikers based on . + /// maps to the + /// because that is the closest visual equivalent available in the catalog. + /// Any other value (including and ) + /// returns . + /// + private static ImageMoniker VisibilityMoniker(Modifiers visibility, + ImageMoniker publicMoniker, ImageMoniker protectedMoniker, + ImageMoniker privateMoniker, ImageMoniker internalMoniker) + { + switch (visibility) + { + case Modifiers.Protected: + case Modifiers.ProtectedInternal: + return protectedMoniker; + case Modifiers.Private: + return privateMoniker; + case Modifiers.Internal: + return internalMoniker; + default: + return publicMoniker; + } + } + } +} diff --git a/src/VisualStudio/LanguageService/LanguageService.csproj b/src/VisualStudio/LanguageService/LanguageService.csproj index 11f1eacde1..57795561d4 100644 --- a/src/VisualStudio/LanguageService/LanguageService.csproj +++ b/src/VisualStudio/LanguageService/LanguageService.csproj @@ -224,6 +224,7 @@ + DocumentOutlineControl.xaml Code diff --git a/src/VisualStudio/LanguageService/LanguageService2022.csproj b/src/VisualStudio/LanguageService/LanguageService2022.csproj index 318c015270..764f73710e 100644 --- a/src/VisualStudio/LanguageService/LanguageService2022.csproj +++ b/src/VisualStudio/LanguageService/LanguageService2022.csproj @@ -225,6 +225,7 @@ + DocumentOutlineControl.xaml Code diff --git a/src/VisualStudio/LanguageService/Lookup/AnalysisClasses.cs b/src/VisualStudio/LanguageService/Lookup/AnalysisClasses.cs index 821e774fc4..d72125e0e4 100644 --- a/src/VisualStudio/LanguageService/Lookup/AnalysisClasses.cs +++ b/src/VisualStudio/LanguageService/Lookup/AnalysisClasses.cs @@ -4,7 +4,6 @@ // See License.txt in the project root for license information. // -using Microsoft.VisualStudio.Imaging; using Microsoft.VisualStudio.Imaging.Interop; using Microsoft.VisualStudio.Language.Intellisense; using Microsoft.VisualStudio.Text.Adornments; @@ -26,35 +25,7 @@ internal XAnalysis(IXSymbol sym) symbol = sym; Name = sym.FullName; } - internal ImageMoniker Image - { - get - { - switch (symbol.Kind) - { - case Kind.Class: - return KnownMonikers.Class; - case Kind.Structure: - return KnownMonikers.Structure; - case Kind.Interface: - return KnownMonikers.Interface; - case Kind.Delegate: - return KnownMonikers.Delegate; - case Kind.Enum: - return KnownMonikers.Enumeration; - case Kind.VOStruct: - return KnownMonikers.ValueType; - case Kind.Union: - return KnownMonikers.Union; - case Kind.Using: - case Kind.Namespace: - return KnownMonikers.Namespace; - case Kind.Keyword: - return KnownMonikers.IntellisenseKeyword; - } - return KnownMonikers.None; - } - } + internal ImageMoniker Image => symbol.Kind.GetImageMoniker(symbol.Visibility); public string Prototype => Name; public virtual ClassifiedTextRun[] WPFDescription From 6ae0401c14e4a18f33f0ef0b3ed5ce22559cd902 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 2 May 2026 13:12:53 +0000 Subject: [PATCH 08/11] Migrate DropDownClient and CompletionHelpers to use GetImageMoniker extension method Agent-Logs-Url: https://github.com/X-Sharp/XSharpPublic/sessions/5a7c76a7-f084-4a3c-ab78-99f4cac72825 Co-authored-by: RobertvanderHulst <14240939+RobertvanderHulst@users.noreply.github.com> --- .../Completion/CompletionHelpers.cs | 33 ++++----- .../Completion/XSharpCompletionSource.cs | 2 +- .../XSharpCompletionSourceProvider.cs | 4 - .../Controls/KindExtensions.cs | 33 +++++++++ .../LanguageService/Generic/DropDownClient.cs | 73 +++++++------------ 5 files changed, 77 insertions(+), 68 deletions(-) diff --git a/src/VisualStudio/LanguageService/Completion/CompletionHelpers.cs b/src/VisualStudio/LanguageService/Completion/CompletionHelpers.cs index 550867eb02..6812dabc26 100644 --- a/src/VisualStudio/LanguageService/Completion/CompletionHelpers.cs +++ b/src/VisualStudio/LanguageService/Completion/CompletionHelpers.cs @@ -6,6 +6,7 @@ using System; using System.Collections.Generic; using System.Linq; +using Microsoft.VisualStudio.Imaging; using Microsoft.VisualStudio.Language.Intellisense; using Microsoft.VisualStudio.Text; using XSharpModel; @@ -19,14 +20,12 @@ namespace XSharp.LanguageService { internal class CompletionHelpers { - internal IGlyphService _glyphService = null; private XDialect _dialect; private XFile _file; private bool _settingIgnoreCase; - internal CompletionHelpers(XDialect dialect, IGlyphService glyphService, XFile file, bool ignoreCase) + internal CompletionHelpers(XDialect dialect, XFile file, bool ignoreCase) { _dialect = dialect; - _glyphService = glyphService; _file = file; _settingIgnoreCase = ignoreCase; } @@ -94,7 +93,7 @@ internal void AddPETypeNamesLike(XCompletionList compList, XSharpSearchLocation continue; var typeAnalysis = new XTypeAnalysis(type); - ImageSource icon = _glyphService.GetGlyph(type.getGlyphGroup(), type.getGlyphItem()); + ImageSource icon = type.Kind.GetImageMoniker(type.Visibility).GetImageSource(); if (!compList.Add(new XSCompletion(displayName, displayName, typeAnalysis.Prototype, icon, null, Kind.Class, ""))) break; } @@ -120,7 +119,7 @@ internal void AddSourceTypeNamesLike(XCompletionList compList, XSharpSearchLocat continue; var typeAnalysis = new XTypeAnalysis(type); - ImageSource icon = _glyphService.GetGlyph(type.getGlyphGroup(), type.getGlyphItem()); + ImageSource icon = type.Kind.GetImageMoniker(type.Visibility).GetImageSource(); if (!compList.Add(new XSCompletion(displayName, displayName, typeAnalysis.Prototype, icon, null, Kind.Class, ""))) break; } @@ -182,7 +181,7 @@ internal void AddXSharpKeywordsLike(XCompletionList compList, string startWith) { foreach (var kw in XSharpSyntax.GetKeywords().Where(ti => nameStartsWith(ti.Name, startWith))) { - ImageSource icon = _glyphService.GetGlyph(kw.getGlyphGroup(), kw.getGlyphItem()); + ImageSource icon = kw.Kind.GetImageMoniker(kw.Visibility).GetImageSource(); var item = new XSCompletion(kw.Name, kw.Name, kw.Prototype, icon, null, Kind.Keyword, ""); compList.Add(item); } @@ -192,7 +191,7 @@ internal void AddSnippets(XCompletionList compList, string startWith) var snippets = SnippetHelpers.FindSnippets(startWith); foreach (var snippet in snippets) { - ImageSource icon = _glyphService.GetGlyph(StandardGlyphGroup.GlyphCSharpExpansion, StandardGlyphItem.GlyphItemPublic); + ImageSource icon = KnownMonikers.Snippet.GetImageSource(); var item = new XSCompletion(snippet.title, "", snippet.description, icon, null, Kind.Snippet, snippet.shortcut); item.Properties.AddProperty(typeof(VsExpansion), snippet); compList.Add(item,false, true); @@ -210,7 +209,7 @@ internal void AddXSharpTypeNamesLike(XCompletionList compList, XSharpSearchLocat continue; // Then remove it - ImageSource icon = _glyphService.GetGlyph(typeInfo.getGlyphGroup(), typeInfo.getGlyphItem()); + ImageSource icon = typeInfo.Kind.GetImageMoniker(typeInfo.Visibility).GetImageSource(); if (!compList.Add(new XSCompletion(typeInfo.Name, typeInfo.Name, typeInfo.FullName, icon, null, typeInfo.Kind, ""))) break; } @@ -237,7 +236,7 @@ internal void AddXSharpKeywordTypeNamesLike(XCompletionList compList, string sta // Then remove it if (dotPos > 0) realTypeName = realTypeName.Substring(0, dotPos); - ImageSource icon = _glyphService.GetGlyph(typeInfo.getGlyphGroup(), typeInfo.getGlyphItem()); + ImageSource icon = typeInfo.Kind.GetImageMoniker(typeInfo.Visibility).GetImageSource(); if (!compList.Add(new XSCompletion(realTypeName, realTypeName, typeInfo.Prototype, icon, null, Kind.Class, ""))) break; } @@ -334,8 +333,8 @@ internal void AddNamespacesLike(XCompletionList compList, XSharpSearchLocation l int dotPos = startWith.LastIndexOf('.'); if (dotPos != -1) startLen = dotPos + 1; - ImageSource icon = _glyphService.GetGlyph(StandardGlyphGroup.GlyphGroupNamespace, StandardGlyphItem.GlyphItemPublic); - ImageSource iconClass = _glyphService.GetGlyph(StandardGlyphGroup.GlyphGroupClass, StandardGlyphItem.GlyphItemPublic); + ImageSource icon = KnownMonikers.Namespace.GetImageSource(); + ImageSource iconClass = KnownMonikers.ClassPublic.GetImageSource(); foreach (string nameSpace in namespaces.Where(ns => nameStartsWith(ns, startWith))) { string displayName = nameSpace; @@ -408,7 +407,7 @@ internal void AddGenericLocalsLike(XCompletionList compList, XSharpSearchLocatio // First, look after Parameters foreach (var paramVar in location.Member.Parameters.Where(p => nameStartsWith(p.Name, startWith))) { - ImageSource icon = _glyphService.GetGlyph(paramVar.getGlyphGroup(), paramVar.getGlyphItem()); + ImageSource icon = paramVar.Kind.GetImageMoniker(paramVar.Visibility).GetImageSource(); if (!compList.Add(new XSCompletion(paramVar.Name, paramVar.Name, paramVar.Prototype, icon, null, Kind.Parameter, ""))) break; } @@ -416,7 +415,7 @@ internal void AddGenericLocalsLike(XCompletionList compList, XSharpSearchLocatio // line numbers in the range are 1 based. currentLine = 0 based ! foreach (var localVar in location.Member.GetLocals(location).Where(l => nameStartsWith(l.Name, startWith) && l.Range.StartLine <= location.LineNumber)) { - ImageSource icon = _glyphService.GetGlyph(localVar.getGlyphGroup(), localVar.getGlyphItem()); + ImageSource icon = localVar.Kind.GetImageMoniker(localVar.Visibility).GetImageSource(); if (!compList.Add(new XSCompletion(localVar.Name, localVar.Name, localVar.Prototype, icon, null, Kind.Local, ""))) break; @@ -440,7 +439,7 @@ internal void AddGenericSelfMembersLike(XCompletionList compList, XSharpSearchLo return; foreach (var member in type.GetMembers(startWith)) { - ImageSource icon = _glyphService.GetGlyph(member.getGlyphGroup(), member.getGlyphItem()); + ImageSource icon = member.Kind.GetImageMoniker(member.Visibility).GetImageSource(); if (!compList.Add(new XSCompletion(member.Name, member.Name, member.Prototype, icon, null, Kind.Field, ""))) break; } @@ -465,7 +464,7 @@ internal void AddGenericInheritedMembersLike(XCompletionList compList, XSharpSea return; foreach (var member in baseType.GetMembers(startWith)) { - ImageSource icon = _glyphService.GetGlyph(member.getGlyphGroup(), member.getGlyphItem()); + ImageSource icon = member.Kind.GetImageMoniker(member.Visibility).GetImageSource(); if (!compList.Add(new XSCompletion(member.Name, member.Name, member.Prototype, icon, null, Kind.Field, ""))) break; } @@ -578,7 +577,7 @@ internal void FillEnumMembers(XSharpSearchLocation location, XCompletionList com continue; if (elt is XPESymbol peSym && peSym.IsSpecialName) continue; - ImageSource icon = _glyphService.GetGlyph(elt.getGlyphGroup(), elt.getGlyphItem()); + ImageSource icon = elt.Kind.GetImageMoniker(elt.Visibility).GetImageSource(); if (!compList.Add(new XSCompletion(elt.Name, elt.Name, elt.Prototype, icon, null, elt.Kind, elt.Value))) break; } @@ -638,7 +637,7 @@ internal void FillMembers(XSharpSearchLocation location, XCompletionList compLis if (!add) continue; // - ImageSource icon = _glyphService.GetGlyph(elt.getGlyphGroup(), elt.getGlyphItem()); + ImageSource icon = elt.Kind.GetImageMoniker(elt.Visibility).GetImageSource(); string toAdd = AddOpenParen(elt.Kind); if (!compList.Add(new XSCompletion(elt.Name, elt.Name + toAdd, elt.Prototype, icon, null, elt.Kind, elt.Value))) break; diff --git a/src/VisualStudio/LanguageService/Completion/XSharpCompletionSource.cs b/src/VisualStudio/LanguageService/Completion/XSharpCompletionSource.cs index 45567b7310..cc903309a4 100644 --- a/src/VisualStudio/LanguageService/Completion/XSharpCompletionSource.cs +++ b/src/VisualStudio/LanguageService/Completion/XSharpCompletionSource.cs @@ -42,7 +42,7 @@ public XSharpCompletionSource(XSharpCompletionSourceProvider provider, ITextBuff _file = file; var prj = _file.Project.ProjectNode; _dialect = _file.Project.Dialect; - helpers = new CompletionHelpers(_dialect, provider.GlyphService, file, !prj.ParseOptions.CaseSensitive); + helpers = new CompletionHelpers(_dialect, file, !prj.ParseOptions.CaseSensitive); this._tagAggregator = aggregator.CreateTagAggregator(_buffer); } diff --git a/src/VisualStudio/LanguageService/Completion/XSharpCompletionSourceProvider.cs b/src/VisualStudio/LanguageService/Completion/XSharpCompletionSourceProvider.cs index 5e297fe8b9..5d7ecdeee8 100644 --- a/src/VisualStudio/LanguageService/Completion/XSharpCompletionSourceProvider.cs +++ b/src/VisualStudio/LanguageService/Completion/XSharpCompletionSourceProvider.cs @@ -12,7 +12,6 @@ using Microsoft.VisualStudio.Utilities; using XSharpModel; using Microsoft.VisualStudio.Shell; -using System.Windows.Media; using LanguageService.SyntaxTree; using LanguageService.CodeAnalysis.XSharp.SyntaxParser; using Microsoft.VisualStudio; @@ -29,9 +28,6 @@ class XSharpCompletionSourceProvider : ICompletionSourceProvider [Import] internal SVsServiceProvider ServiceProvider = null; - [Import] - internal IGlyphService GlyphService = null; - [Import] IBufferTagAggregatorFactoryService aggregator = null; diff --git a/src/VisualStudio/LanguageService/Controls/KindExtensions.cs b/src/VisualStudio/LanguageService/Controls/KindExtensions.cs index 5c9ec6375d..ec714ccd71 100644 --- a/src/VisualStudio/LanguageService/Controls/KindExtensions.cs +++ b/src/VisualStudio/LanguageService/Controls/KindExtensions.cs @@ -4,6 +4,11 @@ // using Microsoft.VisualStudio.Imaging; using Microsoft.VisualStudio.Imaging.Interop; +using Microsoft.VisualStudio.Shell; +using Microsoft.VisualStudio.Shell.Interop; +using System.Runtime.InteropServices; +using System.Windows.Media; +using System.Windows.Media.Imaging; using XSharpModel; namespace XSharp.LanguageService @@ -156,5 +161,33 @@ private static ImageMoniker VisibilityMoniker(Modifiers visibility, return publicMoniker; } } + + /// + /// Converts an to a WPF at 16×16 logical pixels + /// using the VS image service. Returns null when the image service is unavailable. + /// + internal static ImageSource GetImageSource(this ImageMoniker moniker) + { + var imageService = Package.GetGlobalService(typeof(SVsImageService)) as IVsImageService2; + if (imageService == null) + return null; + + var attributes = new ImageAttributes + { + StructSize = Marshal.SizeOf(typeof(ImageAttributes)), + ImageType = (uint)_UIImageType.IT_Bitmap, + Format = (uint)_UIDataFormat.DF_WPF, + LogicalWidth = 16, + LogicalHeight = 16, + Flags = (uint)_ImageAttributesFlags.IAF_RequiredFlags, + }; + + IVsUIObject uiObject = imageService.GetImage(moniker, attributes); + if (uiObject == null) + return null; + + uiObject.get_Data(out object data); + return data as BitmapSource; + } } } diff --git a/src/VisualStudio/LanguageService/Generic/DropDownClient.cs b/src/VisualStudio/LanguageService/Generic/DropDownClient.cs index bdd856e6fc..5eba739fa8 100644 --- a/src/VisualStudio/LanguageService/Generic/DropDownClient.cs +++ b/src/VisualStudio/LanguageService/Generic/DropDownClient.cs @@ -1,18 +1,18 @@ using Microsoft.VisualStudio; +using Microsoft.VisualStudio.Imaging; +using Microsoft.VisualStudio.Imaging.Interop; using Microsoft.VisualStudio.Shell; using Microsoft.VisualStudio.Text.Editor; using Microsoft.VisualStudio.TextManager.Interop; using System; using System.Collections.Generic; using System.Diagnostics; -using System.Drawing; using System.IO; using System.Linq; using System.Threading.Tasks; using System.Windows.Forms; using XSharpModel; using File = System.IO.File; -using MVP = Microsoft.VisualStudio.Package; using Task = System.Threading.Tasks.Task; using XSharp.Settings; using XSharp.Support; @@ -46,13 +46,12 @@ internal bool Changed } - public class XSharpDropDownClient : IVsDropdownBarClient + public class XSharpDropDownClient : IVsDropdownBarClient, IVsDropdownBarClient4 { const int PROJECTINDEX = 0; const int TYPEINDEX = 1; const int MEMBERINDEX = 2; - static readonly ImageList _imageList = new ImageList(); private IVsDropdownBar _dropDownBar; readonly Dictionary _textViews; ITextView _activeView = null; @@ -74,7 +73,6 @@ public class XSharpDropDownClient : IVsDropdownBarClient private DropdownSettings _settings; private List _relatedFiles; private DateTime _lastFileChanged = DateTime.MinValue; - private static readonly int projectIcon = -1; private XDocument _document; XProject ActiveProject { @@ -88,20 +86,6 @@ XProject ActiveProject } } - static XSharpDropDownClient() - { - // Load images from Microsoft and Our project system (linked resource file) - Stream stream = typeof(MVP.LanguageService).Assembly.GetManifestResourceStream("Resources.completionset.bmp"); - _imageList.ImageSize = new Size(16, 16); - _imageList.TransparentColor = Color.FromArgb(255, 0, 255); - _imageList.Images.AddStrip(new Bitmap(stream)); - // the project Icon is the first in the ImageList from the project package - projectIcon = _imageList.Images.Count; - stream = typeof(XSharpDropDownClient).Assembly.GetManifestResourceStream("XSharp.LanguageService.Resources.XSharpProjectImageList.bmp"); - _imageList.Images.AddStrip(new Bitmap(stream)); - } - - public XSharpDropDownClient(IVsDropdownBarManager manager, XFile file) { _manager = manager; @@ -525,7 +509,7 @@ private void loadTypeCombos(int nLine) { name = "?"; } - elt = new XDropDownMember(name, sp, eltType.Glyph, ft, eltType); + elt = new XDropDownMember(name, sp, eltType.Kind.GetImageMoniker(eltType.Visibility), ft, eltType); nSelect = _types.Count; _types.Add(elt); if (eltType.Range.StartLine <= nLine && eltType.Range.EndLine >= nLine) @@ -602,21 +586,21 @@ private void loadMemberCombos(int selectedType) { if (currentType.Kind != Kind.Delegate) { - elt = new XDropDownMember("(" + currentType.Name + ")", spM, currentType.Glyph, ft, currentType); + elt = new XDropDownMember("(" + currentType.Name + ")", spM, currentType.Kind.GetImageMoniker(currentType.Visibility), ft, currentType); _members.Add(elt); _addToDict(currentType); } } else { - elt = new XDropDownMember(currentType.Name, spM, currentType.Glyph, ft, currentType); + elt = new XDropDownMember(currentType.Name, spM, currentType.Kind.GetImageMoniker(currentType.Visibility), ft, currentType); _members.Add(elt); _addToDict(currentType); } } else if (!_settings.IncludeFields) { - elt = new XDropDownMember(globalType.Name, spM, globalType.Glyph, ft, globalType); + elt = new XDropDownMember(globalType.Name, spM, globalType.Kind.GetImageMoniker(globalType.Visibility), ft, globalType); _members.Add(elt); _addToDict(globalType); } @@ -677,7 +661,7 @@ private void loadMemberCombos(int selectedType) ft = DROPDOWNFONTATTR.FONTATTR_GRAY; prototype += " (" + System.IO.Path.GetFileName(member.File.SourcePath) + ")"; } - elt = new XDropDownMember(prototype, spM, member.Glyph, ft, member); + elt = new XDropDownMember(prototype, spM, member.Kind.GetImageMoniker(member.Visibility), ft, member); var nSelect = _members.Count; _members.Add(elt); _addToDict(member); @@ -774,7 +758,7 @@ public async System.Threading.Tasks.Task RefreshDropDownAsync(bool needsUI) public int GetComboAttributes(int combo, out uint entries, out uint entryType, out IntPtr imageList) { entries = 0; - imageList = _imageList.Handle; + imageList = IntPtr.Zero; // no HIMAGELIST needed; IVsDropdownBarClient4.GetEntryImage returns monikers entryType = (uint)(DROPDOWNENTRYTYPE.ENTRY_ATTR | DROPDOWNENTRYTYPE.ENTRY_IMAGE | DROPDOWNENTRYTYPE.ENTRY_TEXT); switch (combo) { @@ -827,30 +811,27 @@ public int GetEntryAttributes(int combo, int index, out uint attr) public int GetEntryImage(int combo, int index, out int imageIndex) { + // IVsDropdownBarClient4.GetEntryImage is called instead when VS supports it + imageIndex = -1; + return VSConstants.E_NOTIMPL; + } - imageIndex = 0; - if (index < 0) - { - return VSConstants.E_FAIL; - } + ImageMoniker IVsDropdownBarClient4.GetEntryImage(int combo, int index) + { switch (combo) { - case TYPEINDEX: // types - if (index < _types.Count) - imageIndex = _types[index].Glyph; - break; - case MEMBERINDEX: // members - if (index < _members.Count) - imageIndex = _members[index].Glyph; + case TYPEINDEX: + if (index >= 0 && index < _types.Count) + return _types[index].Moniker; break; - case PROJECTINDEX: // projects - imageIndex = projectIcon; + case MEMBERINDEX: + if (index >= 0 && index < _members.Count) + return _members[index].Moniker; break; - default: - throw new ArgumentOutOfRangeException(); - + case PROJECTINDEX: + return KnownMonikers.Application; } - return 0; + return default; } public int GetEntryText(int combo, int index, out string text) @@ -984,14 +965,14 @@ internal class XDropDownMember { public TextSpan Span { get; set; } public string Label { get; set; } - public int Glyph { get; set; } + public ImageMoniker Moniker { get; set; } public DROPDOWNFONTATTR FontAttr { get; set; } public XSourceEntity Entity { get; set; } - internal XDropDownMember(string label, TextSpan span, int glyph, DROPDOWNFONTATTR fontAttribute, XSourceEntity element) + internal XDropDownMember(string label, TextSpan span, ImageMoniker moniker, DROPDOWNFONTATTR fontAttribute, XSourceEntity element) { Label = label; Span = span; - Glyph = glyph; + Moniker = moniker; FontAttr = fontAttribute; Entity = element; } From 8007389a269083a6e3bac0136406ec4b03286c99 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 2 May 2026 13:22:54 +0000 Subject: [PATCH 09/11] Remove unused XSharpProjectImageList.bmp embedded resource from LanguageService projects Agent-Logs-Url: https://github.com/X-Sharp/XSharpPublic/sessions/aa358ee7-ebe3-4870-adc8-6a5b06f2c9d4 Co-authored-by: RobertvanderHulst <14240939+RobertvanderHulst@users.noreply.github.com> --- src/VisualStudio/LanguageService/LanguageService.csproj | 3 --- src/VisualStudio/LanguageService/LanguageService2022.csproj | 3 --- 2 files changed, 6 deletions(-) diff --git a/src/VisualStudio/LanguageService/LanguageService.csproj b/src/VisualStudio/LanguageService/LanguageService.csproj index 57795561d4..e59900deb4 100644 --- a/src/VisualStudio/LanguageService/LanguageService.csproj +++ b/src/VisualStudio/LanguageService/LanguageService.csproj @@ -325,9 +325,6 @@ - - Resources\XSharpProjectImageList.bmp - diff --git a/src/VisualStudio/LanguageService/LanguageService2022.csproj b/src/VisualStudio/LanguageService/LanguageService2022.csproj index 764f73710e..994f468ff2 100644 --- a/src/VisualStudio/LanguageService/LanguageService2022.csproj +++ b/src/VisualStudio/LanguageService/LanguageService2022.csproj @@ -342,9 +342,6 @@ - - Resources\XSharpProjectImageList.bmp - From fce5c2708421870d1cff0032806bbffba953ccbc Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 2 May 2026 14:04:29 +0000 Subject: [PATCH 10/11] Convert Windows.Forms UI to WPF in LanguageService project - Replace CtorParamsDlg (WinForms Form) with WPF Window + XAML - Replace XSharpSpecialOptions (WinForms Form) with WPF Window + XAML - Replace all 6 options controls (WinForms UserControls) with WPF UserControls + XAML - Rewrite XSUserControl as WPF UserControl base with reflection-based data binding - Rewrite XSDialogPage as UIElementDialogPage (instead of DialogPage) - Update ConstructorAction.cs to use WPF ShowDialog() bool result - Remove all Designer.cs and .resx files for converted controls - Update LanguageService.csproj and LanguageService2022.csproj accordingly Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: RobertvanderHulst <14240939+RobertvanderHulst@users.noreply.github.com> --- .../LanguageService/LanguageService.csproj | 104 ++--- .../LanguageService2022.csproj | 104 ++--- .../LightBulb/ConstructorAction.cs | 2 +- .../LightBulb/CtorParamsDlg.Designer.cs | 172 -------- .../LightBulb/CtorParamsDlg.cs | 177 ++++---- .../LightBulb/CtorParamsDlg.xaml | 71 ++++ .../CompletionOptionsControl.Designer.cs | 370 ----------------- .../OptionsPages/CompletionOptionsControl.cs | 56 ++- .../CompletionOptionsControl.xaml | 116 ++++++ .../FormattingOptionsControl.Designer.cs | 236 ----------- .../OptionsPages/FormattingOptionsControl.cs | 90 ++--- .../FormattingOptionsControl.xaml | 51 +++ .../GeneratorOptionsControl.Designer.cs | 215 ---------- .../OptionsPages/GeneratorOptionsControl.cs | 67 +-- .../OptionsPages/GeneratorOptionsControl.xaml | 40 ++ .../IndentingOptionsControl.Designer.cs | 106 ----- .../OptionsPages/IndentingOptionsControl.cs | 227 +++++------ .../OptionsPages/IndentingOptionsControl.xaml | 43 ++ .../IntellisenseOptionsControl.Designer.cs | 246 ----------- .../IntellisenseOptionsControl.cs | 72 ++-- .../IntellisenseOptionsControl.xaml | 77 ++++ .../OtherOptionsControl.Designer.cs | 260 ------------ .../OptionsPages/OtherOptionsControl.cs | 33 +- .../OptionsPages/OtherOptionsControl.xaml | 93 +++++ .../OptionsPages/XSDialogPage.cs | 55 ++- .../OptionsPages/XSUserControl.cs | 99 ++--- .../XSharpSpecialOptions.Designer.cs | 381 ------------------ .../OptionsPages/XSharpSpecialOptions.cs | 102 ++--- .../OptionsPages/XSharpSpecialOptions.xaml | 61 +++ 29 files changed, 1045 insertions(+), 2681 deletions(-) delete mode 100644 src/VisualStudio/LanguageService/LightBulb/CtorParamsDlg.Designer.cs create mode 100644 src/VisualStudio/LanguageService/LightBulb/CtorParamsDlg.xaml delete mode 100644 src/VisualStudio/LanguageService/OptionsPages/CompletionOptionsControl.Designer.cs create mode 100644 src/VisualStudio/LanguageService/OptionsPages/CompletionOptionsControl.xaml delete mode 100644 src/VisualStudio/LanguageService/OptionsPages/FormattingOptionsControl.Designer.cs create mode 100644 src/VisualStudio/LanguageService/OptionsPages/FormattingOptionsControl.xaml delete mode 100644 src/VisualStudio/LanguageService/OptionsPages/GeneratorOptionsControl.Designer.cs create mode 100644 src/VisualStudio/LanguageService/OptionsPages/GeneratorOptionsControl.xaml delete mode 100644 src/VisualStudio/LanguageService/OptionsPages/IndentingOptionsControl.Designer.cs create mode 100644 src/VisualStudio/LanguageService/OptionsPages/IndentingOptionsControl.xaml delete mode 100644 src/VisualStudio/LanguageService/OptionsPages/IntellisenseOptionsControl.Designer.cs create mode 100644 src/VisualStudio/LanguageService/OptionsPages/IntellisenseOptionsControl.xaml delete mode 100644 src/VisualStudio/LanguageService/OptionsPages/OtherOptionsControl.Designer.cs create mode 100644 src/VisualStudio/LanguageService/OptionsPages/OtherOptionsControl.xaml delete mode 100644 src/VisualStudio/LanguageService/OptionsPages/XSharpSpecialOptions.Designer.cs create mode 100644 src/VisualStudio/LanguageService/OptionsPages/XSharpSpecialOptions.xaml diff --git a/src/VisualStudio/LanguageService/LanguageService.csproj b/src/VisualStudio/LanguageService/LanguageService.csproj index e59900deb4..410dc2e170 100644 --- a/src/VisualStudio/LanguageService/LanguageService.csproj +++ b/src/VisualStudio/LanguageService/LanguageService.csproj @@ -107,10 +107,7 @@ - Form - - - CtorParamsDlg.cs + CtorParamsDlg.xaml @@ -135,34 +132,22 @@ - UserControl - - - CompletionOptionsControl.cs + CompletionOptionsControl.xaml Component - UserControl - - - IndentingOptionsControl.cs + IndentingOptionsControl.xaml - UserControl - - - FormattingOptionsControl.cs + FormattingOptionsControl.xaml Component - UserControl - - - GeneratorOptionsControl.cs + GeneratorOptionsControl.xaml @@ -172,16 +157,10 @@ - UserControl - - - OtherOptionsControl.cs + OtherOptionsControl.xaml - UserControl - - - IntellisenseOptionsControl.cs + IntellisenseOptionsControl.xaml Component @@ -195,18 +174,11 @@ Component - - Component - + - Form - - - XSharpSpecialOptions.cs - - - UserControl + XSharpSpecialOptions.xaml + @@ -282,30 +254,6 @@ - - CtorParamsDlg.cs - - - CompletionOptionsControl.cs - - - IndentingOptionsControl.cs - - - FormattingOptionsControl.cs - - - GeneratorOptionsControl.cs - - - OtherOptionsControl.cs - - - IntellisenseOptionsControl.cs - - - XSharpSpecialOptions.cs - Designer @@ -349,6 +297,38 @@ MSBuild:Compile Designer + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + diff --git a/src/VisualStudio/LanguageService/LanguageService2022.csproj b/src/VisualStudio/LanguageService/LanguageService2022.csproj index 994f468ff2..f04ae1ebb0 100644 --- a/src/VisualStudio/LanguageService/LanguageService2022.csproj +++ b/src/VisualStudio/LanguageService/LanguageService2022.csproj @@ -109,10 +109,7 @@ - Form - - - CtorParamsDlg.cs + CtorParamsDlg.xaml @@ -136,34 +133,22 @@ - UserControl - - - CompletionOptionsControl.cs + CompletionOptionsControl.xaml Component - UserControl - - - IndentingOptionsControl.cs + IndentingOptionsControl.xaml - UserControl - - - FormattingOptionsControl.cs + FormattingOptionsControl.xaml Component - UserControl - - - GeneratorOptionsControl.cs + GeneratorOptionsControl.xaml @@ -173,16 +158,10 @@ - UserControl - - - OtherOptionsControl.cs + OtherOptionsControl.xaml - UserControl - - - IntellisenseOptionsControl.cs + IntellisenseOptionsControl.xaml Component @@ -196,18 +175,11 @@ Component - - Component - + - Form - - - XSharpSpecialOptions.cs - - - UserControl + XSharpSpecialOptions.xaml + @@ -299,30 +271,6 @@ - - CtorParamsDlg.cs - - - CompletionOptionsControl.cs - - - IndentingOptionsControl.cs - - - FormattingOptionsControl.cs - - - GeneratorOptionsControl.cs - - - OtherOptionsControl.cs - - - IntellisenseOptionsControl.cs - - - XSharpSpecialOptions.cs - Designer @@ -365,6 +313,38 @@ MSBuild:Compile Designer + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + diff --git a/src/VisualStudio/LanguageService/LightBulb/ConstructorAction.cs b/src/VisualStudio/LanguageService/LightBulb/ConstructorAction.cs index 73b32e9f12..bed88da6ec 100644 --- a/src/VisualStudio/LanguageService/LightBulb/ConstructorAction.cs +++ b/src/VisualStudio/LanguageService/LightBulb/ConstructorAction.cs @@ -169,7 +169,7 @@ private List CreateCtor(string prefix, int indentSize) { CtorParamsDlg dlg = new CtorParamsDlg(); dlg.FillMembers(_fieldsNProps); - if ( dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK ) + if ( dlg.ShowDialog() == true ) { insertText.Append(prefix); insertText.Append("PUBLIC "); diff --git a/src/VisualStudio/LanguageService/LightBulb/CtorParamsDlg.Designer.cs b/src/VisualStudio/LanguageService/LightBulb/CtorParamsDlg.Designer.cs deleted file mode 100644 index 4b4b831edf..0000000000 --- a/src/VisualStudio/LanguageService/LightBulb/CtorParamsDlg.Designer.cs +++ /dev/null @@ -1,172 +0,0 @@ - -namespace XSharp.LanguageService.Editors.LightBulb -{ - partial class CtorParamsDlg - { - /// - /// Required designer variable. - /// - private System.ComponentModel.IContainer components = null; - - /// - /// Clean up any resources being used. - /// - /// true if managed resources should be disposed; otherwise, false. - protected override void Dispose(bool disposing) - { - if (disposing && (components != null)) - { - components.Dispose(); - } - base.Dispose(disposing); - } - - #region Windows Form Designer generated code - - /// - /// Required method for Designer support - do not modify - /// the contents of this method with the code editor. - /// - private void InitializeComponent() - { - this.btnCancel = new System.Windows.Forms.Button(); - this.btnOk = new System.Windows.Forms.Button(); - this.groupBox1 = new System.Windows.Forms.GroupBox(); - this.btnDeselect = new System.Windows.Forms.Button(); - this.btnSelect = new System.Windows.Forms.Button(); - this.btnDown = new System.Windows.Forms.Button(); - this.btnUp = new System.Windows.Forms.Button(); - this.listMembers = new System.Windows.Forms.ListView(); - this.colMembers = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); - this.groupBox1.SuspendLayout(); - this.SuspendLayout(); - // - // btnCancel - // - this.btnCancel.Location = new System.Drawing.Point(452, 373); - this.btnCancel.Name = "btnCancel"; - this.btnCancel.Size = new System.Drawing.Size(75, 30); - this.btnCancel.TabIndex = 0; - this.btnCancel.Text = "Cancel"; - this.btnCancel.UseVisualStyleBackColor = true; - this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click); - // - // btnOk - // - this.btnOk.Location = new System.Drawing.Point(371, 373); - this.btnOk.Name = "btnOk"; - this.btnOk.Size = new System.Drawing.Size(75, 30); - this.btnOk.TabIndex = 1; - this.btnOk.Text = "OK"; - this.btnOk.UseVisualStyleBackColor = true; - this.btnOk.Click += new System.EventHandler(this.btnOk_Click); - // - // groupBox1 - // - this.groupBox1.Controls.Add(this.btnDeselect); - this.groupBox1.Controls.Add(this.btnSelect); - this.groupBox1.Controls.Add(this.btnDown); - this.groupBox1.Controls.Add(this.btnUp); - this.groupBox1.Controls.Add(this.listMembers); - this.groupBox1.Location = new System.Drawing.Point(12, 36); - this.groupBox1.Name = "groupBox1"; - this.groupBox1.Size = new System.Drawing.Size(515, 314); - this.groupBox1.TabIndex = 2; - this.groupBox1.TabStop = false; - this.groupBox1.Text = "Pick members to be used as constructor parameters"; - // - // btnDeselect - // - this.btnDeselect.Location = new System.Drawing.Point(404, 161); - this.btnDeselect.Name = "btnDeselect"; - this.btnDeselect.Size = new System.Drawing.Size(105, 30); - this.btnDeselect.TabIndex = 6; - this.btnDeselect.Text = "Deselect All"; - this.btnDeselect.UseVisualStyleBackColor = true; - this.btnDeselect.Click += new System.EventHandler(this.btnDeselect_Click); - // - // btnSelect - // - this.btnSelect.Location = new System.Drawing.Point(404, 125); - this.btnSelect.Name = "btnSelect"; - this.btnSelect.Size = new System.Drawing.Size(105, 30); - this.btnSelect.TabIndex = 5; - this.btnSelect.Text = "Select All"; - this.btnSelect.UseVisualStyleBackColor = true; - this.btnSelect.Click += new System.EventHandler(this.btnSelect_Click); - // - // btnDown - // - this.btnDown.Location = new System.Drawing.Point(404, 67); - this.btnDown.Name = "btnDown"; - this.btnDown.Size = new System.Drawing.Size(105, 30); - this.btnDown.TabIndex = 4; - this.btnDown.Text = "Down"; - this.btnDown.UseVisualStyleBackColor = true; - this.btnDown.Click += new System.EventHandler(this.btnDown_Click); - // - // btnUp - // - this.btnUp.Location = new System.Drawing.Point(404, 31); - this.btnUp.Name = "btnUp"; - this.btnUp.Size = new System.Drawing.Size(105, 30); - this.btnUp.TabIndex = 3; - this.btnUp.Text = "Up"; - this.btnUp.UseVisualStyleBackColor = true; - this.btnUp.Click += new System.EventHandler(this.btnUp_Click); - // - // listMembers - // - this.listMembers.Activation = System.Windows.Forms.ItemActivation.OneClick; - this.listMembers.CheckBoxes = true; - this.listMembers.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { - this.colMembers}); - this.listMembers.FullRowSelect = true; - this.listMembers.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.None; - this.listMembers.HideSelection = false; - this.listMembers.HotTracking = true; - this.listMembers.HoverSelection = true; - this.listMembers.Location = new System.Drawing.Point(19, 31); - this.listMembers.Name = "listMembers"; - this.listMembers.Size = new System.Drawing.Size(368, 265); - this.listMembers.TabIndex = 0; - this.listMembers.UseCompatibleStateImageBehavior = false; - this.listMembers.View = System.Windows.Forms.View.Details; - // - // colMembers - // - this.colMembers.Text = "Members"; - this.colMembers.Width = 329; - // - // CtorParamsDlg - // - this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(539, 415); - this.Controls.Add(this.groupBox1); - this.Controls.Add(this.btnOk); - this.Controls.Add(this.btnCancel); - this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; - this.MaximizeBox = false; - this.MinimizeBox = false; - this.Name = "CtorParamsDlg"; - this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; - this.Text = "Pick members"; - this.groupBox1.ResumeLayout(false); - this.ResumeLayout(false); - - } - - #endregion - - private System.Windows.Forms.Button btnCancel; - private System.Windows.Forms.Button btnOk; - private System.Windows.Forms.GroupBox groupBox1; - private System.Windows.Forms.ListView listMembers; - private System.Windows.Forms.Button btnDeselect; - private System.Windows.Forms.Button btnSelect; - private System.Windows.Forms.Button btnDown; - private System.Windows.Forms.Button btnUp; - private System.Windows.Forms.ColumnHeader colMembers; - } -} diff --git a/src/VisualStudio/LanguageService/LightBulb/CtorParamsDlg.cs b/src/VisualStudio/LanguageService/LightBulb/CtorParamsDlg.cs index e4daf6a07e..da897765dc 100644 --- a/src/VisualStudio/LanguageService/LightBulb/CtorParamsDlg.cs +++ b/src/VisualStudio/LanguageService/LightBulb/CtorParamsDlg.cs @@ -1,156 +1,129 @@ -using System; +// Copyright (c) XSharp B.V. All Rights Reserved. +// Licensed under the Apache License, Version 2.0. +// See License.txt in the project root for license information. +using Microsoft.VisualStudio.Imaging.Interop; using System.Collections.Generic; +using System.Collections.ObjectModel; using System.ComponentModel; -using System.Data; -using System.Drawing; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows.Forms; +using System.Runtime.CompilerServices; +using System.Windows; using XSharpModel; -using MVP = Microsoft.VisualStudio.Package; namespace XSharp.LanguageService.Editors.LightBulb { - public partial class CtorParamsDlg : Form + public partial class CtorParamsDlg : Window { - ImageList _imageList = new ImageList(); - List selectedFieldsNProps = new List(); - - public List FieldsNProps { get { return selectedFieldsNProps; } } + private readonly ObservableCollection _items = new ObservableCollection(); public CtorParamsDlg() { InitializeComponent(); - this.InitImageList(); - // - this.listMembers.ListViewItemSorter = new MemberTagValueComparer(); + _listView.ItemsSource = _items; } - private void InitImageList() + public List FieldsNProps { - Stream stream = typeof(MVP.LanguageService).Assembly.GetManifestResourceStream("Resources.completionset.bmp"); - _imageList.ImageSize = new Size(16, 16); - _imageList.TransparentColor = Color.FromArgb(255, 0, 255); - _imageList.Images.AddStrip(new Bitmap(stream)); - // - this.listMembers.SmallImageList = _imageList; + get + { + var result = new List(); + foreach (var item in _items) + { + if (item.IsChecked) + result.Add(item.Member); + } + return result; + } } - public void FillMembers(List fieldsNProps) + public void FillMembers(List fieldsNProps) { + _items.Clear(); int i = 0; foreach (var mbr in fieldsNProps) { - ListViewItem lvi = new ListViewItem(mbr.Name); - lvi.Checked = true; - lvi.Tag = ( i++, mbr ); - if (mbr is XSymbol xmbr) + _items.Add(new MemberItem { - lvi.ImageIndex = xmbr.Glyph; - } - this.listMembers.Items.Add(lvi); + Name = mbr.Name, + Member = mbr, + IsChecked = true, + Order = i++, + Moniker = mbr.Kind.GetImageMoniker(mbr.Visibility) + }); } } - private void btnSelect_Click(object sender, EventArgs e) + private void OnUp(object sender, RoutedEventArgs e) { - foreach (ListViewItem lvi in listMembers.Items) + int idx = _listView.SelectedIndex; + if (idx > 0) { - lvi.Checked = true; + _items.Move(idx, idx - 1); + _listView.SelectedIndex = idx - 1; } } - private void btnDeselect_Click(object sender, EventArgs e) + private void OnDown(object sender, RoutedEventArgs e) { - foreach (ListViewItem lvi in listMembers.Items) + int idx = _listView.SelectedIndex; + if (idx >= 0 && idx < _items.Count - 1) { - lvi.Checked = false; + _items.Move(idx, idx + 1); + _listView.SelectedIndex = idx + 1; } } - private void btnUp_Click(object sender, EventArgs e) + private void OnSelectAll(object sender, RoutedEventArgs e) { - if (listMembers.SelectedItems.Count > 0) - { - ListViewItem lvi = listMembers.SelectedItems[0]; - (int, IXMemberSymbol) t1 = ((int, IXMemberSymbol))lvi.Tag; - int tagValue = t1.Item1; - if ( tagValue > 0) - { - ListViewItem otherLvi = listMembers.Items[tagValue-1]; - (int, IXMemberSymbol) t2 = ((int, IXMemberSymbol))otherLvi.Tag; - t1.Item1 = t2.Item1; - t2.Item1 = tagValue; - // - lvi.Tag = t1; - otherLvi.Tag = t2; - // - listMembers.Sort(); - } - } + foreach (var item in _items) + item.IsChecked = true; } - private void btnDown_Click(object sender, EventArgs e) + private void OnDeselectAll(object sender, RoutedEventArgs e) { - if (listMembers.SelectedItems.Count > 0) + foreach (var item in _items) + item.IsChecked = false; + } + + private void OnOk(object sender, RoutedEventArgs e) + { + bool any = false; + foreach (var item in _items) { - ListViewItem lvi = listMembers.SelectedItems[0]; - (int, IXMemberSymbol) t1 = ((int, IXMemberSymbol))lvi.Tag; - int tagValue = t1.Item1; - if (tagValue < listMembers.Items.Count-1) - { - ListViewItem otherLvi = listMembers.Items[tagValue + 1]; - (int, IXMemberSymbol) t2 = ((int, IXMemberSymbol))otherLvi.Tag; - t1.Item1 = t2.Item1; - t2.Item1 = tagValue; - // - lvi.Tag = t1; - otherLvi.Tag = t2; - // - listMembers.Sort(); - } + if (item.IsChecked) { any = true; break; } } + DialogResult = any; } - private void btnCancel_Click(object sender, EventArgs e) + private void OnCancel(object sender, RoutedEventArgs e) { - this.DialogResult = DialogResult.Cancel; + DialogResult = false; } + } + + internal sealed class MemberItem : INotifyPropertyChanged + { + private bool _isChecked; - private void btnOk_Click(object sender, EventArgs e) + public bool IsChecked { - foreach( ListViewItem lvi in listMembers.Items ) + get => _isChecked; + set { - if ( lvi.Checked ) + if (_isChecked != value) { - (int, IXMemberSymbol) t1 = ((int, IXMemberSymbol))lvi.Tag; - this.selectedFieldsNProps.Add(t1.Item2); + _isChecked = value; + OnPropertyChanged(); } } - if ( this.selectedFieldsNProps.Count > 0 ) - { - this.DialogResult = DialogResult.OK; - } - else - { - this.DialogResult = DialogResult.Cancel; - } } - } - class MemberTagValueComparer : System.Collections.IComparer - { - public int Compare(object o1, object o2) - { - ListViewItem i1 = (ListViewItem)o1; - ListViewItem i2 = (ListViewItem)o2; - // - (int, IXMemberSymbol) t1 = ((int, IXMemberSymbol))i1.Tag; - (int, IXMemberSymbol) t2 = ((int, IXMemberSymbol))i2.Tag; - // - return t1.Item1.CompareTo(t2.Item1); - } + public string Name { get; set; } + public int Order { get; set; } + public IXMemberSymbol Member { get; set; } + public ImageMoniker Moniker { get; set; } + + public event PropertyChangedEventHandler PropertyChanged; + private void OnPropertyChanged([CallerMemberName] string name = null) + => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name)); } } diff --git a/src/VisualStudio/LanguageService/LightBulb/CtorParamsDlg.xaml b/src/VisualStudio/LanguageService/LightBulb/CtorParamsDlg.xaml new file mode 100644 index 0000000000..7e4e2c3ba8 --- /dev/null +++ b/src/VisualStudio/LanguageService/LightBulb/CtorParamsDlg.xaml @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +