提交 1dbcb4c2 编写于 作者: C CyrusNajmabadi

Break out package searching from reference assembly searching.

上级 17cf310d
......@@ -16,16 +16,15 @@ internal abstract partial class AbstractAddImportCodeFixProvider<TSimpleNameSynt
{
private class AssemblyReference : Reference
{
private readonly PackageWithTypeResult _packageWithType;
private readonly ReferenceAssemblyWithTypeResult _referenceAssemblyWithType;
public AssemblyReference(
AbstractAddImportCodeFixProvider<TSimpleNameSyntax> provider,
IPackageInstallerService installerService,
SearchResult searchResult,
PackageWithTypeResult packageWithType)
ReferenceAssemblyWithTypeResult referenceAssemblyWithType)
: base(provider, searchResult)
{
_packageWithType = packageWithType;
_referenceAssemblyWithType = referenceAssemblyWithType;
}
public override Task<CodeAction> CreateCodeActionAsync(
......@@ -39,12 +38,12 @@ public override bool Equals(object obj)
{
var reference = obj as AssemblyReference;
return base.Equals(obj) &&
_packageWithType.AssemblyName == reference._packageWithType.AssemblyName;
_referenceAssemblyWithType.AssemblyName == reference._referenceAssemblyWithType.AssemblyName;
}
public override int GetHashCode()
{
return Hash.Combine(_packageWithType.AssemblyName, base.GetHashCode());
return Hash.Combine(_referenceAssemblyWithType.AssemblyName, base.GetHashCode());
}
private class AssemblyReferenceCodeAction : CodeAction
......@@ -72,7 +71,7 @@ private class AssemblyReferenceCodeAction : CodeAction
_node = node;
_placeSystemNamespaceFirst = placeSystemNamespaceFirst;
_title = $"{reference.provider.GetDescription(reference.SearchResult.NameParts)} ({string.Format(FeaturesResources.from_0, reference._packageWithType.AssemblyName)})";
_title = $"{reference.provider.GetDescription(reference.SearchResult.NameParts)} ({string.Format(FeaturesResources.from_0, reference._referenceAssemblyWithType.AssemblyName)})";
_lazyResolvedPath = new Lazy<string>(ResolvePath);
}
......@@ -83,7 +82,7 @@ private string ResolvePath()
{
var assemblyResolverService = _document.Project.Solution.Workspace.Services.GetService<IFrameworkAssemblyPathResolver>();
var packageWithType = _reference._packageWithType;
var packageWithType = _reference._referenceAssemblyWithType;
var fullyQualifiedName = string.Join(".", packageWithType.ContainingNamespaceNames.Concat(packageWithType.TypeName));
var assemblyPath = assemblyResolverService?.ResolveAssemblyPath(
_document.Project.Id, packageWithType.AssemblyName, fullyQualifiedName);
......@@ -123,4 +122,4 @@ protected override async Task<IEnumerable<CodeActionOperation>> ComputeOperation
}
}
}
}
}
\ No newline at end of file
......@@ -231,22 +231,61 @@ private async Task<IList<SymbolReference>> GetMatchingTypesAsync(SearchScope sea
string name, int arity, bool isAttributeSearch, CancellationToken cancellationToken)
{
var workspaceServices = _document.Project.Solution.Workspace.Services;
var searchService = _owner._packageSearchService ?? workspaceServices.GetService<IPackageSearchService>();
var packageSearchService = _owner._packageSearchService ?? workspaceServices.GetService<IPackageSearchService>();
var referenceAssemblySearchService = _owner._referenceAssemblySearchService ?? workspaceServices.GetService<IReferenceAssemblySearchService>();
var installerService = _owner._packageInstallerService ?? workspaceServices.GetService<IPackageInstallerService>();
if (searchService != null && installerService != null && installerService.IsEnabled)
if (referenceAssemblySearchService != null)
{
cancellationToken.ThrowIfCancellationRequested();
await FindReferenceAssemblyTypeReferencesAsync(
referenceAssemblySearchService, allReferences, nameNode, name, arity, isAttributeSearch, cancellationToken).ConfigureAwait(false);
}
if (packageSearchService != null &&
referenceAssemblySearchService != null &&
installerService.IsEnabled)
{
foreach (var packageSource in installerService.PackageSources)
{
cancellationToken.ThrowIfCancellationRequested();
await FindNugetOrReferenceAssemblyTypeReferencesAsync(
packageSource, searchService, installerService, allReferences,
await FindNugetTypeReferencesAsync(
packageSource, packageSearchService, installerService, allReferences,
nameNode, name, arity, isAttributeSearch, cancellationToken).ConfigureAwait(false);
}
}
}
private async Task FindNugetOrReferenceAssemblyTypeReferencesAsync(
private async Task FindReferenceAssemblyTypeReferencesAsync(
IReferenceAssemblySearchService searchService,
List<Reference> allReferences,
TSimpleNameSyntax nameNode,
string name,
int arity,
bool isAttributeSearch,
CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
var results = searchService.FindReferenceAssembliesWithType(name, arity, cancellationToken);
var project = _document.Project;
var projectId = project.Id;
var workspace = project.Solution.Workspace;
int weight = 0;
foreach (var result in results)
{
cancellationToken.ThrowIfCancellationRequested();
await HandleReferenceAssemblyReferenceAsync(
allReferences, nameNode, project,
isAttributeSearch, result, weight, cancellationToken).ConfigureAwait(false);
weight++;
}
}
private async Task FindNugetTypeReferencesAsync(
PackageSource source,
IPackageSearchService searchService,
IPackageInstallerService installerService,
......@@ -268,30 +307,20 @@ private async Task<IList<SymbolReference>> GetMatchingTypesAsync(SearchScope sea
foreach (var result in results)
{
cancellationToken.ThrowIfCancellationRequested();
if (result.IsDesktopFramework)
{
await HandleReferenceAssemblyReferenceAsync(
installerService, allReferences, nameNode, project,
isAttributeSearch, result, weight, cancellationToken).ConfigureAwait(false);
}
else
{
await HandleNugetReferenceAsync(
source.Source, installerService, allReferences, nameNode,
project, isAttributeSearch, result, weight).ConfigureAwait(false);
}
await HandleNugetReferenceAsync(
source.Source, installerService, allReferences, nameNode,
project, isAttributeSearch, result, weight).ConfigureAwait(false);
weight++;
}
}
private async Task HandleReferenceAssemblyReferenceAsync(
IPackageInstallerService installerService,
List<Reference> allReferences,
TSimpleNameSyntax nameNode,
Project project,
bool isAttributeSearch,
PackageWithTypeResult result,
ReferenceAssemblyWithTypeResult result,
int weight,
CancellationToken cancellationToken)
{
......@@ -307,8 +336,8 @@ private async Task<IList<SymbolReference>> GetMatchingTypesAsync(SearchScope sea
}
}
var desiredName = GetDesiredName(isAttributeSearch, result);
allReferences.Add(new AssemblyReference(_owner, installerService,
var desiredName = GetDesiredName(isAttributeSearch, result.TypeName);
allReferences.Add(new AssemblyReference(_owner,
new SearchResult(desiredName, nameNode, result.ContainingNamespaceNames, weight), result));
}
......@@ -324,7 +353,7 @@ private async Task<IList<SymbolReference>> GetMatchingTypesAsync(SearchScope sea
{
if (!installerService.IsInstalled(project.Solution.Workspace, project.Id, result.PackageName))
{
var desiredName = GetDesiredName(isAttributeSearch, result);
var desiredName = GetDesiredName(isAttributeSearch, result.TypeName);
allReferences.Add(new PackageReference(_owner, installerService,
new SearchResult(desiredName, nameNode, result.ContainingNamespaceNames, weight),
source, result.PackageName, result.Version));
......@@ -333,9 +362,9 @@ private async Task<IList<SymbolReference>> GetMatchingTypesAsync(SearchScope sea
return SpecializedTasks.EmptyTask;
}
private static string GetDesiredName(bool isAttributeSearch, PackageWithTypeResult result)
private static string GetDesiredName(bool isAttributeSearch, string typeName)
{
var desiredName = result.TypeName;
var desiredName = typeName;
if (isAttributeSearch)
{
desiredName = desiredName.GetWithoutAttributeSuffix(isCaseSensitive: false);
......
......@@ -26,14 +26,17 @@ internal abstract partial class AbstractAddImportCodeFixProvider<TSimpleNameSynt
private readonly IPackageInstallerService _packageInstallerService;
private readonly IPackageSearchService _packageSearchService;
private readonly IReferenceAssemblySearchService _referenceAssemblySearchService;
/// <summary>Values for these parameters can be provided (during testing) for mocking purposes.</summary>
protected AbstractAddImportCodeFixProvider(
IPackageInstallerService packageInstallerService = null,
IPackageSearchService packageSearchService = null)
IPackageSearchService packageSearchService = null,
IReferenceAssemblySearchService referenceAssemblySearchService = null)
{
_packageInstallerService = packageInstallerService;
_packageSearchService = packageSearchService;
_referenceAssemblySearchService = referenceAssemblySearchService;
}
protected abstract bool CanAddImport(SyntaxNode node, CancellationToken cancellationToken);
......
......@@ -25,26 +25,52 @@ internal interface IPackageSearchService : IWorkspaceService
string source, string name, int arity, CancellationToken cancellationToken);
}
internal interface IReferenceAssemblySearchService : IWorkspaceService
{
/// <summary>
/// Searches for reference assemblies that contain a type with the provided name and arity.
/// Note: Implementations are free to return the results they feel best for the
/// given data. Specifically, they can do exact or fuzzy matching on the name.
/// They can use or ignore the arity depending on their capabilities.
///
/// Implementations should return results in order from best to worst (from their
/// perspective).
/// </summary>
IEnumerable<ReferenceAssemblyWithTypeResult> FindReferenceAssembliesWithType(
string name, int arity, CancellationToken cancellationToken);
}
internal class ReferenceAssemblyWithTypeResult
{
public readonly IReadOnlyList<string> ContainingNamespaceNames;
public readonly string AssemblyName;
public readonly string TypeName;
public ReferenceAssemblyWithTypeResult(
string assemblyName,
string typeName,
IReadOnlyList<string> containingNamespaceNames)
{
AssemblyName = assemblyName;
TypeName = typeName;
ContainingNamespaceNames = containingNamespaceNames;
}
}
internal class PackageWithTypeResult
{
public readonly bool IsDesktopFramework;
public readonly IReadOnlyList<string> ContainingNamespaceNames;
public readonly string PackageName;
public readonly string AssemblyName;
public readonly string TypeName;
public readonly string Version;
public PackageWithTypeResult(
bool isDesktopFramework,
string packageName,
string assemblyName,
string typeName,
string version,
IReadOnlyList<string> containingNamespaceNames)
{
IsDesktopFramework = isDesktopFramework;
PackageName = packageName;
AssemblyName = assemblyName;
TypeName = typeName;
Version = string.IsNullOrWhiteSpace(version) ? null : version;
ContainingNamespaceNames = containingNamespaceNames;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册