コード例 #1
0
        public static async Task FindImplementationsAsync(
            ISymbol symbol, Project project, IFindUsagesContext context)
        {
            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.FindImplementationsAsync(solutionInfo, callbackId, symbolAndProjectId, cancellationToken),
                    serverCallback,
                    cancellationToken).ConfigureAwait(false);
            }
            else
            {
                // Couldn't effectively search in OOP. Perform the search in-process.
                await FindImplementationsInCurrentProcessAsync(
                    symbol, project, context).ConfigureAwait(false);
            }
        }
コード例 #2
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(await result.Value.SelectAsArrayAsync(h => h.RehydrateAsync(solution)).ConfigureAwait(false));
            }

            return(await GetDocumentHighlightsInCurrentProcessAsync(
                       document, position, documentsToSearch, cancellationToken).ConfigureAwait(false));
        }
コード例 #3
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.RunRemoteAsync <IList <SerializableDocumentHighlights> >(
                    WellKnownServiceHubService.CodeAnalysis,
                    nameof(IRemoteDocumentHighlights.GetDocumentHighlightsAsync),
                    solution,
                    new object[]
                {
                    document.Id,
                    position,
                    documentsToSearch.Select(d => d.Id).ToArray()
                },
                    callbackTarget : null,
                    cancellationToken).ConfigureAwait(false);

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

            return(await GetDocumentHighlightsInCurrentProcessAsync(
                       document, position, documentsToSearch, cancellationToken).ConfigureAwait(false));
        }
コード例 #4
0
        public async Task <Solution> EncapsulateFieldsAsync(
            Document document, ImmutableArray <IFieldSymbol> fields,
            CleanCodeGenerationOptionsProvider fallbackOptions,
            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 fieldSymbolKeys = fields.SelectAsArray(f => SymbolKey.CreateString(f, cancellationToken));

                    var result = await client.TryInvokeAsync <IRemoteEncapsulateFieldService, ImmutableArray <(DocumentId, ImmutableArray <TextChange>)> >(
                        solution,
                        (service, solutionInfo, callbackId, cancellationToken) => service.EncapsulateFieldsAsync(solutionInfo, callbackId, document.Id, fieldSymbolKeys, updateReferences, cancellationToken),
                        callbackTarget : new RemoteOptionsProvider <CleanCodeGenerationOptions>(solution.Workspace.Services, fallbackOptions),
                        cancellationToken).ConfigureAwait(false);

                    if (!result.HasValue)
                    {
                        return(solution);
                    }

                    return(await RemoteUtilities.UpdateSolutionAsync(
                               solution, result.Value, cancellationToken).ConfigureAwait(false));
                }
            }

            return(await EncapsulateFieldsInCurrentProcessAsync(
                       document, fields, fallbackOptions, updateReferences, cancellationToken).ConfigureAwait(false));
        }
コード例 #5
0
        public static async Task <ImmutableArray <INamedTypeSymbol> > FindTypesAsync(
            INamedTypeSymbol type,
            Solution solution,
            IImmutableSet <Project>?projects,
            bool transitive,
            DependentTypesKind kind,
            CancellationToken cancellationToken)
        {
            if (SerializableSymbolAndProjectId.TryCreate(type, solution, cancellationToken, out var serializedType))
            {
                var client = await RemoteHostClient.TryGetClientAsync(solution.Workspace, cancellationToken).ConfigureAwait(false);

                if (client != null)
                {
                    var projectIds = projects?.Where(p => RemoteSupportedLanguages.IsSupported(p.Language)).SelectAsArray(p => p.Id) ?? default;

                    var result = await client.TryInvokeAsync <IRemoteDependentTypeFinderService, ImmutableArray <SerializableSymbolAndProjectId> >(
                        solution,
                        (service, solutionInfo, cancellationToken) => service.FindTypesAsync(solutionInfo, serializedType, projectIds, transitive, kind, cancellationToken),
                        cancellationToken).ConfigureAwait(false);

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

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

                // TODO: Do not fall back to in-proc https://github.com/dotnet/roslyn/issues/47557
            }

            return(await FindTypesInCurrentProcessAsync(type, solution, projects, transitive, kind, cancellationToken).ConfigureAwait(false));
        }
コード例 #6
0
        public async Task TestHostAnalyzers()
        {
            var code = @"class Test
{
    void Method()
    {
        var t = new Test();
    }
}";

            using (var workspace = CreateWorkspace(LanguageNames.CSharp, code))
            {
                var analyzerType      = typeof(CSharpUseExplicitTypeDiagnosticAnalyzer);
                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.None));

                // set option
                workspace.TryApplyChanges(workspace.CurrentSolution.WithOptions(workspace.Options
                                                                                .WithChangedOption(CSharpCodeStyleOptions.VarWhenTypeIsApparent, new CodeStyleOption <bool>(false, NotificationOption.Suggestion))));

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

                var runner = CreateAnalyzerRunner(workspace);

                var compilationWithAnalyzers = (await project.GetCompilationAsync()).WithAnalyzers(
                    analyzerReference.GetAnalyzers(project.Language).Where(a => a.GetType() == analyzerType).ToImmutableArray(),
                    new WorkspaceAnalyzerOptions(project.AnalyzerOptions, project.Solution));

                // no result for open file only analyzer unless forced
                var result = await runner.AnalyzeAsync(compilationWithAnalyzers, project, forcedAnalysis : false, cancellationToken : CancellationToken.None);

                Assert.Empty(result.AnalysisResult);

                result = await runner.AnalyzeAsync(compilationWithAnalyzers, project, forcedAnalysis : true, cancellationToken : CancellationToken.None);

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

                // check result
                var diagnostics = analyzerResult.GetDocumentDiagnostics(analyzerResult.DocumentIds.First(), AnalysisKind.Semantic);
                Assert.Equal(IDEDiagnosticIds.UseExplicitTypeDiagnosticId, diagnostics[0].Id);
            }
        }
コード例 #7
0
        public async Task AddSemanticClassificationsAsync(Document document, TextSpan textSpan, ClassificationOptions options, ArrayBuilder <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 database = document.Project.Solution.Options.GetPersistentStorageDatabase();

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

            if (client != null)
            {
                // We have an oop connection.  If we're not fully loaded, see if we can retrieve a previously cached set
                // of classifications from the server.  Note: this must be a separate call (instead of being part of
                // service.GetSemanticClassificationsAsync below) as we want to try to read in the cached
                // classifications without doing any syncing to the OOP process.
                var isFullyLoaded = IsFullyLoaded(document, cancellationToken);
                if (await TryGetCachedClassificationsAsync(document, textSpan, result, client, database, isFullyLoaded, cancellationToken).ConfigureAwait(false))
                {
                    return;
                }

                // Call the project overload.  Semantic classification only needs the current project's information
                // to classify properly.
                var classifiedSpans = await client.TryInvokeAsync <IRemoteSemanticClassificationService, SerializableClassifiedSpans>(
                    document.Project,
                    (service, solutionInfo, cancellationToken) => service.GetSemanticClassificationsAsync(solutionInfo, document.Id, textSpan, options, database, isFullyLoaded, cancellationToken),
                    cancellationToken).ConfigureAwait(false);

                // if the remote call fails do nothing (error has already been reported)
                if (classifiedSpans.HasValue)
                {
                    classifiedSpans.Value.Rehydrate(result);
                }
            }
            else
            {
                await AddSemanticClassificationsInCurrentProcessAsync(
                    document, textSpan, options, result, cancellationToken).ConfigureAwait(false);
            }
        }
コード例 #8
0
        public static async Task <RazorRemoteHostClient?> CreateAsync(Workspace workspace, CancellationToken cancellationToken = default)
        {
            var client = await RemoteHostClient.TryGetClientAsync(workspace.Services, cancellationToken).ConfigureAwait(false);

            var descriptors = new RazorServiceDescriptorsWrapper("dummy", _ => throw ExceptionUtilities.Unreachable, ImmutableArray <IMessagePackFormatter> .Empty, ImmutableArray <IFormatterResolver> .Empty, Array.Empty <(Type, Type?)>());

            return(client == null ? null : new RazorRemoteHostClient((ServiceHubRemoteHostClient)client, descriptors, RazorRemoteServiceCallbackDispatcherRegistry.Empty));
        }
コード例 #9
0
        public static async Task <ImmutableArray <ISymbol> > FindSourceDeclarationsWithPatternAsync(
            Project project,
            string pattern,
            SymbolFilter criteria,
            CancellationToken cancellationToken
            )
        {
            if (project == null)
            {
                throw new ArgumentNullException(nameof(project));
            }

            if (pattern == null)
            {
                throw new ArgumentNullException(nameof(pattern));
            }

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

            if (client != null)
            {
                var result = await client
                             .TryInvokeAsync <
                    IRemoteSymbolFinderService,
                    ImmutableArray <SerializableSymbolAndProjectId>
                    >(
                    project.Solution,
                    (service, solutionInfo, cancellationToken) =>
                    service.FindProjectSourceDeclarationsWithPatternAsync(
                        solutionInfo,
                        project.Id,
                        pattern,
                        criteria,
                        cancellationToken
                        ),
                    cancellationToken
                    )
                             .ConfigureAwait(false);

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

                return(await RehydrateAsync(project.Solution, result.Value, cancellationToken)
                       .ConfigureAwait(false));
            }

            return(await FindSourceDeclarationsWithPatternInCurrentProcessAsync(
                       project,
                       pattern,
                       criteria,
                       cancellationToken
                       )
                   .ConfigureAwait(false));
        }
コード例 #10
0
                                    DiagnosticData?syntaxError)> EmitSolutionUpdateAsync(
            Solution solution,
            ActiveStatementSpanProvider activeStatementSpanProvider,
            IDiagnosticAnalyzerService diagnosticService,
            EditAndContinueDiagnosticUpdateSource diagnosticUpdateSource,
            CancellationToken cancellationToken)
        {
            ManagedModuleUpdates            moduleUpdates;
            ImmutableArray <DiagnosticData> diagnosticData;
            ImmutableArray <(DocumentId DocumentId, ImmutableArray <RudeEditDiagnostic> Diagnostics)> rudeEdits;
            DiagnosticData?syntaxError;

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

            if (client == null)
            {
                var results = await GetLocalService().EmitSolutionUpdateAsync(_sessionId, solution, activeStatementSpanProvider, cancellationToken).ConfigureAwait(false);

                moduleUpdates  = results.ModuleUpdates;
                diagnosticData = results.GetDiagnosticData(solution);
                rudeEdits      = results.RudeEdits;
                syntaxError    = results.GetSyntaxErrorData(solution);
            }
            else
            {
                var result = await client.TryInvokeAsync <IRemoteEditAndContinueService, EmitSolutionUpdateResults.Data>(
                    solution,
                    (service, solutionInfo, callbackId, cancellationToken) => service.EmitSolutionUpdateAsync(solutionInfo, callbackId, _sessionId, cancellationToken),
                    callbackTarget : new ActiveStatementSpanProviderCallback(activeStatementSpanProvider),
                    cancellationToken).ConfigureAwait(false);

                if (result.HasValue)
                {
                    moduleUpdates  = result.Value.ModuleUpdates;
                    diagnosticData = result.Value.Diagnostics;
                    rudeEdits      = result.Value.RudeEdits;
                    syntaxError    = result.Value.SyntaxError;
                }
                else
                {
                    moduleUpdates  = new ManagedModuleUpdates(ManagedModuleUpdateStatus.Blocked, ImmutableArray <ManagedModuleUpdate> .Empty);
                    diagnosticData = ImmutableArray <DiagnosticData> .Empty;
                    rudeEdits      = ImmutableArray <(DocumentId DocumentId, ImmutableArray <RudeEditDiagnostic> Diagnostics)> .Empty;
                    syntaxError    = null;
                }
            }

            // clear emit/apply diagnostics reported previously:
            diagnosticUpdateSource.ClearDiagnostics();

            // clear all reported rude edits:
            diagnosticService.Reanalyze(_workspace, documentIds: rudeEdits.Select(d => d.DocumentId));

            // report emit/apply diagnostics:
            diagnosticUpdateSource.ReportDiagnostics(_workspace, solution, diagnosticData);

            return(moduleUpdates, diagnosticData, rudeEdits, syntaxError);
        }
        private async Task ReportAnalyzerPerformanceAsync(Document document, CompilationWithAnalyzers?compilation, CancellationToken cancellationToken)
        {
            try
            {
                if (compilation == null)
                {
                    return;
                }

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

                if (client == null)
                {
                    // no remote support
                    return;
                }

                cancellationToken.ThrowIfCancellationRequested();

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

                var containsData = false;
                foreach (var analyzer in compilation.Analyzers)
                {
                    var telemetryInfo = await compilation.GetAnalyzerTelemetryInfoAsync(analyzer, cancellationToken).ConfigureAwait(false);

                    if (!containsData && telemetryInfo.ExecutionTime.Ticks > 0)
                    {
                        // this is unfortunate tweak due to how GetAnalyzerTelemetryInfoAsync works when analyzers are asked
                        // one by one rather than in bulk.
                        containsData = true;
                    }

                    pooledObject.Object.Add(analyzer, telemetryInfo);
                }

                if (!containsData)
                {
                    // looks like there is no new data from driver. skip reporting.
                    return;
                }

                _ = await client.TryRunRemoteAsync(
                    WellKnownServiceHubService.CodeAnalysis,
                    nameof(IRemoteDiagnosticAnalyzerService.ReportAnalyzerPerformance),
                    solution : null,
                    new object[] { pooledObject.Object.ToAnalyzerPerformanceInfo(DiagnosticAnalyzerInfoCache), /* unit count */ 1 },
                    callbackTarget : null,
                    cancellationToken).ConfigureAwait(false);
            }
            catch (Exception ex) when(FatalError.ReportWithoutCrashUnlessCanceled(ex))
            {
                // this is fire and forget method
            }
        }
コード例 #12
0
        public async ValueTask <ImmutableArray <Diagnostic> > GetDocumentDiagnosticsAsync(Document document, Document designTimeDocument, ActiveStatementSpanProvider activeStatementSpanProvider, CancellationToken cancellationToken)
        {
            var client = await RemoteHostClient.TryGetClientAsync(Workspace, cancellationToken).ConfigureAwait(false);

            if (client == null)
            {
                var diagnostics = await GetLocalService().GetDocumentDiagnosticsAsync(document, activeStatementSpanProvider, cancellationToken).ConfigureAwait(false);

                if (designTimeDocument != document)
                {
                    diagnostics = diagnostics.SelectAsArray(diagnostic => RemapLocation(designTimeDocument, DiagnosticData.Create(diagnostic, document.Project)));
                }

                return(diagnostics);
            }

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

            if (!diagnosticData.HasValue)
            {
                return(ImmutableArray <Diagnostic> .Empty);
            }

            var project = document.Project;

            using var _ = ArrayBuilder <Diagnostic> .GetInstance(out var result);

            foreach (var data in diagnosticData.Value)
            {
                Debug.Assert(data.DataLocation != null);

                Diagnostic diagnostic;

                // Workaround for solution crawler not supporting mapped locations to make Razor work.
                // We pretend the diagnostic is in the original document, but use the mapped line span.
                // Razor will ignore the column (which will be off because #line directives can't currently map columns) and only use the line number.
                if (designTimeDocument != document && data.DataLocation.IsMapped)
                {
                    diagnostic = RemapLocation(designTimeDocument, data);
                }
                else
                {
                    diagnostic = await data.ToDiagnosticAsync(document.Project, cancellationToken).ConfigureAwait(false);
                }

                result.Add(diagnostic);
            }

            return(result.ToImmutable());
        }
コード例 #13
0
        public async Task <string?> TryGetHostGroupIdAsync(CancellationToken cancellationToken)
        {
            var client = await RemoteHostClient.TryGetClientAsync(_workspace, cancellationToken).ConfigureAwait(false);

            if (client == null)
            {
                return(null);
            }

            return(client.ClientId);
        }
コード例 #14
0
        public static async Task <RazorRemoteHostClient?> TryGetClientAsync(HostWorkspaceServices services, RazorServiceDescriptorsWrapper serviceDescriptors, RazorRemoteServiceCallbackDispatcherRegistry callbackDispatchers, CancellationToken cancellationToken = default)
        {
            var client = await RemoteHostClient.TryGetClientAsync(services, cancellationToken).ConfigureAwait(false);

            if (client is null)
            {
                return(null);
            }

            return(new RazorRemoteHostClient((ServiceHubRemoteHostClient)client, serviceDescriptors, callbackDispatchers));
        }
コード例 #15
0
        public async Task <string> GetHostGroupIdAsync(CancellationToken cancellationToken)
        {
            var client = await RemoteHostClient.TryGetClientAsync(_workspace, cancellationToken).ConfigureAwait(false);

            if (client == null)
            {
                // exception is handled by code lens engine
                throw new InvalidOperationException("remote host doesn't exist");
            }

            return(client.ClientId);
        }
コード例 #16
0
        public static async Task <ImmutableArray <SerializableImportCompletionItem> > GetUnimportedExtensionMethodsAsync(
            Document document,
            int position,
            ITypeSymbol receiverTypeSymbol,
            ISet <string> namespaceInScope,
            bool forceIndexCreation,
            CancellationToken cancellationToken)
        {
            SerializableUnimportedExtensionMethods items;

            var ticks = Environment.TickCount;

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

            if (client != null)
            {
                var receiverTypeSymbolKeyData = SymbolKey.CreateString(receiverTypeSymbol, cancellationToken);

                var result = await client.TryInvokeAsync <IRemoteExtensionMethodImportCompletionService, SerializableUnimportedExtensionMethods>(
                    project.Solution,
                    (service, solutionInfo, cancellationToken) => service.GetUnimportedExtensionMethodsAsync(
                        solutionInfo, document.Id, position, receiverTypeSymbolKeyData, namespaceInScope.ToImmutableArray(), forceIndexCreation, cancellationToken),
                    callbackTarget : null,
                    cancellationToken).ConfigureAwait(false);

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

                items = result.Value;
            }
            else
            {
                items = await GetUnimportedExtensionMethodsInCurrentProcessAsync(document, position, receiverTypeSymbol, namespaceInScope, forceIndexCreation, cancellationToken).ConfigureAwait(false);
            }

            // report telemetry:
            var totalTicks = Environment.TickCount - ticks;

            CompletionProvidersLogger.LogExtensionMethodCompletionTicksDataPoint(totalTicks);
            CompletionProvidersLogger.LogExtensionMethodCompletionMethodsProvidedDataPoint(items.CompletionItems.Length);
            CompletionProvidersLogger.LogExtensionMethodCompletionGetSymbolsTicksDataPoint(items.GetSymbolsTicks);
            CompletionProvidersLogger.LogExtensionMethodCompletionCreateItemsTicksDataPoint(items.CreateItemsTicks);

            if (items.IsPartialResult)
            {
                CompletionProvidersLogger.LogExtensionMethodCompletionPartialResultCount();
            }

            return(items.CompletionItems);
        }
            > 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));
            }
        }
コード例 #18
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);
コード例 #19
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);
        }
コード例 #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))
            {
                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));
        }
コード例 #21
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);
        }
コード例 #22
0
        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[])[]>(
コード例 #23
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));
            }
        }
コード例 #24
0
        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);
            }
        }
コード例 #25
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);
                }
            }
        }
コード例 #26
0
        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);
            }
        }
コード例 #27
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));
        }
コード例 #28
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);
            }
        }
コード例 #29
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());
        }
コード例 #30
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);