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);
            }
Beispiel #2
0
        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));
        }
Beispiel #3
0
        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);
            }
        }
    }
Beispiel #4
0
        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());
        }
Beispiel #5
0
        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);
        }
Beispiel #6
0
        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);
            }
        }