提交 11146bfd 编写于 作者: C CyrusNajmabadi

Remove direct access to the IPackageInstaller service from add-usings search engine.

上级 6c322ae6
......@@ -13,6 +13,7 @@
using Microsoft.CodeAnalysis.Host;
using Microsoft.CodeAnalysis.Internal.Log;
using Microsoft.CodeAnalysis.LanguageServices;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Packaging;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.SymbolSearch;
......@@ -67,7 +68,10 @@ public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
var resultCount = 0;
foreach (var diagnostic in context.Diagnostics)
{
resultCount += await HandleDiagnosticAsync(context, diagnostic).ConfigureAwait(false);
var codeActions = await GetCodeActionsAsync(context, diagnostic).ConfigureAwait(false);
context.RegisterFixes(codeActions, diagnostic);
resultCount += codeActions.Length;
if (resultCount >= MaxResults)
{
break;
......@@ -75,7 +79,7 @@ public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
}
}
private async Task<int> HandleDiagnosticAsync(CodeFixContext context, Diagnostic diagnostic)
private async Task<ImmutableArray<CodeAction>> GetCodeActionsAsync(CodeFixContext context, Diagnostic diagnostic)
{
var document = context.Document;
var span = context.Span;
......@@ -85,7 +89,7 @@ private async Task<int> HandleDiagnosticAsync(CodeFixContext context, Diagnostic
var node = root.FindToken(span.Start, findInsideTrivia: true)
.GetAncestor(n => n.Span.Contains(span) && n != root);
var count = 0;
var result = ArrayBuilder<CodeAction>.GetInstance();
if (node != null)
{
var documentOptions = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false);
......@@ -107,22 +111,19 @@ private async Task<int> HandleDiagnosticAsync(CodeFixContext context, Diagnostic
cancellationToken.ThrowIfCancellationRequested();
var fixData = await reference.GetFixDataAsync(document, node, placeSystemNamespaceFirst, cancellationToken).ConfigureAwait(false);
if (fixData != null)
{
var codeAction = CreateCodeAction(document, fixData);
context.RegisterCodeFix(codeAction, diagnostic);
count++;
}
var codeAction = TryCreateCodeAction(document, fixData);
result.AddIfNotNull(codeAction);
}
}
}
}
}
return count;
return result.ToImmutableAndFree();
}
private CodeAction CreateCodeAction(
private CodeAction TryCreateCodeAction(
Document document, AddImportFixData fixData)
{
switch (fixData.Kind)
......@@ -133,22 +134,19 @@ private async Task<int> HandleDiagnosticAsync(CodeFixContext context, Diagnostic
case AddImportFixKind.MetadataSymbol:
return new MetadataSymbolReferenceCodeAction(document, fixData);
case AddImportFixKind.PackageSymbol:
return new ParentInstallPackageCodeAction(document, fixData, GetPackageInstallerService(document));
case AddImportFixKind.ReferenceAssemblySymbol:
return new AssemblyReferenceCodeAction(document, fixData);
case AddImportFixKind.PackageSymbol:
var packageInstaller = GetPackageInstallerService(document);
return !packageInstaller.IsInstalled(document.Project.Solution.Workspace, document.Project.Id, fixData.PackageName)
? new ParentInstallPackageCodeAction(document, fixData, GetPackageInstallerService(document))
: null;
}
throw ExceptionUtilities.Unreachable;
}
private IPackageInstallerService GetPackageInstallerService(Document document)
{
var workspaceServices = document.Project.Solution.Workspace.Services;
return _packageInstallerService ?? workspaceServices.GetService<IPackageInstallerService>();
}
private async Task<ImmutableArray<Reference>> FindResultsAsync(
Document document, SemanticModel semanticModel, string diagnosticId, SyntaxNode node, CancellationToken cancellationToken)
{
......@@ -158,7 +156,15 @@ private IPackageInstallerService GetPackageInstallerService(Document document)
var projectToAssembly = new ConcurrentDictionary<Project, AsyncLazy<IAssemblySymbol>>(concurrencyLevel: 2, capacity: project.Solution.ProjectIds.Count);
var referenceToCompilation = new ConcurrentDictionary<PortableExecutableReference, Compilation>(concurrencyLevel: 2, capacity: project.Solution.Projects.Sum(p => p.MetadataReferences.Count));
var finder = new SymbolReferenceFinder(this, document, semanticModel, diagnosticId, node, cancellationToken);
var language = document.Project.Language;
var options = document.Project.Solution.Options;
var symbolSearchService = GetSymbolSearchService(document);
var packageSources = GetPackageSources(document, symbolSearchService);
var finder = new SymbolReferenceFinder(
this, document, semanticModel, diagnosticId, node,
symbolSearchService, packageSources, cancellationToken);
// Look for exact matches first:
var exactReferences = await FindResultsAsync(projectToAssembly, referenceToCompilation, project, finder, exact: true, cancellationToken: cancellationToken).ConfigureAwait(false);
......@@ -181,6 +187,30 @@ private IPackageInstallerService GetPackageInstallerService(Document document)
return fuzzyReferences;
}
private ISymbolSearchService GetSymbolSearchService(Document document)
=> document.Project.Solution.Options.GetOption(SymbolSearchOptions.SuggestForTypesInReferenceAssemblies, document.Project.Language)
? _symbolSearchService ?? document.Project.Solution.Workspace.Services.GetService<ISymbolSearchService>()
: null;
private IPackageInstallerService GetPackageInstallerService(Document document)
=> document.Project.Solution.Options.GetOption(SymbolSearchOptions.SuggestForTypesInNuGetPackages, document.Project.Language)
? _packageInstallerService ?? document.Project.Solution.Workspace.Services.GetService<IPackageInstallerService>()
: null;
private ImmutableArray<PackageSource> GetPackageSources(Document document, ISymbolSearchService searchService)
{
if (searchService != null)
{
var installerService = GetPackageInstallerService(document);
if (installerService?.IsEnabled(document.Project.Id) == true)
{
return installerService.PackageSources;
}
}
return ImmutableArray<PackageSource>.Empty;
}
private static bool IsHostOrTestWorkspace(Project project)
{
return project.Solution.Workspace.Kind == WorkspaceKind.Host ||
......
......@@ -2,7 +2,6 @@
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Packaging;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.AddImport
......@@ -11,21 +10,18 @@ internal abstract partial class AbstractAddImportCodeFixProvider<TSimpleNameSynt
{
private partial class PackageReference : Reference
{
private readonly IPackageInstallerService _installerService;
private readonly string _source;
private readonly string _packageName;
private readonly string _versionOpt;
public PackageReference(
AbstractAddImportCodeFixProvider<TSimpleNameSyntax> provider,
IPackageInstallerService installerService,
SearchResult searchResult,
string source,
string packageName,
string versionOpt)
: base(provider, searchResult)
{
_installerService = installerService;
_source = source;
_packageName = packageName;
_versionOpt = versionOpt;
......@@ -56,4 +52,4 @@ public override int GetHashCode()
}
}
}
}
}
\ No newline at end of file
......@@ -9,7 +9,9 @@
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.LanguageServices;
using Microsoft.CodeAnalysis.Packaging;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.SymbolSearch;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.AddImport
......@@ -31,11 +33,15 @@ private partial class SymbolReferenceFinder
private readonly AbstractAddImportCodeFixProvider<TSimpleNameSyntax> _owner;
private readonly SyntaxNode _node;
private readonly ISymbolSearchService _symbolSearchService;
private readonly ImmutableArray<PackageSource> _packageSources;
public SymbolReferenceFinder(
AbstractAddImportCodeFixProvider<TSimpleNameSyntax> owner,
Document document, SemanticModel semanticModel,
string diagnosticId, SyntaxNode node,
ISymbolSearchService symbolSearchService,
ImmutableArray<PackageSource> packageSources,
CancellationToken cancellationToken)
{
_owner = owner;
......@@ -43,6 +49,8 @@ private partial class SymbolReferenceFinder
_semanticModel = semanticModel;
_diagnosticId = diagnosticId;
_node = node;
_symbolSearchService = symbolSearchService;
_packageSources = packageSources;
_containingType = semanticModel.GetEnclosingNamedType(node.SpanStart, cancellationToken);
_containingTypeOrAssembly = _containingType ?? (ISymbol)semanticModel.Compilation.Assembly;
......
......@@ -60,44 +60,23 @@ private partial class SymbolReferenceFinder
ArrayBuilder<Reference> allReferences, TSimpleNameSyntax nameNode,
string name, int arity, bool isAttributeSearch, CancellationToken cancellationToken)
{
var workspaceServices = _document.Project.Solution.Workspace.Services;
var symbolSearchService = _owner._symbolSearchService ?? workspaceServices.GetService<ISymbolSearchService>();
var installerService = _owner.GetPackageInstallerService(_document);
var language = _document.Project.Language;
var options = workspaceServices.Workspace.Options;
var searchReferenceAssemblies = options.GetOption(
SymbolSearchOptions.SuggestForTypesInReferenceAssemblies, language);
var searchNugetPackages = options.GetOption(
SymbolSearchOptions.SuggestForTypesInNuGetPackages, language);
if (symbolSearchService != null &&
searchReferenceAssemblies)
if (_symbolSearchService != null)
{
cancellationToken.ThrowIfCancellationRequested();
await FindReferenceAssemblyTypeReferencesAsync(
symbolSearchService, allReferences, nameNode, name, arity, isAttributeSearch, cancellationToken).ConfigureAwait(false);
allReferences, nameNode, name, arity, isAttributeSearch, cancellationToken).ConfigureAwait(false);
}
if (symbolSearchService != null &&
installerService != null &&
searchNugetPackages &&
installerService.IsEnabled(_document.Project.Id))
foreach (var packageSource in _packageSources)
{
foreach (var packageSource in installerService.PackageSources)
{
cancellationToken.ThrowIfCancellationRequested();
await FindNugetTypeReferencesAsync(
packageSource, symbolSearchService, installerService, allReferences,
nameNode, name, arity, isAttributeSearch, cancellationToken).ConfigureAwait(false);
}
cancellationToken.ThrowIfCancellationRequested();
await FindNugetTypeReferencesAsync(
packageSource, allReferences,
nameNode, name, arity, isAttributeSearch, cancellationToken).ConfigureAwait(false);
}
}
private async Task FindReferenceAssemblyTypeReferencesAsync(
ISymbolSearchService searchService,
ArrayBuilder<Reference> allReferences,
TSimpleNameSyntax nameNode,
string name,
......@@ -106,7 +85,7 @@ private partial class SymbolReferenceFinder
CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
var results = await searchService.FindReferenceAssembliesWithTypeAsync(
var results = await _symbolSearchService.FindReferenceAssembliesWithTypeAsync(
name, arity, cancellationToken).ConfigureAwait(false);
if (results.IsDefault)
{
......@@ -129,8 +108,6 @@ private partial class SymbolReferenceFinder
private async Task FindNugetTypeReferencesAsync(
PackageSource source,
ISymbolSearchService searchService,
IPackageInstallerService installerService,
ArrayBuilder<Reference> allReferences,
TSimpleNameSyntax nameNode,
string name,
......@@ -139,7 +116,7 @@ private partial class SymbolReferenceFinder
CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
var results = await searchService.FindPackagesWithTypeAsync(
var results = await _symbolSearchService.FindPackagesWithTypeAsync(
source.Name, name, arity, cancellationToken).ConfigureAwait(false);
if (results.IsDefault)
{
......@@ -153,10 +130,10 @@ private partial class SymbolReferenceFinder
foreach (var result in results)
{
cancellationToken.ThrowIfCancellationRequested();
await HandleNugetReferenceAsync(
source.Source, installerService, allReferences, nameNode,
project, isAttributeSearch, result,
weight: allReferences.Count).ConfigureAwait(false);
HandleNugetReference(
source.Source, allReferences, nameNode,
project, isAttributeSearch, result,
weight: allReferences.Count);
}
}
......@@ -186,9 +163,8 @@ private partial class SymbolReferenceFinder
_owner, new SearchResult(desiredName, nameNode, result.ContainingNamespaceNames, weight), result));
}
private Task HandleNugetReferenceAsync(
private void HandleNugetReference(
string source,
IPackageInstallerService installerService,
ArrayBuilder<Reference> allReferences,
TSimpleNameSyntax nameNode,
Project project,
......@@ -196,15 +172,10 @@ private partial class SymbolReferenceFinder
PackageWithTypeResult result,
int weight)
{
if (!installerService.IsInstalled(project.Solution.Workspace, project.Id, result.PackageName))
{
var desiredName = GetDesiredName(isAttributeSearch, result.TypeName);
allReferences.Add(new PackageReference(_owner, installerService,
new SearchResult(desiredName, nameNode, result.ContainingNamespaceNames, weight),
source, result.PackageName, result.Version));
}
return SpecializedTasks.EmptyTask;
var desiredName = GetDesiredName(isAttributeSearch, result.TypeName);
allReferences.Add(new PackageReference(_owner,
new SearchResult(desiredName, nameNode, result.ContainingNamespaceNames, weight),
source, result.PackageName, result.Version));
}
private static string GetDesiredName(bool isAttributeSearch, string typeName)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册