Esempio n. 1
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);
        }
Esempio n. 2
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);
        }
        public async ValueTask <SourceSpan?> GetCurrentActiveStatementPositionAsync(ManagedInstructionId instruction, CancellationToken cancellationToken)
        {
            try
            {
                var solution = GetCurrentCompileTimeSolution();
                var activeStatementTrackingService = GetActiveStatementTrackingService();

                var activeStatementSpanProvider = new ActiveStatementSpanProvider((documentId, filePath, cancellationToken) =>
                                                                                  activeStatementTrackingService.GetSpansAsync(solution, documentId, filePath, cancellationToken));

                var span = await GetDebuggingSession().GetCurrentActiveStatementPositionAsync(solution, activeStatementSpanProvider, instruction.ToContract(), cancellationToken).ConfigureAwait(false);

                return(span?.ToSourceSpan().FromContract());
            }
            catch (Exception e) when(FatalError.ReportAndCatchUnlessCanceled(e, cancellationToken))
            {
                return(null);
            }
        }
Esempio n. 4
0
        private static async Task <ImmutableArray <Diagnostic> > AnalyzeSemanticsImplAsync(Workspace workspace, Document designTimeDocument, CancellationToken cancellationToken)
        {
            var designTimeSolution  = designTimeDocument.Project.Solution;
            var compileTimeSolution = workspace.Services.GetRequiredService <ICompileTimeSolutionProvider>().GetCompileTimeSolution(designTimeSolution);

            var compileTimeDocument = await compileTimeSolution.GetDocumentAsync(designTimeDocument.Id, includeSourceGenerated : true, cancellationToken).ConfigureAwait(false);

            if (compileTimeDocument == null)
            {
                if (!designTimeDocument.State.Attributes.DesignTimeOnly ||
                    !designTimeDocument.FilePath.EndsWith(".razor.g.cs"))
                {
                    return(ImmutableArray <Diagnostic> .Empty);
                }

                var relativeDocumentPath  = Path.Combine("\\", PathUtilities.GetRelativePath(PathUtilities.GetDirectoryName(designTimeDocument.Project.FilePath), designTimeDocument.FilePath)[..^ ".g.cs".Length]);
                var generatedDocumentPath = Path.Combine("Microsoft.NET.Sdk.Razor.SourceGenerators", "Microsoft.NET.Sdk.Razor.SourceGenerators.RazorSourceGenerator", GetIdentifierFromPath(relativeDocumentPath)) + ".cs";

                var sourceGeneratedDocuments = await compileTimeSolution.GetRequiredProject(designTimeDocument.Project.Id).GetSourceGeneratedDocumentsAsync(cancellationToken).ConfigureAwait(false);

                compileTimeDocument = sourceGeneratedDocuments.SingleOrDefault(d => d.FilePath == generatedDocumentPath);
                if (compileTimeDocument == null)
                {
                    return(ImmutableArray <Diagnostic> .Empty);
                }
            }

            // EnC services should never be called on a design-time solution.

            var proxy = new RemoteEditAndContinueServiceProxy(workspace);

            var activeStatementSpanProvider = new ActiveStatementSpanProvider(async(documentId, filePath, cancellationToken) =>
            {
                var trackingService = workspace.Services.GetRequiredService <IActiveStatementTrackingService>();
                return(await trackingService.GetSpansAsync(compileTimeSolution, documentId, filePath, cancellationToken).ConfigureAwait(false));
            });

            return(await proxy.GetDocumentDiagnosticsAsync(compileTimeDocument, designTimeDocument, activeStatementSpanProvider, cancellationToken).ConfigureAwait(false));
        }
Esempio n. 5
0
        private static async Task <ImmutableArray <Diagnostic> > AnalyzeSemanticsImplAsync(Document designTimeDocument, CancellationToken cancellationToken)
        {
            var workspace = designTimeDocument.Project.Solution.Workspace;

            if (workspace.Services.HostServices is not IMefHostExportProvider mefServices)
            {
                return(ImmutableArray <Diagnostic> .Empty);
            }

            // avoid creating and synchronizing compile-time solution if the Hot Reload/EnC session is not active
            if (mefServices.GetExports <EditAndContinueLanguageService>().SingleOrDefault()?.Value.IsSessionActive != true)
            {
                return(ImmutableArray <Diagnostic> .Empty);
            }

            var designTimeSolution  = designTimeDocument.Project.Solution;
            var compileTimeSolution = workspace.Services.GetRequiredService <ICompileTimeSolutionProvider>().GetCompileTimeSolution(designTimeSolution);

            var compileTimeDocument = await CompileTimeSolutionProvider.TryGetCompileTimeDocumentAsync(designTimeDocument, compileTimeSolution, cancellationToken).ConfigureAwait(false);

            if (compileTimeDocument == null)
            {
                return(ImmutableArray <Diagnostic> .Empty);
            }

            // EnC services should never be called on a design-time solution.

            var proxy = new RemoteEditAndContinueServiceProxy(workspace);

            var activeStatementSpanProvider = new ActiveStatementSpanProvider(async(documentId, filePath, cancellationToken) =>
            {
                var trackingService = workspace.Services.GetRequiredService <IActiveStatementTrackingService>();
                return(await trackingService.GetSpansAsync(compileTimeSolution, documentId, filePath, cancellationToken).ConfigureAwait(false));
            });

            return(await proxy.GetDocumentDiagnosticsAsync(compileTimeDocument, designTimeDocument, activeStatementSpanProvider, cancellationToken).ConfigureAwait(false));
        }
Esempio n. 6
0
        private static async Task <ImmutableArray <Diagnostic> > AnalyzeSemanticsImplAsync(Workspace workspace, Document designTimeDocument, CancellationToken cancellationToken)
        {
            var designTimeSolution  = designTimeDocument.Project.Solution;
            var compileTimeSolution = workspace.Services.GetRequiredService <ICompileTimeSolutionProvider>().GetCompileTimeSolution(designTimeSolution);

            var compileTimeDocument = await CompileTimeSolutionProvider.TryGetCompileTimeDocumentAsync(designTimeDocument, compileTimeSolution, cancellationToken).ConfigureAwait(false);

            if (compileTimeDocument == null)
            {
                return(ImmutableArray <Diagnostic> .Empty);
            }

            // EnC services should never be called on a design-time solution.

            var proxy = new RemoteEditAndContinueServiceProxy(workspace);

            var activeStatementSpanProvider = new ActiveStatementSpanProvider(async(documentId, filePath, cancellationToken) =>
            {
                var trackingService = workspace.Services.GetRequiredService <IActiveStatementTrackingService>();
                return(await trackingService.GetSpansAsync(compileTimeSolution, documentId, filePath, cancellationToken).ConfigureAwait(false));
            });

            return(await proxy.GetDocumentDiagnosticsAsync(compileTimeDocument, designTimeDocument, activeStatementSpanProvider, cancellationToken).ConfigureAwait(false));
        }
Esempio n. 7
0
 public ActiveStatementSpanProviderCallback(ActiveStatementSpanProvider provider)
 => _provider = provider;
Esempio n. 8
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);
        }
Esempio n. 9
0
        public async ValueTask <LinePositionSpan?> GetCurrentActiveStatementPositionAsync(Solution solution, ActiveStatementSpanProvider activeStatementSpanProvider, ManagedInstructionId instructionId, CancellationToken cancellationToken)
        {
            var client = await RemoteHostClient.TryGetClientAsync(_workspace.Services, cancellationToken).ConfigureAwait(false);

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

            var result = await client.TryInvokeAsync <IRemoteEditAndContinueService, LinePositionSpan?>(
                solution,
                (service, solutionInfo, callbackId, cancellationToken) => service.GetCurrentActiveStatementPositionAsync(solutionInfo, callbackId, _sessionId, instructionId, cancellationToken),
                callbackTarget : new ActiveStatementSpanProviderCallback(activeStatementSpanProvider),
                cancellationToken).ConfigureAwait(false);

            return(result.HasValue ? result.Value : null);
        }
Esempio n. 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;

            try
            {
                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.RestartRequired, ImmutableArray <ManagedModuleUpdate> .Empty);
                        diagnosticData = ImmutableArray <DiagnosticData> .Empty;
                        rudeEdits      = ImmutableArray <(DocumentId DocumentId, ImmutableArray <RudeEditDiagnostic> Diagnostics)> .Empty;
                        syntaxError    = null;
                    }
                }
            }
            catch (Exception e) when(FatalError.ReportAndCatchUnlessCanceled(e, cancellationToken))
            {
                var descriptor = EditAndContinueDiagnosticDescriptors.GetDescriptor(RudeEditKind.InternalError);

                var diagnostic = Diagnostic.Create(
                    descriptor,
                    Location.None,
                    string.Format(descriptor.MessageFormat.ToString(), "", e.Message));

                diagnosticData = ImmutableArray.Create(DiagnosticData.Create(diagnostic, project: null));
                rudeEdits      = ImmutableArray <(DocumentId DocumentId, ImmutableArray <RudeEditDiagnostic> Diagnostics)> .Empty;
                moduleUpdates  = new ManagedModuleUpdates(ManagedModuleUpdateStatus.RestartRequired, ImmutableArray <ManagedModuleUpdate> .Empty);
                syntaxError    = null;
            }

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

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

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

            return(moduleUpdates, diagnosticData, rudeEdits, syntaxError);
        }
        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());
        }
Esempio n. 12
0
 public ValueTask <EmitSolutionUpdateResults> EmitSolutionUpdateAsync(DebuggingSessionId sessionId, Solution solution, ActiveStatementSpanProvider activeStatementSpanProvider, CancellationToken cancellationToken)
 => new((EmitSolutionUpdateImpl ?? throw new NotImplementedException()).Invoke(solution, activeStatementSpanProvider));