提交 c7286ffe 编写于 作者: C CyrusNajmabadi

Produce classifications up front.

上级 d0e60d71
......@@ -2,6 +2,7 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Editor.Shared.Utilities;
......@@ -27,9 +28,13 @@ private class FindLiteralsProgressAdapter : IStreamingFindLiteralReferencesProgr
_definition = definition;
}
public Task OnReferenceFoundAsync(Document document, TextSpan span)
=> _context.OnReferenceFoundAsync(new SourceReferenceItem(
_definition, new DocumentSpan(document, span), isWrittenTo: false));
public async Task OnReferenceFoundAsync(Document document, TextSpan span)
{
var documentSpan = await ClassifiedSpansAndHighlightSpan.GetClassifiedDocumentSpanAsync(
document, span, _context.CancellationToken).ConfigureAwait(false);
await _context.OnReferenceFoundAsync(new SourceReferenceItem(
_definition, documentSpan, isWrittenTo: false)).ConfigureAwait(false);
}
public Task ReportProgressAsync(int current, int maximum)
=> _context.ReportProgressAsync(current, maximum);
......@@ -53,16 +58,15 @@ internal class FindReferencesProgressAdapter : ForegroundThreadAffinitizedObject
/// This dictionary allows us to make that mapping once and then keep it around for
/// all future callbacks.
/// </summary>
private readonly ConcurrentDictionary<ISymbol, DefinitionItem> _definitionToItem =
new ConcurrentDictionary<ISymbol, DefinitionItem>(MetadataUnifyingEquivalenceComparer.Instance);
private readonly Dictionary<ISymbol, DefinitionItem> _definitionToItem =
new Dictionary<ISymbol, DefinitionItem>(MetadataUnifyingEquivalenceComparer.Instance);
private readonly Func<ISymbol, DefinitionItem> _definitionFactory;
private readonly SemaphoreSlim _gate = new SemaphoreSlim(initialCount: 1);
public FindReferencesProgressAdapter(Solution solution, IFindUsagesContext context)
{
_solution = solution;
_context = context;
_definitionFactory = s => s.ToDefinitionItem(solution, includeHiddenLocations: false);
}
// Do nothing functions. The streaming far service doesn't care about
......@@ -80,14 +84,27 @@ public FindReferencesProgressAdapter(Solution solution, IFindUsagesContext conte
// used by the FAR engine to the INavigableItems used by the streaming FAR
// feature.
private DefinitionItem GetDefinitionItem(SymbolAndProjectId definition)
private async Task<DefinitionItem> GetDefinitionItemAsync(SymbolAndProjectId definition)
{
return _definitionToItem.GetOrAdd(definition.Symbol, _definitionFactory);
using (await _gate.DisposableWaitAsync(_context.CancellationToken).ConfigureAwait(false))
{
if (!_definitionToItem.TryGetValue(definition.Symbol, out var definitionItem))
{
definitionItem = await definition.Symbol.ToDefinitionItemAsync(
_solution, includeHiddenLocations: false,
cancellationToken: _context.CancellationToken).ConfigureAwait(false);
_definitionToItem[definition.Symbol] = definitionItem;
}
return definitionItem;
}
}
public Task OnDefinitionFoundAsync(SymbolAndProjectId definition)
public async Task OnDefinitionFoundAsync(SymbolAndProjectId definition)
{
return _context.OnDefinitionFoundAsync(GetDefinitionItem(definition));
var definitionItem = await GetDefinitionItemAsync(definition).ConfigureAwait(false);
await _context.OnDefinitionFoundAsync(definitionItem).ConfigureAwait(false);
}
public async Task OnReferenceFoundAsync(SymbolAndProjectId definition, ReferenceLocation location)
......@@ -98,8 +115,10 @@ public async Task OnReferenceFoundAsync(SymbolAndProjectId definition, Reference
return;
}
var referenceItem = location.TryCreateSourceReferenceItem(
GetDefinitionItem(definition), includeHiddenLocations: false);
var definitionItem = await GetDefinitionItemAsync(definition).ConfigureAwait(false);
var referenceItem = await location.TryCreateSourceReferenceItemAsync(
definitionItem, includeHiddenLocations: false,
cancellationToken: _context.CancellationToken).ConfigureAwait(false);
if (referenceItem != null)
{
......
......@@ -7,15 +7,18 @@
using Microsoft.CodeAnalysis.FindUsages;
using Microsoft.CodeAnalysis.LanguageServices;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Text;
namespace Microsoft.CodeAnalysis.Editor.FindUsages
{
internal abstract partial class AbstractFindUsagesService : IFindUsagesService
{
public async Task FindImplementationsAsync(Document document, int position, IFindUsagesContext context)
public async Task FindImplementationsAsync(
Document document, int position, IFindUsagesContext context)
{
var cancellationToken = context.CancellationToken;
var tuple = await FindUsagesHelpers.FindImplementationsAsync(
document, position, context.CancellationToken).ConfigureAwait(false);
document, position, cancellationToken).ConfigureAwait(false);
if (tuple == null)
{
context.ReportMessage(EditorFeaturesResources.Cannot_navigate_to_the_symbol_under_the_caret);
......@@ -36,8 +39,9 @@ public async Task FindImplementationsAsync(Document document, int position, IFin
var project = tuple.Value.project;
foreach (var implementation in tuple.Value.implementations)
{
var definitionItem = implementation.ToDefinitionItem(
project.Solution, includeHiddenLocations: false);
var definitionItem = await implementation.ToDefinitionItemAsync(
project.Solution, includeHiddenLocations: false,
cancellationToken: cancellationToken).ConfigureAwait(false);
await context.OnDefinitionFoundAsync(definitionItem).ConfigureAwait(false);
}
}
......
......@@ -13,6 +13,8 @@ namespace Microsoft.CodeAnalysis.Editor.FindUsages
{
internal struct ClassifiedSpansAndHighlightSpan
{
private const string Key = nameof(ClassifiedSpansAndHighlightSpan);
public readonly ImmutableArray<ClassifiedSpan> ClassifiedSpans;
public readonly TextSpan HighlightSpan;
......@@ -24,13 +26,24 @@ internal struct ClassifiedSpansAndHighlightSpan
HighlightSpan = highlightSpan;
}
public static async Task<DocumentSpan> GetClassifiedDocumentSpanAsync(
Document document, TextSpan sourceSpan, CancellationToken cancellationToken)
{
var classifiedSpans = await ClassifyAsync(
document, sourceSpan, cancellationToken).ConfigureAwait(false);
var properties = ImmutableDictionary<string, object>.Empty.Add(Key, classifiedSpans);
return new DocumentSpan(document, sourceSpan, properties);
}
public static async Task<ClassifiedSpansAndHighlightSpan> ClassifyAsync(
DocumentSpan documentSpan, CancellationToken cancellationToken)
{
// If the document span is providing us with the classified spans up front, then we
// can just use that. Otherwise, go back and actually classify the text for the line
// the document span is on.
if (documentSpan.Properties.TryGetValue(nameof(ClassifiedSpansAndHighlightSpan), out var value))
if (documentSpan.Properties.TryGetValue(Key, out var value))
{
return (ClassifiedSpansAndHighlightSpan)value;
}
......
// 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.Collections.Immutable;
using System.Composition;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Completion;
using Microsoft.CodeAnalysis.FindSymbols;
using Microsoft.CodeAnalysis.FindUsages;
......@@ -18,7 +18,7 @@ namespace Microsoft.CodeAnalysis.Editor.FindUsages
{
internal interface IDefinitionsAndReferencesFactory : IWorkspaceService
{
DefinitionsAndReferences CreateDefinitionsAndReferences(
Task<DefinitionsAndReferences> CreateDefinitionsAndReferencesAsync(
Solution solution, IEnumerable<ReferencedSymbol> referencedSymbols,
bool includeHiddenLocations, CancellationToken cancellationToken);
......@@ -29,7 +29,7 @@ internal interface IDefinitionsAndReferencesFactory : IWorkspaceService
[ExportWorkspaceService(typeof(IDefinitionsAndReferencesFactory)), Shared]
internal class DefaultDefinitionsAndReferencesFactory : IDefinitionsAndReferencesFactory
{
public DefinitionsAndReferences CreateDefinitionsAndReferences(
public async Task<DefinitionsAndReferences> CreateDefinitionsAndReferencesAsync(
Solution solution, IEnumerable<ReferencedSymbol> referencedSymbols,
bool includeHiddenLocations, CancellationToken cancellationToken)
{
......@@ -43,9 +43,9 @@ internal class DefaultDefinitionsAndReferencesFactory : IDefinitionsAndReference
// reference locations.
foreach (var referencedSymbol in referencedSymbols.OrderBy(GetPrecedence))
{
ProcessReferencedSymbol(
await ProcessReferencedSymbolAsync(
solution, referencedSymbol, definitions, references,
includeHiddenLocations, uniqueLocations,cancellationToken);
includeHiddenLocations, uniqueLocations, cancellationToken).ConfigureAwait(false);
}
return new DefinitionsAndReferences(
......@@ -87,7 +87,7 @@ private static int GetPrecedence(ReferencedSymbol referencedSymbol)
}
}
private void ProcessReferencedSymbol(
private async Task ProcessReferencedSymbolAsync(
Solution solution,
ReferencedSymbol referencedSymbol,
ArrayBuilder<DefinitionItem> definitions,
......@@ -103,15 +103,15 @@ private static int GetPrecedence(ReferencedSymbol referencedSymbol)
return;
}
var definitionItem = referencedSymbol.Definition.ToDefinitionItem(
solution, includeHiddenLocations, uniqueSpans);
var definitionItem = await referencedSymbol.Definition.ToDefinitionItemAsync(
solution, includeHiddenLocations, cancellationToken, uniqueSpans).ConfigureAwait(false);
definitions.Add(definitionItem);
// Now, create the SourceReferenceItems for all the reference locations
// for this definition.
CreateReferences(
await CreateReferencesAsync(
referencedSymbol, references, definitionItem,
includeHiddenLocations, uniqueSpans);
includeHiddenLocations, uniqueSpans, cancellationToken).ConfigureAwait(false);
// Finally, see if there are any third parties that want to add their
// own result to our collection.
......@@ -133,17 +133,18 @@ private static int GetPrecedence(ReferencedSymbol referencedSymbol)
return null;
}
private static void CreateReferences(
private static async Task CreateReferencesAsync(
ReferencedSymbol referencedSymbol,
ArrayBuilder<SourceReferenceItem> references,
DefinitionItem definitionItem,
bool includeHiddenLocations,
HashSet<DocumentSpan> uniqueSpans)
HashSet<DocumentSpan> uniqueSpans,
CancellationToken cancellationToken)
{
foreach (var referenceLocation in referencedSymbol.Locations)
{
var sourceReferenceItem = referenceLocation.TryCreateSourceReferenceItem(
definitionItem, includeHiddenLocations);
var sourceReferenceItem = await referenceLocation.TryCreateSourceReferenceItemAsync(
definitionItem, includeHiddenLocations, cancellationToken).ConfigureAwait(false);
if (sourceReferenceItem == null)
{
continue;
......@@ -159,10 +160,11 @@ private static int GetPrecedence(ReferencedSymbol referencedSymbol)
internal static class DefinitionItemExtensions
{
public static DefinitionItem ToDefinitionItem(
public static async Task<DefinitionItem> ToDefinitionItemAsync(
this ISymbol definition,
Solution solution,
bool includeHiddenLocations,
CancellationToken cancellationToken,
HashSet<DocumentSpan> uniqueSpans = null)
{
// Ensure we're working with the original definition for the symbol. I.e. When we're
......@@ -206,7 +208,8 @@ internal static class DefinitionItemExtensions
var document = solution.GetDocument(location.SourceTree);
if (document != null)
{
var documentLocation = new DocumentSpan(document, location.SourceSpan);
var documentLocation = await ClassifiedSpansAndHighlightSpan.GetClassifiedDocumentSpanAsync(
document, location.SourceSpan, cancellationToken).ConfigureAwait(false);
if (sourceLocations.Count == 0)
{
sourceLocations.Add(documentLocation);
......@@ -239,10 +242,11 @@ internal static class DefinitionItemExtensions
nameDisplayParts, displayIfNoReferences);
}
public static SourceReferenceItem TryCreateSourceReferenceItem(
public static async Task<SourceReferenceItem> TryCreateSourceReferenceItemAsync(
this ReferenceLocation referenceLocation,
DefinitionItem definitionItem,
bool includeHiddenLocations)
bool includeHiddenLocations,
CancellationToken cancellationToken)
{
var location = referenceLocation.Location;
......@@ -253,10 +257,13 @@ internal static class DefinitionItemExtensions
return null;
}
return new SourceReferenceItem(
definitionItem,
new DocumentSpan(referenceLocation.Document, location.SourceSpan),
referenceLocation.IsWrittenTo);
var document = referenceLocation.Document;
var sourceSpan = location.SourceSpan;
var documentSpan = await ClassifiedSpansAndHighlightSpan.GetClassifiedDocumentSpanAsync(
document, sourceSpan, cancellationToken).ConfigureAwait(false);
return new SourceReferenceItem(definitionItem, documentSpan, referenceLocation.IsWrittenTo);
}
private static SymbolDisplayFormat GetFormat(ISymbol definition)
......
......@@ -70,7 +70,9 @@ internal static class GoToDefinitionHelpers
var options = project.Solution.Options;
definitions.Add(symbol.ToDefinitionItem(solution, includeHiddenLocations: true));
var definitionItem = symbol.ToDefinitionItemAsync(
solution, includeHiddenLocations: true, cancellationToken: cancellationToken).WaitAndGetResult(cancellationToken);
definitions.Add(definitionItem);
var presenter = GetFindUsagesPresenter(streamingPresenters);
var title = string.Format(EditorFeaturesResources._0_declarations,
......
......@@ -23,10 +23,15 @@ internal struct DocumentSpan : IEquatable<DocumentSpan>
/// </summary>
public ImmutableDictionary<string, object> Properties { get; }
public DocumentSpan(Document document, TextSpan sourceSpan)
: this(document, sourceSpan, properties: null)
{
}
public DocumentSpan(
Document document,
TextSpan sourceSpan,
ImmutableDictionary<string, object> properties = null)
ImmutableDictionary<string, object> properties)
{
Document = document;
SourceSpan = sourceSpan;
......
......@@ -138,6 +138,7 @@
<DesignTime>True</DesignTime>
<DependentUpon>FeaturesResources.resx</DependentUpon>
</Compile>
<Compile Include="FindUsages\DefinitionItem.MetadataDefinitionItem.cs" />
<Compile Include="GenerateConstructorFromMembers\GenerateConstructorFromMembersOptions.cs" />
<Compile Include="GenerateConstructorFromMembers\GenerateConstructorWithDialogCodeAction.cs" />
<Compile Include="GenerateEqualsAndGetHashCodeFromMembers\FormatLargeBinaryExpressionRule.cs" />
......@@ -355,7 +356,6 @@
<Compile Include="FindUsages\DefinitionItem.cs" />
<Compile Include="FindUsages\DefinitionItem.DocumentLocationDefinitionItem.cs" />
<Compile Include="FindUsages\DefinitionItem.NonNavigatingDefinitionItem.cs" />
<Compile Include="FindUsages\DefinitionItem.SymbolDefinitionItem.cs" />
<Compile Include="FindUsages\DefinitionsAndReferences.cs" />
<Compile Include="FindUsages\SourceReferenceItem.cs" />
<Compile Include="Diagnostics\EngineV2\DiagnosticAnalyzerExecutor.cs" />
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册