提交 840b1567 编写于 作者: C CyrusNajmabadi

Initial work to move the existing FAR presented over to using hte new object model.

上级 a2ace5b6
......@@ -13,7 +13,7 @@ internal class CSharpFindReferencesService : AbstractFindReferencesService
{
[ImportingConstructor]
public CSharpFindReferencesService(
[ImportMany] IEnumerable<IReferencedSymbolsPresenter> referencedSymbolsPresenters,
[ImportMany] IEnumerable<IFindReferencesPresenter> referencedSymbolsPresenters,
[ImportMany] IEnumerable<INavigableItemsPresenter> navigableItemsPresenters,
[ImportMany] IEnumerable<IFindReferencesResultProvider> externalReferencesProviders)
: base(referencedSymbolsPresenters, navigableItemsPresenters, externalReferencesProviders)
......
// 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<ReferencedSymbol> result);
void DisplayResult(DefinitionsAndReferences definitionsAndReferences);
}
}
}
\ No newline at end of file
......@@ -16,12 +16,12 @@ namespace Microsoft.CodeAnalysis.Editor.Implementation.FindReferences
{
internal abstract partial class AbstractFindReferencesService : IFindReferencesService
{
private readonly IEnumerable<IReferencedSymbolsPresenter> _referenceSymbolPresenters;
private readonly IEnumerable<IFindReferencesPresenter> _referenceSymbolPresenters;
private readonly IEnumerable<INavigableItemsPresenter> _navigableItemPresenters;
private readonly IEnumerable<IFindReferencesResultProvider> _externalReferencesProviders;
protected AbstractFindReferencesService(
IEnumerable<IReferencedSymbolsPresenter> referenceSymbolPresenters,
IEnumerable<IFindReferencesPresenter> referenceSymbolPresenters,
IEnumerable<INavigableItemsPresenter> navigableItemPresenters,
IEnumerable<IFindReferencesResultProvider> externalReferencesProviders)
{
......@@ -156,10 +156,14 @@ private bool TryDisplayReferences(Tuple<IEnumerable<ReferencedSymbol>, Solution>
{
if (result != null && result.Item1 != null)
{
var searchSolution = result.Item2;
var solution = result.Item2;
var factory = solution.Workspace.Services.GetService<IDefinitionsAndReferencesFactory>();
var definitionsAndReferences = factory.CreateDefinitionsAndReferences(
solution, result.Item1);
foreach (var presenter in _referenceSymbolPresenters)
{
presenter.DisplayResult(searchSolution, result.Item1);
presenter.DisplayResult(definitionsAndReferences);
return true;
}
}
......
......@@ -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<FindReferencesCommandArgs>
{
private readonly IEnumerable<IReferencedSymbolsPresenter> _presenters;
private readonly IEnumerable<IFindReferencesPresenter> _presenters;
private readonly IWaitIndicator _waitIndicator;
[ImportingConstructor]
internal FindReferencesCommandHandler(
IWaitIndicator waitIndicator,
[ImportMany] IEnumerable<IReferencedSymbolsPresenter> presenters)
[ImportMany] IEnumerable<IFindReferencesPresenter> 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<ReferencedSymbol>());
presenter.DisplayResult(DefinitionsAndReferences.Empty);
return;
}
}
......
......@@ -242,6 +242,9 @@ public int CompareTo(SourceReferenceItem other)
internal struct DefinitionsAndReferences
{
public static readonly DefinitionsAndReferences Empty =
new DefinitionsAndReferences(ImmutableArray<DefinitionItem>.Empty, ImmutableArray<SourceReferenceItem>.Empty);
/// <summary>
/// All the definitions to show. Note: not all definitions may have references.
/// </summary>
......
......@@ -36,6 +36,15 @@ internal class DefaultDefinitionsAndReferencesFactory : IDefinitionsAndReference
return new DefinitionsAndReferences(definitions.ToImmutable(), references.ToImmutable());
}
/// <summary>
/// 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.
/// </summary>
private static int GetPrecedence(ReferencedSymbol referencedSymbol)
{
switch (referencedSymbol.Definition.Kind)
......
// 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<ReferencedSymbol> 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
......@@ -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<ReferencedSymbol> Result { get; private set; }
public DefinitionsAndReferences DefinitionsAndReferences;
public void DisplayResult(Solution solution, IEnumerable<ReferencedSymbol> result)
public void DisplayResult(DefinitionsAndReferences definitionsAndReferences)
{
this.Solution = solution;
this.Result = result;
DefinitionsAndReferences = definitionsAndReferences;
}
}
}
}
\ No newline at end of file
......@@ -11,7 +11,7 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.FindReferences
Inherits AbstractFindReferencesService
<ImportingConstructor>
Protected Sub New(<ImportMany> referencedSymbolsPresenters As IEnumerable(Of IReferencedSymbolsPresenter),
Protected Sub New(<ImportMany> referencedSymbolsPresenters As IEnumerable(Of IFindReferencesPresenter),
<ImportMany> navigableItemsPresenters As IEnumerable(Of INavigableItemsPresenter),
<ImportMany> externalReferencesProviders As IEnumerable(Of IFindReferencesResultProvider))
MyBase.New(referencedSymbolsPresenters, navigableItemsPresenters, externalReferencesProviders)
......
// 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<ReferencedSymbol> 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
......@@ -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()
......
......@@ -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<ReferencedSymbol> 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<AbstractTreeItem> CreateFindReferencesItems(Solution solution, IEnumerable<ReferencedSymbol> referencedSymbols)
internal IList<AbstractTreeItem> CreateFindReferencesItems(
DefinitionsAndReferences definitionsAndReferences)
{
var definitions = new List<AbstractTreeItem>();
var uniqueLocations = new HashSet<ValueTuple<Document, TextSpan>>();
var symbolNavigationService = solution.Workspace.Services.GetService<ISymbolNavigationService>();
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();
}
/// <summary>
/// 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.
/// </summary>
private int GetDefinitionPrecedence(ReferencedSymbol referencedSymbol)
private IEnumerable<AbstractTreeItem> 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<AbstractTreeItem> 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<AbstractTreeItem>();
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<SourceReferenceTreeItem> CreateReferenceItems(Solution solution, HashSet<ValueTuple<Document, TextSpan>> uniqueLocations, IEnumerable<Location> locations)
private IList<SourceReferenceTreeItem> CreateReferenceItems(
DefinitionItem definitionItem,
DefinitionsAndReferences definitionsAndReferences)
{
var referenceItems = new List<SourceReferenceTreeItem>();
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, TextSpan>(document, sourceSpan)))
{
referenceItems.Add(new SourceReferenceTreeItem(document, sourceSpan, Glyph.Reference.GetGlyphIndex()));
}
}
var result = new List<SourceReferenceTreeItem>();
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;
}
}
}
// 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
// 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<ISymbolNavigationService>();
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;
}
}
}
// 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
......@@ -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<SourceReferenceTreeItem>.CompareTo(SourceReferenceTreeItem other
return compare;
}
}
}
}
\ No newline at end of file
......@@ -125,7 +125,7 @@ protected override void LoadComponentsInUIContext()
this.ComponentModel.GetService<VisualStudioDiagnosticListTableCommandHandler>().Initialize(this);
this.ComponentModel.GetService<HACK_ThemeColorFixer>();
this.ComponentModel.GetExtensions<IReferencedSymbolsPresenter>();
this.ComponentModel.GetExtensions<IFindReferencesPresenter>();
this.ComponentModel.GetExtensions<INavigableItemsPresenter>();
this.ComponentModel.GetService<VisualStudioMetadataAsSourceFileSupportService>();
this.ComponentModel.GetService<VirtualMemoryNotificationListener>();
......
......@@ -75,7 +75,6 @@
<Compile Include="Implementation\Library\AbstractLibraryService.cs" />
<Compile Include="Implementation\Library\ClassView\AbstractSyncClassViewCommandHandler.cs" />
<Compile Include="Implementation\Library\FindResults\TreeItems\AbstractSourceTreeItem.cs" />
<Compile Include="Implementation\Library\FindResults\TreeItems\MetadataDefinitionTreeItem.cs" />
<Compile Include="Implementation\Library\FindResults\TreeItems\SourceDefinitionTreeItem.cs" />
<Compile Include="Implementation\Library\ILibraryService.cs" />
<Compile Include="Implementation\Library\ObjectBrowser\ObjectBrowserTaskExtensions.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<Lazy<INavigableItemsPresenter>> _navigableItemsPresenters;
private readonly IEnumerable<Lazy<IReferencedSymbolsPresenter>> _referencedSymbolsPresenters;
private readonly IEnumerable<Lazy<IFindReferencesPresenter>> _referencedSymbolsPresenters;
private readonly IEnumerable<Lazy<INavigableDefinitionProvider>> _externalDefinitionProviders;
[ImportingConstructor]
......@@ -35,7 +36,7 @@ internal class RoslynVisualStudioWorkspace : VisualStudioWorkspaceImpl
SVsServiceProvider serviceProvider,
SaveEventsService saveEventsService,
[ImportMany] IEnumerable<Lazy<INavigableItemsPresenter>> navigableItemsPresenters,
[ImportMany] IEnumerable<Lazy<IReferencedSymbolsPresenter>> referencedSymbolsPresenters,
[ImportMany] IEnumerable<Lazy<IFindReferencesPresenter>> referencedSymbolsPresenters,
[ImportMany] IEnumerable<Lazy<INavigableDefinitionProvider>> 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<ReferencedSymbol> referencedSymbols)
public override void DisplayReferencedSymbols(
Solution solution, IEnumerable<ReferencedSymbol> referencedSymbols)
{
var service = this.Services.GetService<IDefinitionsAndReferencesFactory>();
var definitionsAndReferences = service.CreateDefinitionsAndReferences(solution, referencedSymbols);
foreach (var presenter in _referencedSymbolsPresenters)
{
presenter.Value.DisplayResult(solution, referencedSymbols);
presenter.Value.DisplayResult(definitionsAndReferences);
return;
}
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册