Allow dotnet watch to refresh on changes to .razor files in referenced projects

dotnet-watch expects full paths to files to watch in all added items. For files in the current project, this
happens to work. However this does not work very well for files in referenced projects. Using the FullPath metadata
does not work during global evaluation, but we're able to do this in a target.

This change adds extensibility to the dotnet-watch tool that allows calling a target as part of "watch" evaluation.

Fixes https://github.com/dotnet/aspnetcore/issues/22219
This commit is contained in:
Pranav K 2020-08-25 15:25:29 -07:00
parent 3f81caae85
commit 28e18c3058
No known key found for this signature in database
GPG Key ID: F748807460A27E91
6 changed files with 69 additions and 7 deletions

View File

@ -78,6 +78,11 @@ Copyright (c) .NET Foundation. All rights reserved.
This property affects C# projects targeting 3.0 or later.
-->
<RazorUpToDateReloadFileTypes>.cs;.razor;.resx;.cshtml</RazorUpToDateReloadFileTypes>
<!--
Target used by dotnet-watch to resolve additional items.
-->
<CustomCollectWatchItems>$(CustomCollectWatchItems);_RazorSdkCustomCollectWatchItems</CustomCollectWatchItems>
</PropertyGroup>
<ItemGroup Condition="'$(EnableDefaultItems)' == 'true' And '$(EnableDefaultContentItems)' == 'true'">

View File

@ -327,12 +327,6 @@ Copyright (c) .NET Foundation. All rights reserved.
-->
<UpToDateCheckBuilt Include="@(RazorIntermediateAssembly)"
Condition="'$(RazorCompileOnBuild)'=='true' AND '@(Content->WithMetadataValue('Extension', '.cshtml'))' != ''" Set="RazorViews" />
<!-- Set up watchers for dotnet-watch -->
<Watch Include="@(Content->WithMetadataValue('Extension', '.razor'))" />
<Watch Include="@(Content->WithMetadataValue('Extension', '.cshtml'))"
Condition="'$(_Targeting30OrNewerRazorLangVersion)' == 'true' AND '$(AddCshtmlFilesToDotNetWatchList)' != 'false'" />
</ItemGroup>
<!--
@ -870,6 +864,14 @@ Copyright (c) .NET Foundation. All rights reserved.
</PropertyGroup>
</Target>
<Target Name="_RazorSdkCustomCollectWatchItems">
<ItemGroup>
<Watch Include="%(Content.FullPath)" Condition="'%(Content.Extension)' == '.razor' AND '%(Content.Watch)' != 'false'" />
<Watch Include="%(Content.FullPath)"
Condition="'$(_Targeting30OrNewerRazorLangVersion)' == 'true' AND '$(AddCshtmlFilesToDotNetWatchList)' != 'false' AND '%(Content.Extension)' == '.cshtml' AND '%(Content.Watch)' != 'false'" />
</ItemGroup>
</Target>
<PropertyGroup Condition="'$(RazorDesignTimeTargets)'==''">
<RazorDesignTimeTargets>$(MSBuildExtensionsPath)\Microsoft\VisualStudio\Razor\Microsoft.NET.Sdk.Razor.DesignTime.targets</RazorDesignTimeTargets>
<RazorDesignTimeTargets Condition="!Exists('$(RazorDesignTimeTargets)')">$(MSBuildThisFileDirectory)Microsoft.NET.Sdk.Razor.DesignTime.targets</RazorDesignTimeTargets>

View File

@ -41,6 +41,7 @@ Returns: @(Watch)
</_CollectWatchItemsDependsOn>
<_CollectWatchItemsDependsOn Condition=" '$(TargetFramework)' != '' ">
_CoreCollectWatchItems;
$(CustomCollectWatchItems);
</_CollectWatchItemsDependsOn>
</PropertyGroup>

View File

@ -3,6 +3,7 @@
using System;
using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
@ -276,6 +277,53 @@ namespace Microsoft.DotNet.Watcher.Tools.Tests
);
}
[Fact]
public async Task ProjectReferences_RazorFiles()
{
// Arrange
var razorSdkTargetsPath = GetType().Assembly.GetCustomAttributes<AssemblyMetadataAttribute>()
.First(f => f.Key == "RazorSdkPath").Value;
_tempDir
.SubDir("src")
.SubDir("MyLibrary")
.WithCSharpProject("MyLibrary", out var proj3, sdk: "Microsoft.NET.Sdk.Razor")
.WithProperty("CustomCollectWatchItems", "$(CustomCollectWatchItems);_RazorSdkCustomCollectWatchItems")
.WithProperty("RazorSdkCurrentVersionTargets", razorSdkTargetsPath)
.WithTargetFrameworks("net5.0")
.Dir()
.WithFile("MyLibraryFile.razor")
.WithFile("Class2.cs")
.Up()
.SubDir("MainApp")
.WithCSharpProject("MainApp", out var target, sdk: "Microsoft.NET.Sdk.Razor")
.WithProperty("CustomCollectWatchItems", "$(CustomCollectWatchItems);_RazorSdkCustomCollectWatchItems")
.WithProperty("RazorSdkCurrentVersionTargets", razorSdkTargetsPath)
.WithTargetFrameworks("net5.0")
.WithProjectReference(proj3)
.Dir()
.WithFile("Class1.cs")
.WithFile("Index.razor")
.Up();
var fileset = await GetFileSet(target);
AssertEx.EqualFileList(
_tempDir.Root,
new[]
{
"src/MyLibrary/MyLibraryFile.razor",
"src/MyLibrary/Class2.cs",
"src/MyLibrary/MyLibrary.csproj",
"src/MainApp/Class1.cs",
"src/MainApp/Index.razor",
"src/MainApp/MainApp.csproj"
},
fileset
);
}
private Task<IFileSet> GetFileSet(TemporaryCSharpProject target)
=> GetFileSet(new MsBuildFileSetFactory(_reporter, target.Path, waitOnError: false, trace: false));

View File

@ -0,0 +1 @@
.net

View File

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>$(DefaultNetCoreTargetFramework)</TargetFramework>
@ -21,6 +21,11 @@
<_Parameter1>DotnetPath</_Parameter1>
<_Parameter2>$(DotNetTool)</_Parameter2>
</AssemblyAttribute>
<AssemblyAttribute Include="System.Reflection.AssemblyMetadataAttribute">
<_Parameter1>RazorSdkPath</_Parameter1>
<_Parameter2>$(RepoRoot)src\Razor\Microsoft.NET.Sdk.Razor\src\build\netstandard2.0\Sdk.Razor.CurrentVersion.targets</_Parameter2>
</AssemblyAttribute>
</ItemGroup>
<Target Name="CleanTestProjects" BeforeTargets="CoreCompile">