public SymbolReferenceFinder( AbstractAddImportFeatureService <TSimpleNameSyntax> owner, Document document, SemanticModel semanticModel, string diagnosticId, SyntaxNode node, ISymbolSearchService symbolSearchService, AddImportOptions options, ImmutableArray <PackageSource> packageSources, CancellationToken cancellationToken) { _owner = owner; _document = document; _semanticModel = semanticModel; _diagnosticId = diagnosticId; _node = node; _symbolSearchService = symbolSearchService; _options = options; _packageSources = packageSources; if (options.SearchReferenceAssemblies || packageSources.Length > 0) { Contract.ThrowIfNull(symbolSearchService); } _syntaxFacts = document.GetLanguageService <ISyntaxFactsService>(); _namespacesInScope = GetNamespacesInScope(cancellationToken); }
public async Task <ImmutableArray <AddImportFixData> > GetFixesAsync( Document document, TextSpan span, string diagnosticId, int maxResults, bool allowInHiddenRegions, ISymbolSearchService symbolSearchService, AddImportOptions options, ImmutableArray <PackageSource> packageSources, CancellationToken cancellationToken) { var client = await RemoteHostClient.TryGetClientAsync(document.Project, cancellationToken).ConfigureAwait(false); if (client != null) { var result = await client.TryInvokeAsync <IRemoteMissingImportDiscoveryService, ImmutableArray <AddImportFixData> >( document.Project.Solution, (service, solutionInfo, callbackId, cancellationToken) => service.GetFixesAsync(solutionInfo, callbackId, document.Id, span, diagnosticId, maxResults, allowInHiddenRegions, options, packageSources, cancellationToken), callbackTarget : symbolSearchService, cancellationToken).ConfigureAwait(false); return(result.HasValue ? result.Value : ImmutableArray <AddImportFixData> .Empty); } return(await GetFixesInCurrentProcessAsync( document, span, diagnosticId, maxResults, allowInHiddenRegions, symbolSearchService, options, packageSources, cancellationToken).ConfigureAwait(false)); }
public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) { var document = context.Document; var span = context.Span; var cancellationToken = context.CancellationToken; var diagnostics = context.Diagnostics; var addImportService = document.GetRequiredLanguageService <IAddImportFeatureService>(); var services = document.Project.Solution.Workspace.Services; var codeActionOptions = context.Options.GetOptions(document.Project.LanguageServices); var searchOptions = codeActionOptions.SearchOptions; var symbolSearchService = _symbolSearchService ?? services.GetRequiredService <ISymbolSearchService>(); var installerService = searchOptions.SearchNuGetPackages ? _packageInstallerService ?? services.GetService <IPackageInstallerService>() : null; var packageSources = installerService?.IsEnabled(document.Project.Id) == true ? installerService.TryGetPackageSources() : ImmutableArray <PackageSource> .Empty; if (packageSources.IsEmpty) { searchOptions = searchOptions with { SearchNuGetPackages = false }; } var cleanupOptions = await document.GetCodeCleanupOptionsAsync(context.Options, cancellationToken).ConfigureAwait(false); var addImportOptions = new AddImportOptions( searchOptions, cleanupOptions, codeActionOptions.HideAdvancedMembers); var fixesForDiagnostic = await addImportService.GetFixesForDiagnosticsAsync( document, span, diagnostics, MaxResults, symbolSearchService, addImportOptions, packageSources, cancellationToken).ConfigureAwait(false); foreach (var(diagnostic, fixes) in fixesForDiagnostic) { // Limit the results returned since this will be displayed to the user var codeActions = addImportService.GetCodeActionsForFixes(document, fixes, installerService, MaxResults); context.RegisterFixes(codeActions, diagnostic); } } }
private async Task <ImmutableArray <AddImportFixData> > GetFixesInCurrentProcessAsync( Document document, TextSpan span, string diagnosticId, int maxResults, bool allowInHiddenRegions, ISymbolSearchService symbolSearchService, AddImportOptions options, ImmutableArray <PackageSource> packageSources, CancellationToken cancellationToken) { var root = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var node = root.FindToken(span.Start, findInsideTrivia: true) .GetAncestor(n => n.Span.Contains(span) && n != root); using var _ = ArrayBuilder <AddImportFixData> .GetInstance(out var result); if (node != null) { using (Logger.LogBlock(FunctionId.Refactoring_AddImport, cancellationToken)) { if (!cancellationToken.IsCancellationRequested) { if (CanAddImport(node, allowInHiddenRegions, cancellationToken)) { var semanticModel = await document.GetRequiredSemanticModelAsync(cancellationToken).ConfigureAwait(false); var allSymbolReferences = await FindResultsAsync( document, semanticModel, diagnosticId, node, maxResults, symbolSearchService, options, packageSources, cancellationToken).ConfigureAwait(false); // Nothing found at all. No need to proceed. foreach (var reference in allSymbolReferences) { cancellationToken.ThrowIfCancellationRequested(); var fixData = await reference.TryGetFixDataAsync(document, node, allowInHiddenRegions, cancellationToken).ConfigureAwait(false); result.AddIfNotNull(fixData); } } } } } return(result.ToImmutable()); }
private async Task <ImmutableArray <Reference> > FindResultsAsync( Document document, SemanticModel semanticModel, string diagnosticId, SyntaxNode node, int maxResults, ISymbolSearchService symbolSearchService, AddImportOptions options, ImmutableArray <PackageSource> packageSources, CancellationToken cancellationToken) { // Caches so we don't produce the same data multiple times while searching // all over the solution. var project = document.Project; 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, symbolSearchService, options, packageSources, cancellationToken); // Look for exact matches first: var exactReferences = await FindResultsAsync(projectToAssembly, referenceToCompilation, project, maxResults, finder, exact : true, cancellationToken : cancellationToken).ConfigureAwait(false); if (exactReferences.Length > 0) { return(exactReferences); } // No exact matches found. Fall back to fuzzy searching. // Only bother doing this for host workspaces. We don't want this for // things like the Interactive workspace as this will cause us to // create expensive bk-trees which we won't even be able to save for // future use. if (!IsHostOrRemoteWorkspace(project)) { return(ImmutableArray <Reference> .Empty); } var fuzzyReferences = await FindResultsAsync(projectToAssembly, referenceToCompilation, project, maxResults, finder, exact : false, cancellationToken : cancellationToken).ConfigureAwait(false); return(fuzzyReferences); }
public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) { var document = context.Document; var span = context.Span; var cancellationToken = context.CancellationToken; var diagnostics = context.Diagnostics; var addImportService = document.GetLanguageService <IAddImportFeatureService>(); var solution = document.Project.Solution; var searchNuGetPackages = solution.Options.GetOption(SymbolSearchOptions.SuggestForTypesInNuGetPackages, document.Project.Language); var options = new AddImportOptions( context.Options.SearchReferenceAssemblies, context.Options.HideAdvancedMembers); var symbolSearchService = options.SearchReferenceAssemblies || searchNuGetPackages ? _symbolSearchService ?? solution.Workspace.Services.GetService <ISymbolSearchService>() : null; var installerService = GetPackageInstallerService(document); var packageSources = searchNuGetPackages && symbolSearchService != null && installerService?.IsEnabled(document.Project.Id) == true ? installerService.TryGetPackageSources() : ImmutableArray <PackageSource> .Empty; var fixesForDiagnostic = await addImportService.GetFixesForDiagnosticsAsync( document, span, diagnostics, MaxResults, symbolSearchService, options, packageSources, cancellationToken).ConfigureAwait(false); foreach (var(diagnostic, fixes) in fixesForDiagnostic) { // Limit the results returned since this will be displayed to the user var codeActions = addImportService.GetCodeActionsForFixes(document, fixes, installerService, MaxResults); context.RegisterFixes(codeActions, diagnostic); } }