Add prelimianry support for extensions to Razor (#2012)
* Add prelimianry support for extensions to Razor This PR adds MSBuild insfrastructure to the SDK that can understand concepts we need to expose to the project, code generator and runtime like: - Language version - Configuration - Extensions (plugins) As an example of how this works, I've done the wireup for MVC. This will now generate assembly attributes in your application that can act as a source-of-truth for what should be included in runtime compilation, and it's all based on the project-file. This means that it can be delivered and configured by packages. The next step here is to implement a loader for RazorProjectEngine based on these primitives, and then use it in our CLI tools and MVC. The next step after that is to expose it in VS and VS4Mac through the project system.
This commit is contained in:
parent
8c328edfb2
commit
5b28c06d64
|
|
@ -12,6 +12,11 @@
|
|||
</Compile>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="build\**\*.props" PackagePath="build\" />
|
||||
<Content Include="build\**\*.targets" PackagePath="build\" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="../Microsoft.AspNetCore.Razor.Language/Microsoft.AspNetCore.Razor.Language.csproj" />
|
||||
<ProjectReference Include="../Microsoft.CodeAnalysis.Razor/Microsoft.CodeAnalysis.Razor.csproj" />
|
||||
|
|
|
|||
|
|
@ -0,0 +1,32 @@
|
|||
<Project>
|
||||
<!--
|
||||
MSBuild support for Razor code generation that targets ASP.NET Core MVC 2.X
|
||||
|
||||
The properties and items here are designed to be read by CPS so they should be just simple evaluation-time values
|
||||
and should not require targets to initialize.
|
||||
-->
|
||||
<PropertyGroup>
|
||||
<!--
|
||||
Set the primary configuration supported by this pacakge as the default configuration for Razor.
|
||||
-->
|
||||
<RazorDefaultConfiguration Condition="'$(RazorDefaultConfiguration)'==''">MVC-2.1</RazorDefaultConfiguration>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<!--
|
||||
While technically the assembly in this package can provide support for the MVC-2.0 configuration, don't declare
|
||||
it here. The IDE is hardcoded to inject 2.0 support when needed. The settings flowing through MSBuild should reflect
|
||||
the project's runtime.
|
||||
-->
|
||||
<RazorConfiguration Include="MVC-2.1">
|
||||
<Extensions>MVC-2.1;$(CustomRazorExtension)</Extensions>
|
||||
</RazorConfiguration>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<RazorExtension Include="MVC-2.1">
|
||||
<AssemblyName>Microsoft.AspNetCore.Mvc.Razor.Extensions</AssemblyName>
|
||||
<AssemblyFilePath>$(MSBuildThisFileDirectory)..\..\lib\netstandard2.0\Microsoft.AspNetCore.Mvc.Razor.Extensions.dll</AssemblyFilePath>
|
||||
</RazorExtension>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
<Project>
|
||||
<PropertyGroup>
|
||||
|
||||
<!--
|
||||
MVC will generally want to add support for runtime compilation, but only for applications.
|
||||
-->
|
||||
<GenerateRazorAssemblyInfo Condition="'$(GenerateRazorAssemblyInfo)'=='' and '$(OutputType)'=='Exe'">true</GenerateRazorAssemblyInfo>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
|
|
@ -1,15 +1,29 @@
|
|||
<Project ToolsVersion="14.0" TreatAsLocalProperty="_RazorTaskFolder;_RazorTaskAssembly">
|
||||
<PropertyGroup>
|
||||
<!--
|
||||
Used by the Web SDK if the Razor SDK can be used for compilation. This needs to live in a nuget package (not in the SDK)
|
||||
so that it only shows up in supported versions.
|
||||
Used by the Web SDK if the Razor SDK can be used for compilation. This needs to live in a nuget package (not in the SDK)
|
||||
so that it only shows up in supported versions.
|
||||
-->
|
||||
<IsRazorCompilerReferenced>true</IsRazorCompilerReferenced>
|
||||
|
||||
<!--
|
||||
Location of the CodeGeneration targets. The SDK uses this to import the file ensuring deterministic import order.
|
||||
Location of the CodeGeneration targets. The SDK uses this to import the file ensuring deterministic import order.
|
||||
-->
|
||||
<RazorCodeGenerationTargetsPath>$(MSBuildThisFileDirectory)Microsoft.AspNetCore.Razor.Design.CodeGeneration.targets</RazorCodeGenerationTargetsPath>
|
||||
|
||||
<!--
|
||||
Configures the language version of Razor. Supported and default values differ depending on the version of
|
||||
the packages in use.
|
||||
|
||||
Supported:
|
||||
2.0
|
||||
2.1
|
||||
Latest = 2.1
|
||||
|
||||
Default:
|
||||
2.1
|
||||
-->
|
||||
<RazorLangVersion Condition="'$(RazorLangVersion)'==''">2.1</RazorLangVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
|
|
|
|||
|
|
@ -1856,6 +1856,20 @@ namespace Microsoft.AspNetCore.Razor.Language
|
|||
internal static string FormatRazorProjectEngineMissingFeatureDependency(object p0, object p1)
|
||||
=> string.Format(CultureInfo.CurrentCulture, GetString("RazorProjectEngineMissingFeatureDependency"), p0, p1);
|
||||
|
||||
/// <summary>
|
||||
/// The Razor language version '{0}' is unrecognized or not supported by this version of Razor.
|
||||
/// </summary>
|
||||
internal static string RazorLanguageVersion_InvalidVersion
|
||||
{
|
||||
get => GetString("RazorLanguageVersion_InvalidVersion");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The Razor language version '{0}' is unrecognized or not supported by this version of Razor.
|
||||
/// </summary>
|
||||
internal static string FormatRazorLanguageVersion_InvalidVersion(object p0)
|
||||
=> string.Format(CultureInfo.CurrentCulture, GetString("RazorLanguageVersion_InvalidVersion"), p0);
|
||||
|
||||
private static string GetString(string name, params string[] formatterNames)
|
||||
{
|
||||
var value = _resourceManager.GetString(name);
|
||||
|
|
|
|||
|
|
@ -2,24 +2,58 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Language
|
||||
{
|
||||
public sealed class RazorConfiguration
|
||||
{
|
||||
public static readonly RazorConfiguration Default = new RazorConfiguration(RazorLanguageVersion.Latest, designTime: false);
|
||||
public static readonly RazorConfiguration Default = new RazorConfiguration(
|
||||
RazorLanguageVersion.Latest,
|
||||
"unnamed",
|
||||
Array.Empty<RazorExtension>(),
|
||||
designTime: false);
|
||||
|
||||
public RazorConfiguration(RazorLanguageVersion languageVersion, bool designTime)
|
||||
// This is used only in some back-compat scenarios. We don't expose it because there's no
|
||||
// use case for anyone else to use it.
|
||||
internal static readonly RazorConfiguration DefaultDesignTime = new RazorConfiguration(
|
||||
RazorLanguageVersion.Latest,
|
||||
"unnamed",
|
||||
Array.Empty<RazorExtension>(),
|
||||
designTime: true);
|
||||
|
||||
public RazorConfiguration(
|
||||
RazorLanguageVersion languageVersion,
|
||||
string configurationName,
|
||||
IEnumerable<RazorExtension> extensions,
|
||||
bool designTime)
|
||||
{
|
||||
if (languageVersion == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(languageVersion));
|
||||
}
|
||||
|
||||
if (configurationName == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(configurationName));
|
||||
}
|
||||
|
||||
if (extensions == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(extensions));
|
||||
}
|
||||
|
||||
LanguageVersion = languageVersion;
|
||||
ConfigurationName = configurationName;
|
||||
Extensions = extensions.ToArray();
|
||||
DesignTime = designTime;
|
||||
}
|
||||
|
||||
public string ConfigurationName { get; }
|
||||
|
||||
public IReadOnlyList<RazorExtension> Extensions { get; }
|
||||
|
||||
public RazorLanguageVersion LanguageVersion { get; }
|
||||
|
||||
public bool DesignTime { get; }
|
||||
|
|
|
|||
|
|
@ -24,8 +24,7 @@ namespace Microsoft.AspNetCore.Razor.Language
|
|||
return CreateDesignTime(configure: null);
|
||||
}
|
||||
|
||||
public static RazorEngine CreateDesignTime(Action<IRazorEngineBuilder> configure)
|
||||
=> CreateCore(new RazorConfiguration(RazorLanguageVersion.Latest, designTime: true), configure);
|
||||
public static RazorEngine CreateDesignTime(Action<IRazorEngineBuilder> configure) => CreateCore(RazorConfiguration.DefaultDesignTime, configure);
|
||||
|
||||
// Internal since RazorEngine APIs are going to be obsolete.
|
||||
internal static RazorEngine CreateCore(RazorConfiguration configuration, Action<IRazorEngineBuilder> configure)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,10 @@
|
|||
// Copyright(c) .NET Foundation.All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Language
|
||||
{
|
||||
public abstract class RazorExtension
|
||||
{
|
||||
public abstract string ExtensionName { get; }
|
||||
}
|
||||
}
|
||||
|
|
@ -2,10 +2,12 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Language
|
||||
{
|
||||
public sealed class RazorLanguageVersion : IEquatable<RazorLanguageVersion>
|
||||
[DebuggerDisplay("{" + nameof(DebuggerToString) + "(),nq}")]
|
||||
public sealed class RazorLanguageVersion : IEquatable<RazorLanguageVersion>, IComparable<RazorLanguageVersion>
|
||||
{
|
||||
public static readonly RazorLanguageVersion Version_1_0 = new RazorLanguageVersion(1, 0);
|
||||
|
||||
|
|
@ -17,6 +19,60 @@ namespace Microsoft.AspNetCore.Razor.Language
|
|||
|
||||
public static readonly RazorLanguageVersion Latest = Version_2_1;
|
||||
|
||||
public static bool TryParse(string languageVersion, out RazorLanguageVersion version)
|
||||
{
|
||||
if (languageVersion == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(languageVersion));
|
||||
}
|
||||
|
||||
if (string.Equals(languageVersion, "latest", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
version = Version_2_1;
|
||||
return true;
|
||||
}
|
||||
else if (languageVersion == "2.1")
|
||||
{
|
||||
version = Version_2_1;
|
||||
return true;
|
||||
}
|
||||
else if (languageVersion == "2.0")
|
||||
{
|
||||
version = Version_2_0;
|
||||
return true;
|
||||
}
|
||||
else if (languageVersion == "1.1")
|
||||
{
|
||||
version = Version_1_1;
|
||||
return true;
|
||||
}
|
||||
else if (languageVersion == "1.0")
|
||||
{
|
||||
version = Version_1_0;
|
||||
return true;
|
||||
}
|
||||
|
||||
version = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
public static RazorLanguageVersion Parse(string languageVersion)
|
||||
{
|
||||
if (languageVersion == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(languageVersion));
|
||||
}
|
||||
|
||||
if (TryParse(languageVersion, out var parsed))
|
||||
{
|
||||
return parsed;
|
||||
}
|
||||
|
||||
throw new ArgumentException(
|
||||
Resources.FormatRazorLanguageVersion_InvalidVersion(languageVersion),
|
||||
nameof(languageVersion));
|
||||
}
|
||||
|
||||
// Don't want anyone else constructing language versions.
|
||||
private RazorLanguageVersion(int major, int minor)
|
||||
{
|
||||
|
|
@ -28,6 +84,22 @@ namespace Microsoft.AspNetCore.Razor.Language
|
|||
|
||||
public int Minor { get; }
|
||||
|
||||
public int CompareTo(RazorLanguageVersion other)
|
||||
{
|
||||
if (other == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(other));
|
||||
}
|
||||
|
||||
var result = Major.CompareTo(other.Major);
|
||||
if (result != 0)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
return Minor.CompareTo(other.Minor);
|
||||
}
|
||||
|
||||
public bool Equals(RazorLanguageVersion other)
|
||||
{
|
||||
if (other == null)
|
||||
|
|
@ -44,7 +116,9 @@ namespace Microsoft.AspNetCore.Razor.Language
|
|||
// We don't need to do anything special for our hash code since reference equality is what we're going for.
|
||||
return base.GetHashCode();
|
||||
}
|
||||
|
||||
public override string ToString() => $"{Major}.{Minor}";
|
||||
|
||||
public override string ToString() => $"Razor '{Major}.{Minor}'";
|
||||
private string DebuggerToString() => $"Razor '{Major}.{Minor}'";
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,8 +9,9 @@ namespace Microsoft.AspNetCore.Razor.Language
|
|||
{
|
||||
var allowMinimizedBooleanTagHelperAttributes = false;
|
||||
|
||||
if (version == RazorLanguageVersion.Version_2_1)
|
||||
if (version.CompareTo(RazorLanguageVersion.Version_2_1) >= 0)
|
||||
{
|
||||
// Added in 2.1
|
||||
allowMinimizedBooleanTagHelperAttributes = true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -533,4 +533,7 @@ Instead, wrap the contents of the block in "{{}}":
|
|||
<data name="RazorProjectEngineMissingFeatureDependency" xml:space="preserve">
|
||||
<value>The '{0}' is missing feature '{1}'.</value>
|
||||
</data>
|
||||
<data name="RazorLanguageVersion_InvalidVersion" xml:space="preserve">
|
||||
<value>The Razor language version '{0}' is unrecognized or not supported by this version of Razor.</value>
|
||||
</data>
|
||||
</root>
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Hosting
|
||||
{
|
||||
/// <summary>
|
||||
/// Specifies the name of a Razor configuration as defined by the Razor SDK.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This attribute is applied to an application's entry point assembly by the Razor SDK during the build,
|
||||
/// so that the Razor configuration can be loaded at runtime based on the settings provided by the project
|
||||
/// file.
|
||||
/// </remarks>
|
||||
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = false, Inherited = false)]
|
||||
public sealed class RazorConfigurationNameAttribute : Attribute
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new instance of <see cref="RazorConfigurationNameAttribute"/>.
|
||||
/// </summary>
|
||||
/// <param name="configurationName">The name of the Razor configuration.</param>
|
||||
public RazorConfigurationNameAttribute(string configurationName)
|
||||
{
|
||||
if (configurationName == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(configurationName));
|
||||
}
|
||||
|
||||
ConfigurationName = configurationName;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name of the Razor configuration.
|
||||
/// </summary>
|
||||
public string ConfigurationName { get; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Hosting
|
||||
{
|
||||
/// <summary>
|
||||
/// Specifies the name of a Razor extension as defined by the Razor SDK.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This attribute is applied to an application's entry point assembly by the Razor SDK during the build,
|
||||
/// so that the Razor configuration can be loaded at runtime based on the settings provided by the project
|
||||
/// file.
|
||||
/// </remarks>
|
||||
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true, Inherited = false)]
|
||||
public sealed class RazorExtensionAssemblyNameAttribute : Attribute
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new instance of <see cref="RazorExtensionAssemblyNameAttribute"/>.
|
||||
/// </summary>
|
||||
/// <param name="extensionName">The name of the extension.</param>
|
||||
/// <param name="assemblyName">The assembly name of the extension.</param>
|
||||
public RazorExtensionAssemblyNameAttribute(string extensionName, string assemblyName)
|
||||
{
|
||||
if (extensionName == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(extensionName));
|
||||
}
|
||||
|
||||
if (assemblyName == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(assemblyName));
|
||||
}
|
||||
|
||||
ExtensionName = extensionName;
|
||||
AssemblyName = assemblyName;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the assembly name of the extension.
|
||||
/// </summary>
|
||||
public string AssemblyName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name of the extension.
|
||||
/// </summary>
|
||||
public string ExtensionName { get; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Hosting
|
||||
{
|
||||
/// <summary>
|
||||
/// Specifies the name of a Razor configuration as defined by the Razor SDK.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This attribute is part of a set of metadata attributes that can be applied to an assembly at build
|
||||
/// time by the Razor SDK. These attributes allow the Razor configuration to be loaded at runtime based
|
||||
/// on the settings originally provided by the project file.
|
||||
/// </remarks>
|
||||
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = false, Inherited = false)]
|
||||
public sealed class RazorLanguageVersionAttribute : Attribute
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new instance of <see cref="RazorLanguageVersionAttribute"/>.
|
||||
/// </summary>
|
||||
/// <param name="languageVersion">The language version of Razor</param>
|
||||
public RazorLanguageVersionAttribute(string languageVersion)
|
||||
{
|
||||
if (languageVersion == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(languageVersion));
|
||||
}
|
||||
|
||||
LanguageVersion = languageVersion;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Razor language version.
|
||||
/// </summary>
|
||||
public string LanguageVersion { get; }
|
||||
}
|
||||
}
|
||||
|
|
@ -161,6 +161,46 @@ Copyright (c) .NET Foundation. All rights reserved.
|
|||
<Target Name="RazorCompile" DependsOnTargets="$(RazorCompileDependsOn)">
|
||||
</Target>
|
||||
|
||||
<!--
|
||||
Generates assembly attributes in support for Razor runtime code generation. This is a set of standard
|
||||
metadata attributes (defined in Microsoft.AspNetCore.Razor.Runtime) that capture the build-time
|
||||
Razor configuration of an application to be used at runtime.
|
||||
|
||||
This allows the project file to act as the source of truth for the applicable Razor configuration regardless
|
||||
of how Razor is used.
|
||||
|
||||
The SDK expects configurations that use runtime compilation to set $(GenerateRazorAssemblyInfo) to true,
|
||||
it will be unset by default.
|
||||
-->
|
||||
<Target
|
||||
Name="RazorGetAssemblyAttributes"
|
||||
AfterTargets="GetAssemblyAttributes"
|
||||
Condition="'$(GenerateRazorAssemblyInfo)'=='true' and '$(RazorDefaultConfiguration)'!=''">
|
||||
|
||||
<ItemGroup>
|
||||
<_ResolvedRazorConfiguration Include="@(RazorConfiguration)" Condition="'%(RazorConfiguration.Identity)'=='$(RazorDefaultConfiguration)'" />
|
||||
<_ResolvedRazorExtensionName Include="%(_ResolvedRazorConfiguration.Extensions)"/>
|
||||
</ItemGroup>
|
||||
|
||||
<FindInList List="@(RazorExtension)" ItemSpecToFind="%(_ResolvedRazorExtensionName.Identity)">
|
||||
<Output TaskParameter="ItemFound" ItemName="_ResolvedRazorExtension" />
|
||||
</FindInList>
|
||||
|
||||
<ItemGroup>
|
||||
<AssemblyAttribute Include="Microsoft.AspNetCore.Razor.Hosting.RazorLanguageVersionAttribute">
|
||||
<_Parameter1>$(RazorLangVersion)</_Parameter1>
|
||||
</AssemblyAttribute>
|
||||
<AssemblyAttribute Include="Microsoft.AspNetCore.Razor.Hosting.RazorConfigurationNameAttribute">
|
||||
<_Parameter1>$(RazorDefaultConfiguration)</_Parameter1>
|
||||
</AssemblyAttribute>
|
||||
<AssemblyAttribute Include="Microsoft.AspNetCore.Razor.Hosting.RazorExtensionAssemblyNameAttribute" Condition="'%(_ResolvedRazorExtension.AssemblyName)'!=''">
|
||||
<_Parameter1>%(_ResolvedRazorExtension.Identity)</_Parameter1>
|
||||
<_Parameter2>%(_ResolvedRazorExtension.AssemblyName)</_Parameter2>
|
||||
</AssemblyAttribute>
|
||||
</ItemGroup>
|
||||
|
||||
</Target>
|
||||
|
||||
<!--
|
||||
Gathers input source files for code generation. This is a separate target so that we can avoid
|
||||
lots of work when there are no inputs for code generation.
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ namespace Microsoft.VisualStudio.Editor.Razor
|
|||
var project = FindProject(projectPath);
|
||||
var configuration = (project?.Configuration as MvcExtensibilityConfiguration) ?? DefaultConfiguration;
|
||||
var razorLanguageVersion = configuration.LanguageVersion;
|
||||
var razorConfiguration = new RazorConfiguration(razorLanguageVersion, designTime: true);
|
||||
var razorConfiguration = new RazorConfiguration(razorLanguageVersion, "unnamed", Array.Empty<RazorExtension>(), designTime: true);
|
||||
|
||||
RazorEngine engine;
|
||||
if (razorLanguageVersion.Major == 1)
|
||||
|
|
|
|||
|
|
@ -100,6 +100,50 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
|
|||
throw new BuildOutputMissingException(result, match);
|
||||
}
|
||||
|
||||
public static void FileContainsLine(MSBuildResult result, string filePath, string match)
|
||||
{
|
||||
if (result == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(result));
|
||||
}
|
||||
|
||||
filePath = Path.Combine(result.Project.DirectoryPath, filePath);
|
||||
FileExists(result, filePath);
|
||||
|
||||
var lines = File.ReadAllLines(filePath);
|
||||
for (var i = 0; i < lines.Length; i++)
|
||||
{
|
||||
var line = lines[i].Trim();
|
||||
if (line == match)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
throw new FileContentMissingException(result, filePath, File.ReadAllText(filePath), match);
|
||||
}
|
||||
|
||||
public static void FileDoesNotContainLine(MSBuildResult result, string filePath, string match)
|
||||
{
|
||||
if (result == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(result));
|
||||
}
|
||||
|
||||
filePath = Path.Combine(result.Project.DirectoryPath, filePath);
|
||||
FileExists(result, filePath);
|
||||
|
||||
var lines = File.ReadAllLines(filePath);
|
||||
for (var i = 0; i < lines.Length; i++)
|
||||
{
|
||||
var line = lines[i].Trim();
|
||||
if (line == match)
|
||||
{
|
||||
throw new FileContentFoundException(result, filePath, File.ReadAllText(filePath), match);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void FileExists(MSBuildResult result, params string[] paths)
|
||||
{
|
||||
if (result == null)
|
||||
|
|
@ -304,6 +348,66 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
|
|||
protected override string Heading => $"Build did not contain the line: '{Match}'.";
|
||||
}
|
||||
|
||||
private class FileContentFoundException : MSBuildXunitException
|
||||
{
|
||||
public FileContentFoundException(MSBuildResult result, string filePath, string content, string match)
|
||||
: base(result)
|
||||
{
|
||||
FilePath = filePath;
|
||||
Content = content;
|
||||
Match = match;
|
||||
}
|
||||
|
||||
public string Content { get; }
|
||||
|
||||
public string FilePath { get; }
|
||||
|
||||
public string Match { get; }
|
||||
|
||||
protected override string Heading
|
||||
{
|
||||
get
|
||||
{
|
||||
var builder = new StringBuilder();
|
||||
builder.AppendFormat("File content of '{0}' should not contain line: '{1}'.", FilePath, Match);
|
||||
builder.AppendLine();
|
||||
builder.AppendLine();
|
||||
builder.AppendLine(Content);
|
||||
return builder.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class FileContentMissingException : MSBuildXunitException
|
||||
{
|
||||
public FileContentMissingException(MSBuildResult result, string filePath, string content, string match)
|
||||
: base(result)
|
||||
{
|
||||
FilePath = filePath;
|
||||
Content = content;
|
||||
Match = match;
|
||||
}
|
||||
|
||||
public string Content { get; }
|
||||
|
||||
public string FilePath { get; }
|
||||
|
||||
public string Match { get; }
|
||||
|
||||
protected override string Heading
|
||||
{
|
||||
get
|
||||
{
|
||||
var builder = new StringBuilder();
|
||||
builder.AppendFormat("File content of '{0}' did not contain the line: '{1}'.", FilePath, Match);
|
||||
builder.AppendLine();
|
||||
builder.AppendLine();
|
||||
builder.AppendLine(Content);
|
||||
return builder.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class FileMissingException : MSBuildXunitException
|
||||
{
|
||||
public FileMissingException(MSBuildResult result, string filePath)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,90 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
|
||||
{
|
||||
public class ConfigurationMetadataIntegrationTest : MSBuildIntegrationTestBase
|
||||
{
|
||||
[Fact]
|
||||
[InitializeTestProject("SimpleMvc")]
|
||||
public async Task Build_WithMvc_AddsConfigurationMetadata()
|
||||
{
|
||||
var result = await DotnetMSBuild("Build", $"/p:RazorCompileOnBuild=true");
|
||||
|
||||
Assert.BuildPassed(result);
|
||||
|
||||
Assert.FileExists(result, IntermediateOutputPath, "SimpleMvc.PrecompiledViews.dll");
|
||||
Assert.FileExists(result, IntermediateOutputPath, "SimpleMvc.PrecompiledViews.pdb");
|
||||
|
||||
Assert.FileExists(result, IntermediateOutputPath, "SimpleMvc.AssemblyInfo.cs");
|
||||
Assert.FileContainsLine(
|
||||
result,
|
||||
Path.Combine(IntermediateOutputPath, "SimpleMvc.AssemblyInfo.cs"),
|
||||
"[assembly: Microsoft.AspNetCore.Razor.Hosting.RazorLanguageVersionAttribute(\"2.1\")]");
|
||||
Assert.FileContainsLine(
|
||||
result,
|
||||
Path.Combine(IntermediateOutputPath, "SimpleMvc.AssemblyInfo.cs"),
|
||||
"[assembly: Microsoft.AspNetCore.Razor.Hosting.RazorConfigurationNameAttribute(\"MVC-2.1\")]");
|
||||
Assert.FileContainsLine(
|
||||
result,
|
||||
Path.Combine(IntermediateOutputPath, "SimpleMvc.AssemblyInfo.cs"),
|
||||
"[assembly: Microsoft.AspNetCore.Razor.Hosting.RazorExtensionAssemblyNameAttribute(\"MVC-2.1\", \"Microsoft.AspNetCore.Mvc.Razor.Extensions\")]");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[InitializeTestProject("SimpleMvc")]
|
||||
public async Task Build_WithGenerateRazorAssemblyInfo_False_SuppressesConfigurationMetadata()
|
||||
{
|
||||
var result = await DotnetMSBuild("Build", $"/p:RazorCompileOnBuild=true /p:GenerateRazorAssemblyInfo=false");
|
||||
|
||||
Assert.BuildPassed(result);
|
||||
|
||||
Assert.FileExists(result, IntermediateOutputPath, "SimpleMvc.PrecompiledViews.dll");
|
||||
Assert.FileExists(result, IntermediateOutputPath, "SimpleMvc.PrecompiledViews.pdb");
|
||||
|
||||
Assert.FileExists(result, IntermediateOutputPath, "SimpleMvc.AssemblyInfo.cs");
|
||||
Assert.FileDoesNotContainLine(
|
||||
result,
|
||||
Path.Combine(IntermediateOutputPath, "SimpleMvc.AssemblyInfo.cs"),
|
||||
"[assembly: Microsoft.AspNetCore.Razor.Hosting.RazorLanguageVersionAttribute(\"2.1\")]");
|
||||
Assert.FileDoesNotContainLine(
|
||||
result,
|
||||
Path.Combine(IntermediateOutputPath, "SimpleMvc.AssemblyInfo.cs"),
|
||||
"[assembly: Microsoft.AspNetCore.Razor.Hosting.RazorConfigurationNameAttribute(\"MVC-2.1\")]");
|
||||
Assert.FileDoesNotContainLine(
|
||||
result,
|
||||
Path.Combine(IntermediateOutputPath, "SimpleMvc.AssemblyInfo.cs"),
|
||||
"[assembly: Microsoft.AspNetCore.Razor.Hosting.RazorExtensionAssemblyNameAttribute(\"MVC-2.1\", \"Microsoft.AspNetCore.Razor.Extensions\")]");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[InitializeTestProject("ClassLibrary")]
|
||||
public async Task Build_ForClassLibrary_SuppressesConfigurationMetadata()
|
||||
{
|
||||
var result = await DotnetMSBuild("Build", $"/p:RazorCompileOnBuild=true");
|
||||
|
||||
Assert.BuildPassed(result);
|
||||
|
||||
Assert.FileExists(result, IntermediateOutputPath, "ClassLibrary.PrecompiledViews.dll");
|
||||
Assert.FileExists(result, IntermediateOutputPath, "ClassLibrary.PrecompiledViews.pdb");
|
||||
|
||||
Assert.FileExists(result, IntermediateOutputPath, "ClassLibrary.AssemblyInfo.cs");
|
||||
Assert.FileDoesNotContainLine(
|
||||
result,
|
||||
Path.Combine(IntermediateOutputPath, "ClassLibrary.AssemblyInfo.cs"),
|
||||
"[assembly: Microsoft.AspNetCore.Razor.Hosting.RazorLanguageVersionAttribute(\"2.1\")]");
|
||||
Assert.FileDoesNotContainLine(
|
||||
result,
|
||||
Path.Combine(IntermediateOutputPath, "ClassLibrary.AssemblyInfo.cs"),
|
||||
"[assembly: Microsoft.AspNetCore.Razor.Hosting.RazorConfigurationNameAttribute(\"MVC-2.1\")]");
|
||||
Assert.FileDoesNotContainLine(
|
||||
result,
|
||||
Path.Combine(IntermediateOutputPath, "ClassLibrary.AssemblyInfo.cs"),
|
||||
"[assembly: Microsoft.AspNetCore.Razor.Hosting.RazorExtensionAssemblyNameAttribute(\"MVC-2.1\", \"Microsoft.AspNetCore.Razor.Extensions\")]");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,10 +1,13 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
<Project>
|
||||
|
||||
<Import Project="Sdk.props" Sdk="Microsoft.NET.Sdk.Web" />
|
||||
|
||||
<PropertyGroup>
|
||||
<_RazorMSBuildRoot>$(SolutionRoot)src\Microsoft.AspNetCore.Razor.Design\bin\$(Configuration)\netstandard2.0\</_RazorMSBuildRoot>
|
||||
</PropertyGroup>
|
||||
|
||||
<Import Project="$(SolutionRoot)src\Microsoft.NET.Sdk.Razor\SDK\Sdk.props" />
|
||||
<Import Project="$(SolutionRoot)src\Microsoft.AspNetCore.Razor.Design\build\netstandard2.0\Microsoft.AspNetCore.Razor.Design.props" />
|
||||
<Import Project="$(SolutionRoot)src\Microsoft.AspNetCore.Mvc.Razor.Extensions\build\netstandard2.0\Microsoft.AspNetCore.Mvc.Razor.props" />
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp2.0</TargetFramework>
|
||||
|
|
@ -18,4 +21,9 @@
|
|||
<ItemGroup>
|
||||
<ProjectReference Include="..\ClassLibrary\ClassLibrary.csproj"/>
|
||||
</ItemGroup>
|
||||
|
||||
<Import Project="$(SolutionRoot)src\Microsoft.AspNetCore.Mvc.Razor.Extensions\build\netstandard2.0\Microsoft.AspNetCore.Mvc.Razor.targets" />
|
||||
|
||||
<Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk.Web" />
|
||||
<Import Project="$(SolutionRoot)src\Microsoft.NET.Sdk.Razor\SDK\Sdk.targets" />
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -1,10 +1,14 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project>
|
||||
|
||||
<Import Project="Sdk.props" Sdk="Microsoft.NET.Sdk" />
|
||||
|
||||
<PropertyGroup>
|
||||
<_RazorMSBuildRoot>$(SolutionRoot)src\Microsoft.AspNetCore.Razor.Design\bin\$(Configuration)\netstandard2.0\</_RazorMSBuildRoot>
|
||||
</PropertyGroup>
|
||||
|
||||
<Import Project="$(SolutionRoot)src\Microsoft.NET.Sdk.Razor\SDK\Sdk.props" />
|
||||
<Import Project="$(SolutionRoot)src\Microsoft.AspNetCore.Razor.Design\build\netstandard2.0\Microsoft.AspNetCore.Razor.Design.props" />
|
||||
<Import Project="$(SolutionRoot)src\Microsoft.AspNetCore.Mvc.Razor.Extensions\build\netstandard2.0\Microsoft.AspNetCore.Mvc.Razor.props" />
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp2.0</TargetFramework>
|
||||
|
|
@ -20,4 +24,10 @@
|
|||
<Pack>false</Pack>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
<Import Project="$(SolutionRoot)src\Microsoft.AspNetCore.Mvc.Razor.Extensions\build\netstandard2.0\Microsoft.AspNetCore.Mvc.Razor.targets" />
|
||||
|
||||
<Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk" />
|
||||
<Import Project="$(SolutionRoot)src\Microsoft.NET.Sdk.Razor\SDK\Sdk.targets" />
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -1,3 +1,2 @@
|
|||
<Project>
|
||||
<Import Project="$(SolutionRoot)src\Microsoft.NET.Sdk.Razor\SDK\Sdk.targets" />
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -1,10 +1,14 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
<Project>
|
||||
|
||||
<Import Project="Sdk.props" Sdk="Microsoft.NET.Sdk.Web" />
|
||||
|
||||
<PropertyGroup>
|
||||
<_RazorMSBuildRoot>$(SolutionRoot)src\Microsoft.AspNetCore.Razor.Design\bin\$(Configuration)\netstandard2.0\</_RazorMSBuildRoot>
|
||||
</PropertyGroup>
|
||||
|
||||
<Import Project="$(SolutionRoot)src\Microsoft.NET.Sdk.Razor\SDK\Sdk.props" />
|
||||
<Import Project="$(SolutionRoot)src\Microsoft.AspNetCore.Razor.Design\build\netstandard2.0\Microsoft.AspNetCore.Razor.Design.props" />
|
||||
<Import Project="$(SolutionRoot)src\Microsoft.AspNetCore.Mvc.Razor.Extensions\build\netstandard2.0\Microsoft.AspNetCore.Mvc.Razor.props" />
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp2.0</TargetFramework>
|
||||
|
|
@ -15,4 +19,9 @@
|
|||
|
||||
<!-- Test Placeholder -->
|
||||
|
||||
<Import Project="$(SolutionRoot)src\Microsoft.AspNetCore.Mvc.Razor.Extensions\build\netstandard2.0\Microsoft.AspNetCore.Mvc.Razor.targets" />
|
||||
|
||||
<Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk.Web" />
|
||||
<Import Project="$(SolutionRoot)src\Microsoft.NET.Sdk.Razor\SDK\Sdk.targets" />
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -1,10 +1,14 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
<Project>
|
||||
|
||||
<Import Project="Sdk.props" Sdk="Microsoft.NET.Sdk.Web" />
|
||||
|
||||
<PropertyGroup>
|
||||
<_RazorMSBuildRoot>$(SolutionRoot)src\Microsoft.AspNetCore.Razor.Design\bin\$(Configuration)\netstandard2.0\</_RazorMSBuildRoot>
|
||||
</PropertyGroup>
|
||||
|
||||
<Import Project="$(SolutionRoot)src\Microsoft.NET.Sdk.Razor\SDK\Sdk.props" />
|
||||
<Import Project="$(SolutionRoot)src\Microsoft.AspNetCore.Razor.Design\build\netstandard2.0\Microsoft.AspNetCore.Razor.Design.props" />
|
||||
<Import Project="$(SolutionRoot)src\Microsoft.AspNetCore.Mvc.Razor.Extensions\build\netstandard2.0\Microsoft.AspNetCore.Mvc.Razor.props" />
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp2.0</TargetFramework>
|
||||
|
|
@ -15,4 +19,9 @@
|
|||
|
||||
<!-- Test Placeholder -->
|
||||
|
||||
<Import Project="$(SolutionRoot)src\Microsoft.AspNetCore.Mvc.Razor.Extensions\build\netstandard2.0\Microsoft.AspNetCore.Mvc.Razor.targets" />
|
||||
|
||||
<Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk.Web" />
|
||||
<Import Project="$(SolutionRoot)src\Microsoft.NET.Sdk.Razor\SDK\Sdk.targets" />
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
Loading…
Reference in New Issue