Skip to content

Commit 20d85a1

Browse files
authored
Workaround for MSbuildProjectLoader.LoadProjectInfoAsync throwing on unrecognized project language (#44928)
1 parent c5a9b26 commit 20d85a1

File tree

4 files changed

+77
-2
lines changed

4 files changed

+77
-2
lines changed

src/BuiltInTools/dotnet-watch/EnvironmentVariablesBuilder.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ public void SetVariable(string name, string value)
6060

6161
public void ConfigureProcess(ProcessSpec processSpec)
6262
{
63-
processSpec.Arguments = [.. GetCommandLineDirectives(), .. processSpec.Arguments];
63+
processSpec.Arguments = [.. GetCommandLineDirectives(), .. processSpec.Arguments ?? []];
6464
AddToEnvironment(processSpec.EnvironmentVariables);
6565
}
6666

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

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,17 @@ public async Task UpdateProjectConeAsync(string rootProjectPath, CancellationTok
3838

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

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

src/BuiltInTools/dotnet-watch/HotReloadDotNetWatcher.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ public override async Task WatchAsync(CancellationToken shutdownCancellationToke
9191

9292
var rootProjectOptions = Context.RootProjectOptions;
9393
var rootProjectNode = Context.ProjectGraph.GraphRoots.Single();
94+
var rootProjectCapabilities = rootProjectNode.GetCapabilities();
9495

9596
await using var runtimeProcessLauncher = _runtimeProcessLauncherFactory?.TryCreate(rootProjectNode, projectLauncher, rootProjectOptions.BuildProperties);
9697
if (runtimeProcessLauncher != null)
@@ -211,6 +212,16 @@ public override async Task WatchAsync(CancellationToken shutdownCancellationToke
211212
await compilationHandler.Workspace.UpdateFileContentAsync(changedFiles, iterationCancellationToken);
212213
}
213214

215+
if (!rootProjectCapabilities.Contains("SupportsHotReload"))
216+
{
217+
Context.Reporter.Warn($"Project '{rootProjectNode.GetDisplayName()}' does not support Hot Reload and must be rebuilt.");
218+
219+
// file change already detected
220+
waitForFileChangeBeforeRestarting = false;
221+
iterationCancellationSource.Cancel();
222+
break;
223+
}
224+
214225
HotReloadEventSource.Log.HotReloadStart(HotReloadEventSource.StartType.Main);
215226
var stopwatch = Stopwatch.StartNew();
216227

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

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,60 @@ public static void Print()
6868
await App.AssertOutputLineStartsWith("Changed!");
6969
}
7070

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

0 commit comments

Comments
 (0)