Skip to content

Commit 4f0bcf1

Browse files
authored
Workaround for MSBuildProjectLoader.LoadProjectInfoAsync throwing on unrecognized project language (#44927)
1 parent 3e99449 commit 4f0bcf1

File tree

3 files changed

+78
-3
lines changed

3 files changed

+78
-3
lines changed

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

+11-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,17 @@ public async Task UpdateProjectConeAsync(string rootProjectPath, CancellationTok
3636

3737
var loader = new MSBuildProjectLoader(this);
3838
var projectMap = ProjectMap.Create();
39-
var projectInfos = await loader.LoadProjectInfoAsync(rootProjectPath, projectMap, progress: null, msbuildLogger: null, cancellationToken).ConfigureAwait(false);
39+
40+
ImmutableArray<ProjectInfo> projectInfos;
41+
try
42+
{
43+
projectInfos = await loader.LoadProjectInfoAsync(rootProjectPath, projectMap, progress: null, msbuildLogger: null, cancellationToken).ConfigureAwait(false);
44+
}
45+
catch (InvalidOperationException)
46+
{
47+
// TODO: workaround for https://github.com/dotnet/roslyn/issues/75956
48+
projectInfos = [];
49+
}
4050

4151
var oldProjectIdsByPath = oldSolution.Projects.ToDictionary(keySelector: static p => p.FilePath!, elementSelector: static p => p.Id);
4252

src/BuiltInTools/dotnet-watch/HotReloadDotNetWatcher.cs

+13-2
Original file line numberDiff line numberDiff line change
@@ -93,12 +93,13 @@ public override async Task WatchAsync(CancellationToken shutdownCancellationToke
9393
// use normalized MSBuild path so that we can index into the ProjectGraph
9494
rootProjectOptions = rootProjectOptions with { ProjectPath = rootProject.ProjectInstance.FullPath };
9595

96-
if (rootProject.GetCapabilities().Contains(AspireServiceFactory.AppHostProjectCapability))
96+
var rootProjectCapabilities = rootProject.GetCapabilities();
97+
if (rootProjectCapabilities.Contains(AspireServiceFactory.AppHostProjectCapability))
9798
{
9899
runtimeProcessLauncherFactory ??= AspireServiceFactory.Instance;
99100
Context.Reporter.Verbose("Using Aspire process launcher.");
100101
}
101-
102+
102103
await using var browserConnector = new BrowserConnector(Context);
103104
var projectMap = new ProjectNodeMap(evaluationResult.ProjectGraph, Context.Reporter);
104105
compilationHandler = new CompilationHandler(Context.Reporter);
@@ -231,6 +232,16 @@ void FileChangedCallback(string path, ChangeKind kind)
231232
continue;
232233
}
233234

235+
if (!rootProjectCapabilities.Contains("SupportsHotReload"))
236+
{
237+
Context.Reporter.Warn($"Project '{rootProject.GetDisplayName()}' does not support Hot Reload and must be rebuilt.");
238+
239+
// file change already detected
240+
waitForFileChangeBeforeRestarting = false;
241+
iterationCancellationSource.Cancel();
242+
break;
243+
}
244+
234245
HotReloadEventSource.Log.HotReloadStart(HotReloadEventSource.StartType.Main);
235246
var stopwatch = Stopwatch.StartNew();
236247

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

+54
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,60 @@ public static void Print()
6565
await App.AssertOutputLineStartsWith("Changed!");
6666
}
6767

68+
[Fact]
69+
public async Task ChangeFileInFSharpProject()
70+
{
71+
var testAsset = TestAssets.CopyTestAsset("FSharpTestAppSimple")
72+
.WithSource();
73+
74+
App.Start(testAsset, []);
75+
76+
await App.AssertOutputLineStartsWith(MessageDescriptor.WaitingForFileChangeBeforeRestarting);
77+
78+
UpdateSourceFile(Path.Combine(testAsset.Path, "Program.fs"), content => content.Replace("Hello World!", "<Updated>"));
79+
80+
await App.AssertOutputLineStartsWith("<Updated>");
81+
}
82+
83+
[Fact]
84+
public async Task ChangeFileInFSharpProjectWithLoop()
85+
{
86+
var testAsset = TestAssets.CopyTestAsset("FSharpTestAppSimple")
87+
.WithSource();
88+
89+
var source = """
90+
module ConsoleApplication.Program
91+
92+
open System
93+
open System.Threading
94+
95+
[<EntryPoint>]
96+
let main argv =
97+
while true do
98+
printfn "Waiting"
99+
Thread.Sleep(200)
100+
0
101+
""";
102+
103+
var sourcePath = Path.Combine(testAsset.Path, "Program.fs");
104+
105+
File.WriteAllText(sourcePath, source);
106+
107+
App.Start(testAsset, []);
108+
109+
await App.AssertOutputLineStartsWith(MessageDescriptor.WaitingForChanges);
110+
111+
UpdateSourceFile(sourcePath, content => content.Replace("Waiting", "<Updated>"));
112+
113+
await App.AssertOutputLineStartsWith(MessageDescriptor.WaitingForChanges, failure: _ => false);
114+
await App.AssertOutputLineStartsWith("<Updated>");
115+
116+
UpdateSourceFile(sourcePath, content => content.Replace("<Updated>", "<Updated2>"));
117+
118+
await App.AssertOutputLineStartsWith(MessageDescriptor.WaitingForChanges, failure: _ => false);
119+
await App.AssertOutputLineStartsWith("<Updated2>");
120+
}
121+
68122
// Test is timing out on .NET Framework: https://github.com/dotnet/sdk/issues/41669
69123
[CoreMSBuildOnlyFact]
70124
public async Task HandleTypeLoadFailure()

0 commit comments

Comments
 (0)