Skip to content

Commit

Permalink
Avoid invoking remote EnC service for documents that do not support r…
Browse files Browse the repository at this point in the history
…emote workspace (dotnet#64302)
  • Loading branch information
tmat authored Sep 28, 2022
1 parent 3fd98b2 commit 486c09c
Show file tree
Hide file tree
Showing 4 changed files with 129 additions and 73 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -747,34 +747,30 @@ public async Task DesignTimeOnlyDocument_Dynamic()

[Theory]
[CombinatorialData]
public async Task DesignTimeOnlyDocument_Wpf(bool delayLoad, bool open)
public async Task DesignTimeOnlyDocument_Wpf([CombinatorialValues(LanguageNames.CSharp, LanguageNames.VisualBasic)] string language, bool delayLoad, bool open)
{
var sourceA = "class A { }";
var sourceB = "class B { }";
var sourceC = "Class C : End Class";
var sourceB = (language == LanguageNames.CSharp) ? "class B { }" : "Class C : End Class";
var sourceB2 = (language == LanguageNames.CSharp) ? "class B2 { }" : "Class C2 : End Class";

var dir = Temp.CreateDirectory();
var sourceFileA = dir.CreateFile("a.cs").WriteAllText(sourceA);

using var _ = CreateWorkspace(out var solution, out var service);

// the workspace starts with a version of the source that's not updated with the output of single file generator (or design-time build):
var csProjectId = ProjectId.CreateNewId();
var vbProjectId = ProjectId.CreateNewId();
var documentAId = DocumentId.CreateNewId(csProjectId);
var documentBId = DocumentId.CreateNewId(csProjectId);
var documentCId = DocumentId.CreateNewId(vbProjectId);

var projectId = ProjectId.CreateNewId();
var documentAId = DocumentId.CreateNewId(projectId);
var documentBId = DocumentId.CreateNewId(projectId);

solution = solution.
AddProject(csProjectId, "test_cs", "test_cs", LanguageNames.CSharp).
AddDocument(documentAId, "a.cs", SourceText.From(sourceA, Encoding.UTF8), filePath: sourceFileA.Path).
AddDocument(documentBId, "b.g.i.cs", SourceText.From(sourceB, Encoding.UTF8), filePath: "b.g.i.cs").
AddMetadataReferences(csProjectId, TargetFrameworkUtil.GetReferences(TargetFramework.Mscorlib40)).
AddProject(vbProjectId, "test_vb", "test_vb", LanguageNames.VisualBasic).
AddDocument(documentCId, "c.g.i.vb", SourceText.From(sourceC, Encoding.UTF8), filePath: "c.g.i.vb").
AddMetadataReferences(vbProjectId, TargetFrameworkUtil.GetReferences(TargetFramework.Mscorlib40));

// only compile A; B and C are design-time-only:
AddProject(projectId, "test", "test", language).
AddDocument(documentAId, "a.xx", SourceText.From(sourceA, Encoding.UTF8), filePath: sourceFileA.Path).
AddDocument(documentBId, "b.g.i.xx", SourceText.From(sourceB, Encoding.UTF8), filePath: Path.Combine(dir.Path, "b.g.i.xx")).
AddMetadataReferences(projectId, TargetFrameworkUtil.GetReferences(TargetFramework.Mscorlib40));

// only compile A; B is design-time-only:
var moduleId = EmitLibrary(sourceA, sourceFilePath: sourceFileA.Path);

if (!delayLoad)
Expand All @@ -785,23 +781,39 @@ public async Task DesignTimeOnlyDocument_Wpf(bool delayLoad, bool open)
// make sure renames are not supported:
_debuggerService.GetCapabilitiesImpl = () => ImmutableArray.Create("Baseline");

var openDocumentIds = open ? ImmutableArray.Create(documentBId, documentCId) : ImmutableArray<DocumentId>.Empty;
var openDocumentIds = open ? ImmutableArray.Create(documentBId) : ImmutableArray<DocumentId>.Empty;
var sessionId = await service.StartDebuggingSessionAsync(solution, _debuggerService, captureMatchingDocuments: openDocumentIds, captureAllMatchingDocuments: false, reportDiagnostics: true, CancellationToken.None);
var debuggingSession = service.GetTestAccessor().GetDebuggingSession(sessionId);

EnterBreakState(debuggingSession);
var documentB = solution.GetDocument(documentBId);

var activeLineSpan = new LinePositionSpan(new(0, 0), new(0, 1));
var activeStatements = ImmutableArray.Create(
new ManagedActiveStatementDebugInfo(
new ManagedInstructionId(new ManagedMethodId(moduleId, token: 0x06000001, version: 1), ilOffset: 1),
documentB.FilePath,
activeLineSpan.ToSourceSpan(),
ActiveStatementFlags.NonLeafFrame | ActiveStatementFlags.MethodUpToDate));

EnterBreakState(debuggingSession, activeStatements);

// change the source (rude edit):
solution = solution.
WithDocumentText(documentBId, SourceText.From("class B1 { }")).
WithDocumentText(documentCId, SourceText.From("Class C2 : End Class"));
solution = solution.WithDocumentText(documentBId, SourceText.From(sourceB2));

var documentB2 = solution.GetDocument(documentBId);
var documentC2 = solution.GetDocument(documentCId);

Assert.True(documentB2.State.SupportsEditAndContinue());
Assert.True(documentB2.Project.SupportsEditAndContinue());

var activeStatementMap = await debuggingSession.EditSession.BaseActiveStatements.GetValueAsync(CancellationToken.None);
Assert.NotEmpty(activeStatementMap.DocumentPathMap);

// Active statements in design-time documents should be left unchanged.
var asSpans = await debuggingSession.GetBaseActiveStatementSpansAsync(solution, ImmutableArray.Create(documentBId), CancellationToken.None);
Assert.Equal(activeLineSpan, asSpans.Single().Single().LineSpan);

// no Rude Edits reported:
Assert.Empty(await service.GetDocumentDiagnosticsAsync(documentB2, s_noActiveSpans, CancellationToken.None));
Assert.Empty(await service.GetDocumentDiagnosticsAsync(documentC2, s_noActiveSpans, CancellationToken.None));

// validate solution update status and emit:
var (updates, emitDiagnostics) = await EmitSolutionUpdateAsync(debuggingSession, solution);
Expand Down
Loading

0 comments on commit 486c09c

Please sign in to comment.