Skip to content

Commit 9809204

Browse files
authored
Refresh browser for all transitively referencing projects (#45096)
1 parent 20d85a1 commit 9809204

File tree

3 files changed

+66
-21
lines changed

3 files changed

+66
-21
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -348,7 +348,7 @@ private async ValueTask DisplayResultsAsync(WatchHotReloadService.Updates update
348348
switch (updates.Status)
349349
{
350350
case ModuleUpdateStatus.None:
351-
_reporter.Output("No hot reload changes to apply.");
351+
_reporter.Output("No C# changes to apply.");
352352
break;
353353

354354
case ModuleUpdateStatus.Ready:

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

Lines changed: 41 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using System.Collections;
66
using System.Diagnostics;
77
using Microsoft.Build.Graph;
8+
using Microsoft.Build.Framework;
89
using Microsoft.DotNet.Watcher.Internal;
910
using Microsoft.Extensions.Tools.Internal;
1011

@@ -52,41 +53,61 @@ public async ValueTask HandleFileChangesAsync(IReadOnlyList<ChangedFile> files,
5253
}
5354
}
5455

55-
var logger = reporter.IsVerbose ? new[] { new Build.Logging.ConsoleLogger() } : null;
56+
if (!hasApplicableFiles)
57+
{
58+
return;
59+
}
60+
61+
var logger = reporter.IsVerbose ? new[] { new Build.Logging.ConsoleLogger(LoggerVerbosity.Minimal) } : null;
5662

57-
var tasks = projectsToRefresh.Select(async projectNode =>
63+
var buildTasks = projectsToRefresh.Select(projectNode => Task.Run(() =>
5864
{
59-
if (!projectNode.ProjectInstance.DeepCopy().Build(BuildTargetName, logger))
65+
try
6066
{
61-
return false;
67+
if (!projectNode.ProjectInstance.DeepCopy().Build(BuildTargetName, logger))
68+
{
69+
return null;
70+
}
6271
}
63-
64-
if (browserConnector.TryGetRefreshServer(projectNode, out var browserRefreshServer))
72+
catch (Exception e)
6573
{
66-
await HandleBrowserRefresh(browserRefreshServer, projectNode.ProjectInstance.FullPath, cancellationToken);
74+
reporter.Error($"[{projectNode.GetDisplayName()}] Target {BuildTargetName} failed to build: {e}");
75+
return null;
6776
}
6877

69-
return true;
70-
});
78+
return projectNode;
79+
}));
7180

72-
var results = await Task.WhenAll(tasks).WaitAsync(cancellationToken);
81+
var buildResults = await Task.WhenAll(buildTasks).WaitAsync(cancellationToken);
7382

74-
if (hasApplicableFiles)
83+
var browserRefreshTasks = buildResults.Where(p => p != null)!.GetTransitivelyReferencingProjects().Select(async projectNode =>
7584
{
76-
var successfulCount = results.Sum(r => r ? 1 : 0);
77-
78-
if (successfulCount == results.Length)
79-
{
80-
reporter.Output("Hot reload of scoped css succeeded.", emoji: "🔥");
81-
}
82-
else if (successfulCount > 0)
85+
if (browserConnector.TryGetRefreshServer(projectNode, out var browserRefreshServer))
8386
{
84-
reporter.Output($"Hot reload of scoped css partially succeeded: {successfulCount} project(s) out of {results.Length} were updated.", emoji: "🔥");
87+
reporter.Verbose($"[{projectNode.GetDisplayName()}] Refreshing browser.");
88+
await HandleBrowserRefresh(browserRefreshServer, projectNode.ProjectInstance.FullPath, cancellationToken);
8589
}
8690
else
8791
{
88-
reporter.Output("Hot reload of scoped css failed.", emoji: "🔥");
92+
reporter.Verbose($"[{projectNode.GetDisplayName()}] No refresh server.");
8993
}
94+
});
95+
96+
await Task.WhenAll(browserRefreshTasks).WaitAsync(cancellationToken);
97+
98+
var successfulCount = buildResults.Sum(r => r != null ? 1 : 0);
99+
100+
if (successfulCount == buildResults.Length)
101+
{
102+
reporter.Output("Hot reload of scoped css succeeded.", emoji: "🔥");
103+
}
104+
else if (successfulCount > 0)
105+
{
106+
reporter.Output($"Hot reload of scoped css partially succeeded: {successfulCount} project(s) out of {buildResults.Length} were updated.", emoji: "🔥");
107+
}
108+
else
109+
{
110+
reporter.Output("Hot reload of scoped css failed.", emoji: "🔥");
90111
}
91112
}
92113

src/BuiltInTools/dotnet-watch/Utilities/ProjectGraphNodeExtensions.cs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,28 @@ public static bool IsNetCoreApp(this ProjectGraphNode projectNode, Version minVe
3131

3232
public static IEnumerable<string> GetCapabilities(this ProjectGraphNode projectNode)
3333
=> projectNode.ProjectInstance.GetItems("ProjectCapability").Select(item => item.EvaluatedInclude);
34+
35+
public static IEnumerable<ProjectGraphNode> GetTransitivelyReferencingProjects(this IEnumerable<ProjectGraphNode> projects)
36+
{
37+
var visited = new HashSet<ProjectGraphNode>();
38+
var queue = new Queue<ProjectGraphNode>();
39+
foreach (var project in projects)
40+
{
41+
queue.Enqueue(project);
42+
}
43+
44+
while (queue.Count > 0)
45+
{
46+
var project = queue.Dequeue();
47+
if (visited.Add(project))
48+
{
49+
foreach (var referencingProject in project.ReferencingProjects)
50+
{
51+
queue.Enqueue(referencingProject);
52+
}
53+
}
54+
}
55+
56+
return visited;
57+
}
3458
}

0 commit comments

Comments
 (0)