提交 9cd78a39 编写于 作者: C CyrusNajmabadi

Be a bit paranoid before calling to get a compilation from a random project.

上级 abeeff24
......@@ -144,15 +144,18 @@ private ImmutableArray<ProjectId> GetProjectsForAssembly(IAssemblySymbol assembl
private async Task<ISymbol> GetSymbolAsync(Solution solution, ProjectId projectId, string symbolId, CancellationToken cancellationToken)
{
var comp = await solution.GetProject(projectId).GetCompilationAsync(cancellationToken).ConfigureAwait(false);
var symbols = DocumentationCommentId.GetSymbolsForDeclarationId(symbolId, comp).ToList();
if (symbols.Count == 1)
{
return symbols[0];
}
else if (symbols.Count > 1)
var project = solution.GetProject(projectId);
if (project.SupportsCompilation)
{
var comp = await solution.GetProject(projectId).GetCompilationAsync(cancellationToken).ConfigureAwait(false);
var symbols = DocumentationCommentId.GetSymbolsForDeclarationId(symbolId, comp).ToList();
if (symbols.Count == 1)
{
return symbols[0];
}
else if (symbols.Count > 1)
{
#if false
// if we have multiple matches, use the same index that it appeared as in the original solution.
var originalComp = await this.originalSolution.GetProject(projectId).GetCompilationAsync(cancellationToken).ConfigureAwait(false);
......@@ -163,8 +166,9 @@ private async Task<ISymbol> GetSymbolAsync(Solution solution, ProjectId projectI
return symbols[index];
}
#else
return symbols[0];
return symbols[0];
#endif
}
}
return null;
......
......@@ -3,7 +3,6 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.PooledObjects;
......@@ -50,42 +49,45 @@ internal static partial class DeclarationFinder
internal static async Task<ImmutableArray<SymbolAndProjectId>> FindAllDeclarationsWithNormalQueryInCurrentProcessAsync(
Project project, SearchQuery query, SymbolFilter criteria, CancellationToken cancellationToken)
{
var compilation = await project.GetCompilationAsync(cancellationToken).ConfigureAwait(false);
var list = ArrayBuilder<SymbolAndProjectId>.GetInstance();
// get declarations from the compilation's assembly
await AddCompilationDeclarationsWithNormalQueryAsync(
project, query, criteria, list, cancellationToken).ConfigureAwait(false);
// get declarations from directly referenced projects and metadata
foreach (var assembly in compilation.GetReferencedAssemblySymbols())
if (project.SupportsCompilation)
{
var assemblyProject = project.Solution.GetProject(assembly, cancellationToken);
if (assemblyProject != null)
{
await AddCompilationDeclarationsWithNormalQueryAsync(
assemblyProject, query, criteria, list,
compilation, assembly, cancellationToken).ConfigureAwait(false);
}
else
var compilation = await project.GetCompilationAsync(cancellationToken).ConfigureAwait(false);
// get declarations from the compilation's assembly
await AddCompilationDeclarationsWithNormalQueryAsync(
project, query, criteria, list, cancellationToken).ConfigureAwait(false);
// get declarations from directly referenced projects and metadata
foreach (var assembly in compilation.GetReferencedAssemblySymbols())
{
await AddMetadataDeclarationsWithNormalQueryAsync(
project, assembly, compilation.GetMetadataReference(assembly) as PortableExecutableReference,
query, criteria, list, cancellationToken).ConfigureAwait(false);
var assemblyProject = project.Solution.GetProject(assembly, cancellationToken);
if (assemblyProject != null)
{
await AddCompilationDeclarationsWithNormalQueryAsync(
assemblyProject, query, criteria, list,
compilation, assembly, cancellationToken).ConfigureAwait(false);
}
else
{
await AddMetadataDeclarationsWithNormalQueryAsync(
project, assembly, compilation.GetMetadataReference(assembly) as PortableExecutableReference,
query, criteria, list, cancellationToken).ConfigureAwait(false);
}
}
}
// Make certain all namespace symbols returned by API are from the compilation
// for the passed in project.
for (var i = 0; i < list.Count; i++)
{
var symbolAndProjectId = list[i];
if (symbolAndProjectId.Symbol is INamespaceSymbol ns)
// Make certain all namespace symbols returned by API are from the compilation
// for the passed in project.
for (var i = 0; i < list.Count; i++)
{
list[i] = new SymbolAndProjectId(
compilation.GetCompilationNamespace(ns),
project.Id);
var symbolAndProjectId = list[i];
if (symbolAndProjectId.Symbol is INamespaceSymbol ns)
{
list[i] = new SymbolAndProjectId(
compilation.GetCompilationNamespace(ns),
project.Id);
}
}
}
......
......@@ -108,14 +108,17 @@ internal static partial class DependentTypeFinder
foreach (var group in orderedGroups)
{
var project = solution.GetProject(group.Key);
var compilation = await project.GetCompilationAsync(cancellationToken).ConfigureAwait(false);
foreach (var (symbolKey, _) in group)
if (project.SupportsCompilation)
{
var resolvedSymbol = symbolKey.Resolve(compilation, cancellationToken: cancellationToken).GetAnySymbol();
if (resolvedSymbol is INamedTypeSymbol namedType)
var compilation = await project.GetCompilationAsync(cancellationToken).ConfigureAwait(false);
foreach (var (symbolKey, _) in group)
{
builder.Add(new SymbolAndProjectId<INamedTypeSymbol>(namedType, project.Id));
var resolvedSymbol = symbolKey.Resolve(compilation, cancellationToken: cancellationToken).GetAnySymbol();
if (resolvedSymbol is INamedTypeSymbol namedType)
{
builder.Add(new SymbolAndProjectId<INamedTypeSymbol>(namedType, project.Id));
}
}
}
}
......@@ -538,6 +541,11 @@ bool metadataTypeMatches(SymbolAndProjectIdSet s, INamedTypeSymbol t)
return;
}
if (!project.SupportsCompilation)
{
return;
}
var compilation = await project.GetCompilationAsync(cancellationToken).ConfigureAwait(false);
// Seed the current set of types we're searching for with the types we were given.
......
......@@ -80,26 +80,29 @@ internal partial class FindReferencesSearchEngine
{
using (Logger.LogBlock(FunctionId.FindReference_ProcessProjectAsync, project.Name, _cancellationToken))
{
// make sure we hold onto compilation while we search documents belong to this project
var compilation = await project.GetCompilationAsync(_cancellationToken).ConfigureAwait(false);
var documentTasks = new List<Task>();
foreach (var kvp in documentMap)
if (project.SupportsCompilation)
{
var document = kvp.Key;
// make sure we hold onto compilation while we search documents belong to this project
var compilation = await project.GetCompilationAsync(_cancellationToken).ConfigureAwait(false);
if (document.Project == project)
var documentTasks = new List<Task>();
foreach (var kvp in documentMap)
{
var documentQueue = kvp.Value;
var document = kvp.Key;
if (document.Project == project)
{
var documentQueue = kvp.Value;
documentTasks.Add(Task.Run(() => ProcessDocumentQueueAsync(
document, documentQueue), _cancellationToken));
documentTasks.Add(Task.Run(() => ProcessDocumentQueueAsync(
document, documentQueue), _cancellationToken));
}
}
}
await Task.WhenAll(documentTasks).ConfigureAwait(false);
await Task.WhenAll(documentTasks).ConfigureAwait(false);
GC.KeepAlive(compilation);
GC.KeepAlive(compilation);
}
}
}
}
......
......@@ -24,15 +24,18 @@ internal static class ReferenceLocationExtensions
cancellationToken.ThrowIfCancellationRequested();
var project = projectGroup.Key;
var compilation = await project.GetCompilationAsync(cancellationToken).ConfigureAwait(false);
foreach (var documentGroup in projectGroup)
if (project.SupportsCompilation)
{
var document = documentGroup.Key;
await AddSymbolsAsync(document, documentGroup, result, cancellationToken).ConfigureAwait(false);
}
var compilation = await project.GetCompilationAsync(cancellationToken).ConfigureAwait(false);
foreach (var documentGroup in projectGroup)
{
var document = documentGroup.Key;
await AddSymbolsAsync(document, documentGroup, result, cancellationToken).ConfigureAwait(false);
}
GC.KeepAlive(compilation);
GC.KeepAlive(compilation);
}
}
return result;
......
......@@ -154,7 +154,7 @@ public static partial class SymbolFinder
}
var project = solution.GetProject(symbol.ContainingAssembly, cancellationToken);
if (project != null)
if (project != null && project.SupportsCompilation)
{
var symbolId = symbol.GetSymbolKey();
var compilation = await project.GetCompilationAsync(cancellationToken).ConfigureAwait(false);
......@@ -169,10 +169,8 @@ public static partial class SymbolFinder
return SymbolAndProjectId.Create(result.CandidateSymbols.FirstOrDefault(InSource), project.Id);
}
}
else
{
return default;
}
return default;
}
private static bool InSource(ISymbol symbol)
......
......@@ -95,26 +95,22 @@ public static async Task<IEnumerable<ISymbol>> FindSourceDeclarationsAsync(Proje
throw new ArgumentNullException(nameof(project));
}
if (query.Name != null && string.IsNullOrWhiteSpace(query.Name))
{
return ImmutableArray<SymbolAndProjectId>.Empty;
}
using (Logger.LogBlock(FunctionId.SymbolFinder_Project_Predicate_FindSourceDeclarationsAsync, cancellationToken))
{
if (!await project.ContainsSymbolsWithNameAsync(query.GetPredicate(), filter, cancellationToken).ConfigureAwait(false))
if (!string.IsNullOrWhiteSpace(query.Name) &&
await project.ContainsSymbolsWithNameAsync(query.GetPredicate(), filter, cancellationToken).ConfigureAwait(false))
{
return ImmutableArray<SymbolAndProjectId>.Empty;
}
var compilation = await project.GetCompilationAsync(cancellationToken).ConfigureAwait(false);
var compilation = await project.GetCompilationAsync(cancellationToken).ConfigureAwait(false);
var unfiltered = compilation.GetSymbolsWithName(query.GetPredicate(), filter, cancellationToken)
.Select(s => new SymbolAndProjectId(s, project.Id))
.ToImmutableArray();
var unfiltered = compilation.GetSymbolsWithName(query.GetPredicate(), filter, cancellationToken)
.Select(s => new SymbolAndProjectId(s, project.Id))
.ToImmutableArray();
return DeclarationFinder.FilterByCriteria(unfiltered, filter);
return DeclarationFinder.FilterByCriteria(unfiltered, filter);
}
}
return ImmutableArray<SymbolAndProjectId>.Empty;
}
}
}
......@@ -101,7 +101,7 @@ public static Task<Checksum> GetSourceSymbolsChecksumAsync(Project project, Canc
Project project, Checksum checksum, CancellationToken cancellationToken)
{
var compilation = await project.GetCompilationAsync(cancellationToken).ConfigureAwait(false);
var assembly = compilation.Assembly;
var assembly = compilation?.Assembly;
if (assembly == null)
{
return CreateEmpty(checksum);
......
......@@ -20,8 +20,11 @@ internal static partial class ISolutionExtensions
foreach (var projectId in solution.ProjectIds)
{
var project = solution.GetProject(projectId);
var compilation = await project.GetCompilationAsync(cancellationToken).ConfigureAwait(false);
results.Add(compilation.Assembly.GlobalNamespace);
if (project.SupportsCompilation)
{
var compilation = await project.GetCompilationAsync(cancellationToken).ConfigureAwait(false);
results.Add(compilation.Assembly.GlobalNamespace);
}
}
return results.ToImmutableAndFree();
......
......@@ -219,9 +219,10 @@ internal TextDocumentState GetAdditionalDocumentState(DocumentId documentId)
return _projectState.GetAdditionalDocumentState(documentId);
}
internal Task<bool> ContainsSymbolsWithNameAsync(Func<string, bool> predicate, SymbolFilter filter, CancellationToken cancellationToken)
internal async Task<bool> ContainsSymbolsWithNameAsync(Func<string, bool> predicate, SymbolFilter filter, CancellationToken cancellationToken)
{
return _solution.State.ContainsSymbolsWithNameAsync(Id, predicate, filter, cancellationToken);
return this.SupportsCompilation &&
await _solution.State.ContainsSymbolsWithNameAsync(Id, predicate, filter, cancellationToken).ConfigureAwait(false);
}
internal async Task<IEnumerable<Document>> GetDocumentsWithNameAsync(Func<string, bool> predicate, SymbolFilter filter, CancellationToken cancellationToken)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册