From 840b156704437808c7d1854f39f75292994a6d1f Mon Sep 17 00:00:00 2001 From: CyrusNajmabadi Date: Sun, 24 Jul 2016 15:10:57 -0700 Subject: [PATCH] Initial work to move the existing FAR presented over to using hte new object model. --- .../CSharpFindReferencesService.cs | 2 +- .../Core/Host/IReferencedSymbolsPresenter.cs | 7 +- .../AbstractFindReferencesService.cs | 12 +- .../FindReferencesCommandHandler.cs | 7 +- .../FindReferences/FindReferencesItems.cs | 3 + .../IDefinitionsAndReferencesFactory.cs | 9 + .../FindReferencesCommandHandlerTests.cs | 16 +- .../MockReferencedSymbolsPresenter.cs | 13 +- .../VisualBasicFindReferencesService.vb | 2 +- .../ReferencedSymbolsPresenter.cs | 35 +-- .../Library/FindResults/LibraryManager.cs | 5 + .../LibraryManager_FindReferences.cs | 209 +++++++----------- .../ExternalLanguageDefinitionTreeItem.cs | 2 + .../TreeItems/MetadataDefinitionTreeItem.cs | 72 ------ .../TreeItems/SourceDefinitionTreeItem.cs | 95 +++++++- .../TreeItems/SourceReferenceTreeItem.cs | 15 +- src/VisualStudio/Core/Def/RoslynPackage.cs | 2 +- .../Core/Def/ServicesVisualStudio.csproj | 1 - .../Core/Impl/RoslynVisualStudioWorkspace.cs | 14 +- 19 files changed, 239 insertions(+), 282 deletions(-) delete mode 100644 src/VisualStudio/Core/Def/Implementation/Library/FindResults/TreeItems/MetadataDefinitionTreeItem.cs diff --git a/src/EditorFeatures/CSharp/FindReferences/CSharpFindReferencesService.cs b/src/EditorFeatures/CSharp/FindReferences/CSharpFindReferencesService.cs index 01abefa35cc..9bd62d5460e 100644 --- a/src/EditorFeatures/CSharp/FindReferences/CSharpFindReferencesService.cs +++ b/src/EditorFeatures/CSharp/FindReferences/CSharpFindReferencesService.cs @@ -13,7 +13,7 @@ internal class CSharpFindReferencesService : AbstractFindReferencesService { [ImportingConstructor] public CSharpFindReferencesService( - [ImportMany] IEnumerable referencedSymbolsPresenters, + [ImportMany] IEnumerable referencedSymbolsPresenters, [ImportMany] IEnumerable navigableItemsPresenters, [ImportMany] IEnumerable externalReferencesProviders) : base(referencedSymbolsPresenters, navigableItemsPresenters, externalReferencesProviders) diff --git a/src/EditorFeatures/Core/Host/IReferencedSymbolsPresenter.cs b/src/EditorFeatures/Core/Host/IReferencedSymbolsPresenter.cs index fe2227a0a73..63e504b1e61 100644 --- a/src/EditorFeatures/Core/Host/IReferencedSymbolsPresenter.cs +++ b/src/EditorFeatures/Core/Host/IReferencedSymbolsPresenter.cs @@ -1,12 +1,13 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Collections.Generic; +using Microsoft.CodeAnalysis.Editor.Implementation.FindReferences; using Microsoft.CodeAnalysis.FindSymbols; namespace Microsoft.CodeAnalysis.Editor.Host { - internal interface IReferencedSymbolsPresenter + internal interface IFindReferencesPresenter { - void DisplayResult(Solution solution, IEnumerable result); + void DisplayResult(DefinitionsAndReferences definitionsAndReferences); } -} +} \ No newline at end of file diff --git a/src/EditorFeatures/Core/Implementation/FindReferences/AbstractFindReferencesService.cs b/src/EditorFeatures/Core/Implementation/FindReferences/AbstractFindReferencesService.cs index 4677456c5f9..6bce5e278bd 100644 --- a/src/EditorFeatures/Core/Implementation/FindReferences/AbstractFindReferencesService.cs +++ b/src/EditorFeatures/Core/Implementation/FindReferences/AbstractFindReferencesService.cs @@ -16,12 +16,12 @@ namespace Microsoft.CodeAnalysis.Editor.Implementation.FindReferences { internal abstract partial class AbstractFindReferencesService : IFindReferencesService { - private readonly IEnumerable _referenceSymbolPresenters; + private readonly IEnumerable _referenceSymbolPresenters; private readonly IEnumerable _navigableItemPresenters; private readonly IEnumerable _externalReferencesProviders; protected AbstractFindReferencesService( - IEnumerable referenceSymbolPresenters, + IEnumerable referenceSymbolPresenters, IEnumerable navigableItemPresenters, IEnumerable externalReferencesProviders) { @@ -156,10 +156,14 @@ private bool TryDisplayReferences(Tuple, Solution> { if (result != null && result.Item1 != null) { - var searchSolution = result.Item2; + var solution = result.Item2; + var factory = solution.Workspace.Services.GetService(); + var definitionsAndReferences = factory.CreateDefinitionsAndReferences( + solution, result.Item1); + foreach (var presenter in _referenceSymbolPresenters) { - presenter.DisplayResult(searchSolution, result.Item1); + presenter.DisplayResult(definitionsAndReferences); return true; } } diff --git a/src/EditorFeatures/Core/Implementation/FindReferences/FindReferencesCommandHandler.cs b/src/EditorFeatures/Core/Implementation/FindReferences/FindReferencesCommandHandler.cs index 37b86c538da..f4220b6dc06 100644 --- a/src/EditorFeatures/Core/Implementation/FindReferences/FindReferencesCommandHandler.cs +++ b/src/EditorFeatures/Core/Implementation/FindReferences/FindReferencesCommandHandler.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; +using System.Collections.Immutable; using System.ComponentModel.Composition; using Microsoft.CodeAnalysis.Editor.Commands; using Microsoft.CodeAnalysis.Editor.Host; @@ -19,13 +20,13 @@ namespace Microsoft.CodeAnalysis.Editor.Implementation.FindReferences internal class FindReferencesCommandHandler : ICommandHandler { - private readonly IEnumerable _presenters; + private readonly IEnumerable _presenters; private readonly IWaitIndicator _waitIndicator; [ImportingConstructor] internal FindReferencesCommandHandler( IWaitIndicator waitIndicator, - [ImportMany] IEnumerable presenters) + [ImportMany] IEnumerable presenters) { Contract.ThrowIfNull(waitIndicator); Contract.ThrowIfNull(presenters); @@ -53,7 +54,7 @@ internal void FindReferences(ITextSnapshot snapshot, int caretPosition) { foreach (var presenter in _presenters) { - presenter.DisplayResult(document.Project.Solution, SpecializedCollections.EmptyEnumerable()); + presenter.DisplayResult(DefinitionsAndReferences.Empty); return; } } diff --git a/src/EditorFeatures/Core/Implementation/FindReferences/FindReferencesItems.cs b/src/EditorFeatures/Core/Implementation/FindReferences/FindReferencesItems.cs index ee86e41ce4a..d652e2cc591 100644 --- a/src/EditorFeatures/Core/Implementation/FindReferences/FindReferencesItems.cs +++ b/src/EditorFeatures/Core/Implementation/FindReferences/FindReferencesItems.cs @@ -242,6 +242,9 @@ public int CompareTo(SourceReferenceItem other) internal struct DefinitionsAndReferences { + public static readonly DefinitionsAndReferences Empty = + new DefinitionsAndReferences(ImmutableArray.Empty, ImmutableArray.Empty); + /// /// All the definitions to show. Note: not all definitions may have references. /// diff --git a/src/EditorFeatures/Core/Implementation/FindReferences/IDefinitionsAndReferencesFactory.cs b/src/EditorFeatures/Core/Implementation/FindReferences/IDefinitionsAndReferencesFactory.cs index 44dd01866d5..8471e0a0d7c 100644 --- a/src/EditorFeatures/Core/Implementation/FindReferences/IDefinitionsAndReferencesFactory.cs +++ b/src/EditorFeatures/Core/Implementation/FindReferences/IDefinitionsAndReferencesFactory.cs @@ -36,6 +36,15 @@ internal class DefaultDefinitionsAndReferencesFactory : IDefinitionsAndReference return new DefinitionsAndReferences(definitions.ToImmutable(), references.ToImmutable()); } + /// + /// Reference locations are deduplicated across the entire find references result set + /// Order the definitions so that references to multiple definitions appear under the + /// desired definition (e.g. constructor references should prefer the constructor method + /// over the type definition). Note that this does not change the order in which + /// definitions are displayed in Find Symbol Results, it only changes which definition + /// a given reference should appear under when its location is a reference to multiple + /// definitions. + /// private static int GetPrecedence(ReferencedSymbol referencedSymbol) { switch (referencedSymbol.Definition.Kind) diff --git a/src/EditorFeatures/Test/FindReferences/FindReferencesCommandHandlerTests.cs b/src/EditorFeatures/Test/FindReferences/FindReferencesCommandHandlerTests.cs index 7878e3ae28c..c1c00acd53a 100644 --- a/src/EditorFeatures/Test/FindReferences/FindReferencesCommandHandlerTests.cs +++ b/src/EditorFeatures/Test/FindReferences/FindReferencesCommandHandlerTests.cs @@ -1,17 +1,12 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.CodeAnalysis.Editor.Commands; using Microsoft.CodeAnalysis.Editor.Implementation.FindReferences; -using Microsoft.CodeAnalysis.Editor.Navigation; using Microsoft.CodeAnalysis.Editor.UnitTests.Utilities; using Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces; -using Microsoft.CodeAnalysis.FindSymbols; -using Microsoft.VisualStudio.Language.Intellisense; using Microsoft.VisualStudio.Text; -using Moq; using Roslyn.Test.Utilities; using Roslyn.Utilities; using Xunit; @@ -37,13 +32,16 @@ public async Task TestFindReferencesSynchronousCall() textView, textView.TextBuffer), () => { }); - AssertResult(findReferencesPresenter.Result, "C", ".ctor"); + AssertResult(findReferencesPresenter.DefinitionsAndReferences, "C", ".ctor"); } } - private bool AssertResult(IEnumerable result, params string[] definitions) + private bool AssertResult( + DefinitionsAndReferences definitionsAndReferences, + params string[] definitions) { - return result.Select(r => r.Definition.Name).SetEquals(definitions); + return definitionsAndReferences.Definitions.Select(r => r.DisplayParts.JoinText()) + .SetEquals(definitions); } } -} +} \ No newline at end of file diff --git a/src/EditorFeatures/Test/FindReferences/MockReferencedSymbolsPresenter.cs b/src/EditorFeatures/Test/FindReferences/MockReferencedSymbolsPresenter.cs index 782f677af26..8922685a22a 100644 --- a/src/EditorFeatures/Test/FindReferences/MockReferencedSymbolsPresenter.cs +++ b/src/EditorFeatures/Test/FindReferences/MockReferencedSymbolsPresenter.cs @@ -3,19 +3,18 @@ using System; using System.Collections.Generic; using Microsoft.CodeAnalysis.Editor.Host; +using Microsoft.CodeAnalysis.Editor.Implementation.FindReferences; using Microsoft.CodeAnalysis.FindSymbols; namespace Microsoft.CodeAnalysis.Editor.UnitTests.FindReferences { - internal class MockReferencedSymbolsPresenter : IReferencedSymbolsPresenter + internal class MockReferencedSymbolsPresenter : IFindReferencesPresenter { - public Solution Solution { get; private set; } - public IEnumerable Result { get; private set; } + public DefinitionsAndReferences DefinitionsAndReferences; - public void DisplayResult(Solution solution, IEnumerable result) + public void DisplayResult(DefinitionsAndReferences definitionsAndReferences) { - this.Solution = solution; - this.Result = result; + DefinitionsAndReferences = definitionsAndReferences; } } -} +} \ No newline at end of file diff --git a/src/EditorFeatures/VisualBasic/FindReferences/VisualBasicFindReferencesService.vb b/src/EditorFeatures/VisualBasic/FindReferences/VisualBasicFindReferencesService.vb index 5a3bff46515..7ad543b6fab 100644 --- a/src/EditorFeatures/VisualBasic/FindReferences/VisualBasicFindReferencesService.vb +++ b/src/EditorFeatures/VisualBasic/FindReferences/VisualBasicFindReferencesService.vb @@ -11,7 +11,7 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.FindReferences Inherits AbstractFindReferencesService - Protected Sub New( referencedSymbolsPresenters As IEnumerable(Of IReferencedSymbolsPresenter), + Protected Sub New( referencedSymbolsPresenters As IEnumerable(Of IFindReferencesPresenter), navigableItemsPresenters As IEnumerable(Of INavigableItemsPresenter), externalReferencesProviders As IEnumerable(Of IFindReferencesResultProvider)) MyBase.New(referencedSymbolsPresenters, navigableItemsPresenters, externalReferencesProviders) diff --git a/src/VisualStudio/Core/Def/Implementation/FindReferences/ReferencedSymbolsPresenter.cs b/src/VisualStudio/Core/Def/Implementation/FindReferences/ReferencedSymbolsPresenter.cs index 61cca0d83a8..532b1967768 100644 --- a/src/VisualStudio/Core/Def/Implementation/FindReferences/ReferencedSymbolsPresenter.cs +++ b/src/VisualStudio/Core/Def/Implementation/FindReferences/ReferencedSymbolsPresenter.cs @@ -1,27 +1,23 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; -using System.Collections.Generic; using System.ComponentModel.Composition; -using System.Linq; -using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Editor.Host; +using Microsoft.CodeAnalysis.Editor.Implementation.FindReferences; using Microsoft.CodeAnalysis.Editor.Shared.Utilities; -using Microsoft.CodeAnalysis.FindSymbols; -using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.VisualStudio.LanguageServices.Implementation.Library.FindResults; using Microsoft.VisualStudio.Shell; namespace Microsoft.VisualStudio.LanguageServices.Implementation.FindReferences { - [Export(typeof(IReferencedSymbolsPresenter))] - internal sealed class ReferencedSymbolsPresenter : ForegroundThreadAffinitizedObject, IReferencedSymbolsPresenter + [Export(typeof(IFindReferencesPresenter))] + internal sealed class FindReferencesPresenter : ForegroundThreadAffinitizedObject, IFindReferencesPresenter { private readonly IServiceProvider _serviceProvider; private readonly LibraryManager _manager; [ImportingConstructor] - private ReferencedSymbolsPresenter(SVsServiceProvider serviceProvider) : + private FindReferencesPresenter(SVsServiceProvider serviceProvider) : base(assertIsForeground: true) { _serviceProvider = serviceProvider; @@ -30,26 +26,9 @@ internal sealed class ReferencedSymbolsPresenter : ForegroundThreadAffinitizedOb _manager = (LibraryManager)serviceProvider.GetService(typeof(LibraryManager)); } - public void DisplayResult(Solution solution, IEnumerable symbols) + public void DisplayResult(DefinitionsAndReferences definitionsAndReferences) { - var firstResult = symbols.FirstOrDefault(); - string title; - if (firstResult != null) - { - title = firstResult.Definition.Name; - if (title == string.Empty) - { - // Anonymous types have no name. - title = firstResult.Definition.ToDisplayString(); - } - } - else - { - // PresentFindReferencesResult ignores the title for an empty result, but "VS library" system throws if it is an empty string. - title = "None"; - } - - _manager.PresentReferencedSymbols(title, solution, symbols); + _manager.PresentDefinitionsAndReferences(definitionsAndReferences); } } -} +} \ No newline at end of file diff --git a/src/VisualStudio/Core/Def/Implementation/Library/FindResults/LibraryManager.cs b/src/VisualStudio/Core/Def/Implementation/Library/FindResults/LibraryManager.cs index bbe50b97dcc..b60d5848cff 100644 --- a/src/VisualStudio/Core/Def/Implementation/Library/FindResults/LibraryManager.cs +++ b/src/VisualStudio/Core/Def/Implementation/Library/FindResults/LibraryManager.cs @@ -66,6 +66,11 @@ protected override uint GetUpdateCounter() private void PresentObjectList(string title, ObjectList objectList) { + if (string.IsNullOrWhiteSpace(title)) + { + title = "None"; + } + var navInfo = new NavInfo(objectList); var findSymbol = (IVsFindSymbol)this.ServiceProvider.GetService(typeof(SVsObjectSearch)); var searchCriteria = new VSOBSEARCHCRITERIA2() diff --git a/src/VisualStudio/Core/Def/Implementation/Library/FindResults/LibraryManager_FindReferences.cs b/src/VisualStudio/Core/Def/Implementation/Library/FindResults/LibraryManager_FindReferences.cs index c1843256606..bb97edcb857 100644 --- a/src/VisualStudio/Core/Def/Implementation/Library/FindResults/LibraryManager_FindReferences.cs +++ b/src/VisualStudio/Core/Def/Implementation/Library/FindResults/LibraryManager_FindReferences.cs @@ -2,8 +2,10 @@ using System; using System.Collections.Generic; +using System.Collections.Immutable; using System.Linq; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Editor.Implementation.FindReferences; using Microsoft.CodeAnalysis.FindSymbols; using Microsoft.CodeAnalysis.Navigation; using Microsoft.CodeAnalysis.Shared.Extensions; @@ -15,158 +17,109 @@ namespace Microsoft.VisualStudio.LanguageServices.Implementation.Library.FindRes { internal partial class LibraryManager { - public void PresentReferencedSymbols(string title, Solution solution, IEnumerable items) + public void PresentDefinitionsAndReferences(DefinitionsAndReferences definitionsAndReferences) { - PresentObjectList(title, new ObjectList(CreateFindReferencesItems(solution, items), this)); + var firstDefinition = definitionsAndReferences.Definitions.FirstOrDefault(); + var title = firstDefinition?.DisplayParts.JoinText(); + + PresentObjectList(title, new ObjectList(CreateFindReferencesItems(definitionsAndReferences), this)); } // internal for test purposes - internal IList CreateFindReferencesItems(Solution solution, IEnumerable referencedSymbols) + internal IList CreateFindReferencesItems( + DefinitionsAndReferences definitionsAndReferences) { - var definitions = new List(); - var uniqueLocations = new HashSet>(); - var symbolNavigationService = solution.Workspace.Services.GetService(); - - referencedSymbols = referencedSymbols.FilterToItemsToShow().ToList(); - - foreach (var referencedSymbol in referencedSymbols.OrderBy(GetDefinitionPrecedence)) - { - var definition = referencedSymbol.Definition; - var locations = definition.Locations; - - // When finding references of a namespace, the data provided by the ReferenceFinder - // will include one definition location for each of its exact namespace - // declarations and each declaration of its children namespaces that mention - // its name (e.g. definitions of A.B will include "namespace A.B.C"). The list of - // reference locations includes both these namespace declarations and their - // references in usings or fully qualified names. Instead of showing many top-level - // declaration nodes (one of which will contain the full list of references - // including declarations, the rest of which will say "0 references" due to - // reference deduplication and there being no meaningful way to partition them), - // we pick a single declaration to use as the top-level definition and nest all of - // the declarations & references underneath. - var definitionLocations = definition.IsKind(SymbolKind.Namespace) - ? SpecializedCollections.SingletonEnumerable(definition.Locations.First()) - : definition.Locations; - - foreach (var definitionLocation in definitionLocations) - { - var definitionItem = ConvertToDefinitionItem(solution, referencedSymbol, definitionLocation, definition.GetGlyph()); - if (definitionItem != null) - { - definitions.Add(definitionItem); - - var referenceItems = CreateReferenceItems(solution, uniqueLocations, referencedSymbol.Locations.Select(loc => loc.Location)); - definitionItem.Children.AddRange(referenceItems); - definitionItem.SetReferenceCount(referenceItems.Count); - } - } - - // Add on any definition locations from third party language services - string filePath; - int lineNumber, charOffset; - if (symbolNavigationService.WouldNavigateToSymbol(definition, solution, out filePath, out lineNumber, out charOffset)) - { - definitions.Add(new ExternalLanguageDefinitionTreeItem(filePath, lineNumber, charOffset, definition.Name, definition.GetGlyph().GetGlyphIndex(), this.ServiceProvider)); - } - } - - return definitions; + var definitionItems = definitionsAndReferences.Definitions; + return definitionItems.SelectMany(d => CreateDefinitionItems(d, definitionsAndReferences)) + .ToList(); } - /// - /// Reference locations are deduplicated across the entire find references result set - /// Order the definitions so that references to multiple definitions appear under the - /// desired definition (e.g. constructor references should prefer the constructor method - /// over the type definition). Note that this does not change the order in which - /// definitions are displayed in Find Symbol Results, it only changes which definition - /// a given reference should appear under when its location is a reference to multiple - /// definitions. - /// - private int GetDefinitionPrecedence(ReferencedSymbol referencedSymbol) + private IEnumerable CreateDefinitionItems( + DefinitionItem definitionItem, + DefinitionsAndReferences definitionsAndReferences) { - switch (referencedSymbol.Definition.Kind) + // Each definition item may end up as several top nodes (because of partials). + // Add the references to the last item actually in the list. + var definitionTreeItems = ConvertToDefinitionTreeItems(definitionItem); + if (!definitionTreeItems.IsEmpty) { - case SymbolKind.Event: - case SymbolKind.Field: - case SymbolKind.Label: - case SymbolKind.Local: - case SymbolKind.Method: - case SymbolKind.Parameter: - case SymbolKind.Property: - case SymbolKind.RangeVariable: - return 0; - - case SymbolKind.ArrayType: - case SymbolKind.DynamicType: - case SymbolKind.ErrorType: - case SymbolKind.NamedType: - case SymbolKind.PointerType: - return 1; - - default: - return 2; + var lastTreeItem = definitionTreeItems.Last(); + var referenceItems = CreateReferenceItems(definitionItem, definitionsAndReferences); + + lastTreeItem.Children.AddRange(referenceItems); + lastTreeItem.SetReferenceCount(referenceItems.Count); } + + return definitionTreeItems; + + // // Add on any definition locations from third party language services + // string filePath; + // int lineNumber, charOffset; + // if (symbolNavigationService.WouldNavigateToSymbol(definition, solution, out filePath, out lineNumber, out charOffset)) + // { + // definitions.Add(new ExternalLanguageDefinitionTreeItem(filePath, lineNumber, charOffset, definition.Name, definition.GetGlyph().GetGlyphIndex(), this.ServiceProvider)); + // } + //} + + //return definitions; } - private AbstractTreeItem ConvertToDefinitionItem( - Solution solution, - ReferencedSymbol referencedSymbol, - Location location, - Glyph glyph) + private ImmutableArray ConvertToDefinitionTreeItems( + DefinitionItem definitionItem) { - if (!location.IsInSource) - { - return referencedSymbol.Locations.Any() - ? new MetadataDefinitionTreeItem( - solution.Workspace, - referencedSymbol.Definition, - referencedSymbol.Locations.First().Document.Project.Id, - glyph.GetGlyphIndex()) - : null; - } + var result = ImmutableArray.CreateBuilder(); - var document = solution.GetDocument(location.SourceTree); - var sourceSpan = location.SourceSpan; - if (!IsValidSourceLocation(document, sourceSpan)) + foreach (var location in definitionItem.Locations) { - return null; + result.Add(new DefinitionTreeItem(definitionItem, location)); } - return new SourceDefinitionTreeItem(document, sourceSpan, referencedSymbol.Definition, glyph.GetGlyphIndex()); + return result.ToImmutable(); + //if (!location.IsInSource) + //{ + // return referencedSymbol.Locations.Any() + // ? new MetadataDefinitionTreeItem( + // solution.Workspace, + // referencedSymbol.Definition, + // referencedSymbol.Locations.First().Document.Project.Id, + // glyph.GetGlyphIndex()) + // : null; + //} + + //var document = solution.GetDocument(location.SourceTree); + //var sourceSpan = location.SourceSpan; + //if (!IsValidSourceLocation(document, sourceSpan)) + //{ + // return null; + //} + + //return new SourceDefinitionTreeItem(document, sourceSpan, referencedSymbol.Definition, glyph.GetGlyphIndex()); } - private IList CreateReferenceItems(Solution solution, HashSet> uniqueLocations, IEnumerable locations) + private IList CreateReferenceItems( + DefinitionItem definitionItem, + DefinitionsAndReferences definitionsAndReferences) { - var referenceItems = new List(); - foreach (var location in locations) - { - if (!location.IsInSource) - { - continue; - } - - var document = solution.GetDocument(location.SourceTree); - var sourceSpan = location.SourceSpan; - if (!IsValidSourceLocation(document, sourceSpan)) - { - continue; - } - - if (uniqueLocations.Add(new ValueTuple(document, sourceSpan))) - { - referenceItems.Add(new SourceReferenceTreeItem(document, sourceSpan, Glyph.Reference.GetGlyphIndex())); - } - } + var result = new List(); - var linkedReferences = referenceItems.GroupBy(r => r.DisplayText.ToLowerInvariant()).Where(g => g.Count() > 1).SelectMany(g => g); - foreach (var linkedReference in linkedReferences) + var referenceItems = definitionsAndReferences.References.Where(r => r.Definition == definitionItem); + foreach (var referenceItem in referenceItems) { - linkedReference.AddProjectNameDisambiguator(); + var documentLocation = referenceItem.Location; + result.Add(new SourceReferenceTreeItem( + documentLocation.Document, + documentLocation.SourceSpan, + Glyph.Reference.GetGlyphIndex())); } - referenceItems.Sort(); - return referenceItems; + //var linkedReferences = referenceItems.GroupBy(r => r.DisplayText.ToLowerInvariant()).Where(g => g.Count() > 1).SelectMany(g => g); + //foreach (var linkedReference in linkedReferences) + //{ + // linkedReference.AddProjectNameDisambiguator(); + //} + + result.Sort(); + return result; } } } diff --git a/src/VisualStudio/Core/Def/Implementation/Library/FindResults/TreeItems/ExternalLanguageDefinitionTreeItem.cs b/src/VisualStudio/Core/Def/Implementation/Library/FindResults/TreeItems/ExternalLanguageDefinitionTreeItem.cs index 18b8f575aa2..27f16bbb7bc 100644 --- a/src/VisualStudio/Core/Def/Implementation/Library/FindResults/TreeItems/ExternalLanguageDefinitionTreeItem.cs +++ b/src/VisualStudio/Core/Def/Implementation/Library/FindResults/TreeItems/ExternalLanguageDefinitionTreeItem.cs @@ -1,5 +1,6 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#if false using System; using System.Runtime.InteropServices; using Microsoft.VisualStudio.LanguageServices.Implementation.ProjectSystem; @@ -125,3 +126,4 @@ private bool TryNavigateToPosition() } } } +#endif \ No newline at end of file diff --git a/src/VisualStudio/Core/Def/Implementation/Library/FindResults/TreeItems/MetadataDefinitionTreeItem.cs b/src/VisualStudio/Core/Def/Implementation/Library/FindResults/TreeItems/MetadataDefinitionTreeItem.cs deleted file mode 100644 index 496b81f7330..00000000000 --- a/src/VisualStudio/Core/Def/Implementation/Library/FindResults/TreeItems/MetadataDefinitionTreeItem.cs +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Threading; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.Editor; -using Microsoft.CodeAnalysis.Editor.Implementation.FindReferences; -using Microsoft.CodeAnalysis.Navigation; - -namespace Microsoft.VisualStudio.LanguageServices.Implementation.Library.FindResults -{ - internal class MetadataDefinitionTreeItem : AbstractTreeItem - { - private readonly string _assemblyName; - private readonly string _symbolDefinition; - private readonly SymbolKey _symbolKey; - private readonly bool _canGoToDefinition; - private readonly Workspace _workspace; - private readonly ProjectId _referencingProjectId; - - public MetadataDefinitionTreeItem(Workspace workspace, ISymbol definition, ProjectId referencingProjectId, ushort glyphIndex) - : base(glyphIndex) - { - _workspace = workspace; - _referencingProjectId = referencingProjectId; - _symbolKey = definition.GetSymbolKey(); - _assemblyName = definition.ContainingAssembly?.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat); - _symbolDefinition = definition.ToDisplayString(FindReferencesUtilities.DefinitionDisplayFormat); - _canGoToDefinition = definition.Kind != SymbolKind.Namespace; - - this.DisplayText = $"{GetAssemblyNameString()}{_symbolDefinition}"; - } - - public override bool CanGoToDefinition() - { - return _canGoToDefinition; - } - - public override int GoToSource() - { - var symbol = ResolveSymbolInCurrentSolution(); - var referencingProject = _workspace.CurrentSolution.GetProject(_referencingProjectId); - if (symbol != null && referencingProject != null) - { - var navigationService = _workspace.Services.GetService(); - return navigationService.TryNavigateToSymbol(symbol, referencingProject, cancellationToken: CancellationToken.None) - ? VSConstants.S_OK - : VSConstants.E_FAIL; - } - - return VSConstants.E_FAIL; - } - - private ISymbol ResolveSymbolInCurrentSolution() - { - return _symbolKey.Resolve(_workspace.CurrentSolution.GetProject(_referencingProjectId).GetCompilationAsync(CancellationToken.None).Result).Symbol; - } - - internal override void SetReferenceCount(int referenceCount) - { - var referenceCountDisplay = referenceCount == 1 - ? ServicesVSResources._1_reference - : string.Format(ServicesVSResources._0_references, referenceCount); - - this.DisplayText = $"{GetAssemblyNameString()}{_symbolDefinition} ({referenceCountDisplay})"; - } - - private string GetAssemblyNameString() - { - return (_assemblyName != null && _canGoToDefinition) ? $"[{_assemblyName}] " : string.Empty; - } - } -} diff --git a/src/VisualStudio/Core/Def/Implementation/Library/FindResults/TreeItems/SourceDefinitionTreeItem.cs b/src/VisualStudio/Core/Def/Implementation/Library/FindResults/TreeItems/SourceDefinitionTreeItem.cs index bfd7ea957ce..f00580bfe1d 100644 --- a/src/VisualStudio/Core/Def/Implementation/Library/FindResults/TreeItems/SourceDefinitionTreeItem.cs +++ b/src/VisualStudio/Core/Def/Implementation/Library/FindResults/TreeItems/SourceDefinitionTreeItem.cs @@ -1,42 +1,121 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Completion; using Microsoft.CodeAnalysis.Editor.Implementation.FindReferences; +using Microsoft.CodeAnalysis.Editor.Shared.Extensions; using Microsoft.CodeAnalysis.Text; +using Microsoft.VisualStudio.LanguageServices.Implementation.Utilities; namespace Microsoft.VisualStudio.LanguageServices.Implementation.Library.FindResults { - internal class SourceDefinitionTreeItem : AbstractSourceTreeItem + internal class DefinitionTreeItem : AbstractTreeItem { - private readonly bool _canGoToDefinition; - private readonly string _symbolDisplay; + private readonly DefinitionItem _definitionItem; + private readonly DefinitionLocation _definitionLocation; - public SourceDefinitionTreeItem(Document document, TextSpan sourceSpan, ISymbol symbol, ushort glyphIndex) - : base(document, sourceSpan, glyphIndex) + public DefinitionTreeItem(DefinitionItem definitionItem, DefinitionLocation definitionLocation) + : base(definitionItem.Tags.GetGlyph().GetGlyphIndex()) { - _symbolDisplay = symbol.ToDisplayString(FindReferencesUtilities.DefinitionDisplayFormat); + _definitionItem = definitionItem; + _definitionLocation = definitionLocation; + +#if false // source base constructor + // We store the document ID, line and offset for navigation so that we + // still provide reasonable navigation if the user makes changes elsewhere + // in the document other than inserting or removing lines. + + _workspace = document.Project.Solution.Workspace; + _documentId = document.Id; + _projectName = document.Project.Name; + _filePath = GetFilePath(document, commonPathElements); + _sourceSpan = sourceSpan; + + var text = document.GetTextAsync(CancellationToken.None).WaitAndGetResult(CancellationToken.None); + var textLine = text.Lines.GetLineFromPosition(_sourceSpan.Start); + _textLineString = textLine.ToString(); + + _lineNumber = textLine.LineNumber; + _offset = sourceSpan.Start - textLine.Start; + + var spanInSecondaryBuffer = text.GetVsTextSpanForLineOffset(_lineNumber, _offset); + + VsTextSpan spanInPrimaryBuffer; + var succeeded = spanInSecondaryBuffer.TryMapSpanFromSecondaryBufferToPrimaryBuffer(_workspace, _documentId, out spanInPrimaryBuffer); + + _mappedLineNumber = succeeded ? spanInPrimaryBuffer.iStartLine : _lineNumber; + _mappedOffset = succeeded ? spanInPrimaryBuffer.iStartIndex : _offset; + +#endif + +#if false // source contructor + _symbolDisplay = symbol.ToDisplayString(FindReferencesUtilities.DefinitionDisplayFormat); this.DisplayText = $"{GetProjectNameString()}{_symbolDisplay}"; _canGoToDefinition = symbol.Kind != SymbolKind.Namespace; + +#endif + +#if false // metadata constructor + _workspace = workspace; + _referencingProjectId = referencingProjectId; + _symbolKey = definition.GetSymbolKey(); + _assemblyName = definition.ContainingAssembly?.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat); + _symbolDefinition = definition.ToDisplayString(FindReferencesUtilities.DefinitionDisplayFormat); + _canGoToDefinition = definition.Kind != SymbolKind.Namespace; + + this.DisplayText = $"{GetAssemblyNameString()}{_symbolDefinition}"; + +#endif + } + + public override int GoToSource() + { + return _definitionLocation.TryNavigateTo() + ? VSConstants.S_OK + : VSConstants.E_FAIL; } public override bool CanGoToDefinition() { - return _canGoToDefinition; + return _definitionLocation.CanNavigateTo(); } internal override void SetReferenceCount(int referenceCount) { + // source case. var referenceCountDisplay = referenceCount == 1 ? ServicesVSResources._1_reference : string.Format(ServicesVSResources._0_references, referenceCount); +#if false // source case this.DisplayText = $"{GetProjectNameString()}{_symbolDisplay} ({referenceCountDisplay})"; +#endif + +#if false // metadata case + var referenceCountDisplay = referenceCount == 1 + ? ServicesVSResources._1_reference + : string.Format(ServicesVSResources._0_references, referenceCount); + + this.DisplayText = $"{GetAssemblyNameString()}{_symbolDefinition} ({referenceCountDisplay})"; +#endif + } + +#if false + private string GetAssemblyNameString() + { + return (_assemblyName != null && _canGoToDefinition) ? $"[{_assemblyName}] " : string.Empty; } +#endif private string GetProjectNameString() { + return ""; + +#if false return (_projectName != null && _canGoToDefinition) ? $"[{_projectName}] " : string.Empty; +#endif } } -} +} \ No newline at end of file diff --git a/src/VisualStudio/Core/Def/Implementation/Library/FindResults/TreeItems/SourceReferenceTreeItem.cs b/src/VisualStudio/Core/Def/Implementation/Library/FindResults/TreeItems/SourceReferenceTreeItem.cs index e8feff5b255..8eef77f49f8 100644 --- a/src/VisualStudio/Core/Def/Implementation/Library/FindResults/TreeItems/SourceReferenceTreeItem.cs +++ b/src/VisualStudio/Core/Def/Implementation/Library/FindResults/TreeItems/SourceReferenceTreeItem.cs @@ -30,18 +30,9 @@ public SourceReferenceTreeItem(Document document, TextSpan sourceSpan, ushort gl } } - public override bool CanGoToReference() - { - return true; - } + public override bool CanGoToReference() => true; - public override bool UseGrayText - { - get - { - return false; - } - } + public override bool UseGrayText => false; public void AddProjectNameDisambiguator() { @@ -70,4 +61,4 @@ int IComparable.CompareTo(SourceReferenceTreeItem other return compare; } } -} +} \ No newline at end of file diff --git a/src/VisualStudio/Core/Def/RoslynPackage.cs b/src/VisualStudio/Core/Def/RoslynPackage.cs index 2bbc9ea2c8b..ee5e95ce170 100644 --- a/src/VisualStudio/Core/Def/RoslynPackage.cs +++ b/src/VisualStudio/Core/Def/RoslynPackage.cs @@ -125,7 +125,7 @@ protected override void LoadComponentsInUIContext() this.ComponentModel.GetService().Initialize(this); this.ComponentModel.GetService(); - this.ComponentModel.GetExtensions(); + this.ComponentModel.GetExtensions(); this.ComponentModel.GetExtensions(); this.ComponentModel.GetService(); this.ComponentModel.GetService(); diff --git a/src/VisualStudio/Core/Def/ServicesVisualStudio.csproj b/src/VisualStudio/Core/Def/ServicesVisualStudio.csproj index 10f7e4ff6ed..747c12c0bed 100644 --- a/src/VisualStudio/Core/Def/ServicesVisualStudio.csproj +++ b/src/VisualStudio/Core/Def/ServicesVisualStudio.csproj @@ -75,7 +75,6 @@ - diff --git a/src/VisualStudio/Core/Impl/RoslynVisualStudioWorkspace.cs b/src/VisualStudio/Core/Impl/RoslynVisualStudioWorkspace.cs index 53b55812b72..9d37055a242 100644 --- a/src/VisualStudio/Core/Impl/RoslynVisualStudioWorkspace.cs +++ b/src/VisualStudio/Core/Impl/RoslynVisualStudioWorkspace.cs @@ -8,6 +8,7 @@ using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Editor; using Microsoft.CodeAnalysis.Editor.Host; +using Microsoft.CodeAnalysis.Editor.Implementation.FindReferences; using Microsoft.CodeAnalysis.Editor.Implementation.GoToDefinition; using Microsoft.CodeAnalysis.Editor.Undo; using Microsoft.CodeAnalysis.FindSymbols; @@ -27,7 +28,7 @@ namespace Microsoft.VisualStudio.LanguageServices internal class RoslynVisualStudioWorkspace : VisualStudioWorkspaceImpl { private readonly IEnumerable> _navigableItemsPresenters; - private readonly IEnumerable> _referencedSymbolsPresenters; + private readonly IEnumerable> _referencedSymbolsPresenters; private readonly IEnumerable> _externalDefinitionProviders; [ImportingConstructor] @@ -35,7 +36,7 @@ internal class RoslynVisualStudioWorkspace : VisualStudioWorkspaceImpl SVsServiceProvider serviceProvider, SaveEventsService saveEventsService, [ImportMany] IEnumerable> navigableItemsPresenters, - [ImportMany] IEnumerable> referencedSymbolsPresenters, + [ImportMany] IEnumerable> referencedSymbolsPresenters, [ImportMany] IEnumerable> externalDefinitionProviders) : base( serviceProvider, @@ -222,11 +223,16 @@ public override bool TryFindAllReferences(ISymbol symbol, Project project, Cance return false; } - public override void DisplayReferencedSymbols(Solution solution, IEnumerable referencedSymbols) + public override void DisplayReferencedSymbols( + Solution solution, IEnumerable referencedSymbols) { + var service = this.Services.GetService(); + var definitionsAndReferences = service.CreateDefinitionsAndReferences(solution, referencedSymbols); + foreach (var presenter in _referencedSymbolsPresenters) { - presenter.Value.DisplayResult(solution, referencedSymbols); + presenter.Value.DisplayResult(definitionsAndReferences); + return; } } -- GitLab