提交 2100aeab 编写于 作者: C CyrusNajmabadi 提交者: GitHub

Merge pull request #14024 from CyrusNajmabadi/asyncFarProperties

Don't create definition-entries for items that have no references and have specified DisplayIfNoReferences=false
......@@ -150,8 +150,8 @@ private async Task CreateNoResultsFoundEntryIfNecessaryAsync()
{
// Create a fake definition/reference called "search found no results"
await OnEntryFoundAsync(NoResultsDefinitionItem,
(db, c) => SimpleMessageEntry.CreateAsync(
db, ServicesVisualStudioNextResources.Search_found_no_results)).ConfigureAwait(false);
bucket => SimpleMessageEntry.CreateAsync(
bucket, ServicesVisualStudioNextResources.Search_found_no_results)).ConfigureAwait(false);
}
}
......@@ -173,8 +173,8 @@ private async Task CreateMissingReferenceEntriesIfNecessaryAsync()
// Create a fake reference to this definition that says
// "no references found to <symbolname>".
await OnEntryFoundAsync(definition,
(db, c) => SimpleMessageEntry.CreateAsync(
db, GetMessage(db.DefinitionItem))).ConfigureAwait(false);
bucket => SimpleMessageEntry.CreateAsync(
bucket, GetMessage(bucket.DefinitionItem))).ConfigureAwait(false);
}
}
......@@ -230,27 +230,74 @@ public override async Task OnDefinitionFoundAsync(DefinitionItem definition)
_definitions.Add(definition);
}
foreach (var location in definition.SourceSpans)
// If this is a definition we always want to show, then create entries
// for all the definition locations immediately.
if (definition.DisplayIfNoReferences)
{
await OnEntryFoundAsync(definition,
(db, c) => CreateDocumentLocationEntryAsync(
db, location, isDefinitionLocation: true, cancellationToken: c)).ConfigureAwait(false);
await AddDefinitionEntriesAsync(definition).ConfigureAwait(false);
}
}
private async Task AddDefinitionEntriesAsync(DefinitionItem definition)
{
CancellationToken.ThrowIfCancellationRequested();
// Don't do anything if we already have entries for this definition
// (i.e. another thread beat us to this).
if (HasEntriesForDefinition(definition))
{
return;
}
// First find the bucket corresponding to our definition. If we can't find/create
// one, then don't do anything for this reference.
var definitionBucket = GetOrCreateDefinitionBucket(definition);
if (definitionBucket == null)
{
return;
}
// We could do this inside the lock. but that would mean async activity in a
// lock, and i'd like to avoid that. That does mean that we might do extra
// work if multiple threads end up down htis path. But only one of them will
// win when we access the lock below.
var builder = ImmutableArray.CreateBuilder<Entry>();
foreach (var definitionLocation in definition.SourceSpans)
{
var definitionEntry = await CreateDocumentLocationEntryAsync(
definitionBucket, definitionLocation, isDefinitionLocation: true).ConfigureAwait(false);
if (definitionEntry != null)
{
builder.Add(definitionEntry);
}
}
lock (_gate)
{
// Do one final check to ensure that no other thread beat us here.
if (!HasEntriesForDefinition(definition))
{
_entries = _entries.AddRange(builder);
CurrentVersionNumber++;
}
}
// Let all our subscriptions know that we've updated.
_tableDataSink.FactorySnapshotChanged(this);
}
public override Task OnReferenceFoundAsync(SourceReferenceItem reference)
{
return OnEntryFoundAsync(reference.Definition,
(db, c) => CreateDocumentLocationEntryAsync(
db, reference.SourceSpan, isDefinitionLocation: false, cancellationToken: c));
bucket => CreateDocumentLocationEntryAsync(
bucket, reference.SourceSpan, isDefinitionLocation: false));
}
private async Task OnEntryFoundAsync(
DefinitionItem definition,
Func<RoslynDefinitionBucket, CancellationToken, Task<Entry>> createEntryAsync)
DefinitionItem definition,
Func<RoslynDefinitionBucket, Task<Entry>> createEntryAsync)
{
var cancellationToken = _cancellationTokenSource.Token;
cancellationToken.ThrowIfCancellationRequested();
CancellationToken.ThrowIfCancellationRequested();
// First find the bucket corresponding to our definition. If we can't find/create
// one, then don't do anything for this reference.
......@@ -260,13 +307,19 @@ public override Task OnReferenceFoundAsync(SourceReferenceItem reference)
return;
}
var entry = await createEntryAsync(
definitionBucket, cancellationToken).ConfigureAwait(false);
var entry = await createEntryAsync(definitionBucket).ConfigureAwait(false);
if (entry == null)
{
return;
}
// Ok, we got a *reference* to some definition item. This may have been
// a reference for some definition that we haven't created any definition
// entries for (i.e. becuase it had DisplayIfNoReferences = false). Because
// we've now found a reference, we want to make sure all tis definition
// entries are added.
await AddDefinitionEntriesAsync(definition).ConfigureAwait(false);
lock (_gate)
{
// Once we can make the new entry, add it to our list.
......@@ -278,11 +331,18 @@ public override Task OnReferenceFoundAsync(SourceReferenceItem reference)
_tableDataSink.FactorySnapshotChanged(this);
}
private bool HasEntriesForDefinition(DefinitionItem definition)
{
lock (_gate)
{
return _entries.Any(e => e.DefinitionBucket.DefinitionItem == definition);
}
}
private async Task<Entry> CreateDocumentLocationEntryAsync(
RoslynDefinitionBucket definitionBucket,
DocumentSpan documentSpan,
bool isDefinitionLocation,
CancellationToken cancellationToken)
bool isDefinitionLocation)
{
var document = documentSpan.Document;
......@@ -300,12 +360,12 @@ public override Task OnReferenceFoundAsync(SourceReferenceItem reference)
return null;
}
var sourceText = await document.GetTextAsync(cancellationToken).ConfigureAwait(false);
var sourceText = await document.GetTextAsync(CancellationToken).ConfigureAwait(false);
var referenceSpan = documentSpan.SourceSpan;
var lineSpan = GetLineSpanForReference(sourceText, referenceSpan);
var taggedLineParts = await GetTaggedTextForReferenceAsync(document, referenceSpan, lineSpan, cancellationToken).ConfigureAwait(false);
var taggedLineParts = await GetTaggedTextForReferenceAsync(document, referenceSpan, lineSpan).ConfigureAwait(false);
return new DocumentSpanEntry(
this, workspace, definitionBucket, documentSpan,
......@@ -334,7 +394,7 @@ private TextSpan GetRegionSpanForReference(SourceText sourceText, TextSpan refer
}
private async Task<ClassifiedSpansAndHighlightSpan> GetTaggedTextForReferenceAsync(
Document document, TextSpan referenceSpan, TextSpan widenedSpan, CancellationToken cancellationToken)
Document document, TextSpan referenceSpan, TextSpan widenedSpan)
{
var classificationService = document.GetLanguageService<IEditorClassificationService>();
if (classificationService == null)
......@@ -352,12 +412,12 @@ private TextSpan GetRegionSpanForReference(SourceText sourceText, TextSpan refer
var syntaxSpans = new List<ClassifiedSpan>();
var semanticSpans = new List<ClassifiedSpan>();
var sourceText = await document.GetTextAsync(cancellationToken).ConfigureAwait(false);
var sourceText = await document.GetTextAsync(CancellationToken).ConfigureAwait(false);
await classificationService.AddSyntacticClassificationsAsync(
document, widenedSpan, syntaxSpans, cancellationToken).ConfigureAwait(false);
document, widenedSpan, syntaxSpans, CancellationToken).ConfigureAwait(false);
await classificationService.AddSemanticClassificationsAsync(
document, widenedSpan, semanticSpans, cancellationToken).ConfigureAwait(false);
document, widenedSpan, semanticSpans, CancellationToken).ConfigureAwait(false);
var classifiedSpans = MergeClassifiedSpans(
syntaxSpans, semanticSpans, widenedSpan, sourceText);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册