diff --git a/Codist/Classifiers/HighlighterFormats.cs b/Codist/Classifiers/HighlighterFormats.cs index 1ff11fdb..f6e46ce8 100644 --- a/Codist/Classifiers/HighlighterFormats.cs +++ b/Codist/Classifiers/HighlighterFormats.cs @@ -14,7 +14,7 @@ namespace Codist.Classifiers sealed class Highlight1Format : ClassificationFormatDefinition { public Highlight1Format() { - BackgroundBrush = Brushes.Red.Alpha(0.5); + BackgroundBrush = Brushes.Salmon.Alpha(0.5); } } @@ -50,7 +50,7 @@ public Highlight3Format() { sealed class Highlight4Format : ClassificationFormatDefinition { public Highlight4Format() { - BackgroundBrush = Brushes.Green.Alpha(0.5); + BackgroundBrush = Brushes.LawnGreen.Alpha(0.5); } } @@ -74,7 +74,7 @@ public Highlight5Format() { sealed class Highlight6Format : ClassificationFormatDefinition { public Highlight6Format() { - BackgroundBrush = Brushes.Blue.Alpha(0.5); + BackgroundBrush = Brushes.SkyBlue.Alpha(0.5); } } @@ -98,7 +98,7 @@ public Highlight7Format() { sealed class Highlight8Format : ClassificationFormatDefinition { public Highlight8Format() { - BackgroundBrush = Brushes.Gray.Alpha(0.5); + BackgroundBrush = Brushes.DarkGray.Alpha(0.5); } } diff --git a/Codist/Classifiers/SymbolMarkManager.cs b/Codist/Classifiers/SymbolMarkManager.cs index 0d70def5..466dd17a 100644 --- a/Codist/Classifiers/SymbolMarkManager.cs +++ b/Codist/Classifiers/SymbolMarkManager.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System.Collections.Concurrent; +using System.Collections.Generic; using Microsoft.CodeAnalysis; using Microsoft.VisualStudio.Text.Classification; @@ -6,10 +7,10 @@ namespace Codist.Classifiers { static class SymbolMarkManager { - static readonly Dictionary _Bookmarks = new Dictionary(7, new SymbolComparer()); - static readonly object _SyncRoot = new object(); + static readonly ConcurrentDictionary _Bookmarks = new ConcurrentDictionary(new SymbolComparer()); internal static IEnumerable MarkedSymbols => _Bookmarks.Keys; + internal static bool HasMark => _Bookmarks.IsEmpty == false; internal static bool CanBookmark(ISymbol symbol) { symbol = symbol.GetAliasTarget(); @@ -20,31 +21,28 @@ internal static bool CanBookmark(ISymbol symbol) { case SymbolKind.Method: case SymbolKind.NamedType: case SymbolKind.Property: + case SymbolKind.Parameter: return true; } return false; } internal static IClassificationType GetSymbolMarkerStyle(ISymbol symbol) { - if (_Bookmarks.Count > 0 && _Bookmarks.TryGetValue(symbol, out var result)) { + if (_Bookmarks.IsEmpty == false && _Bookmarks.TryGetValue(symbol, out var result)) { return result; } return null; } internal static void Clear() { - lock (_SyncRoot) { - _Bookmarks.Clear(); - } + _Bookmarks.Clear(); + } + internal static bool Contains(ISymbol symbol) { + return _Bookmarks.ContainsKey(symbol); } internal static void Update(ISymbol symbol, IClassificationType classificationType) { - lock (_SyncRoot) { - _Bookmarks.Remove(symbol); - _Bookmarks.Add(symbol, classificationType); - } + _Bookmarks[symbol] = classificationType; } - internal static void Remove(ISymbol symbol) { - lock (_SyncRoot) { - _Bookmarks.Remove(symbol); - } + internal static bool Remove(ISymbol symbol) { + return _Bookmarks.TryRemove(symbol, out var dummy); } /// @@ -58,37 +56,44 @@ public bool Equals(ISymbol x, ISymbol y) { } if (x.Kind != y.Kind || x.DeclaredAccessibility != y.DeclaredAccessibility || x.Name != y.Name - || CompareNamedType(x.ContainingType, y.ContainingType) == false) { + || AreNamedTypesEqual(x.ContainingType, y.ContainingType) == false) { return false; } switch (x.Kind) { case SymbolKind.Field: - return CompareNamedType(((IFieldSymbol)x).Type as INamedTypeSymbol, ((IFieldSymbol)y).Type as INamedTypeSymbol); + return AreNamedTypesEqual(((IFieldSymbol)x).Type as INamedTypeSymbol, ((IFieldSymbol)y).Type as INamedTypeSymbol); case SymbolKind.Property: - return CompareNamedType(((IPropertySymbol)x).Type as INamedTypeSymbol, ((IPropertySymbol)y).Type as INamedTypeSymbol); + return AreNamedTypesEqual(((IPropertySymbol)x).Type as INamedTypeSymbol, ((IPropertySymbol)y).Type as INamedTypeSymbol); case SymbolKind.Local: - return CompareNamedType(((ILocalSymbol)x).Type as INamedTypeSymbol, ((ILocalSymbol)y).Type as INamedTypeSymbol); + return AreNamedTypesEqual(((ILocalSymbol)x).Type as INamedTypeSymbol, ((ILocalSymbol)y).Type as INamedTypeSymbol); + case SymbolKind.Parameter: + return AreMethodsEqual(((IParameterSymbol)x).ContainingSymbol as IMethodSymbol, ((IParameterSymbol)y).ContainingSymbol as IMethodSymbol); case SymbolKind.Method: var mx = (IMethodSymbol)x; var my = (IMethodSymbol)y; - if (CompareNamedType(mx.ReturnType as INamedTypeSymbol, my.ReturnType as INamedTypeSymbol) == false) { - return false; - } - var px = mx.Parameters; - var py = my.Parameters; - if (px.Length != py.Length) { - return false; - } - for (int i = px.Length - 1; i >= 0; i--) { - if (CompareType(px[i].Type, py[i].Type) == false) { - return false; - } - } - return true; + return AreMethodsEqual(mx, my); } return true; } - static bool CompareType(ITypeSymbol x, ITypeSymbol y) { + + static bool AreMethodsEqual(IMethodSymbol mx, IMethodSymbol my) { + if (AreNamedTypesEqual(mx.ReturnType as INamedTypeSymbol, my.ReturnType as INamedTypeSymbol) == false) { + return false; + } + var px = mx.Parameters; + var py = my.Parameters; + if (px.Length != py.Length) { + return false; + } + for (int i = px.Length - 1; i >= 0; i--) { + if (AreTypesEqual(px[i].Type, py[i].Type) == false) { + return false; + } + } + return true; + } + + static bool AreTypesEqual(ITypeSymbol x, ITypeSymbol y) { if (x == null || y == null) { return x == y; } @@ -98,7 +103,7 @@ static bool CompareType(ITypeSymbol x, ITypeSymbol y) { } return true; } - static bool CompareNamedType(INamedTypeSymbol x, INamedTypeSymbol y) { + static bool AreNamedTypesEqual(INamedTypeSymbol x, INamedTypeSymbol y) { if (x == null || y == null) { return x == y; } diff --git a/Codist/SmartBars/CSharpSmartBar.cs b/Codist/SmartBars/CSharpSmartBar.cs index 6f12ef21..c54b0518 100644 --- a/Codist/SmartBars/CSharpSmartBar.cs +++ b/Codist/SmartBars/CSharpSmartBar.cs @@ -228,18 +228,36 @@ void AddXmlDocCommands() { }); } - CommandItem[] GetMarkerCommands(CommandContext arg) { - return new CommandItem[] { - new CommandItem("Mark symbol " + _Symbol.Name, KnownImageIds.Flag, AddHighlightMenuItems, null), - CreateCommandMenu("Remove symbol mark...", KnownImageIds.FlagOutline, null, "No symbol marked", (m, s) => { + List GetMarkerCommands(CommandContext arg) { + var r = new List(3); + var symbol = _Symbol; + if (symbol.Kind == SymbolKind.Method) { + var ctor = symbol as IMethodSymbol; + if (ctor != null && ctor.MethodKind == MethodKind.Constructor) { + symbol = ctor.ContainingType; + } + } + r.Add(new CommandItem("Mark symbol " + symbol.Name, KnownImageIds.Flag, AddHighlightMenuItems, null)); + if (Classifiers.SymbolMarkManager.Contains(symbol)) { + r.Add(new CommandItem("Remove symbol mark for " + symbol.Name, KnownImageIds.FlagOutline, null, ctx => { + UpdateSemanticModel(); + if (_Symbol != null && Classifiers.SymbolMarkManager.Remove(_Symbol)) { + Config.Instance.FireConfigChangedEvent(Features.SyntaxHighlight); + return; + } + })); + } + else if (Classifiers.SymbolMarkManager.HasMark) { + r.Add(CreateCommandMenu("Remove symbol mark...", KnownImageIds.FlagOutline, symbol, "No symbol marked", (m, s) => { foreach (var item in Classifiers.SymbolMarkManager.MarkedSymbols) { m.Items.Add(new CommandMenuItem(this, new CommandItem(item.ToDisplayString(__MemberNameFormat), item.GetImageId(), null, ctx => { Classifiers.SymbolMarkManager.Remove(item); Config.Instance.FireConfigChangedEvent(Features.SyntaxHighlight); }))); } - }) - }; + })); + } + return r; } void AddHighlightMenuItems(MenuItem menuItem) { @@ -250,12 +268,20 @@ void AddHighlightMenuItems(MenuItem menuItem) { menuItem.Items.Add(new CommandMenuItem(this, new CommandItem("Highlight 5", KnownImageIds.Flag, item => item.Tag = __HighlightClassifications.Highlight5, SetSymbolMark))); menuItem.Items.Add(new CommandMenuItem(this, new CommandItem("Highlight 6", KnownImageIds.Flag, item => item.Tag = __HighlightClassifications.Highlight6, SetSymbolMark))); menuItem.Items.Add(new CommandMenuItem(this, new CommandItem("Highlight 7", KnownImageIds.Flag, item => item.Tag = __HighlightClassifications.Highlight7, SetSymbolMark))); + menuItem.Items.Add(new CommandMenuItem(this, new CommandItem("Highlight 8", KnownImageIds.Flag, item => item.Tag = __HighlightClassifications.Highlight8, SetSymbolMark))); + menuItem.Items.Add(new CommandMenuItem(this, new CommandItem("Highlight 9", KnownImageIds.Flag, item => item.Tag = __HighlightClassifications.Highlight9, SetSymbolMark))); } void SetSymbolMark(CommandContext context) { if (_Symbol == null) { return; } + if (_Symbol.Kind == SymbolKind.Method) { + var ctor = _Symbol as IMethodSymbol; + if (ctor != null && ctor.MethodKind == MethodKind.Constructor) { + _Symbol = ctor.ContainingType; + } + } Classifiers.SymbolMarkManager.Update(_Symbol, context.Sender.Tag as Microsoft.VisualStudio.Text.Classification.IClassificationType); Config.Instance.FireConfigChangedEvent(Features.SyntaxHighlight); }