From 2474fecdf133ed3ffae1c5614ea43a77986d255b Mon Sep 17 00:00:00 2001 From: Pranav K Date: Thu, 10 Jun 2021 16:12:23 -0700 Subject: [PATCH] Allow WatchHotReloadService to specify runtime apply-update capabilities Contributes to https://github.com/dotnet/aspnetcore/issues/33402 --- eng/targets/Settings.props | 17 +++--- .../EditAndContinueWorkspaceServiceTests.cs | 54 +++++++++---------- .../Watch/Api/WatchHotReloadService.cs | 19 +++---- 3 files changed, 46 insertions(+), 44 deletions(-) diff --git a/eng/targets/Settings.props b/eng/targets/Settings.props index f41f12b4dd4ae..a52f472d68855 100644 --- a/eng/targets/Settings.props +++ b/eng/targets/Settings.props @@ -43,7 +43,7 @@ enable - true - true + true true true @@ -110,7 +111,7 @@ $([System.IO.Path]::GetFullPath('$(DevEnvDir)')) - @@ -130,14 +131,14 @@ false - - diff --git a/src/EditorFeatures/Test/EditAndContinue/EditAndContinueWorkspaceServiceTests.cs b/src/EditorFeatures/Test/EditAndContinue/EditAndContinueWorkspaceServiceTests.cs index 6f9478481297d..37813f634cb99 100644 --- a/src/EditorFeatures/Test/EditAndContinue/EditAndContinueWorkspaceServiceTests.cs +++ b/src/EditorFeatures/Test/EditAndContinue/EditAndContinueWorkspaceServiceTests.cs @@ -986,25 +986,25 @@ public async Task BreakMode_ModuleDisallowsEditAndContinue() var moduleId = Guid.NewGuid(); var source1 = @" -class C1 -{ - void M() +class C1 +{ + void M() { - System.Console.WriteLine(1); - System.Console.WriteLine(2); - System.Console.WriteLine(3); - } + System.Console.WriteLine(1); + System.Console.WriteLine(2); + System.Console.WriteLine(3); + } }"; var source2 = @" -class C1 -{ +class C1 +{ - void M() + void M() { - System.Console.WriteLine(9); - System.Console.WriteLine(); - System.Console.WriteLine(30); - } + System.Console.WriteLine(9); + System.Console.WriteLine(); + System.Console.WriteLine(30); + } }"; using var _ = CreateWorkspace(out var solution, out var service); (solution, var document) = AddDefaultTestProject(solution, source1); @@ -1158,7 +1158,7 @@ public async Task BreakMode_RudeEdits_SourceGenerators() var sourceV1 = @" /* GENERATE: class G { int X1 => 1; } */ -class C { int Y => 1; } +class C { int Y => 1; } "; var sourceV2 = @" /* GENERATE: class G { int X2 => 1; } */ @@ -2236,7 +2236,7 @@ public async Task BreakMode_ValidSignificantChange_SourceGenerators_DocumentUpda var sourceV1 = @" /* GENERATE: class G { int X => 1; } */ -class C { int Y => 1; } +class C { int Y => 1; } "; var sourceV2 = @" /* GENERATE: class G { int X => 2; } */ @@ -2282,7 +2282,7 @@ public async Task BreakMode_ValidSignificantChange_SourceGenerators_DocumentUpda /* GENERATE: class G { - int M() + int M() { return 1; } @@ -2294,7 +2294,7 @@ int M() class G { - int M() + int M() { return 1; } @@ -2340,7 +2340,7 @@ int M() public async Task BreakMode_ValidSignificantChange_SourceGenerators_DocumentUpdate_GeneratedDocumentInsert() { var sourceV1 = @" -partial class C { int X = 1; } +partial class C { int X = 1; } "; var sourceV2 = @" /* GENERATE: partial class C { int Y = 2; } */ @@ -2383,7 +2383,7 @@ partial class C { int X = 1; } public async Task BreakMode_ValidSignificantChange_SourceGenerators_AdditionalDocumentUpdate() { var source = @" -class C { int Y => 1; } +class C { int Y => 1; } "; var additionalSourceV1 = @" @@ -2429,7 +2429,7 @@ class C { int Y => 1; } public async Task BreakMode_ValidSignificantChange_SourceGenerators_AnalyzerConfigUpdate() { var source = @" -class C { int Y => 1; } +class C { int Y => 1; } "; var configV1 = new[] { ("enc_generator_output", "1") }; @@ -2948,7 +2948,7 @@ public async Task ActiveStatements_LinkedDocuments() methodRowIds: new[] { 1, 2, 1 }, modules: new[] { module4, module2, module1 }); - // Project1: Test1.cs, Test2.cs + // Project1: Test1.cs, Test2.cs // Project2: Test1.cs (link from P1) // Project3: Test1.cs (link from P1) // Project4: Test2.cs (link from P1) @@ -3030,7 +3030,7 @@ public async Task ActiveStatements_OutOfSyncDocuments() { static void M() { - try + try { } catch (Exception e) @@ -3044,7 +3044,7 @@ static void M() { static void M() { - try + try { } catch (Exception e) @@ -3209,7 +3209,7 @@ void F() /// 2) Hot-reload edit F (without breaking) to version 3. /// Function remapping is produced for F v2 -> F v3 based on the last set of active statements calculated for F v2. /// Assume that the execution did not progress since the last resume. - /// These active statements will likely not match the actual runtime active statements, + /// These active statements will likely not match the actual runtime active statements, /// however F v2 will never be remapped since it was hot-reloaded and not EnC'd. /// This remapping is needed for mapping from F v1 to F v3. /// 3) Break. Update F to v4. @@ -3290,7 +3290,7 @@ static void F() // EnC update F v3 -> v4 EnterBreakState(debuggingSession, GetActiveStatementDebugInfosCSharp( - new[] { markedSourceV1 }, // matches F v1 + new[] { markedSourceV1 }, // matches F v1 modules: new[] { moduleId, moduleId }, methodRowIds: new[] { 2, 3 }, methodVersions: new[] { 1, 1 }, // frame F v1 is still executing (G has not returned) @@ -3608,7 +3608,7 @@ public async Task WatchHotReloadServiceTest() loader: new FileTextLoader(sourceFileA.Path, Encoding.UTF8), filePath: sourceFileA.Path)); - var hotReload = new WatchHotReloadService(workspace.Services); + var hotReload = new WatchHotReloadService(workspace.Services, ImmutableArray.Create("Baseline", "AddDefinitionToExistingType", "NewTypeDefinition")); await hotReload.StartSessionAsync(solution, CancellationToken.None); diff --git a/src/Features/Core/Portable/ExternalAccess/Watch/Api/WatchHotReloadService.cs b/src/Features/Core/Portable/ExternalAccess/Watch/Api/WatchHotReloadService.cs index c8148eb835f3e..fb1651592fd8a 100644 --- a/src/Features/Core/Portable/ExternalAccess/Watch/Api/WatchHotReloadService.cs +++ b/src/Features/Core/Portable/ExternalAccess/Watch/Api/WatchHotReloadService.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Immutable; -using System.Linq; using System.Runtime.CompilerServices; using System.Threading; using System.Threading.Tasks; @@ -19,7 +18,10 @@ internal sealed class WatchHotReloadService { private sealed class DebuggerService : IManagedEditAndContinueDebuggerService { - public static readonly DebuggerService Instance = new(); + private readonly ImmutableArray _capabilities; + + public DebuggerService(ImmutableArray capabilities) + => _capabilities = capabilities; public Task> GetActiveStatementsAsync(CancellationToken cancellationToken) => Task.FromResult(ImmutableArray.Empty); @@ -27,9 +29,7 @@ public Task> GetActiveStatements public Task GetAvailabilityAsync(Guid module, CancellationToken cancellationToken) => Task.FromResult(new ManagedEditAndContinueAvailability(ManagedEditAndContinueAvailabilityStatus.Available)); - // TODO: get capabilities from the runtime: https://github.com/dotnet/aspnetcore/issues/33402 - public Task> GetCapabilitiesAsync(CancellationToken cancellationToken) - => Task.FromResult(ImmutableArray.Create("Baseline", "AddDefinitionToExistingType", "NewTypeDefinition")); + public Task> GetCapabilitiesAsync(CancellationToken cancellationToken) => Task.FromResult(_capabilities); public Task PrepareModuleForUpdateAsync(Guid module, CancellationToken cancellationToken) => Task.CompletedTask; @@ -56,9 +56,10 @@ public Update(Guid moduleId, ImmutableArray ilDelta, ImmutableArray private readonly IEditAndContinueWorkspaceService _encService; private DebuggingSessionId _sessionId; + private readonly ImmutableArray _capabilities; - public WatchHotReloadService(HostWorkspaceServices services) - => _encService = services.GetRequiredService(); + public WatchHotReloadService(HostWorkspaceServices services, ImmutableArray capabilities) + => (_encService, _capabilities) = (services.GetRequiredService(), capabilities); /// /// Starts the watcher. @@ -67,13 +68,13 @@ public WatchHotReloadService(HostWorkspaceServices services) /// Cancellation token. public async Task StartSessionAsync(Solution solution, CancellationToken cancellationToken) { - var newSessionId = await _encService.StartDebuggingSessionAsync(solution, DebuggerService.Instance, captureMatchingDocuments: true, reportDiagnostics: false, cancellationToken).ConfigureAwait(false); + var newSessionId = await _encService.StartDebuggingSessionAsync(solution, new DebuggerService(_capabilities), captureMatchingDocuments: true, reportDiagnostics: false, cancellationToken).ConfigureAwait(false); Contract.ThrowIfFalse(_sessionId == default, "Session already started"); _sessionId = newSessionId; } /// - /// Emits updates for all projects that differ between the given snapshot and the one given to the previous successful call or + /// Emits updates for all projects that differ between the given snapshot and the one given to the previous successful call or /// the one passed to for the first invocation. /// /// Solution snapshot.