提交 0022e29b 编写于 作者: C CyrusNajmabadi 提交者: GitHub

Merge pull request #19970 from CyrusNajmabadi/addUsingOOP6

Extract a service component from Add-using independent of the CodeFixProvider
......@@ -465,24 +465,8 @@ private async Task<IEnumerable<Diagnostic>> GetProjectDiagnosticsAsync(Project p
private bool IsInteractiveCodeFixProvider(CodeFixProvider provider)
{
// TODO (https://github.com/dotnet/roslyn/issues/4932): Don't restrict CodeFixes in Interactive
if (provider is FullyQualify.AbstractFullyQualifyCodeFixProvider)
{
return true;
}
var providerType = provider?.GetType();
while (providerType != null)
{
if (providerType.IsConstructedGenericType &&
providerType.GetGenericTypeDefinition() == typeof(AddImport.AbstractAddImportCodeFixProvider<>))
{
return true;
}
providerType = providerType.GetTypeInfo().BaseType;
}
return false;
return provider is FullyQualify.AbstractFullyQualifyCodeFixProvider ||
provider is AddImport.AbstractAddImportCodeFixProvider;
}
private static readonly Func<DiagnosticId, List<CodeFixProvider>> s_createList = _ => new List<CodeFixProvider>();
......
......@@ -14,6 +14,7 @@
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Formatting;
using Microsoft.CodeAnalysis.Host.Mef;
using Microsoft.CodeAnalysis.LanguageServices;
using Microsoft.CodeAnalysis.Packaging;
using Microsoft.CodeAnalysis.Shared.Extensions;
......@@ -147,7 +148,7 @@ internal static class AddImportDiagnosticIds
}
[ExportCodeFixProvider(LanguageNames.CSharp, Name = PredefinedCodeFixProviderNames.AddImport), Shared]
internal class CSharpAddImportCodeFixProvider : AbstractAddImportCodeFixProvider<SimpleNameSyntax>
internal class CSharpAddImportCodeFixProvider : AbstractAddImportCodeFixProvider
{
public override ImmutableArray<string> FixableDiagnosticIds => AddImportDiagnosticIds.FixableDiagnosticIds;
......@@ -162,7 +163,11 @@ public CSharpAddImportCodeFixProvider()
: base(installerService, symbolSearchService)
{
}
}
[ExportLanguageService(typeof(IAddImportFeatureService), LanguageNames.CSharp), Shared]
internal class CSharpAddImportFeatureService : AbstractAddImportFeatureService<SimpleNameSyntax>
{
protected override bool CanAddImport(SyntaxNode node, CancellationToken cancellationToken)
{
if (cancellationToken.IsCancellationRequested)
......
......@@ -13,17 +13,15 @@
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;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.AddImport
{
internal abstract partial class AbstractAddImportCodeFixProvider<TSimpleNameSyntax>
: CodeFixProvider, IEqualityComparer<PortableExecutableReference>
where TSimpleNameSyntax : SyntaxNode
internal abstract partial class AbstractAddImportCodeFixProvider : CodeFixProvider
{
private const int MaxResults = 3;
......@@ -41,6 +39,111 @@ internal abstract partial class AbstractAddImportCodeFixProvider<TSimpleNameSynt
_symbolSearchService = symbolSearchService;
}
public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
{
var document = context.Document;
var span = context.Span;
var cancellationToken = context.CancellationToken;
var addImportService = document.GetLanguageService<IAddImportFeatureService>();
var solution = document.Project.Solution;
var options = solution.Options;
var searchReferenceAssemblies = options.GetOption(SymbolSearchOptions.SuggestForTypesInReferenceAssemblies, document.Project.Language);
var searchNuGetPackages = options.GetOption(SymbolSearchOptions.SuggestForTypesInNuGetPackages, document.Project.Language);
var symbolSearchService = searchReferenceAssemblies || searchNuGetPackages
? _symbolSearchService ?? solution.Workspace.Services.GetService<ISymbolSearchService>()
: null;
var packageSources = symbolSearchService != null && searchNuGetPackages
? GetPackageSources(document)
: ImmutableArray<PackageSource>.Empty;
// We might have multiple different diagnostics covering the same span. Have to
// process them all as we might produce different fixes for each diagnostic.
foreach (var diagnostic in context.Diagnostics)
{
var fixes = await addImportService.GetFixesAsync(
document, span, diagnostic.Id, symbolSearchService,
searchReferenceAssemblies, packageSources,
cancellationToken).ConfigureAwait(false);
var codeActions = ArrayBuilder<CodeAction>.GetInstance();
foreach (var fix in fixes)
{
var codeAction = TryCreateCodeAction(document, fix);
codeActions.AddIfNotNull(codeAction);
if (codeActions.Count >= MaxResults)
{
break;
}
}
context.RegisterFixes(codeActions, diagnostic);
codeActions.Free();
}
}
private IPackageInstallerService GetPackageInstallerService(Document document)
=> _packageInstallerService ?? document.Project.Solution.Workspace.Services.GetService<IPackageInstallerService>();
private ImmutableArray<PackageSource> GetPackageSources(Document document)
=> GetPackageInstallerService(document)?.PackageSources ?? ImmutableArray<PackageSource>.Empty;
private CodeAction TryCreateCodeAction(Document document, AddImportFixData fixData)
{
if (fixData == null)
{
return null;
}
switch (fixData.Kind)
{
case AddImportFixKind.ProjectSymbol:
return new ProjectSymbolReferenceCodeAction(document, fixData);
case AddImportFixKind.MetadataSymbol:
return new MetadataSymbolReferenceCodeAction(document, fixData);
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;
}
}
internal interface IAddImportFeatureService : ILanguageService
{
Task<ImmutableArray<AddImportFixData>> GetFixesAsync(
Document document, TextSpan span, string diagnosticId, ISymbolSearchService symbolSearchService,
bool searchReferenceAssemblies, ImmutableArray<PackageSource> packageSources, CancellationToken cancellationToken);
}
internal abstract partial class AbstractAddImportFeatureService<TSimpleNameSyntax>
: IAddImportFeatureService, IEqualityComparer<PortableExecutableReference>
where TSimpleNameSyntax : SyntaxNode
{
private const int MaxResults = 3;
/// <summary>
/// Values for these parameters can be provided (during testing) for mocking purposes.
/// </summary>
protected AbstractAddImportFeatureService()
{
}
protected abstract bool CanAddImport(SyntaxNode node, CancellationToken cancellationToken);
protected abstract bool CanAddImportForMethod(string diagnosticId, ISyntaxFactsService syntaxFacts, SyntaxNode node, out TSimpleNameSyntax nameNode);
protected abstract bool CanAddImportForNamespace(string diagnosticId, SyntaxNode node, out TSimpleNameSyntax nameNode);
......@@ -61,35 +164,16 @@ internal abstract partial class AbstractAddImportCodeFixProvider<TSimpleNameSynt
protected abstract string GetDescription(IReadOnlyList<string> nameParts);
protected abstract (string description, bool hasExistingImport) GetDescription(Document document, INamespaceOrTypeSymbol symbol, SemanticModel semanticModel, SyntaxNode root, CancellationToken cancellationToken);
public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
{
// We might have multiple different diagnostics covering the same span. Have to
// process them all as we might produce different fixes for each diagnostic.
var resultCount = 0;
foreach (var diagnostic in context.Diagnostics)
{
var codeActions = await GetCodeActionsAsync(context, diagnostic).ConfigureAwait(false);
context.RegisterFixes(codeActions, diagnostic);
resultCount += codeActions.Length;
if (resultCount >= MaxResults)
{
break;
}
}
}
private async Task<ImmutableArray<CodeAction>> GetCodeActionsAsync(CodeFixContext context, Diagnostic diagnostic)
public async Task<ImmutableArray<AddImportFixData>> GetFixesAsync(
Document document, TextSpan span, string diagnosticId, ISymbolSearchService symbolSearchService,
bool searchReferenceAssemblies, ImmutableArray<PackageSource> packageSources,
CancellationToken cancellationToken)
{
var document = context.Document;
var span = context.Span;
var cancellationToken = context.CancellationToken;
var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
var node = root.FindToken(span.Start, findInsideTrivia: true)
.GetAncestor(n => n.Span.Contains(span) && n != root);
var result = ArrayBuilder<CodeAction>.GetInstance();
var result = ArrayBuilder<AddImportFixData>.GetInstance();
if (node != null)
{
var documentOptions = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false);
......@@ -103,7 +187,9 @@ private async Task<ImmutableArray<CodeAction>> GetCodeActionsAsync(CodeFixContex
if (this.CanAddImport(node, cancellationToken))
{
var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);
var allSymbolReferences = await FindResultsAsync(document, semanticModel, diagnostic.Id, node, cancellationToken).ConfigureAwait(false);
var allSymbolReferences = await FindResultsAsync(
document, semanticModel, diagnosticId, node, symbolSearchService,
searchReferenceAssemblies, packageSources, cancellationToken).ConfigureAwait(false);
// Nothing found at all. No need to proceed.
foreach (var reference in allSymbolReferences)
......@@ -111,9 +197,7 @@ private async Task<ImmutableArray<CodeAction>> GetCodeActionsAsync(CodeFixContex
cancellationToken.ThrowIfCancellationRequested();
var fixData = await reference.TryGetFixDataAsync(document, node, placeSystemNamespaceFirst, cancellationToken).ConfigureAwait(false);
var codeAction = TryCreateCodeAction(document, fixData);
result.AddIfNotNull(codeAction);
result.AddIfNotNull(fixData);
}
}
}
......@@ -123,36 +207,9 @@ private async Task<ImmutableArray<CodeAction>> GetCodeActionsAsync(CodeFixContex
return result.ToImmutableAndFree();
}
private CodeAction TryCreateCodeAction(Document document, AddImportFixData fixData)
{
if (fixData == null)
{
return null;
}
switch (fixData.Kind)
{
case AddImportFixKind.ProjectSymbol:
return new ProjectSymbolReferenceCodeAction(document, fixData);
case AddImportFixKind.MetadataSymbol:
return new MetadataSymbolReferenceCodeAction(document, fixData);
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 async Task<ImmutableArray<Reference>> FindResultsAsync(
Document document, SemanticModel semanticModel, string diagnosticId, SyntaxNode node, CancellationToken cancellationToken)
Document document, SemanticModel semanticModel, string diagnosticId, SyntaxNode node, ISymbolSearchService symbolSearchService,
bool searchReferenceAssemblies, ImmutableArray<PackageSource> packageSources, CancellationToken cancellationToken)
{
// Caches so we don't produce the same data multiple times while searching
// all over the solution.
......@@ -160,15 +217,9 @@ private CodeAction TryCreateCodeAction(Document document, AddImportFixData fixDa
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 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);
this, document, semanticModel, diagnosticId, node, symbolSearchService,
searchReferenceAssemblies, packageSources, cancellationToken);
// Look for exact matches first:
var exactReferences = await FindResultsAsync(projectToAssembly, referenceToCompilation, project, finder, exact: true, cancellationToken: cancellationToken).ConfigureAwait(false);
......@@ -191,30 +242,6 @@ private CodeAction TryCreateCodeAction(Document document, AddImportFixData fixDa
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 ||
......
......@@ -8,7 +8,7 @@
namespace Microsoft.CodeAnalysis.AddImport
{
internal abstract partial class AbstractAddImportCodeFixProvider<TSimpleNameSyntax>
internal abstract partial class AbstractAddImportCodeFixProvider
{
/// <summary>
/// Code action we use when just adding a using, possibly with a project or
......
......@@ -10,7 +10,7 @@
namespace Microsoft.CodeAnalysis.AddImport
{
internal abstract partial class AbstractAddImportCodeFixProvider<TSimpleNameSyntax>
internal abstract partial class AbstractAddImportCodeFixProvider
{
private class AssemblyReferenceCodeAction : AddImportCodeAction
{
......
......@@ -12,7 +12,7 @@
namespace Microsoft.CodeAnalysis.AddImport
{
internal abstract partial class AbstractAddImportCodeFixProvider<TSimpleNameSyntax>
internal abstract partial class AbstractAddImportCodeFixProvider
{
private class InstallPackageAndAddImportCodeAction : AddImportCodeAction
{
......
......@@ -9,7 +9,7 @@
namespace Microsoft.CodeAnalysis.AddImport
{
internal abstract partial class AbstractAddImportCodeFixProvider<TSimpleNameSyntax>
internal abstract partial class AbstractAddImportCodeFixProvider
{
private class InstallWithPackageManagerCodeAction : CodeAction
{
......
......@@ -5,7 +5,7 @@
namespace Microsoft.CodeAnalysis.AddImport
{
internal abstract partial class AbstractAddImportCodeFixProvider<TSimpleNameSyntax>
internal abstract partial class AbstractAddImportCodeFixProvider
{
private class MetadataSymbolReferenceCodeAction : SymbolReferenceCodeAction
{
......
......@@ -10,7 +10,7 @@
namespace Microsoft.CodeAnalysis.AddImport
{
internal abstract partial class AbstractAddImportCodeFixProvider<TSimpleNameSyntax>
internal abstract partial class AbstractAddImportCodeFixProvider
{
/// <summary>
/// This is the top level 'Install Nuget Package' code action we show in
......
......@@ -4,7 +4,7 @@
namespace Microsoft.CodeAnalysis.AddImport
{
internal abstract partial class AbstractAddImportCodeFixProvider<TSimpleNameSyntax>
internal abstract partial class AbstractAddImportCodeFixProvider
{
/// <summary>
/// Code action for adding an import when we find a symbol in source in either our
......
......@@ -5,7 +5,7 @@
namespace Microsoft.CodeAnalysis.AddImport
{
internal abstract partial class AbstractAddImportCodeFixProvider<TSimpleNameSyntax>
internal abstract partial class AbstractAddImportCodeFixProvider
{
/// <summary>
/// Code action we use when just adding a using, possibly with a project or
......
......@@ -7,14 +7,14 @@
namespace Microsoft.CodeAnalysis.AddImport
{
internal abstract partial class AbstractAddImportCodeFixProvider<TSimpleNameSyntax>
internal abstract partial class AbstractAddImportFeatureService<TSimpleNameSyntax>
{
private partial class AssemblyReference : Reference
{
private readonly ReferenceAssemblyWithTypeResult _referenceAssemblyWithType;
public AssemblyReference(
AbstractAddImportCodeFixProvider<TSimpleNameSyntax> provider,
AbstractAddImportFeatureService<TSimpleNameSyntax> provider,
SearchResult searchResult,
ReferenceAssemblyWithTypeResult referenceAssemblyWithType)
: base(provider, searchResult)
......
......@@ -11,7 +11,7 @@
namespace Microsoft.CodeAnalysis.AddImport
{
internal abstract partial class AbstractAddImportCodeFixProvider<TSimpleNameSyntax>
internal abstract partial class AbstractAddImportFeatureService<TSimpleNameSyntax>
{
private partial class MetadataSymbolReference : SymbolReference
{
......@@ -19,7 +19,7 @@ private partial class MetadataSymbolReference : SymbolReference
private readonly PortableExecutableReference _reference;
public MetadataSymbolReference(
AbstractAddImportCodeFixProvider<TSimpleNameSyntax> provider,
AbstractAddImportFeatureService<TSimpleNameSyntax> provider,
SymbolResult<INamespaceOrTypeSymbol> symbolResult,
ProjectId referenceProjectId,
PortableExecutableReference reference)
......
......@@ -6,7 +6,7 @@
namespace Microsoft.CodeAnalysis.AddImport
{
internal abstract partial class AbstractAddImportCodeFixProvider<TSimpleNameSyntax>
internal abstract partial class AbstractAddImportFeatureService<TSimpleNameSyntax>
{
private partial class PackageReference : Reference
{
......@@ -15,7 +15,7 @@ private partial class PackageReference : Reference
private readonly string _versionOpt;
public PackageReference(
AbstractAddImportCodeFixProvider<TSimpleNameSyntax> provider,
AbstractAddImportFeatureService<TSimpleNameSyntax> provider,
SearchResult searchResult,
string source,
string packageName,
......
......@@ -9,7 +9,7 @@
namespace Microsoft.CodeAnalysis.AddImport
{
internal abstract partial class AbstractAddImportCodeFixProvider<TSimpleNameSyntax>
internal abstract partial class AbstractAddImportFeatureService<TSimpleNameSyntax>
{
/// <summary>
/// Handles references to source symbols both from the current project the user is invoking
......@@ -24,7 +24,7 @@ private partial class ProjectSymbolReference : SymbolReference
private readonly Project _project;
public ProjectSymbolReference(
AbstractAddImportCodeFixProvider<TSimpleNameSyntax> provider,
AbstractAddImportFeatureService<TSimpleNameSyntax> provider,
SymbolResult<INamespaceOrTypeSymbol> symbolResult,
Project project)
: base(provider, symbolResult)
......
......@@ -13,15 +13,15 @@
namespace Microsoft.CodeAnalysis.AddImport
{
internal abstract partial class AbstractAddImportCodeFixProvider<TSimpleNameSyntax>
internal abstract partial class AbstractAddImportFeatureService<TSimpleNameSyntax>
{
private abstract class Reference : IEquatable<Reference>
{
protected readonly AbstractAddImportCodeFixProvider<TSimpleNameSyntax> provider;
protected readonly AbstractAddImportFeatureService<TSimpleNameSyntax> provider;
public readonly SearchResult SearchResult;
protected Reference(
AbstractAddImportCodeFixProvider<TSimpleNameSyntax> provider,
AbstractAddImportFeatureService<TSimpleNameSyntax> provider,
SearchResult searchResult)
{
this.provider = provider;
......
......@@ -10,7 +10,7 @@
namespace Microsoft.CodeAnalysis.AddImport
{
internal abstract partial class AbstractAddImportCodeFixProvider<TSimpleNameSyntax>
internal abstract partial class AbstractAddImportFeatureService<TSimpleNameSyntax>
{
private abstract partial class SymbolReference : Reference
{
......@@ -19,7 +19,7 @@ private abstract partial class SymbolReference : Reference
protected abstract bool ShouldAddWithExistingImport(Document document);
public SymbolReference(
AbstractAddImportCodeFixProvider<TSimpleNameSyntax> provider,
AbstractAddImportFeatureService<TSimpleNameSyntax> provider,
SymbolResult<INamespaceOrTypeSymbol> symbolResult)
: base(provider, new SearchResult(symbolResult))
{
......
......@@ -7,7 +7,7 @@
namespace Microsoft.CodeAnalysis.AddImport
{
internal abstract partial class AbstractAddImportCodeFixProvider<TSimpleNameSyntax>
internal abstract partial class AbstractAddImportFeatureService<TSimpleNameSyntax>
{
/// <summary>
/// SearchScope used for searching *all* the symbols contained within a project/compilation.
......@@ -17,7 +17,7 @@ internal abstract partial class AbstractAddImportCodeFixProvider<TSimpleNameSynt
private class AllSymbolsProjectSearchScope : ProjectSearchScope
{
public AllSymbolsProjectSearchScope(
AbstractAddImportCodeFixProvider<TSimpleNameSyntax> provider,
AbstractAddImportFeatureService<TSimpleNameSyntax> provider,
Project project,
bool exact,
CancellationToken cancellationToken)
......
......@@ -8,7 +8,7 @@
namespace Microsoft.CodeAnalysis.AddImport
{
internal abstract partial class AbstractAddImportCodeFixProvider<TSimpleNameSyntax>
internal abstract partial class AbstractAddImportFeatureService<TSimpleNameSyntax>
{
private class MetadataSymbolsSearchScope : SearchScope
{
......@@ -18,7 +18,7 @@ private class MetadataSymbolsSearchScope : SearchScope
private readonly PortableExecutableReference _metadataReference;
public MetadataSymbolsSearchScope(
AbstractAddImportCodeFixProvider<TSimpleNameSyntax> provider,
AbstractAddImportFeatureService<TSimpleNameSyntax> provider,
Solution solution,
IAssemblySymbol assembly,
ProjectId assemblyProjectId,
......
......@@ -4,14 +4,14 @@
namespace Microsoft.CodeAnalysis.AddImport
{
internal abstract partial class AbstractAddImportCodeFixProvider<TSimpleNameSyntax>
internal abstract partial class AbstractAddImportFeatureService<TSimpleNameSyntax>
{
private abstract class ProjectSearchScope : SearchScope
{
protected readonly Project _project;
public ProjectSearchScope(
AbstractAddImportCodeFixProvider<TSimpleNameSyntax> provider,
AbstractAddImportFeatureService<TSimpleNameSyntax> provider,
Project project,
bool exact,
CancellationToken cancellationToken)
......
......@@ -9,10 +9,10 @@
namespace Microsoft.CodeAnalysis.AddImport
{
internal abstract partial class AbstractAddImportCodeFixProvider<TSimpleNameSyntax>
internal abstract partial class AbstractAddImportFeatureService<TSimpleNameSyntax>
{
/// <summary>
/// SearchScope is used to control where the <see cref="AbstractAddImportCodeFixProvider{TSimpleNameSyntax}"/>
/// SearchScope is used to control where the <see cref="AbstractAddImportFeatureService{TSimpleNameSyntax}"/>
/// searches. We search different scopes in different ways. For example we use
/// SymbolTreeInfos to search unreferenced projects and metadata dlls. However,
/// for the current project we're editing we defer to the compiler to do the
......@@ -21,10 +21,10 @@ internal abstract partial class AbstractAddImportCodeFixProvider<TSimpleNameSynt
private abstract class SearchScope
{
public readonly bool Exact;
protected readonly AbstractAddImportCodeFixProvider<TSimpleNameSyntax> provider;
protected readonly AbstractAddImportFeatureService<TSimpleNameSyntax> provider;
public readonly CancellationToken CancellationToken;
protected SearchScope(AbstractAddImportCodeFixProvider<TSimpleNameSyntax> provider, bool exact, CancellationToken cancellationToken)
protected SearchScope(AbstractAddImportFeatureService<TSimpleNameSyntax> provider, bool exact, CancellationToken cancellationToken)
{
this.provider = provider;
Exact = exact;
......
......@@ -10,7 +10,7 @@
namespace Microsoft.CodeAnalysis.AddImport
{
internal abstract partial class AbstractAddImportCodeFixProvider<TSimpleNameSyntax>
internal abstract partial class AbstractAddImportFeatureService<TSimpleNameSyntax>
{
/// <summary>
/// SearchScope used for searching *only* the source symbols contained within a project/compilation.
......@@ -21,7 +21,7 @@ private class SourceSymbolsProjectSearchScope : ProjectSearchScope
private readonly ConcurrentDictionary<Project, AsyncLazy<IAssemblySymbol>> _projectToAssembly;
public SourceSymbolsProjectSearchScope(
AbstractAddImportCodeFixProvider<TSimpleNameSyntax> provider,
AbstractAddImportFeatureService<TSimpleNameSyntax> provider,
ConcurrentDictionary<Project, AsyncLazy<IAssemblySymbol>> projectToAssembly,
Project project, bool ignoreCase, CancellationToken cancellationToken)
: base(provider, project, ignoreCase, cancellationToken)
......
......@@ -16,7 +16,7 @@
namespace Microsoft.CodeAnalysis.AddImport
{
internal abstract partial class AbstractAddImportCodeFixProvider<TSimpleNameSyntax>
internal abstract partial class AbstractAddImportFeatureService<TSimpleNameSyntax>
{
private partial class SymbolReferenceFinder
{
......@@ -30,17 +30,19 @@ private partial class SymbolReferenceFinder
private readonly ISymbol _containingTypeOrAssembly;
private readonly ISet<INamespaceSymbol> _namespacesInScope;
private readonly ISyntaxFactsService _syntaxFacts;
private readonly AbstractAddImportCodeFixProvider<TSimpleNameSyntax> _owner;
private readonly AbstractAddImportFeatureService<TSimpleNameSyntax> _owner;
private readonly SyntaxNode _node;
private readonly ISymbolSearchService _symbolSearchService;
private readonly bool _searchReferenceAssemblies;
private readonly ImmutableArray<PackageSource> _packageSources;
public SymbolReferenceFinder(
AbstractAddImportCodeFixProvider<TSimpleNameSyntax> owner,
AbstractAddImportFeatureService<TSimpleNameSyntax> owner,
Document document, SemanticModel semanticModel,
string diagnosticId, SyntaxNode node,
ISymbolSearchService symbolSearchService,
bool searchReferenceAssemblies,
ImmutableArray<PackageSource> packageSources,
CancellationToken cancellationToken)
{
......@@ -49,9 +51,16 @@ private partial class SymbolReferenceFinder
_semanticModel = semanticModel;
_diagnosticId = diagnosticId;
_node = node;
_symbolSearchService = symbolSearchService;
_searchReferenceAssemblies = searchReferenceAssemblies;
_packageSources = packageSources;
if (_searchReferenceAssemblies || packageSources.Length> 0)
{
Contract.ThrowIfNull(symbolSearchService);
}
_containingType = semanticModel.GetEnclosingNamedType(node.SpanStart, cancellationToken);
_containingTypeOrAssembly = _containingType ?? (ISymbol)semanticModel.Compilation.Assembly;
_syntaxFacts = document.GetLanguageService<ISyntaxFactsService>();
......
......@@ -8,7 +8,7 @@
namespace Microsoft.CodeAnalysis.AddImport
{
internal abstract partial class AbstractAddImportCodeFixProvider<TSimpleNameSyntax>
internal abstract partial class AbstractAddImportFeatureService<TSimpleNameSyntax>
{
private partial class SymbolReferenceFinder
{
......@@ -60,7 +60,7 @@ private partial class SymbolReferenceFinder
ArrayBuilder<Reference> allReferences, TSimpleNameSyntax nameNode,
string name, int arity, bool isAttributeSearch, CancellationToken cancellationToken)
{
if (_symbolSearchService != null)
if (_searchReferenceAssemblies)
{
cancellationToken.ThrowIfCancellationRequested();
await FindReferenceAssemblyTypeReferencesAsync(
......
......@@ -8,7 +8,7 @@
namespace Microsoft.CodeAnalysis.AddImport
{
internal abstract partial class AbstractAddImportCodeFixProvider<TSimpleNameSyntax>
internal abstract partial class AbstractAddImportFeatureService<TSimpleNameSyntax>
{
private struct SearchResult
{
......
......@@ -8,6 +8,7 @@ Imports Microsoft.CodeAnalysis.AddImports
Imports Microsoft.CodeAnalysis.CaseCorrection
Imports Microsoft.CodeAnalysis.CodeFixes
Imports Microsoft.CodeAnalysis.Formatting
Imports Microsoft.CodeAnalysis.Host.Mef
Imports Microsoft.CodeAnalysis.LanguageServices
Imports Microsoft.CodeAnalysis.Packaging
Imports Microsoft.CodeAnalysis.Simplification
......@@ -17,7 +18,7 @@ Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
Namespace Microsoft.CodeAnalysis.VisualBasic.AddImport
<ExportCodeFixProvider(LanguageNames.VisualBasic, Name:=PredefinedCodeFixProviderNames.AddImport), [Shared]>
Friend Class VisualBasicAddImportCodeFixProvider
Inherits AbstractAddImportCodeFixProvider(Of SimpleNameSyntax)
Inherits AbstractAddImportCodeFixProvider
Public Sub New()
End Sub
......@@ -110,6 +111,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.AddImport
Return ImmutableArray.Create(BC30002, BC30451, BC30456, BC32042, BC36593, BC32045, BC30389, BC31504, BC32016, BC36610, BC36719, BC30512, BC30390, BC42309, BC30182)
End Get
End Property
End Class
<ExportLanguageService(GetType(IAddImportFeatureService), LanguageNames.VisualBasic), [Shared]>
Friend Class VisualBasicAddImportFeatureService
Inherits AbstractAddImportFeatureService(Of SimpleNameSyntax)
Protected Overrides Function CanAddImport(node As SyntaxNode, cancellationToken As CancellationToken) As Boolean
If node.GetAncestor(Of ImportsStatementSyntax)() IsNot Nothing Then
......@@ -125,9 +131,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.AddImport
node As SyntaxNode,
ByRef nameNode As SimpleNameSyntax) As Boolean
Select Case diagnosticId
Case BC30456, BC30390, BC42309, BC30451
Case VisualBasicAddImportCodeFixProvider.BC30456,
VisualBasicAddImportCodeFixProvider.BC30390,
VisualBasicAddImportCodeFixProvider.BC42309,
VisualBasicAddImportCodeFixProvider.BC30451
Exit Select
Case BC30512
Case VisualBasicAddImportCodeFixProvider.BC30512
' look up its corresponding method name
Dim parent = node.GetAncestor(Of InvocationExpressionSyntax)()
If parent Is Nothing Then
......@@ -140,13 +149,13 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.AddImport
node = parent.Expression
End If
Exit Select
Case BC36719
Case VisualBasicAddImportCodeFixProvider.BC36719
If node.IsKind(SyntaxKind.ObjectCollectionInitializer) Then
Return True
End If
Return False
Case BC32016
Case VisualBasicAddImportCodeFixProvider.BC32016
Dim memberAccessName = TryCast(node, MemberAccessExpressionSyntax)?.Name
Dim conditionalAccessName = TryCast(TryCast(TryCast(node, ConditionalAccessExpressionSyntax)?.WhenNotNull, InvocationExpressionSyntax)?.Expression, MemberAccessExpressionSyntax)?.Name
......@@ -179,7 +188,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.AddImport
Protected Overrides Function CanAddImportForNamespace(diagnosticId As String, node As SyntaxNode, ByRef nameNode As SimpleNameSyntax) As Boolean
Select Case diagnosticId
Case BC30002, BC30451
Case VisualBasicAddImportCodeFixProvider.BC30002,
VisualBasicAddImportCodeFixProvider.BC30451
Exit Select
Case Else
Return False
......@@ -194,7 +204,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.AddImport
End Function
Protected Overrides Function CanAddImportForQuery(diagnosticId As String, node As SyntaxNode) As Boolean
If diagnosticId <> BC36593 Then
If diagnosticId <> VisualBasicAddImportCodeFixProvider.BC36593 Then
Return False
End If
......@@ -210,9 +220,16 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.AddImport
Protected Overrides Function CanAddImportForType(
diagnosticId As String, node As SyntaxNode, ByRef nameNode As SimpleNameSyntax) As Boolean
Select Case diagnosticId
Case BC30002, BC30451, BC32042, BC32045, BC30389, BC31504, BC36610, BC30182
Case VisualBasicAddImportCodeFixProvider.BC30002,
VisualBasicAddImportCodeFixProvider.BC30451,
VisualBasicAddImportCodeFixProvider.BC32042,
VisualBasicAddImportCodeFixProvider.BC32045,
VisualBasicAddImportCodeFixProvider.BC30389,
VisualBasicAddImportCodeFixProvider.BC31504,
VisualBasicAddImportCodeFixProvider.BC36610,
VisualBasicAddImportCodeFixProvider.BC30182
Exit Select
Case BC42309
Case VisualBasicAddImportCodeFixProvider.BC42309
Select Case node.Kind
Case SyntaxKind.XmlCrefAttribute
node = CType(node, XmlCrefAttributeSyntax).Reference.DescendantNodes().OfType(Of IdentifierNameSyntax).FirstOrDefault()
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册