提交 5eaae79c 编写于 作者: C CyrusNajmabadi

Cleanup code.

上级 38a7837e
...@@ -126,7 +126,7 @@ private IStreamingFindUsagesPresenter GetStreamingPresenter() ...@@ -126,7 +126,7 @@ private IStreamingFindUsagesPresenter GetStreamingPresenter()
// Let the presented know we're starging a search. It will give us back // Let the presented know we're starging a search. It will give us back
// the context object that the FAR service will push results into. // the context object that the FAR service will push results into.
var context = presenter.StartSearch( var context = presenter.StartSearch(
EditorFeaturesResources.Find_References, canShowReferences: true); EditorFeaturesResources.Find_References, supportsReferences: true);
await findUsagesService.FindReferencesAsync(document, caretPosition, context).ConfigureAwait(false); await findUsagesService.FindReferencesAsync(document, caretPosition, context).ConfigureAwait(false);
// Note: we don't need to put this in a finally. The only time we might not hit // Note: we don't need to put this in a finally. The only time we might not hit
......
...@@ -21,7 +21,13 @@ internal interface IStreamingFindUsagesPresenter ...@@ -21,7 +21,13 @@ internal interface IStreamingFindUsagesPresenter
/// search completes <see cref="FindUsagesContext.OnCompletedAsync"/> should be called. /// search completes <see cref="FindUsagesContext.OnCompletedAsync"/> should be called.
/// etc. etc. /// etc. etc.
/// </summary> /// </summary>
FindUsagesContext StartSearch(string title, bool canShowReferences); /// <param name="title">A title to display to the user in the presentation of the results.</param>
/// <param name="supportsReferences">Whether or not showing references is supported.
/// If true, then the presenter can group by definition, showing references underneath.
/// It can also show messages about no references being found at the end of the search.
/// If false, the presenter will not group by definitions, and will show the definition
/// items in isolation.</param>
FindUsagesContext StartSearch(string title, bool supportsReferences);
} }
internal static class IStreamingFindUsagesPresenterExtensions internal static class IStreamingFindUsagesPresenterExtensions
...@@ -65,8 +71,7 @@ internal static class IStreamingFindUsagesPresenterExtensions ...@@ -65,8 +71,7 @@ internal static class IStreamingFindUsagesPresenterExtensions
{ {
// We have multiple definitions, or we have definitions with multiple locations. // We have multiple definitions, or we have definitions with multiple locations.
// Present this to the user so they can decide where they want to go to. // Present this to the user so they can decide where they want to go to.
var context = presenter.StartSearch(title, supportsReferences: false);
var context = presenter.StartSearch(title, canShowReferences: false);
foreach (var definition in nonExternalItems) foreach (var definition in nonExternalItems)
{ {
await context.OnDefinitionFoundAsync(definition).ConfigureAwait(false); await context.OnDefinitionFoundAsync(definition).ConfigureAwait(false);
......
...@@ -9,75 +9,82 @@ ...@@ -9,75 +9,82 @@
namespace Microsoft.VisualStudio.LanguageServices.FindUsages namespace Microsoft.VisualStudio.LanguageServices.FindUsages
{ {
internal class WithoutReferencesFindUsagesContext : AbstractTableDataSourceFindUsagesContext /// <summary>
/// Context to be used for FindImplementations/GoToDef (as opposed to FindReferences).
/// This context will not group entries by definition, and will instead just create
/// entries for the definitions themselves.
/// </summary>
internal class WithoutReferencesFindUsagesContext : AbstractTableDataSourceFindUsagesContext
{
public WithoutReferencesFindUsagesContext(
StreamingFindUsagesPresenter presenter,
IFindAllReferencesWindow findReferencesWindow)
: base(presenter, findReferencesWindow)
{ {
public WithoutReferencesFindUsagesContext( }
StreamingFindUsagesPresenter presenter,
IFindAllReferencesWindow findReferencesWindow)
: base(presenter, findReferencesWindow)
{
}
protected override Task OnReferenceFoundWorkerAsync(SourceReferenceItem reference) // We should never be called in a context where we get references.
=> throw new InvalidOperationException(); protected override Task OnReferenceFoundWorkerAsync(SourceReferenceItem reference)
=> throw new InvalidOperationException();
protected override Task OnCompletedAsyncWorkerAsync() // Nothing to do on completion.
=> SpecializedTasks.EmptyTask; protected override Task OnCompletedAsyncWorkerAsync()
=> SpecializedTasks.EmptyTask;
protected override async Task OnDefinitionFoundWorkerAsync(DefinitionItem definition) protected override async Task OnDefinitionFoundWorkerAsync(DefinitionItem definition)
{ {
var definitionBucket = GetOrCreateDefinitionBucket(definition); var definitionBucket = GetOrCreateDefinitionBucket(definition);
var entries = ArrayBuilder<Entry>.GetInstance(); var entries = ArrayBuilder<Entry>.GetInstance();
try try
{
if (definition.SourceSpans.Length == 1)
{ {
if (definition.SourceSpans.Length == 1) // If we only have a single location, then use the DisplayParts of the
// definition as what to show. That way we show enough information for things
// methods. i.e. we'll show "void TypeName.MethodName(args...)" allowing
// the user to see the type the method was created in.
var entry = await CreateEntryAsync(definitionBucket, definition).ConfigureAwait(false);
entries.Add(entry);
}
else
{
// If we have multiple spans (i.e. for partial types), then create a
// DocumentSpanEntry for each. That way we can easily see the source
// code where each location is to help the user decide which they want
// to navigate to.
foreach (var sourceSpan in definition.SourceSpans)
{ {
// If we only have a single location, then use the DisplayParts of the var entry = await CreateDocumentSpanEntryAsync(
// definition as what to show. That way we show enough information for things definitionBucket, sourceSpan, isDefinitionLocation: true).ConfigureAwait(false);
// methods. i.e. we'll show "void TypeName.MethodName(args...)" allowing
// the user to see the type the method was created in.
var entry = await CreateEntryAsync(definitionBucket, definition).ConfigureAwait(false);
entries.Add(entry); entries.Add(entry);
} }
else }
{
// If we have multiple spans (i.e. for partial types), then create a
// DocumentSpanEntry for each. That way we can easily see the source
// code where each location is to help the user decide which they want
// to navigate to.
foreach (var sourceSpan in definition.SourceSpans)
{
var entry = await CreateDocumentSpanEntryAsync(
definitionBucket, sourceSpan, isDefinitionLocation: true).ConfigureAwait(false);
entries.Add(entry);
}
}
if (entries.Count > 0) if (entries.Count > 0)
{
lock (_gate)
{ {
lock (_gate) _entriesWhenGroupingByDefinition = _entriesWhenGroupingByDefinition.AddRange(entries);
{ _entriesWhenNotGroupingByDefinition = _entriesWhenNotGroupingByDefinition.AddRange(entries);
_entriesWhenGroupingByDefinition = _entriesWhenGroupingByDefinition.AddRange(entries);
_entriesWhenNotGroupingByDefinition = _entriesWhenNotGroupingByDefinition.AddRange(entries);
}
this.NotifyChange();
} }
}
finally this.NotifyChange();
{
entries.Free();
} }
} }
finally
private async Task<Entry> CreateEntryAsync(
RoslynDefinitionBucket definitionBucket, DefinitionItem definition)
{ {
var documentSpan = definition.SourceSpans[0]; entries.Free();
var (guid, sourceText) = await GetGuidAndSourceTextAsync(documentSpan.Document).ConfigureAwait(false);
return new DefinitionItemEntry(this, definitionBucket, documentSpan, guid, sourceText);
} }
} }
private async Task<Entry> CreateEntryAsync(
RoslynDefinitionBucket definitionBucket, DefinitionItem definition)
{
var documentSpan = definition.SourceSpans[0];
var (guid, sourceText) = await GetGuidAndSourceTextAsync(documentSpan.Document).ConfigureAwait(false);
return new DefinitionItemEntry(this, definitionBucket, documentSpan, guid, sourceText);
}
}
} }
\ 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. // 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;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Documents;
using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Editor.Shared.Extensions;
using Microsoft.CodeAnalysis.Text; using Microsoft.CodeAnalysis.Text;
using Microsoft.VisualStudio.Shell.TableControl;
using Microsoft.VisualStudio.Shell.TableManager; using Microsoft.VisualStudio.Shell.TableManager;
namespace Microsoft.VisualStudio.LanguageServices.FindUsages namespace Microsoft.VisualStudio.LanguageServices.FindUsages
{ {
internal abstract class AbstractDocumentSpanEntry : Entry /// <summary>
/// Base type of all <see cref="Entry"/>s that represent some source location in
/// a <see cref="Document"/>. Navigation to that location is provided by this type.
/// Subclasses can be used to provide customized line text to display in the entry.
/// </summary>
internal abstract class AbstractDocumentSpanEntry : Entry
{
private readonly AbstractTableDataSourceFindUsagesContext _context;
private readonly DocumentSpan _documentSpan;
private readonly object _boxedProjectGuid;
protected readonly SourceText _sourceText;
protected AbstractDocumentSpanEntry(
AbstractTableDataSourceFindUsagesContext context,
RoslynDefinitionBucket definitionBucket,
DocumentSpan documentSpan,
Guid projectGuid,
SourceText sourceText)
: base(definitionBucket)
{ {
private readonly AbstractTableDataSourceFindUsagesContext _context; _context = context;
private readonly DocumentSpan _documentSpan;
private readonly object _boxedProjectGuid;
protected readonly SourceText _sourceText;
protected AbstractDocumentSpanEntry(
AbstractTableDataSourceFindUsagesContext context,
RoslynDefinitionBucket definitionBucket,
DocumentSpan documentSpan,
Guid projectGuid,
SourceText sourceText)
: base(definitionBucket)
{
_context = context;
_documentSpan = documentSpan; _documentSpan = documentSpan;
_boxedProjectGuid = projectGuid; _boxedProjectGuid = projectGuid;
_sourceText = sourceText; _sourceText = sourceText;
} }
protected StreamingFindUsagesPresenter Presenter => _context.Presenter; protected StreamingFindUsagesPresenter Presenter => _context.Presenter;
protected Document Document => _documentSpan.Document; protected Document Document => _documentSpan.Document;
protected TextSpan SourceSpan => _documentSpan.SourceSpan; protected TextSpan SourceSpan => _documentSpan.SourceSpan;
protected override object GetValueWorker(string keyName) protected override object GetValueWorker(string keyName)
{
switch (keyName)
{ {
switch (keyName) case StandardTableKeyNames.DocumentName:
{ return Document.FilePath;
case StandardTableKeyNames.DocumentName: case StandardTableKeyNames.Line:
return Document.FilePath; return _sourceText.Lines.GetLinePosition(SourceSpan.Start).Line;
case StandardTableKeyNames.Line: case StandardTableKeyNames.Column:
return _sourceText.Lines.GetLinePosition(SourceSpan.Start).Line; return _sourceText.Lines.GetLinePosition(SourceSpan.Start).Character;
case StandardTableKeyNames.Column: case StandardTableKeyNames.ProjectName:
return _sourceText.Lines.GetLinePosition(SourceSpan.Start).Character; return Document.Project.Name;
case StandardTableKeyNames.ProjectName: case StandardTableKeyNames.ProjectGuid:
return Document.Project.Name; return _boxedProjectGuid;
case StandardTableKeyNames.ProjectGuid: case StandardTableKeyNames.Text:
return _boxedProjectGuid; return _sourceText.Lines.GetLineFromPosition(SourceSpan.Start).ToString().Trim();
case StandardTableKeyNames.Text:
return _sourceText.Lines.GetLineFromPosition(SourceSpan.Start).ToString().Trim();
}
return null;
} }
return null;
} }
public sealed override bool TryCreateColumnContent(string columnName, out FrameworkElement content)
{
if (columnName == StandardTableColumnDefinitions2.LineText)
{
var inlines = CreateLineTextInlines();
var textBlock = inlines.ToTextBlock(Presenter.TypeMap, wrap: false);
content = textBlock;
return true;
}
content = null;
return false;
}
protected abstract IList<Inline> CreateLineTextInlines();
}
} }
\ 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. // 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;
using System.Windows; using System.Collections.Generic;
using System.Windows.Documents;
using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Editor.Shared.Extensions; using Microsoft.CodeAnalysis.Editor.Shared.Extensions;
using Microsoft.CodeAnalysis.Text; using Microsoft.CodeAnalysis.Text;
using Microsoft.VisualStudio.Shell.TableControl;
namespace Microsoft.VisualStudio.LanguageServices.FindUsages namespace Microsoft.VisualStudio.LanguageServices.FindUsages
{ {
internal class DefinitionItemEntry : AbstractDocumentSpanEntry /// <summary>
/// Shows a DefinitionItem as a Row in the FindReferencesWindow. Only used for
/// GoToDefinition/FindImplementations. In these operations, we don't want to
/// create a DefinitionBucket. So we instead just so the symbol as a normal row.
/// </summary>
internal class DefinitionItemEntry : AbstractDocumentSpanEntry
{
public DefinitionItemEntry(
AbstractTableDataSourceFindUsagesContext context,
RoslynDefinitionBucket definitionBucket,
DocumentSpan documentSpan,
Guid projectGuid,
SourceText sourceText)
: base(context, definitionBucket, documentSpan, projectGuid, sourceText)
{ {
public DefinitionItemEntry(
AbstractTableDataSourceFindUsagesContext context,
RoslynDefinitionBucket definitionBucket,
DocumentSpan documentSpan,
Guid projectGuid,
SourceText sourceText)
: base(context, definitionBucket, documentSpan, projectGuid, sourceText)
{
}
public override bool TryCreateColumnContent(string columnName, out FrameworkElement content)
{
if (columnName == StandardTableColumnDefinitions2.LineText)
{
var inlines = DefinitionBucket.DefinitionItem.DisplayParts.ToInlines(Presenter.TypeMap);
var textBlock = inlines.ToTextBlock(Presenter.TypeMap, wrap: false);
content = textBlock;
return true;
}
content = null;
return false;
}
} }
protected override IList<Inline> CreateLineTextInlines()
=> DefinitionBucket.DefinitionItem.DisplayParts.ToInlines(Presenter.TypeMap);
}
} }
\ No newline at end of file
...@@ -25,7 +25,7 @@ namespace Microsoft.VisualStudio.LanguageServices.FindUsages ...@@ -25,7 +25,7 @@ namespace Microsoft.VisualStudio.LanguageServices.FindUsages
internal class DocumentSpanEntry : AbstractDocumentSpanEntry internal class DocumentSpanEntry : AbstractDocumentSpanEntry
{ {
private readonly bool _isDefinitionLocation; private readonly bool _isDefinitionLocation;
private readonly ClassifiedSpansAndHighlightSpan _classifiedSpans; private readonly ClassifiedSpansAndHighlightSpan _classifiedSpansAndHighlights;
public DocumentSpanEntry( public DocumentSpanEntry(
AbstractTableDataSourceFindUsagesContext context, AbstractTableDataSourceFindUsagesContext context,
...@@ -38,52 +38,31 @@ internal class DocumentSpanEntry : AbstractDocumentSpanEntry ...@@ -38,52 +38,31 @@ internal class DocumentSpanEntry : AbstractDocumentSpanEntry
: base(context, definitionBucket, documentSpan, projectGuid, sourceText) : base(context, definitionBucket, documentSpan, projectGuid, sourceText)
{ {
_isDefinitionLocation = isDefinitionLocation; _isDefinitionLocation = isDefinitionLocation;
_classifiedSpans = classifiedSpans; _classifiedSpansAndHighlights = classifiedSpans;
} }
public override bool TryCreateColumnContent(string columnName, out FrameworkElement content) protected override IList<System.Windows.Documents.Inline> CreateLineTextInlines()
{ {
if (columnName == StandardTableColumnDefinitions2.LineText) var propertyId = _isDefinitionLocation
{
var inlines = GetHighlightedInlines(Presenter, _sourceText, _classifiedSpans, _isDefinitionLocation);
var textBlock = inlines.ToTextBlock(Presenter.TypeMap, wrap: false);
LazyToolTip.AttachTo(textBlock, CreateDisposableToolTip);
content = textBlock;
return true;
}
content = null;
return false;
}
private static IList<System.Windows.Documents.Inline> GetHighlightedInlines(
StreamingFindUsagesPresenter presenter,
SourceText sourceText,
ClassifiedSpansAndHighlightSpan classifiedSpansAndHighlight,
bool isDefinition)
{
var propertyId = isDefinition
? DefinitionHighlightTag.TagId ? DefinitionHighlightTag.TagId
: ReferenceHighlightTag.TagId; : ReferenceHighlightTag.TagId;
var properties = presenter.FormatMapService var properties = Presenter.FormatMapService
.GetEditorFormatMap("text") .GetEditorFormatMap("text")
.GetProperties(propertyId); .GetProperties(propertyId);
var highlightBrush = properties["Background"] as Brush; var highlightBrush = properties["Background"] as Brush;
var classifiedSpans = classifiedSpansAndHighlight.ClassifiedSpans; var classifiedSpans = _classifiedSpansAndHighlights.ClassifiedSpans;
var classifiedTexts = classifiedSpans.SelectAsArray( var classifiedTexts = classifiedSpans.SelectAsArray(
cs => new ClassifiedText(cs.ClassificationType, sourceText.ToString(cs.TextSpan))); cs => new ClassifiedText(cs.ClassificationType, _sourceText.ToString(cs.TextSpan)));
var inlines = classifiedTexts.ToInlines( var inlines = classifiedTexts.ToInlines(
presenter.TypeMap, Presenter.TypeMap,
runCallback: (run, classifiedText, position) => runCallback: (run, classifiedText, position) =>
{ {
if (highlightBrush != null) if (highlightBrush != null)
{ {
if (position == classifiedSpansAndHighlight.HighlightSpan.Start) if (position == _classifiedSpansAndHighlights.HighlightSpan.Start)
{ {
run.SetValue( run.SetValue(
System.Windows.Documents.TextElement.BackgroundProperty, System.Windows.Documents.TextElement.BackgroundProperty,
......
...@@ -28,16 +28,16 @@ internal partial class StreamingFindUsagesPresenter : ...@@ -28,16 +28,16 @@ internal partial class StreamingFindUsagesPresenter :
private readonly IServiceProvider _serviceProvider; private readonly IServiceProvider _serviceProvider;
private readonly IFindAllReferencesService _vsFindAllReferencesService;
private readonly VisualStudioWorkspace _workspace;
public readonly ITextBufferFactoryService TextBufferFactoryService; public readonly ITextBufferFactoryService TextBufferFactoryService;
public readonly IProjectionBufferFactoryService ProjectionBufferFactoryService; public readonly IProjectionBufferFactoryService ProjectionBufferFactoryService;
public readonly IEditorOptionsFactoryService EditorOptionsFactoryService; public readonly IEditorOptionsFactoryService EditorOptionsFactoryService;
public readonly ITextEditorFactoryService TextEditorFactoryService; public readonly ITextEditorFactoryService TextEditorFactoryService;
public readonly IContentTypeRegistryService ContentTypeRegistryService; public readonly IContentTypeRegistryService ContentTypeRegistryService;
public readonly IEditorFormatMapService FormatMapService;
public readonly ClassificationTypeMap TypeMap; public readonly ClassificationTypeMap TypeMap;
public readonly IEditorFormatMapService FormatMapService;
private readonly IFindAllReferencesService _vsFindAllReferencesService;
private readonly VisualStudioWorkspace _workspace;
[ImportingConstructor] [ImportingConstructor]
public StreamingFindUsagesPresenter( public StreamingFindUsagesPresenter(
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册