Skip to content

Commit 84aa7ea

Browse files
committed
Update to new Roslyn APIs
1 parent 47e79ef commit 84aa7ea

File tree

4 files changed

+25
-31
lines changed

4 files changed

+25
-31
lines changed

src/BuiltInTools/dotnet-watch/HotReload/CompilationHandler.cs

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ public async ValueTask TerminateNonRootProcessesAndDispose(CancellationToken can
7474
Dispose();
7575
}
7676

77-
public ValueTask RestartSessionAsync(ImmutableDictionary<ProjectId, string> projectsToBeRebuilt, CancellationToken cancellationToken)
77+
public void UpdateProjectBaselines(ImmutableDictionary<ProjectId, string> projectsToBeRebuilt, CancellationToken cancellationToken)
7878
{
7979
// Remove previous updates to all modules that were affected by rude edits.
8080
// All running projects that statically reference these modules have been terminated.
@@ -87,9 +87,8 @@ public ValueTask RestartSessionAsync(ImmutableDictionary<ProjectId, string> proj
8787
_previousUpdates = _previousUpdates.RemoveAll(update => projectsToBeRebuilt.ContainsKey(update.ProjectId));
8888
}
8989

90-
_hotReloadService.EndSession();
91-
_reporter.Report(MessageDescriptor.HotReloadSessionEnded);
92-
return StartSessionAsync(cancellationToken);
90+
_hotReloadService.UpdateBaselines(Workspace.CurrentSolution, projectsToBeRebuilt.Keys.ToImmutableArray());
91+
_reporter.Report(MessageDescriptor.ProjectBaselinesUpdates);
9392
}
9493

9594
public async ValueTask StartSessionAsync(CancellationToken cancellationToken)
@@ -277,14 +276,19 @@ private static void PrepareCompilations(Solution solution, string projectPath, C
277276
}
278277

279278
public async ValueTask<(ImmutableDictionary<ProjectId, string> projectsToRebuild, ImmutableArray<RunningProject> terminatedProjects)> HandleFileChangesAsync(
280-
Func<IEnumerable<Project>, CancellationToken, Task> restartPrompt,
279+
Func<IEnumerable<string>, CancellationToken, Task> restartPrompt,
281280
CancellationToken cancellationToken)
282281
{
283282
var currentSolution = Workspace.CurrentSolution;
284283
var runningProjects = _runningProjects;
285284

286-
var updates = await _hotReloadService.GetUpdatesAsync(currentSolution, isRunningProject: p => runningProjects.ContainsKey(p.FilePath!), cancellationToken);
287-
var anyProcessNeedsRestart = updates.ProjectsToRestart.Count > 0;
285+
var runningProjectIds = currentSolution.Projects
286+
.Where(project => project.FilePath != null && runningProjects.ContainsKey(project.FilePath))
287+
.Select(project => project.Id)
288+
.ToImmutableHashSet();
289+
290+
var updates = await _hotReloadService.GetUpdatesAsync(currentSolution, runningProjectIds, cancellationToken);
291+
var anyProcessNeedsRestart = !updates.ProjectIdsToRestart.IsEmpty;
288292

289293
await DisplayResultsAsync(updates, cancellationToken);
290294

@@ -302,13 +306,13 @@ private static void PrepareCompilations(Solution solution, string projectPath, C
302306
return (ImmutableDictionary<ProjectId, string>.Empty, []);
303307
}
304308

305-
await restartPrompt.Invoke(updates.ProjectsToRestart, cancellationToken);
309+
await restartPrompt.Invoke(updates.ProjectIdsToRestart.Select(id => currentSolution.GetProject(id)!.Name), cancellationToken);
306310

307311
// Terminate all tracked processes that need to be restarted,
308312
// except for the root process, which will terminate later on.
309-
var terminatedProjects = await TerminateNonRootProcessesAsync(updates.ProjectsToRestart.Select(p => p.FilePath!), cancellationToken);
313+
var terminatedProjects = await TerminateNonRootProcessesAsync(updates.ProjectIdsToRestart.Select(id => currentSolution.GetProject(id)!.FilePath!), cancellationToken);
310314

311-
return (updates.ProjectsToRebuild.ToImmutableDictionary(keySelector: p => p.Id, elementSelector: p => p.FilePath!), terminatedProjects);
315+
return (updates.ProjectIdsToRebuild.ToImmutableDictionary(keySelector: id => id, elementSelector: id => currentSolution.GetProject(id)!.FilePath!), terminatedProjects);
312316
}
313317

314318
Debug.Assert(updates.Status == ModuleUpdateStatus.Ready);
@@ -353,7 +357,7 @@ await ForEachProjectAsync(projectsToUpdate, async (runningProject, cancellationT
353357

354358
private async ValueTask DisplayResultsAsync(WatchHotReloadService.Updates updates, CancellationToken cancellationToken)
355359
{
356-
var anyProcessNeedsRestart = updates.ProjectsToRestart.Count > 0;
360+
var anyProcessNeedsRestart = !updates.ProjectIdsToRestart.IsEmpty;
357361

358362
switch (updates.Status)
359363
{

src/BuiltInTools/dotnet-watch/HotReloadDotNetWatcher.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,7 @@ void FileChangedCallback(string path, ChangeKind kind)
249249

250250
HotReloadEventSource.Log.HotReloadStart(HotReloadEventSource.StartType.CompilationHandler);
251251

252-
var (projectsToRebuild, projectsToRestart) = await compilationHandler.HandleFileChangesAsync(restartPrompt: async (projects, cancellationToken) =>
252+
var (projectsToRebuild, projectsToRestart) = await compilationHandler.HandleFileChangesAsync(restartPrompt: async (projectNames, cancellationToken) =>
253253
{
254254
if (_rudeEditRestartPrompt != null)
255255
{
@@ -265,9 +265,9 @@ void FileChangedCallback(string path, ChangeKind kind)
265265
{
266266
Context.Reporter.Output("Affected projects:");
267267

268-
foreach (var project in projects.OrderBy(p => p.Name))
268+
foreach (var projectName in projectNames.OrderBy(n => n))
269269
{
270-
Context.Reporter.Output(" " + project.Name);
270+
Context.Reporter.Output(" " + projectName);
271271
}
272272

273273
question = "Do you want to restart these projects?";
@@ -283,9 +283,9 @@ void FileChangedCallback(string path, ChangeKind kind)
283283
{
284284
Context.Reporter.Verbose("Restarting without prompt since dotnet-watch is running in non-interactive mode.");
285285

286-
foreach (var project in projects)
286+
foreach (var projectName in projectNames)
287287
{
288-
Context.Reporter.Verbose($" Project to restart: '{project.Name}'");
288+
Context.Reporter.Verbose($" Project to restart: '{projectName}'");
289289
}
290290
}
291291
}, iterationCancellationToken);
@@ -341,8 +341,8 @@ void FileChangedCallback(string path, ChangeKind kind)
341341
// Apply them to the workspace.
342342
_ = await CaptureChangedFilesSnapshot(projectsToRebuild);
343343

344-
// Restart session to capture new baseline that reflects the changes to the restarted projects.
345-
await compilationHandler.RestartSessionAsync(projectsToRebuild, iterationCancellationToken);
344+
// Update project baselines to reflect changes to the restarted projects.
345+
compilationHandler.UpdateProjectBaselines(projectsToRebuild, iterationCancellationToken);
346346
}
347347

348348
if (projectsToRestart is not [])

src/BuiltInTools/dotnet-watch/Internal/IReporter.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ public bool TryGetMessage(string? prefix, object?[] args, [NotNullWhen(true)] ou
5555
// predefined messages used for testing:
5656
public static readonly MessageDescriptor HotReloadSessionStarting = new(Format: null, Emoji: null, MessageSeverity.None, s_id++);
5757
public static readonly MessageDescriptor HotReloadSessionStarted = new("Hot reload session started.", "🔥", MessageSeverity.Verbose, s_id++);
58-
public static readonly MessageDescriptor HotReloadSessionEnded = new("Hot reload session ended.", "🔥", MessageSeverity.Verbose, s_id++);
58+
public static readonly MessageDescriptor ProjectBaselinesUpdates = new("Project baselines updated.", "🔥", MessageSeverity.Verbose, s_id++);
5959
public static readonly MessageDescriptor FixBuildError = new("Fix the error to continue or press Ctrl+C to exit.", "⌚", MessageSeverity.Warning, s_id++);
6060
public static readonly MessageDescriptor WaitingForChanges = new("Waiting for changes", "⌚", MessageSeverity.Verbose, s_id++);
6161
public static readonly MessageDescriptor LaunchedProcess = new("Launched '{0}' with arguments '{1}': process id {2}", "🚀", MessageSeverity.Verbose, s_id++);

test/dotnet-watch.Tests/HotReload/ApplyDeltaTests.cs

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -409,7 +409,6 @@ public async Task Aspire()
409409
Assert.Equal(1, App.Process.Output.Count(line => line.StartsWith("dotnet watch ⌚ Launching browser: ")));
410410
App.Process.ClearOutput();
411411

412-
#if TODO // needs Roslyn update
413412
// rude edit with build error:
414413
UpdateSourceFile(
415414
serviceSourcePath,
@@ -441,16 +440,6 @@ public async Task Aspire()
441440
App.AssertOutputContains("error CS0246: The type or namespace name 'WeatherForecast' could not be found");
442441
App.Process.ClearOutput();
443442

444-
// TODO: remove
445-
Log("dotnet build-server shutdown");
446-
var workloadInstallCommandSpec = new DotnetCommand(Logger, ["build-server", "shutdown"])
447-
{
448-
WorkingDirectory = testAsset.Path,
449-
};
450-
451-
var result = workloadInstallCommandSpec.Execute();
452-
Assert.Equal(0, result.ExitCode);
453-
454443
// fix build error:
455444
UpdateSourceFile(
456445
serviceSourcePath,
@@ -459,8 +448,9 @@ public async Task Aspire()
459448
await App.AssertOutputLineStartsWith("dotnet watch ⌚ [WatchAspire.ApiService (net9.0)] Capabilities");
460449

461450
App.AssertOutputContains("dotnet watch ⌚ Build succeeded.");
451+
App.AssertOutputContains("dotnet watch 🔥 Project baselines updated.");
462452
App.AssertOutputContains($"dotnet watch ⭐ Starting project: {serviceProjectPath}");
463-
#endif
453+
464454
App.SendControlC();
465455

466456
await App.AssertOutputLineStartsWith("dotnet watch 🛑 Shutdown requested. Press Ctrl+C again to force exit.");

0 commit comments

Comments
 (0)