private async Task<DiagnosticAnalysisResultMap<DiagnosticAnalyzer, DiagnosticAnalysisResult>> AnalyzeOutOfProcAsync(
            RemoteHostClient client, CompilationWithAnalyzers analyzerDriver, Project project, CancellationToken cancellationToken)
        {
            var solution = project.Solution;

            var snapshotService = solution.Workspace.Services.GetService<ISolutionChecksumService>();

            // TODO: this should be moved out
            var hostChecksums = GetHostAnalyzerReferences(snapshotService, _analyzerService.GetHostAnalyzerReferences(), cancellationToken);
            var analyzerMap = CreateAnalyzerMap(analyzerDriver.Analyzers.Where(a => !a.MustRunInProcess()));
            if (analyzerMap.Count == 0)
            {
                return DiagnosticAnalysisResultMap.Create(ImmutableDictionary<DiagnosticAnalyzer, DiagnosticAnalysisResult>.Empty, ImmutableDictionary<DiagnosticAnalyzer, AnalyzerTelemetryInfo>.Empty);
            }

            // TODO: send telemetry on session
            using (var session = await client.CreateCodeAnalysisServiceSessionAsync(solution, cancellationToken).ConfigureAwait(false))
            {
                var argument = new DiagnosticArguments(
                    analyzerDriver.AnalysisOptions.ReportSuppressedDiagnostics,
                    analyzerDriver.AnalysisOptions.LogAnalyzerExecutionTime,
                    project.Id, hostChecksums, analyzerMap.Keys.ToArray());

                var result = await session.InvokeAsync(
                    WellKnownServiceHubServices.CodeAnalysisService_CalculateDiagnosticsAsync,
                    new object[] { argument },
                    (s, c) => GetCompilerAnalysisResultAsync(s, analyzerMap, project, c)).ConfigureAwait(false);

                ReportAnalyzerExceptions(project, result.Exceptions);

                return result;
            }
        }
        private static void RegisterWorkspaceHost(Workspace workspace, RemoteHostClient client)
        {
            var vsWorkspace = workspace as VisualStudioWorkspaceImpl;
            if (vsWorkspace == null)
            {
                return;
            }

            vsWorkspace.ProjectTracker.RegisterWorkspaceHost(
                new WorkspaceHost(vsWorkspace, client));
        }
        private async Task <KeepAliveSession> TryGetKeepAliveSessionAsync(RemoteHostClient client, CancellationToken cancellationToken)
        {
            using (await _gate.DisposableWaitAsync(cancellationToken).ConfigureAwait(false))
            {
                if (_sessionDoNotAccessDirectly == null)
                {
                    _sessionDoNotAccessDirectly = await client.TryCreateCodeAnalysisKeepAliveSessionAsync(cancellationToken).ConfigureAwait(false);
                }

                return(_sessionDoNotAccessDirectly);
            }
        }
            public WorkspaceHost(
                VisualStudioWorkspaceImpl workspace,
                RemoteHostClient client)
            {
                _workspace = workspace;
                _client = client;
                _currentSolutionId = workspace.CurrentSolution.Id;

                // Ensure that we populate the remote service with the initial state of
                // the workspace's solution.
                RegisterPrimarySolutionAsync().Wait();
            }
        private async Task <IList <TodoComment> > GetTodoCommentsInRemoteHostAsync(
            RemoteHostClient client, Document document, ImmutableArray <TodoCommentDescriptor> commentDescriptors, CancellationToken cancellationToken)
        {
            var keepAliveSession = await TryGetKeepAliveSessionAsync(client, cancellationToken).ConfigureAwait(false);

            var result = await keepAliveSession.TryInvokeAsync <IList <TodoComment> >(
                nameof(IRemoteTodoCommentService.GetTodoCommentsAsync),
                document.Project.Solution,
                new object[] { document.Id, commentDescriptors }, cancellationToken).ConfigureAwait(false);

            return(result ?? SpecializedCollections.EmptyList <TodoComment>());
        }
            > AnalyzeAsync(
            DocumentAnalysisScope?documentAnalysisScope,
            Project project,
            CompilationWithAnalyzers compilationWithAnalyzers,
            bool forceExecuteAllAnalyzers,
            bool logPerformanceInfo,
            bool getTelemetryInfo,
            CancellationToken cancellationToken
            )
        {
            var result = await AnalyzeCoreAsync().ConfigureAwait(false);

            Debug.Assert(getTelemetryInfo || result.TelemetryInfo.IsEmpty);
            return(result);

            async Task <
                DiagnosticAnalysisResultMap <DiagnosticAnalyzer, DiagnosticAnalysisResult>
                > AnalyzeCoreAsync()
            {
                Contract.ThrowIfFalse(!compilationWithAnalyzers.Analyzers.IsEmpty);

                var remoteHostClient = await RemoteHostClient
                                       .TryGetClientAsync(project, cancellationToken)
                                       .ConfigureAwait(false);

                if (remoteHostClient != null)
                {
                    return(await AnalyzeOutOfProcAsync(
                               documentAnalysisScope,
                               project,
                               compilationWithAnalyzers,
                               remoteHostClient,
                               forceExecuteAllAnalyzers,
                               logPerformanceInfo,
                               getTelemetryInfo,
                               cancellationToken
                               )
                           .ConfigureAwait(false));
                }

                return(await AnalyzeInProcAsync(
                           documentAnalysisScope,
                           project,
                           compilationWithAnalyzers,
                           client : null,
                           logPerformanceInfo,
                           getTelemetryInfo,
                           cancellationToken
                           )
                       .ConfigureAwait(false));
            }
        }
Esempio n. 7
0
            public RemoteUpdateEngine(
                Workspace workspace, RemoteHostClient client,
                ISymbolSearchLogService logService, CancellationToken cancellationToken)
            {
                _workspace         = workspace;
                _logService        = logService;
                _cancellationToken = cancellationToken;

                // this engine is stateful service which maintaining a connection to remote host. so
                // this feature is required to handle remote host recycle situation.
                _client = client;
                _client.ConnectionChanged += OnConnectionChanged;
            }
Esempio n. 8
0
        public async Task <ImmutableArray <ClassifiedSpan> > GetCachedSemanticClassificationsAsync(
            Document document,
            TextSpan textSpan,
            CancellationToken cancellationToken)
        {
            var client = await RemoteHostClient.TryGetClientAsync(document.Project.Solution.Workspace, cancellationToken).ConfigureAwait(false);

            if (client == null)
            {
                // We don't do anything if we fail to get the external process.  That's the case when something has gone
                // wrong, or the user is explicitly choosing to run inproc only.   In neither of those cases do we want
                // to bog down the VS process with the work to semantically classify files.
                return(default);
Esempio n. 9
0
        internal static async Task <ConflictResolution> RenameSymbolAsync(
            Solution solution,
            ISymbol symbol,
            string newName,
            RenameOptionSet optionSet,
            ImmutableHashSet <ISymbol>?nonConflictSymbols,
            CancellationToken cancellationToken)
        {
            Contract.ThrowIfNull(solution);
            Contract.ThrowIfNull(symbol);
            Contract.ThrowIfTrue(string.IsNullOrEmpty(newName));

            cancellationToken.ThrowIfCancellationRequested();

            using (Logger.LogBlock(FunctionId.Renamer_RenameSymbolAsync, cancellationToken))
            {
                if (SerializableSymbolAndProjectId.TryCreate(symbol, solution, cancellationToken, out var serializedSymbol))
                {
                    var client = await RemoteHostClient.TryGetClientAsync(solution.Workspace, cancellationToken).ConfigureAwait(false);

                    if (client != null)
                    {
                        var options = SerializableRenameOptionSet.Dehydrate(optionSet);
                        var nonConflictSymbolIds = nonConflictSymbols?.SelectAsArray(s => SerializableSymbolAndProjectId.Dehydrate(solution, s, cancellationToken)) ?? default;

                        var result = await client.TryInvokeAsync <IRemoteRenamerService, SerializableConflictResolution?>(
                            solution,
                            (service, solutionInfo, cancellationToken) => service.RenameSymbolAsync(
                                solutionInfo,
                                serializedSymbol,
                                newName,
                                options,
                                nonConflictSymbolIds,
                                cancellationToken),
                            callbackTarget : null,
                            cancellationToken).ConfigureAwait(false);

                        if (result.HasValue && result.Value != null)
                        {
                            return(await result.Value.RehydrateAsync(solution, cancellationToken).ConfigureAwait(false));
                        }

                        // TODO: do not fall back to in-proc if client is available (https://github.com/dotnet/roslyn/issues/47557)
                    }
                }
            }

            return(await RenameSymbolInCurrentProcessAsync(
                       solution, symbol, newName, optionSet,
                       nonConflictSymbols, cancellationToken).ConfigureAwait(false));
        }
Esempio n. 10
0
        private static async Task SearchFullyLoadedProjectAsync(
            Project project,
            ImmutableArray <Document> priorityDocuments,
            string searchPattern,
            IImmutableSet <string> kinds,
            Func <INavigateToSearchResult, Task> onResultFound,
            CancellationToken cancellationToken
            )
        {
            var solution = project.Solution;
            var client   = await RemoteHostClient
                           .TryGetClientAsync(project, cancellationToken)
                           .ConfigureAwait(false);

            var onItemFound = GetOnItemFoundCallback(solution, onResultFound, cancellationToken);

            if (client != null)
            {
                var priorityDocumentIds = priorityDocuments.SelectAsArray(d => d.Id);
                var callback            = new NavigateToSearchServiceCallback(onItemFound);
                await client
                .TryInvokeAsync <IRemoteNavigateToSearchService>(
                    solution,
                    (service, solutionInfo, callbackId, cancellationToken) =>
                    service.SearchFullyLoadedProjectAsync(
                        solutionInfo,
                        project.Id,
                        priorityDocumentIds,
                        searchPattern,
                        kinds.ToImmutableArray(),
                        callbackId,
                        cancellationToken
                        ),
                    callback,
                    cancellationToken
                    )
                .ConfigureAwait(false);

                return;
            }

            await SearchFullyLoadedProjectInCurrentProcessAsync(
                project,
                priorityDocuments,
                searchPattern,
                kinds,
                onItemFound,
                cancellationToken
                )
            .ConfigureAwait(false);
        }
Esempio n. 11
0
        private async Task <KeepAliveSession> TryGetKeepAliveSessionAsync(RemoteHostClient client, CancellationToken cancellation)
        {
            using (await _gate.DisposableWaitAsync(cancellation).ConfigureAwait(false))
            {
                if (_sessionDoNotAccessDirectly == null)
                {
                    // we give cancellation none here since the cancellation will cause KeepAlive session to be shutdown
                    // when raised
                    _sessionDoNotAccessDirectly = await client.TryCreateCodeAnalysisKeepAliveSessionAsync(CancellationToken.None).ConfigureAwait(false);
                }

                return(_sessionDoNotAccessDirectly);
            }
        }
        public async Task <Solution> EncapsulateFieldsAsync(
            Document document, ImmutableArray <IFieldSymbol> fields,
            bool updateReferences, CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();

            using (Logger.LogBlock(FunctionId.Renamer_FindRenameLocationsAsync, cancellationToken))
            {
                var solution = document.Project.Solution;
                var client   = await RemoteHostClient.TryGetClientAsync(solution.Workspace, cancellationToken).ConfigureAwait(false);

                if (client != null)
                {
                    var result = await client.TryRunRemoteAsync <(DocumentId, TextChange[])[]>(
Esempio n. 13
0
        public async Task <ReferenceCount?> GetReferenceCountAsync(
            Solution solution,
            DocumentId documentId,
            SyntaxNode?syntaxNode,
            int maxSearchResults,
            CancellationToken cancellationToken
            )
        {
            using (Logger.LogBlock(FunctionId.CodeLens_GetReferenceCountAsync, cancellationToken))
            {
                if (syntaxNode == null)
                {
                    return(null);
                }

                var client = await RemoteHostClient
                             .TryGetClientAsync(solution.Workspace, cancellationToken)
                             .ConfigureAwait(false);

                if (client != null)
                {
                    var result = await client
                                 .TryInvokeAsync <IRemoteCodeLensReferencesService, ReferenceCount?>(
                        solution,
                        (service, solutionInfo, cancellationToken) =>
                        service.GetReferenceCountAsync(
                            solutionInfo,
                            documentId,
                            syntaxNode.Span,
                            maxSearchResults,
                            cancellationToken
                            ),
                        cancellationToken
                        )
                                 .ConfigureAwait(false);

                    return(result.HasValue ? result.Value : null);
                }

                return(await CodeLensReferencesServiceFactory.Instance
                       .GetReferenceCountAsync(
                           solution,
                           documentId,
                           syntaxNode,
                           maxSearchResults,
                           cancellationToken
                           )
                       .ConfigureAwait(false));
            }
        }
Esempio n. 14
0
        public async ValueTask DiscardSolutionUpdateAsync(CancellationToken cancellationToken)
        {
            var client = await RemoteHostClient.TryGetClientAsync(_workspace, cancellationToken).ConfigureAwait(false);

            if (client == null)
            {
                GetLocalService().DiscardSolutionUpdate(_sessionId);
                return;
            }

            await client.TryInvokeAsync <IRemoteEditAndContinueService>(
                (service, cancellationToken) => service.DiscardSolutionUpdateAsync(_sessionId, cancellationToken),
                cancellationToken).ConfigureAwait(false);
        }
        public async Task TestDuplicatedAnalyzers()
        {
            var code = @"class Test
{
    void Method()
    {
        var t = new Test();
    }
}";

            using (var workspace = CreateWorkspace(LanguageNames.CSharp, code))
            {
                var analyzerType      = typeof(DuplicateAnalyzer);
                var analyzerReference = new AnalyzerFileReference(analyzerType.Assembly.Location, new TestAnalyzerAssemblyLoader());

                // add host analyzer as global assets
                var snapshotService = workspace.Services.GetService <IRemotableDataService>();
                var assetBuilder    = new CustomAssetBuilder(workspace);

                var asset = assetBuilder.Build(analyzerReference, CancellationToken.None);
                snapshotService.AddGlobalAsset(analyzerReference, asset, CancellationToken.None);

                var client = await RemoteHostClient.TryGetClientAsync(workspace, CancellationToken.None).ConfigureAwait(false);

                Assert.True(await client.TryRunRemoteAsync(
                                WellKnownRemoteHostServices.RemoteHostService,
                                nameof(IRemoteHostService.SynchronizeGlobalAssetsAsync),
                                new[] { new Checksum[] { asset.Checksum } },
                                workspace.CurrentSolution,
                                callbackTarget: null,
                                cancellationToken: CancellationToken.None));

                // run analysis
                var project = workspace.CurrentSolution.Projects.First().AddAnalyzerReference(analyzerReference);

                var executor       = new DiagnosticIncrementalAnalyzer.InProcOrRemoteHostAnalyzerRunner(owner: null, hostDiagnosticUpdateSource: new MyUpdateSource(workspace));
                var analyzerDriver = (await project.GetCompilationAsync()).WithAnalyzers(
                    analyzerReference.GetAnalyzers(project.Language).Where(a => a.GetType() == analyzerType).ToImmutableArray(),
                    new WorkspaceAnalyzerOptions(project.AnalyzerOptions, project.Solution));

                var result = await executor.AnalyzeAsync(analyzerDriver, project, forcedAnalysis : false, cancellationToken : CancellationToken.None);

                var analyzerResult = result.AnalysisResult[analyzerDriver.Analyzers[0]];

                // check result
                var diagnostics = analyzerResult.GetDocumentDiagnostics(analyzerResult.DocumentIds.First(), AnalysisKind.Syntax);
                Assert.Equal("test", diagnostics[0].Id);
            }
        }
Esempio n. 16
0
        private async Task <DiagnosticAnalysisResultMap <DiagnosticAnalyzer, DiagnosticAnalysisResult> > AnalyzeOutOfProcAsync(
            DocumentAnalysisScope?documentAnalysisScope,
            Project project,
            CompilationWithAnalyzers compilationWithAnalyzers,
            RemoteHostClient client,
            bool forceExecuteAllAnalyzers,
            bool logPerformanceInfo,
            bool getTelemetryInfo,
            CancellationToken cancellationToken)
        {
            var solution = project.Solution;

            using var pooledObject = SharedPools.Default <Dictionary <string, DiagnosticAnalyzer> >().GetPooledObject();
            var analyzerMap = pooledObject.Object;

            var analyzers = documentAnalysisScope?.Analyzers ??
                            compilationWithAnalyzers.Analyzers.Where(a => forceExecuteAllAnalyzers || !a.IsOpenFileOnly(solution.Options));

            analyzerMap.AppendAnalyzerMap(analyzers);

            if (analyzerMap.Count == 0)
            {
                return(DiagnosticAnalysisResultMap <DiagnosticAnalyzer, DiagnosticAnalysisResult> .Empty);
            }

            // Use high priority if we are force executing all analyzers for user action OR serving an active document request.
            var isHighPriority = forceExecuteAllAnalyzers ||
                                 documentAnalysisScope != null && _documentTrackingService?.TryGetActiveDocument() == documentAnalysisScope.TextDocument.Id;

            var argument = new DiagnosticArguments(
                isHighPriority,
                compilationWithAnalyzers.AnalysisOptions.ReportSuppressedDiagnostics,
                logPerformanceInfo,
                getTelemetryInfo,
                documentAnalysisScope?.TextDocument.Id,
                documentAnalysisScope?.Span,
                documentAnalysisScope?.Kind,
                project.Id,
                analyzerMap.Keys.ToArray());

            return(await client.RunRemoteAsync(
                       WellKnownServiceHubService.CodeAnalysis,
                       nameof(IRemoteDiagnosticAnalyzerService.CalculateDiagnosticsAsync),
                       solution,
                       new object[] { argument },
                       callbackTarget : null,
                       (s, c) => ReadCompilerAnalysisResultAsync(s, analyzerMap, documentAnalysisScope, project, c),
                       cancellationToken).ConfigureAwait(false));
        }
Esempio n. 17
0
        internal static async Task FindLiteralReferencesAsync(
            object value,
            TypeCode typeCode,
            Solution solution,
            IStreamingFindLiteralReferencesProgress progress,
            CancellationToken cancellationToken
            )
        {
            using (Logger.LogBlock(FunctionId.FindReference, cancellationToken))
            {
                var client = await RemoteHostClient
                             .TryGetClientAsync(solution.Workspace, cancellationToken)
                             .ConfigureAwait(false);

                if (client != null)
                {
                    // Create a callback that we can pass to the server process to hear about the
                    // results as it finds them.  When we hear about results we'll forward them to
                    // the 'progress' parameter which will then update the UI.
                    var serverCallback = new FindLiteralsServerCallback(solution, progress);

                    _ = await client
                        .TryInvokeAsync <IRemoteSymbolFinderService>(
                        solution,
                        (service, solutionInfo, callbackId, cancellationToken) =>
                        service.FindLiteralReferencesAsync(
                            solutionInfo,
                            callbackId,
                            value,
                            typeCode,
                            cancellationToken
                            ),
                        serverCallback,
                        cancellationToken
                        )
                        .ConfigureAwait(false);
                }
                else
                {
                    await FindLiteralReferencesInCurrentProcessAsync(
                        value,
                        solution,
                        progress,
                        cancellationToken
                        )
                    .ConfigureAwait(false);
                }
            }
        }
Esempio n. 18
0
        public async Task AddSemanticClassificationsAsync(Document document, TextSpan textSpan, List <ClassifiedSpan> result, CancellationToken cancellationToken)
        {
            var classificationService = document.GetLanguageService <ISyntaxClassificationService>();

            if (classificationService == null)
            {
                // When renaming a file's extension through VS when it's opened in editor,
                // the content type might change and the content type changed event can be
                // raised before the renaming propagate through VS workspace. As a result,
                // the document we got (based on the buffer) could still be the one in the workspace
                // before rename happened. This would cause us problem if the document is supported
                // by workspace but not a roslyn language (e.g. xaml, F#, etc.), since none of the roslyn
                // language services would be available.
                //
                // If this is the case, we will simply bail out. It's OK to ignore the request
                // because when the buffer eventually get associated with the correct document in roslyn
                // workspace, we will be invoked again.
                //
                // For example, if you open a xaml from from a WPF project in designer view,
                // and then rename file extension from .xaml to .cs, then the document we received
                // here would still belong to the special "-xaml" project.
                return;
            }

            var client = await RemoteHostClient.TryGetClientAsync(document.Project, cancellationToken).ConfigureAwait(false);

            if (client != null)
            {
                var classifiedSpans = await client.TryInvokeAsync <IRemoteSemanticClassificationService, SerializableClassifiedSpans>(
                    document.Project.Solution,
                    (service, solutionInfo, cancellationToken) => service.GetSemanticClassificationsAsync(solutionInfo, document.Id, textSpan, cancellationToken),
                    callbackTarget : null,
                    cancellationToken).ConfigureAwait(false);

                // if the remote call fails do nothing (error has already been reported)
                if (classifiedSpans.HasValue)
                {
                    classifiedSpans.Value.Rehydrate(result);
                }
            }
            else
            {
                using var _ = ArrayBuilder <ClassifiedSpan> .GetInstance(out var temp);
                await AddSemanticClassificationsInCurrentProcessAsync(
                    document, textSpan, temp, cancellationToken).ConfigureAwait(false);

                AddRange(temp, result);
            }
        }
Esempio n. 19
0
        public async Task <ImmutableArray <DocumentHighlights> > GetDocumentHighlightsAsync(
            Document document,
            int position,
            IImmutableSet <Document> documentsToSearch,
            CancellationToken cancellationToken
            )
        {
            var solution = document.Project.Solution;

            var client = await RemoteHostClient
                         .TryGetClientAsync(document.Project, cancellationToken)
                         .ConfigureAwait(false);

            if (client != null)
            {
                var result = await client
                             .TryInvokeAsync <
                    IRemoteDocumentHighlightsService,
                    ImmutableArray <SerializableDocumentHighlights>
                    >(
                    solution,
                    (service, solutionInfo, cancellationToken) =>
                    service.GetDocumentHighlightsAsync(
                        solutionInfo,
                        document.Id,
                        position,
                        documentsToSearch.SelectAsArray(d => d.Id),
                        cancellationToken
                        ),
                    cancellationToken
                    )
                             .ConfigureAwait(false);

                if (!result.HasValue)
                {
                    return(ImmutableArray <DocumentHighlights> .Empty);
                }

                return(result.Value.SelectAsArray(h => h.Rehydrate(solution)));
            }

            return(await GetDocumentHighlightsInCurrentProcessAsync(
                       document,
                       position,
                       documentsToSearch,
                       cancellationToken
                       )
                   .ConfigureAwait(false));
        }
Esempio n. 20
0
        internal static async Task <ConflictResolution> RenameSymbolAsync(
            Solution solution,
            ISymbol symbol,
            string newName,
            RenameOptionSet optionSet,
            ImmutableHashSet <ISymbol> nonConflictSymbols,
            CancellationToken cancellationToken)
        {
            Contract.ThrowIfNull(solution);
            Contract.ThrowIfNull(symbol);
            Contract.ThrowIfTrue(string.IsNullOrEmpty(newName));

            cancellationToken.ThrowIfCancellationRequested();

            using (Logger.LogBlock(FunctionId.Renamer_RenameSymbolAsync, cancellationToken))
            {
                var project = solution.GetOriginatingProject(symbol);
                if (project != null)
                {
                    var client = await RemoteHostClient.TryGetClientAsync(solution.Workspace, cancellationToken).ConfigureAwait(false);

                    if (client != null)
                    {
                        var result = await client.TryRunRemoteAsync <SerializableConflictResolution>(
                            WellKnownServiceHubServices.CodeAnalysisService,
                            nameof(IRemoteRenamer.RenameSymbolAsync),
                            solution,
                            new object[]
                        {
                            SerializableSymbolAndProjectId.Create(symbol, project, cancellationToken),
                            newName,
                            SerializableRenameOptionSet.Dehydrate(optionSet),
                            nonConflictSymbols?.Select(s => SerializableSymbolAndProjectId.Dehydrate(solution, s, cancellationToken)).ToArray(),
                        },
                            callbackTarget : null,
                            cancellationToken).ConfigureAwait(false);

                        if (result.HasValue)
                        {
                            return(await result.Value.RehydrateAsync(solution, cancellationToken).ConfigureAwait(false));
                        }
                    }
                }
            }

            return(await RenameSymbolInCurrentProcessAsync(
                       solution, symbol, newName, optionSet,
                       nonConflictSymbols, cancellationToken).ConfigureAwait(false));
        }
        internal static async Task FindReferencesAsync(
            SymbolAndProjectId symbolAndProjectId,
            Solution solution,
            IStreamingFindReferencesProgress progress,
            IImmutableSet <Document> documents,
            FindReferencesSearchOptions options,
            CancellationToken cancellationToken)
        {
            using (Logger.LogBlock(FunctionId.FindReference, cancellationToken))
            {
                // If ProjectId is null then this is a call through our old public API.  We don't have
                // the necessary data to effectively run the call out of proc.
                if (symbolAndProjectId.ProjectId != null)
                {
                    var client = await RemoteHostClient.TryGetClientAsync(solution.Workspace, cancellationToken).ConfigureAwait(false);

                    if (client != null)
                    {
                        // Create a callback that we can pass to the server process to hear about the
                        // results as it finds them.  When we hear about results we'll forward them to
                        // the 'progress' parameter which will then update the UI.
                        var serverCallback = new FindReferencesServerCallback(solution, progress, cancellationToken);

                        var success = await client.TryRunRemoteAsync(
                            WellKnownServiceHubServices.CodeAnalysisService,
                            nameof(IRemoteSymbolFinder.FindReferencesAsync),
                            solution,
                            new object[]
                        {
                            SerializableSymbolAndProjectId.Dehydrate(symbolAndProjectId),
                            documents?.Select(d => d.Id).ToArray(),
                            SerializableFindReferencesSearchOptions.Dehydrate(options),
                        },
                            serverCallback,
                            cancellationToken).ConfigureAwait(false);

                        if (success)
                        {
                            return;
                        }
                    }
                }

                // Couldn't effectively search in OOP. Perform the search in-proc.
                await FindReferencesInCurrentProcessAsync(
                    symbolAndProjectId, solution, progress,
                    documents, options, cancellationToken).ConfigureAwait(false);
            }
        }
Esempio n. 22
0
        private async Task <ImmutableArray <SymbolInformation> > GetVsSearchResultsAsync(TestWorkspace workspace, string query)
        {
            var solution = workspace.CurrentSolution;

            using var client = await RemoteHostClient.TryGetClientAsync(workspace, CancellationToken.None).ConfigureAwait(false);

            Assert.NotNull(client);

            var document = solution.Projects.First().Documents.First();

            await UpdatePrimaryWorkspace(client, solution.WithDocumentFilePath(document.Id, Path.Combine(TempRoot.Root, document.FilePath)));

            var workspaceSymbolParams = new WorkspaceSymbolParams
            {
                Query = query,
            };

            var symbolResultsBuilder = ArrayBuilder <SymbolInformation> .GetInstance();

            var threadingContext = workspace.ExportProvider.GetExportedValue <IThreadingContext>();

            var awaitableProgress = new ProgressWithCompletion <SymbolInformation[]>(
                symbols => symbolResultsBuilder.AddRange(symbols),
                threadingContext.JoinableTaskFactory);

            workspaceSymbolParams.PartialResultToken = awaitableProgress;

            var result = await client.RunRemoteAsync <JObject>(
                WellKnownServiceHubService.RemoteLanguageServer,
                Methods.InitializeName,
                solution : null,
                new object[] { new InitializeParams() },
                callbackTarget : null,
                CancellationToken.None).ConfigureAwait(false);

            Assert.True(result["capabilities"]["workspaceSymbolProvider"].ToObject <bool>());

            _ = await client.RunRemoteAsync <SymbolInformation[]>(
                WellKnownServiceHubService.RemoteLanguageServer,
                Methods.WorkspaceSymbolName,
                solution : null,
                new object[] { workspaceSymbolParams },
                callbackTarget : null,
                CancellationToken.None).ConfigureAwait(false);

            await awaitableProgress.WaitAsync(CancellationToken.None);

            return(symbolResultsBuilder.ToImmutableAndFree());
        }
Esempio n. 23
0
        public static async Task <ISymbolSearchUpdateEngine> CreateEngineAsync(
            Workspace workspace,
            ISymbolSearchLogService logService,
            CancellationToken cancellationToken)
        {
            var client = await RemoteHostClient.TryGetClientAsync(workspace, cancellationToken).ConfigureAwait(false);

            if (client != null)
            {
                return(new RemoteUpdateEngine(client, logService));
            }

            // Couldn't go out of proc.  Just do everything inside the current process.
            return(CreateEngineInProcess());
        }
Esempio n. 24
0
        public static async Task <Optional <T> > TryRunRemoteAsync <T>(
            Workspace workspace,
            string targetName,
            Solution?solution,
            IReadOnlyList <object?> arguments,
            CancellationToken cancellationToken
            )
        {
            var client = await RemoteHostClient
                         .TryGetClientAsync(workspace, cancellationToken)
                         .ConfigureAwait(false);

            if (client == null)
            {
                return(default);
Esempio n. 25
0
        public static async Task FindReferencesAsync(
            IFindUsagesContext context,
            ISymbol symbol,
            Project project,
            FindReferencesSearchOptions options
            )
        {
            var cancellationToken = context.CancellationToken;
            var solution          = project.Solution;
            var client            = await RemoteHostClient
                                    .TryGetClientAsync(solution.Workspace, cancellationToken)
                                    .ConfigureAwait(false);

            if (client != null)
            {
                // Create a callback that we can pass to the server process to hear about the
                // results as it finds them.  When we hear about results we'll forward them to
                // the 'progress' parameter which will then update the UI.
                var serverCallback     = new FindUsagesServerCallback(solution, context);
                var symbolAndProjectId = SerializableSymbolAndProjectId.Create(
                    symbol,
                    project,
                    cancellationToken
                    );

                _ = await client
                    .TryInvokeAsync <IRemoteFindUsagesService>(
                    solution,
                    (service, solutionInfo, callbackId, cancellationToken) =>
                    service.FindReferencesAsync(
                        solutionInfo,
                        callbackId,
                        symbolAndProjectId,
                        options,
                        cancellationToken
                        ),
                    serverCallback,
                    cancellationToken
                    )
                    .ConfigureAwait(false);
            }
            else
            {
                // Couldn't effectively search in OOP. Perform the search in-process.
                await FindReferencesInCurrentProcessAsync(context, symbol, project, options)
                .ConfigureAwait(false);
            }
        }
Esempio n. 26
0
        /// <summary>
        /// Signals that the extension has been loaded.  The server can be started immediately, or wait for user action to start.
        /// To start the server, invoke the <see cref="StartAsync"/> event;
        /// </summary>
        public Task OnLoadedAsync()
        {
            var token = _asyncListener.BeginAsyncOperation("OnLoadedAsync");

            // set up event stream so that we start LSP server once Roslyn is loaded
            _eventListener.WorkspaceStarted.ContinueWith(async _ =>
            {
                // initialize things on UI thread
                await InitializeOnUIAsync().ConfigureAwait(false);

                // this might get called before solution is fully loaded and before file is opened.
                // we delay our OOP start until then, but user might do vsstart before that. so we make sure we start OOP if
                // it is not running yet. multiple start is no-op
                ((RemoteHostClientServiceFactory.RemoteHostClientService)_workspace.Services.GetService <IRemoteHostClientService>()).Enable();

                // wait until remote host is available before let platform know that they can activate our LSP
                var client = await RemoteHostClient.TryGetClientAsync(_workspace, CancellationToken.None).ConfigureAwait(false);
                if (client == null)
                {
                    // there is no OOP. either user turned it off, or process got killed.
                    // don't ask platform to start LSP
                    return;
                }

                // let platform know that they can start us
                await StartAsync.InvokeAsync(this, EventArgs.Empty).ConfigureAwait(false);
            }, TaskScheduler.Default).CompletesAsyncOperation(token);

            return(Task.CompletedTask);

            async Task InitializeOnUIAsync()
            {
                await _threadingContext.JoinableTaskFactory.SwitchToMainThreadAsync();

                // this doesn't attempt to solve our JTF and some services being not free-thread issue here, but
                // try to fix this particular deadlock issue only. we already have long discussion on
                // how we need to deal with JTF, Roslyn service requirements and VS services reality conflicting
                // each others. architectural fix should come from the result of that discussion.

                // Ensure the options persisters are loaded since we have to fetch options from the shell
                _lazyOptions.Select(o => o.Value);

                // experimentation service unfortunately uses JTF to jump to UI thread in certain cases
                // which can cause deadlock if 2 parties try to enable OOP from BG and then FG before
                // experimentation service tries to jump to UI thread.
                var experimentationService = _workspace.Services.GetService <IExperimentationService>();
            }
        }
        private async Task<ImmutableArray<INavigateToSearchResult>> SearchDocumentInRemoteProcessAsync(
            RemoteHostClient client, Document document, string searchPattern, CancellationToken cancellationToken)
        {
            var solution = document.Project.Solution;

            using (var session = await client.CreateCodeAnalysisServiceSessionAsync(
                solution, cancellationToken).ConfigureAwait(false))
            {
                var serializableResults = await session.InvokeAsync<SerializableNavigateToSearchResult[]>(
                    WellKnownServiceHubServices.CodeAnalysisService_SearchDocumentAsync,
                    SerializableDocumentId.Dehydrate(document),
                    searchPattern).ConfigureAwait(false);

                return serializableResults.Select(r => r.Rehydrate(solution)).ToImmutableArray();
            }
        }
        private async Task<ImmutableArray<INavigateToSearchResult>> SearchProjectInRemoteProcessAsync(
            RemoteHostClient client, Project project, string searchPattern, CancellationToken cancellationToken)
        {
            var solution = project.Solution;

            using (var session = await client.CreateCodeAnalysisServiceSessionAsync(
                solution, cancellationToken).ConfigureAwait(false))
            {
                var serializableResults = await session.InvokeAsync<SerializableNavigateToSearchResult[]>(
                    nameof(IRemoteNavigateToSearchService.SearchProjectAsync),
                    SerializableProjectId.Dehydrate(project.Id),
                    searchPattern).ConfigureAwait(false);

                return serializableResults.Select(r => r.Rehydrate(solution)).ToImmutableArray();
            }
        }
        private async Task <ImmutableArray <INavigateToSearchResult> > SearchProjectInRemoteProcessAsync(
            RemoteHostClient client, Project project, string searchPattern, CancellationToken cancellationToken)
        {
            var solution = project.Solution;

            using (var session = await client.CreateCodeAnalysisServiceSessionAsync(
                       solution, cancellationToken).ConfigureAwait(false))
            {
                var serializableResults = await session.InvokeAsync <SerializableNavigateToSearchResult[]>(
                    nameof(IRemoteNavigateToSearchService.SearchProjectAsync),
                    SerializableProjectId.Dehydrate(project.Id),
                    searchPattern).ConfigureAwait(false);

                return(serializableResults.Select(r => r.Rehydrate(solution)).ToImmutableArray());
            }
        }
Esempio n. 30
0
        public async ValueTask <bool?> IsActiveStatementInExceptionRegionAsync(Solution solution, ManagedInstructionId instructionId, CancellationToken cancellationToken)
        {
            var client = await RemoteHostClient.TryGetClientAsync(_workspace.Services, cancellationToken).ConfigureAwait(false);

            if (client == null)
            {
                return(await GetLocalService().IsActiveStatementInExceptionRegionAsync(_sessionId, solution, instructionId, cancellationToken).ConfigureAwait(false));
            }

            var result = await client.TryInvokeAsync <IRemoteEditAndContinueService, bool?>(
                solution,
                (service, solutionInfo, cancellationToken) => service.IsActiveStatementInExceptionRegionAsync(solutionInfo, _sessionId, instructionId, cancellationToken),
                cancellationToken).ConfigureAwait(false);

            return(result.HasValue ? result.Value : null);
        }
Esempio n. 31
0
        public async ValueTask <ImmutableArray <ImmutableArray <ActiveStatementSpan> > > GetBaseActiveStatementSpansAsync(Solution solution, ImmutableArray <DocumentId> documentIds, CancellationToken cancellationToken)
        {
            var client = await RemoteHostClient.TryGetClientAsync(_workspace, cancellationToken).ConfigureAwait(false);

            if (client == null)
            {
                return(await GetLocalService().GetBaseActiveStatementSpansAsync(_sessionId, solution, documentIds, cancellationToken).ConfigureAwait(false));
            }

            var result = await client.TryInvokeAsync <IRemoteEditAndContinueService, ImmutableArray <ImmutableArray <ActiveStatementSpan> > >(
                solution,
                (service, solutionInfo, cancellationToken) => service.GetBaseActiveStatementSpansAsync(solutionInfo, _sessionId, documentIds, cancellationToken),
                cancellationToken).ConfigureAwait(false);

            return(result.HasValue ? result.Value : ImmutableArray <ImmutableArray <ActiveStatementSpan> > .Empty);
        }
Esempio n. 32
0
        public async Task <ImmutableArray <ReferenceMethodDescriptor>?> FindReferenceMethodsAsync(
            Solution solution,
            DocumentId documentId,
            SyntaxNode?syntaxNode,
            CancellationToken cancellationToken
            )
        {
            using (
                Logger.LogBlock(FunctionId.CodeLens_FindReferenceMethodsAsync, cancellationToken)
                )
            {
                if (syntaxNode == null)
                {
                    return(null);
                }

                var client = await RemoteHostClient
                             .TryGetClientAsync(solution.Workspace, cancellationToken)
                             .ConfigureAwait(false);

                if (client != null)
                {
                    var result = await client
                                 .TryInvokeAsync <
                        IRemoteCodeLensReferencesService,
                        ImmutableArray <ReferenceMethodDescriptor>?
                        >(
                        solution,
                        (service, solutionInfo, cancellationToken) =>
                        service.FindReferenceMethodsAsync(
                            solutionInfo,
                            documentId,
                            syntaxNode.Span,
                            cancellationToken
                            ),
                        cancellationToken
                        )
                                 .ConfigureAwait(false);

                    return(result.HasValue ? result.Value : null);
                }

                return(await CodeLensReferencesServiceFactory.Instance
                       .FindReferenceMethodsAsync(solution, documentId, syntaxNode, cancellationToken)
                       .ConfigureAwait(false));
            }
        }
Esempio n. 33
0
        /// <summary>
        /// Find the locations that need to be renamed.  Can cross process boundaries efficiently to do this.
        /// </summary>
        public static async Task <LightweightRenameLocations> FindRenameLocationsAsync(
            ISymbol symbol, Solution solution, SymbolRenameOptions options, CodeCleanupOptionsProvider fallbackOptions, CancellationToken cancellationToken)
        {
            Contract.ThrowIfNull(solution);
            Contract.ThrowIfNull(symbol);

            cancellationToken.ThrowIfCancellationRequested();

            using (Logger.LogBlock(FunctionId.Renamer_FindRenameLocationsAsync, cancellationToken))
            {
                if (SerializableSymbolAndProjectId.TryCreate(symbol, solution, cancellationToken, out var serializedSymbol))
                {
                    var client = await RemoteHostClient.TryGetClientAsync(solution.Workspace, cancellationToken).ConfigureAwait(false);

                    if (client != null)
                    {
                        var result = await client.TryInvokeAsync <IRemoteRenamerService, SerializableRenameLocations?>(
                            solution,
                            (service, solutionInfo, callbackId, cancellationToken) => service.FindRenameLocationsAsync(solutionInfo, callbackId, serializedSymbol, options, cancellationToken),
                            callbackTarget : new RemoteOptionsProvider <CodeCleanupOptions>(solution.Workspace.Services, fallbackOptions),
                            cancellationToken).ConfigureAwait(false);

                        if (result.HasValue && result.Value != null)
                        {
                            var rehydrated = await TryRehydrateAsync(
                                solution, symbol, fallbackOptions, result.Value, cancellationToken).ConfigureAwait(false);

                            if (rehydrated != null)
                            {
                                return(rehydrated);
                            }
                        }

                        // TODO: do not fall back to in-proc if client is available (https://github.com/dotnet/roslyn/issues/47557)
                    }
                }
            }

            // Couldn't effectively search in OOP. Perform the search in-proc.
            var renameLocations = await HeavyweightRenameLocations.FindLocationsInCurrentProcessAsync(
                symbol, solution, options, fallbackOptions, cancellationToken).ConfigureAwait(false);

            return(new LightweightRenameLocations(
                       symbol, solution, options, fallbackOptions, renameLocations.Locations,
                       renameLocations.ImplicitLocations.IsDefault ? null : renameLocations.ImplicitLocations.Select(loc => SerializableReferenceLocation.Dehydrate(loc, cancellationToken)).ToArray(),
                       renameLocations.ReferencedSymbols.IsDefault ? null : renameLocations.ReferencedSymbols.Select(sym => SerializableSymbolAndProjectId.Dehydrate(solution, sym, cancellationToken)).ToArray()));
        }
Esempio n. 34
0
        public async ValueTask <bool> HasChangesAsync(Solution solution, ActiveStatementSpanProvider activeStatementSpanProvider, string?sourceFilePath, CancellationToken cancellationToken)
        {
            var client = await RemoteHostClient.TryGetClientAsync(_workspace, cancellationToken).ConfigureAwait(false);

            if (client == null)
            {
                return(await GetLocalService().HasChangesAsync(_sessionId, solution, activeStatementSpanProvider, sourceFilePath, cancellationToken).ConfigureAwait(false));
            }

            var result = await client.TryInvokeAsync <IRemoteEditAndContinueService, bool>(
                solution,
                (service, solutionInfo, callbackId, cancellationToken) => service.HasChangesAsync(solutionInfo, callbackId, _sessionId, sourceFilePath, cancellationToken),
                callbackTarget : new ActiveStatementSpanProviderCallback(activeStatementSpanProvider),
                cancellationToken).ConfigureAwait(false);

            return(result.HasValue ? result.Value : true);
        }
Esempio n. 35
0
        public async ValueTask <ImmutableArray <ActiveStatementSpan> > GetAdjustedActiveStatementSpansAsync(TextDocument document, ActiveStatementSpanProvider activeStatementSpanProvider, CancellationToken cancellationToken)
        {
            var client = await RemoteHostClient.TryGetClientAsync(_workspace, cancellationToken).ConfigureAwait(false);

            if (client == null)
            {
                return(await GetLocalService().GetAdjustedActiveStatementSpansAsync(_sessionId, document, activeStatementSpanProvider, cancellationToken).ConfigureAwait(false));
            }

            var result = await client.TryInvokeAsync <IRemoteEditAndContinueService, ImmutableArray <ActiveStatementSpan> >(
                document.Project.Solution,
                (service, solutionInfo, callbackId, cancellationToken) => service.GetAdjustedActiveStatementSpansAsync(solutionInfo, callbackId, _sessionId, document.Id, cancellationToken),
                callbackTarget : new ActiveStatementSpanProviderCallback(activeStatementSpanProvider),
                cancellationToken).ConfigureAwait(false);

            return(result.HasValue ? result.Value : ImmutableArray <ActiveStatementSpan> .Empty);
        }
 public RemoteUpdateEngine(RemoteHostClient.Session session)
 {
     _session = session;
 }