Skip to content

Commit 1413e73

Browse files
committed
2
1 parent d484411 commit 1413e73

File tree

9 files changed

+78
-19
lines changed

9 files changed

+78
-19
lines changed

src/BuiltInTools/dotnet-watch/EvaluationResult.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ internal sealed class EvaluationResult(IReadOnlyDictionary<string, FileItem> fil
1515
private readonly Lazy<IReadOnlySet<string>> _lazyBuildFiles = new(() => projectGraph != null ? CreateBuildFileSet(projectGraph) : new HashSet<string>());
1616

1717
public static IReadOnlySet<string> CreateBuildFileSet(ProjectGraph projectGraph)
18-
=> projectGraph.ProjectNodes
19-
.SelectMany(p => p.ProjectInstance.ImportPaths)
18+
=> projectGraph.ProjectNodes.SelectMany(p => p.ProjectInstance.ImportPaths)
19+
.Concat(projectGraph.ProjectNodes.Select(p => p.ProjectInstance.FullPath))
2020
.ToHashSet(PathUtilities.OSSpecificPathComparer);
2121

2222
public IReadOnlySet<string> BuildFiles => _lazyBuildFiles.Value;

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,9 @@ void TryAddOutputDir(string? dir)
7070

7171
public void Report(IReporter reporter)
7272
{
73-
foreach (var (_, value, projectDir) in exclusionGlobs)
73+
foreach (var globsPerDirectory in exclusionGlobs.GroupBy(keySelector: static g => g.projectDir, elementSelector: static g => g.value))
7474
{
75-
reporter.Verbose($"Exclusion glob: '{value}' under project '{projectDir}'");
75+
reporter.Verbose($"Exclusion glob: '{string.Join(";", globsPerDirectory)}' under project '{globsPerDirectory.Key}'");
7676
}
7777

7878
foreach (var dir in outputDirectories)

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

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

4+
using System.Collections.Concurrent;
45
using System.Diagnostics;
56
using System.Text.Json;
7+
using Microsoft.Build.Evaluation;
8+
using Microsoft.Build.Execution;
9+
using Microsoft.Build.FileSystem;
610
using Microsoft.Build.Graph;
711

812
namespace Microsoft.DotNet.Watch
@@ -120,7 +124,7 @@ void AddFile(string filePath, string? staticWebAssetPath)
120124
ProjectGraph? projectGraph = null;
121125
if (requireProjectGraph != null)
122126
{
123-
projectGraph = TryLoadProjectGraph(requireProjectGraph.Value);
127+
projectGraph = TryLoadProjectGraph(requireProjectGraph.Value, cancellationToken);
124128
if (projectGraph == null && requireProjectGraph == true)
125129
{
126130
return null;
@@ -193,7 +197,11 @@ private static string FindTargetsFile()
193197
}
194198

195199
// internal for testing
196-
internal ProjectGraph? TryLoadProjectGraph(bool projectGraphRequired)
200+
201+
/// <summary>
202+
/// Tries to create a project graph by running the build evaluation phase on the <see cref="rootProjectFile"/>.
203+
/// </summary>
204+
internal ProjectGraph? TryLoadProjectGraph(bool projectGraphRequired, CancellationToken cancellationToken)
197205
{
198206
var globalOptions = new Dictionary<string, string>();
199207

@@ -202,9 +210,11 @@ private static string FindTargetsFile()
202210
globalOptions[name] = value;
203211
}
204212

213+
var entryPoint = new ProjectGraphEntryPoint(rootProjectFile, globalOptions);
214+
205215
try
206216
{
207-
return new ProjectGraph(rootProjectFile, globalOptions);
217+
return new ProjectGraph([entryPoint], ProjectCollection.GlobalProjectCollection, projectInstanceFactory: null, cancellationToken);
208218
}
209219
catch (Exception e)
210220
{

src/BuiltInTools/dotnet-watch/Properties/launchSettings.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"dotnet-watch": {
44
"commandName": "Project",
55
"commandLineArgs": "--verbose /bl:DotnetRun.binlog",
6-
"workingDirectory": "C:\\Temp\\app\\dir",
6+
"workingDirectory": "C:\\sdk4\\artifacts\\tmp\\Debug\\ProjectChange---0B95B003\\AppWithDeps",
77
"environmentVariables": {
88
"DOTNET_WATCH_DEBUG_SDK_DIRECTORY": "$(RepoRoot)artifacts\\bin\\redist\\$(Configuration)\\dotnet\\sdk\\$(Version)",
99
"DCP_IDE_REQUEST_TIMEOUT_SECONDS": "100000",

test/TestAssets/TestProjects/WatchAppWithProjectDeps/AppWithDeps/Program.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ public static void Main(string[] args)
2020
while (true)
2121
{
2222
Lib.Print();
23-
Thread.Sleep(10);
23+
Thread.Sleep(1000);
2424
}
2525
}
2626
}

test/TestAssets/TestProjects/WatchAppWithProjectDeps/Dependency/Dependency.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
<PropertyGroup>
44
<TargetFrameworks>netstandard2.0;$(CurrentTargetFramework)</TargetFrameworks>
55
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
6+
<DefineConstants>$(DefineConstants);BUILD_CONST_IN_CSPROJ</DefineConstants>
67
</PropertyGroup>
78

89
</Project>
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<Project>
22
<PropertyGroup>
33
<AllowUnsafeBlocks>false</AllowUnsafeBlocks>
4-
<DefineConstants>$(DefineConstants);BUILD_CONST</DefineConstants>
4+
<DefineConstants>$(DefineConstants);BUILD_CONST_IN_PROPS</DefineConstants>
55
</PropertyGroup>
66
</Project>

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

Lines changed: 56 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -105,14 +105,63 @@ public static unsafe void Print()
105105
await App.WaitUntilOutputContains($"dotnet watch 🔥 [App.WithDeps ({ToolsetInfo.CurrentTargetFramework})] Hot reload succeeded.");
106106
}
107107

108-
[Fact]
109-
public async Task ProjectChange_DirectoryBuildProps_Update()
108+
[Theory]
109+
[CombinatorialData]
110+
public async Task ProjectChange_Update(bool isDirectoryProps)
111+
{
112+
var testAsset = TestAssets.CopyTestAsset("WatchAppWithProjectDeps", identifier: isDirectoryProps.ToString())
113+
.WithSource();
114+
115+
var symbolName = isDirectoryProps ? "BUILD_CONST_IN_PROPS" : "BUILD_CONST_IN_CSPROJ";
116+
117+
var dependencyDir = Path.Combine(testAsset.Path, "Dependency");
118+
var libSourcePath = Path.Combine(dependencyDir, "Foo.cs");
119+
var buildFilePath = isDirectoryProps ? Path.Combine(testAsset.Path, "Directory.Build.props") : Path.Combine(dependencyDir, "Dependency.csproj");
120+
121+
File.WriteAllText(libSourcePath, $$"""
122+
public class Lib
123+
{
124+
public static void Print()
125+
{
126+
#if {{symbolName}}
127+
System.Console.WriteLine("{{symbolName}} set");
128+
#else
129+
System.Console.WriteLine("{{symbolName}} not set");
130+
#endif
131+
}
132+
}
133+
""");
134+
135+
App.Start(testAsset, [], "AppWithDeps");
136+
137+
await App.AssertWaitingForChanges();
138+
await App.WaitUntilOutputContains($"{symbolName} set");
139+
App.Process.ClearOutput();
140+
141+
UpdateSourceFile(buildFilePath, src => src.Replace(symbolName, ""));
142+
143+
// TODO: https://github.com/dotnet/roslyn/issues/78921
144+
145+
// Roslyn should detect change in build constant and apply it or flag it as rude edit.
146+
//await App.WaitUntilOutputContains($"dotnet watch 🔥 [App.WithDeps ({ToolsetInfo.CurrentTargetFramework})] Hot reload succeeded.");
147+
//await App.WaitUntilOutputContains("BUILD_CONST not set");
148+
149+
await App.AssertOutputLineStartsWith(MessageDescriptor.NoCSharpChangesToApply);
150+
App.AssertOutputContains(MessageDescriptor.ProjectChangeTriggeredReEvaluation);
151+
}
152+
153+
[Fact(Skip = "https://github.com/dotnet/msbuild/issues/12001")]
154+
public async Task ProjectChange_DirectoryBuildProps_Add()
110155
{
111156
var testAsset = TestAssets.CopyTestAsset("WatchAppWithProjectDeps")
112157
.WithSource();
113158

114159
var dependencyDir = Path.Combine(testAsset.Path, "Dependency");
115160
var libSourcePath = Path.Combine(dependencyDir, "Foo.cs");
161+
var directoryBuildProps = Path.Combine(testAsset.Path, "Directory.Build.props");
162+
163+
// delete the file before we start the app, it will be added later:
164+
File.Delete(directoryBuildProps);
116165

117166
File.WriteAllText(libSourcePath, """
118167
public class Lib
@@ -133,17 +182,16 @@ public static void Print()
133182

134183
await App.AssertWaitingForChanges();
135184
await App.WaitUntilOutputContains("BUILD_CONST set");
185+
App.Process.ClearOutput();
136186

137187
UpdateSourceFile(
138-
Path.Combine(testAsset.Path, "Directory.Build.props"),
188+
directoryBuildProps,
139189
src => src.Replace("BUILD_CONST", ""));
140190

141-
//await App.AssertOutputLineStartsWith(MessageDescriptor.NoCSharpChangesToApply);
142-
//App.AssertOutputContains(MessageDescriptor.ProjectChangeTriggeredReEvaluation);
143-
//App.Process.ClearOutput();
144-
145-
await App.AssertOutputLineStartsWith("BUILD_CONST not set");
146191
await App.WaitUntilOutputContains($"dotnet watch 🔥 [App.WithDeps ({ToolsetInfo.CurrentTargetFramework})] Hot reload succeeded.");
192+
await App.WaitUntilOutputContains("BUILD_CONST not set");
193+
194+
App.AssertOutputContains(MessageDescriptor.ProjectChangeTriggeredReEvaluation);
147195
}
148196

149197
[Fact]

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ public async Task ReferenceOutputAssembly_False()
2626
environmentOptions: environmentOptions,
2727
reporter);
2828

29-
var projectGraph = factory.TryLoadProjectGraph(projectGraphRequired: false);
29+
var projectGraph = factory.TryLoadProjectGraph(projectGraphRequired: false, CancellationToken.None);
3030
var handler = new CompilationHandler(reporter, environmentOptions, CancellationToken.None);
3131

3232
await handler.Workspace.UpdateProjectConeAsync(hostProject, CancellationToken.None);

0 commit comments

Comments
 (0)