Skip to content

Commit 78b7013

Browse files
Remove back to prevent raising exception when there's no active session (#9794)
* Improve session management in ProjectHotReloadSession by adding null checks and conditional logic to prevent errors when stopping and applying updates. * Refactor ProjectHotReloadSession to remove RequireActiveSession method and update tests to handle session state without exceptions. * add comment * Remove unused using directive for System.Diagnostics.CodeAnalysis in ProjectHotReloadSession.cs * Remove unused using directive for Microsoft.VisualStudio.RpcContracts.Commands in ProjectHotReloadSessionTests.cs
1 parent 55fc446 commit 78b7013

File tree

2 files changed

+27
-24
lines changed

2 files changed

+27
-24
lines changed

src/Microsoft.VisualStudio.ProjectSystem.Managed/ProjectSystem/HotReload/ProjectHotReloadSession.cs

Lines changed: 25 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
// Licensed to the .NET Foundation under one or more agreements. The .NET Foundation licenses this file to you under the MIT license. See the LICENSE.md file in the project root for more information.
22

3-
using System.Diagnostics.CodeAnalysis;
43
using System.Runtime.Versioning;
54
using Microsoft.DotNet.HotReload;
65
using Microsoft.VisualStudio.Debugger.Contracts.EditAndContinue;
@@ -72,16 +71,6 @@ internal static string GetInjectedAssemblyPath(string targetFramework, string as
7271
public IDeltaApplier? DeltaApplier
7372
=> _lazyDeltaApplier;
7473

75-
[MemberNotNull(nameof(_lazyDeltaApplier))]
76-
private void RequireActiveSession()
77-
{
78-
if (!_sessionActive)
79-
throw new InvalidOperationException($"Hot Reload session has not started");
80-
81-
if (_lazyDeltaApplier is null)
82-
throw new InvalidOperationException();
83-
}
84-
8574
public async Task ApplyChangesAsync(CancellationToken cancellationToken)
8675
{
8776
if (_sessionActive)
@@ -199,19 +188,29 @@ public async Task StartSessionAsync(CancellationToken cancellationToken)
199188

200189
public async Task StopSessionAsync(CancellationToken cancellationToken)
201190
{
202-
RequireActiveSession();
203-
204-
_sessionActive = false;
205-
_lazyDeltaApplier.Dispose();
206-
_lazyDeltaApplier = null;
191+
if (_sessionActive && _lazyDeltaApplier is not null)
192+
{
193+
_sessionActive = false;
194+
_lazyDeltaApplier.Dispose();
195+
_lazyDeltaApplier = null;
207196

208-
await _hotReloadAgentManagerClient.Value.AgentTerminatedAsync(this, cancellationToken);
209-
WriteToOutputWindow(Resources.HotReloadStopSession, default);
197+
await _hotReloadAgentManagerClient.Value.AgentTerminatedAsync(this, cancellationToken);
198+
WriteToOutputWindow(Resources.HotReloadStopSession, default);
199+
}
210200
}
211201

212202
public async ValueTask ApplyUpdatesAsync(ImmutableArray<ManagedHotReloadUpdate> updates, CancellationToken cancellationToken)
213203
{
214-
RequireActiveSession();
204+
// A stricter check for session active could be done here, like raise an exception when not active session or no delta applier
205+
// But sometimes debugger would call ApplyUpdatesAsync even when there is not active session
206+
// e.g. when user restarts on rude edits
207+
// We need to talk to debugger team to see if we can avoid such calls in the future
208+
// https://devdiv.visualstudio.com/DevDiv/_workitems/edit/2581474
209+
if (_sessionActive is false || _lazyDeltaApplier is null)
210+
{
211+
DebugTrace($"{nameof(ApplyUpdatesAsync)} called but the session is not active.");
212+
return;
213+
}
215214

216215
try
217216
{
@@ -248,11 +247,15 @@ private bool LogAndPropagate(Exception e, CancellationToken cancellationToken)
248247
return false;
249248
}
250249

251-
public ValueTask<ImmutableArray<string>> GetCapabilitiesAsync(CancellationToken cancellationToken)
250+
public async ValueTask<ImmutableArray<string>> GetCapabilitiesAsync(CancellationToken cancellationToken)
252251
{
253-
RequireActiveSession();
252+
// Delegate to the delta applier for the session
253+
if (_lazyDeltaApplier is not null)
254+
{
255+
return await _lazyDeltaApplier.GetCapabilitiesAsync(cancellationToken);
256+
}
254257

255-
return _lazyDeltaApplier.GetCapabilitiesAsync(cancellationToken);
258+
return [];
256259
}
257260

258261
public ValueTask ReportDiagnosticsAsync(ImmutableArray<ManagedHotReloadDiagnostic> diagnostics, CancellationToken cancellationToken)

tests/Microsoft.VisualStudio.ProjectSystem.Managed.UnitTests/ProjectSystem/HotReload/ProjectHotReloadSessionTests.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -325,7 +325,7 @@ public async Task StopSessionAsync_WhenSessionNotActive_DoesNotCallAgentTerminat
325325
// Session is not started/active
326326

327327
// Act
328-
await Assert.ThrowsAsync<InvalidOperationException>(() => session.StopSessionAsync(CancellationToken.None));
328+
await session.StopSessionAsync(CancellationToken.None);
329329

330330
// Assert
331331
hotReloadAgentManagerClient.Verify(
@@ -381,7 +381,7 @@ public async Task ApplyUpdatesAsync_WhenSessionNotActive_DoesNotCallDeltaApplier
381381
var updates = ImmutableArray.Create<ManagedHotReloadUpdate>();
382382

383383
// Act
384-
await Assert.ThrowsAsync<InvalidOperationException>(() => session.ApplyUpdatesAsync(updates, CancellationToken.None).AsTask());
384+
await session.ApplyUpdatesAsync(updates, CancellationToken.None);
385385

386386
// Assert
387387
deltaApplier.Verify(

0 commit comments

Comments
 (0)