public async Task TrackingService_GetLatestSpansAsync(
            bool scheduleInitialTrackingBeforeOpenDoc
            )
        {
            var source1 =
                "class C { void F() => G(1); void G(int a) => System.Console.WriteLine(1); }";
            var source2 = "class D { }";

            using var workspace = new TestWorkspace();

            var span11 = new LinePositionSpan(new LinePosition(0, 10), new LinePosition(0, 15));
            var span12 = new LinePositionSpan(new LinePosition(0, 20), new LinePosition(0, 25));
            var span21 = new LinePositionSpan(new LinePosition(0, 11), new LinePosition(0, 16));
            var span22 = new LinePositionSpan(new LinePosition(0, 21), new LinePosition(0, 26));

            var encService = new MockEditAndContinueWorkspaceService();

            encService.GetBaseActiveStatementSpansImpl = (_, documentIds) =>
                                                         ImmutableArray.Create(
                ImmutableArray.Create(
                    (span11, ActiveStatementFlags.IsNonLeafFrame),
                    (span12, ActiveStatementFlags.IsLeafFrame)
                    ),
                ImmutableArray <(LinePositionSpan, ActiveStatementFlags)> .Empty
                );

            encService.GetAdjustedActiveStatementSpansImpl = (document, _) =>
                                                             document.Name switch
            {
                "1.cs"
                => ImmutableArray.Create(
                    (span21, ActiveStatementFlags.IsNonLeafFrame),
                    (span22, ActiveStatementFlags.IsLeafFrame)
                    ),
                "2.cs" => ImmutableArray <(LinePositionSpan, ActiveStatementFlags)> .Empty,
                _ => throw ExceptionUtilities.Unreachable
            };

            var testDocument1 = new TestHostDocument(
                text: source1,
                displayName: "1.cs",
                exportProvider: workspace.ExportProvider
                );
            var testDocument2 = new TestHostDocument(
                text: source2,
                displayName: "2.cs",
                exportProvider: workspace.ExportProvider
                );

            workspace.AddTestProject(
                new TestHostProject(workspace, documents: new[] { testDocument1, testDocument2 })
                );

            // opens the documents
            var textBuffer1 = testDocument1.GetTextBuffer();
            var textBuffer2 = testDocument2.GetTextBuffer();

            var solution  = workspace.CurrentSolution;
            var project   = solution.Projects.Single();
            var document1 = project.Documents.Single(d => d.Name == "1.cs");
            var document2 = project.Documents.Single(d => d.Name == "2.cs");
            var snapshot1 = textBuffer1.CurrentSnapshot;
            var snapshot2 = textBuffer2.CurrentSnapshot;

            Assert.Same(
                snapshot1,
                document1
                .GetTextSynchronously(CancellationToken.None)
                .FindCorrespondingEditorTextSnapshot()
                );
            Assert.Same(
                snapshot2,
                document2
                .GetTextSynchronously(CancellationToken.None)
                .FindCorrespondingEditorTextSnapshot()
                );

            var trackingSession = new ActiveStatementTrackingService.TrackingSession(
                workspace,
                encService
                );

            if (scheduleInitialTrackingBeforeOpenDoc)
            {
                await trackingSession.TrackActiveSpansAsync(solution, CancellationToken.None);

                var spans1 = trackingSession.Test_GetTrackingSpans();
                AssertEx.Equal(
                    new[] { $"V0 →←@[10..15): IsNonLeafFrame", $"V0 →←@[20..25): IsLeafFrame" },
                    spans1[document1.Id].Select(s => $"{s.Span}: {s.Flags}")
                    );

                var spans2 = await trackingSession.GetSpansAsync(document1, CancellationToken.None);

                AssertEx.Equal(new[] { "[10..15)", "[20..25)" }, spans2.Select(s => s.ToString()));

                var spans3 = await trackingSession.GetSpansAsync(document2, CancellationToken.None);

                Assert.Empty(spans3);
            }

            var spans4 = await trackingSession.GetAdjustedTrackingSpansAsync(
                document1,
                snapshot1,
                CancellationToken.None
                );

            AssertEx.Equal(
                new[] { $"V0 →←@[11..16): IsNonLeafFrame", $"V0 →←@[21..26): IsLeafFrame" },
                spans4.Select(s => $"{s.Span}: {s.Flags}")
                );

            AssertEx.Empty(
                await trackingSession.GetAdjustedTrackingSpansAsync(
                    document2,
                    snapshot2,
                    CancellationToken.None
                    )
                );

            if (!scheduleInitialTrackingBeforeOpenDoc)
            {
                await trackingSession.TrackActiveSpansAsync(solution, CancellationToken.None);

                var spans5 = trackingSession.Test_GetTrackingSpans();
                AssertEx.Equal(
                    new[] { $"V0 →←@[11..16): IsNonLeafFrame", $"V0 →←@[21..26): IsLeafFrame" },
                    spans5[document1.Id].Select(s => $"{s.Span}: {s.Flags}")
                    );
            }

            // we are not able to determine active statements in a document:
            encService.GetAdjustedActiveStatementSpansImpl = (_, _) => default;

            var spans6 = await trackingSession.GetAdjustedTrackingSpansAsync(
                document1,
                snapshot1,
                CancellationToken.None
                );

            AssertEx.Equal(
                new[] { $"V0 →←@[11..16): IsNonLeafFrame", $"V0 →←@[21..26): IsLeafFrame" },
                spans6.Select(s => $"{s.Span}: {s.Flags}")
                );
        }
    }
        public void ReportDiagnostics()
        {
            var source = new EditAndContinueDiagnosticUpdateSource();

            var updates = new List <string>();

            var srcC1 = "class C1 {}";
            var srcC2 = "class C2 {}";
            var srcD1 = "class D1 {}";
            var srcD2 = "class D2 {}";
            var docC1 = new TestHostDocument(srcC1, displayName: "DocC1");
            var docC2 = new TestHostDocument(srcC2, displayName: "DocC2");
            var docD1 = new TestHostDocument(srcD1, displayName: "DocD1");
            var docD2 = new TestHostDocument(srcD2, displayName: "DocD2");

            var workspace = new TestWorkspace();

            source.DiagnosticsUpdated += (object sender, DiagnosticsUpdatedArgs e) =>
            {
                var diagnostics = e.GetPushDiagnostics(workspace, InternalDiagnosticsOptions.NormalDiagnosticMode);
                updates.Add($"{e.Kind} p={e.ProjectId} d={e.DocumentId}: {string.Join(",", diagnostics.Select(d => d.Id.ToString()))}");
            };

            var projC = new TestHostProject(workspace, "ProjC");

            projC.AddDocument(docC1);
            projC.AddDocument(docC2);
            var projD = new TestHostProject(workspace, "ProjD");

            projD.AddDocument(docD1);
            projD.AddDocument(docD2);

            workspace.AddTestProject(projC);
            workspace.AddTestProject(projD);

            var treeC1 = workspace.CurrentSolution.GetDocument(docC1.Id).GetSyntaxTreeAsync().Result;
            var treeC2 = workspace.CurrentSolution.GetDocument(docC2.Id).GetSyntaxTreeAsync().Result;
            var treeD1 = workspace.CurrentSolution.GetDocument(docD1.Id).GetSyntaxTreeAsync().Result;
            var treeD2 = workspace.CurrentSolution.GetDocument(docD2.Id).GetSyntaxTreeAsync().Result;

            var diagnostics = new[]
            {
                Diagnostic.Create(new DiagnosticDescriptor("TST0001", "title1", "message1", "category", DiagnosticSeverity.Error, true), Location.Create(treeC1, new TextSpan(1, 1))),
                Diagnostic.Create(new DiagnosticDescriptor("TST0002", "title2", "message2", "category", DiagnosticSeverity.Error, true), Location.Create(treeC1, new TextSpan(1, 2))),
                Diagnostic.Create(new DiagnosticDescriptor("TST0003", "title3", "message3", "category", DiagnosticSeverity.Error, true), Location.Create(treeD1, new TextSpan(1, 2))),
                Diagnostic.Create(new DiagnosticDescriptor("TST0004", "title4", "message4", "category", DiagnosticSeverity.Error, true), Location.Create(treeD2, new TextSpan(1, 2))),
                Diagnostic.Create(new DiagnosticDescriptor("TST0005", "title5", "message5", "category", DiagnosticSeverity.Error, true), Location.None),
            };

            updates.Clear();
            source.ReportDiagnostics(workspace, workspace.CurrentSolution, projC.Id, diagnostics);
            AssertEx.Equal(new[]
            {
                $"DiagnosticsCreated p={projC.Id} d={docC1.Id}: TST0001,TST0002",
                $"DiagnosticsCreated p={projC.Id} d={docD1.Id}: TST0003",
                $"DiagnosticsCreated p={projC.Id} d={docD2.Id}: TST0004",
                $"DiagnosticsCreated p={projC.Id} d=: TST0005"
            }, updates);

            updates.Clear();
            source.ReportDiagnostics(workspace, workspace.CurrentSolution, projD.Id, diagnostics);
            AssertEx.Equal(new[]
            {
                $"DiagnosticsCreated p={projD.Id} d={docC1.Id}: TST0001,TST0002",
                $"DiagnosticsCreated p={projD.Id} d={docD1.Id}: TST0003",
                $"DiagnosticsCreated p={projD.Id} d={docD2.Id}: TST0004",
                $"DiagnosticsCreated p={projD.Id} d=: TST0005"
            }, updates);

            updates.Clear();
            source.ReportDiagnostics(workspace, workspace.CurrentSolution, null, diagnostics);
            AssertEx.Equal(new[]
            {
                $"DiagnosticsCreated p= d={docC1.Id}: TST0001,TST0002",
                $"DiagnosticsCreated p= d={docD1.Id}: TST0003",
                $"DiagnosticsCreated p= d={docD2.Id}: TST0004",
                $"DiagnosticsCreated p= d=: TST0005"
            }, updates);
        }
Ejemplo n.º 3
0
        public void ReportDiagnostics()
        {
            var service = new DiagnosticService(
                AsynchronousOperationListenerProvider.NullProvider, Array.Empty <Lazy <IEventListener, EventListenerMetadata> >());
            var source = new EditAndContinueDiagnosticUpdateSource(service);

            var updates = new List <string>();

            source.DiagnosticsUpdated += (object sender, DiagnosticsUpdatedArgs e) =>
            {
                updates.Add($"{e.Kind} p={e.ProjectId} d={e.DocumentId}: {string.Join(",", e.Diagnostics.Select(d => d.Id.ToString()))}");
            };

            var id = new object();

            var srcC1 = "class C1 {}";
            var srcC2 = "class C2 {}";
            var srcD1 = "class D1 {}";
            var srcD2 = "class D2 {}";
            var docC1 = new TestHostDocument(srcC1, displayName: "DocC1");
            var docC2 = new TestHostDocument(srcC2, displayName: "DocC2");
            var docD1 = new TestHostDocument(srcD1, displayName: "DocD1");
            var docD2 = new TestHostDocument(srcD2, displayName: "DocD2");

            var workspace = new TestWorkspace();
            var projC     = new TestHostProject(workspace, "ProjC");

            projC.AddDocument(docC1);
            projC.AddDocument(docC2);
            var projD = new TestHostProject(workspace, "ProjD");

            projD.AddDocument(docD1);
            projD.AddDocument(docD2);

            workspace.AddTestProject(projC);
            workspace.AddTestProject(projD);

            var treeC1 = workspace.CurrentSolution.GetDocument(docC1.Id).GetSyntaxTreeAsync().Result;
            var treeC2 = workspace.CurrentSolution.GetDocument(docC2.Id).GetSyntaxTreeAsync().Result;
            var treeD1 = workspace.CurrentSolution.GetDocument(docD1.Id).GetSyntaxTreeAsync().Result;
            var treeD2 = workspace.CurrentSolution.GetDocument(docD2.Id).GetSyntaxTreeAsync().Result;

            var diagnostics = new[]
            {
                Diagnostic.Create(new DiagnosticDescriptor("TST0001", "title1", "message1", "category", DiagnosticSeverity.Error, true), Location.Create(treeC1, new TextSpan(1, 1))),
                Diagnostic.Create(new DiagnosticDescriptor("TST0002", "title2", "message2", "category", DiagnosticSeverity.Error, true), Location.Create(treeC1, new TextSpan(1, 2))),
                Diagnostic.Create(new DiagnosticDescriptor("TST0003", "title3", "message3", "category", DiagnosticSeverity.Error, true), Location.Create(treeD1, new TextSpan(1, 2))),
                Diagnostic.Create(new DiagnosticDescriptor("TST0004", "title4", "message4", "category", DiagnosticSeverity.Error, true), Location.Create(treeD2, new TextSpan(1, 2))),
            };

            updates.Clear();
            var actual = source.ReportDiagnostics(id, workspace.CurrentSolution, projC.Id, diagnostics);

            AssertEx.Equal(new[] { docC1.Id }, actual);
            AssertEx.Equal(new[]
            {
                $"DiagnosticsCreated p={projC.Id} d={docC1.Id}: TST0001,TST0002",
                $"DiagnosticsCreated p={projC.Id} d={docD1.Id}: TST0003",
                $"DiagnosticsCreated p={projC.Id} d={docD2.Id}: TST0004"
            }, updates);

            updates.Clear();
            actual = source.ReportDiagnostics(id, workspace.CurrentSolution, projD.Id, diagnostics);
            AssertEx.SetEqual(new[] { docD1.Id, docD2.Id }, actual);
            AssertEx.Equal(new[]
            {
                $"DiagnosticsCreated p={projD.Id} d={docC1.Id}: TST0001,TST0002",
                $"DiagnosticsCreated p={projD.Id} d={docD1.Id}: TST0003",
                $"DiagnosticsCreated p={projD.Id} d={docD2.Id}: TST0004"
            }, updates);
        }
        public async Task TrackingService_GetLatestSpansAsync(bool scheduleInitialTrackingBeforeOpenDoc)
        {
            var sourceV1 = "class C { void F() => G(1); void G(int a) => System.Console.WriteLine(1); }";

            using var workspace = new TestWorkspace();

            var span11 = new LinePositionSpan(new LinePosition(0, 10), new LinePosition(0, 15));
            var span12 = new LinePositionSpan(new LinePosition(0, 20), new LinePosition(0, 25));
            var span21 = new LinePositionSpan(new LinePosition(0, 11), new LinePosition(0, 16));
            var span22 = new LinePositionSpan(new LinePosition(0, 21), new LinePosition(0, 26));

            var encService = new MockEditAndContinueWorkspaceService();

            encService.GetBaseActiveStatementSpansAsyncImpl = documentIds => ImmutableArray.Create(ImmutableArray.Create(
                                                                                                       (span11, ActiveStatementFlags.IsNonLeafFrame),
                                                                                                       (span12, ActiveStatementFlags.IsLeafFrame)));

            encService.GetAdjustedDocumentActiveStatementSpansAsyncImpl = document => ImmutableArray.Create(
                (span21, ActiveStatementFlags.IsNonLeafFrame),
                (span22, ActiveStatementFlags.IsLeafFrame));

            var testDocument = new TestHostDocument(text: sourceV1, exportProvider: workspace.ExportProvider);

            workspace.AddTestProject(new TestHostProject(workspace, testDocument));
            var textBuffer = testDocument.GetTextBuffer();

            var solution = workspace.CurrentSolution;
            var project  = solution.Projects.Single();
            var document = project.Documents.Single();
            var snapshot = textBuffer.CurrentSnapshot;

            Assert.Same(snapshot, document.GetTextSynchronously(CancellationToken.None).FindCorrespondingEditorTextSnapshot());

            var trackingSession = new ActiveStatementTrackingService.TrackingSession(workspace, encService);

            if (scheduleInitialTrackingBeforeOpenDoc)
            {
                await trackingSession.TrackActiveSpansAsync().ConfigureAwait(false);

                var spans1 = trackingSession.Test_GetTrackingSpans();
                AssertEx.Equal(new[]
                {
                    $"V0 →←@[10..15): IsNonLeafFrame",
                    $"V0 →←@[20..25): IsLeafFrame"
                }, spans1[document.Id].Select(s => $"{s.Span}: {s.Flags}"));
            }

            var spans2 = await trackingSession.GetAdjustedTrackingSpansAsync(document, snapshot, CancellationToken.None).ConfigureAwait(false);

            AssertEx.Equal(new[]
            {
                $"V0 →←@[11..16): IsNonLeafFrame",
                $"V0 →←@[21..26): IsLeafFrame"
            }, spans2.Select(s => $"{s.Span}: {s.Flags}"));

            if (!scheduleInitialTrackingBeforeOpenDoc)
            {
                await trackingSession.TrackActiveSpansAsync().ConfigureAwait(false);

                var spans1 = trackingSession.Test_GetTrackingSpans();
                AssertEx.Equal(new[]
                {
                    $"V0 →←@[11..16): IsNonLeafFrame",
                    $"V0 →←@[21..26): IsLeafFrame"
                }, spans1[document.Id].Select(s => $"{s.Span}: {s.Flags}"));
            }

            // we are not able to determine active statements in a document:
            encService.GetAdjustedDocumentActiveStatementSpansAsyncImpl = document => default;

            var spans3 = await trackingSession.GetAdjustedTrackingSpansAsync(document, snapshot, CancellationToken.None).ConfigureAwait(false);

            AssertEx.Equal(new[]
            {
                $"V0 →←@[11..16): IsNonLeafFrame",
                $"V0 →←@[21..26): IsLeafFrame"
            }, spans3.Select(s => $"{s.Span}: {s.Flags}"));
        }