diff --git a/src/Microsoft.AspNetCore.Razor.Language/Properties/Resources.Designer.cs b/src/Microsoft.AspNetCore.Razor.Language/Properties/Resources.Designer.cs index adb2a92453..1f95e0176c 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/Properties/Resources.Designer.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/Properties/Resources.Designer.cs @@ -822,6 +822,20 @@ namespace Microsoft.AspNetCore.Razor.Language internal static string FormatSectionDirective_NameToken_Name() => GetString("SectionDirective_NameToken_Name"); + /// + /// The Razor language version '{0}' is unrecognized or not supported by this version of Razor. + /// + internal static string RazorLanguageVersion_InvalidVersion + { + get => GetString("RazorLanguageVersion_InvalidVersion"); + } + + /// + /// The Razor language version '{0}' is unrecognized or not supported by this version of Razor. + /// + 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); diff --git a/src/Microsoft.AspNetCore.Razor.Language/RazorConfiguration.cs b/src/Microsoft.AspNetCore.Razor.Language/RazorConfiguration.cs index 32420721ee..0f00751497 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/RazorConfiguration.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/RazorConfiguration.cs @@ -2,25 +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 DefaultRuntime = new RazorConfiguration(RazorLanguageVersion.Latest, designTime: false); - public static readonly RazorConfiguration DefaultDesignTime = new RazorConfiguration(RazorLanguageVersion.Latest, designTime: true); + public static readonly RazorConfiguration Default = new RazorConfiguration( + RazorLanguageVersion.Latest, + "unnamed", + Array.Empty(), + 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(), + designTime: true); + + public RazorConfiguration( + RazorLanguageVersion languageVersion, + string configurationName, + IEnumerable 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 Extensions { get; } + public RazorLanguageVersion LanguageVersion { get; } public bool DesignTime { get; } diff --git a/src/Microsoft.AspNetCore.Razor.Language/RazorEngine.cs b/src/Microsoft.AspNetCore.Razor.Language/RazorEngine.cs index 0fe5e14d19..aa06b9f9ab 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/RazorEngine.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/RazorEngine.cs @@ -15,7 +15,7 @@ namespace Microsoft.AspNetCore.Razor.Language return Create(configure: null); } - public static RazorEngine Create(Action configure) => CreateCore(RazorConfiguration.DefaultRuntime, configure); + public static RazorEngine Create(Action configure) => CreateCore(RazorConfiguration.Default, configure); public static RazorEngine CreateDesignTime() { diff --git a/src/Microsoft.AspNetCore.Razor.Language/RazorExtension.cs b/src/Microsoft.AspNetCore.Razor.Language/RazorExtension.cs new file mode 100644 index 0000000000..feb94b0ede --- /dev/null +++ b/src/Microsoft.AspNetCore.Razor.Language/RazorExtension.cs @@ -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; } + } +} diff --git a/src/Microsoft.AspNetCore.Razor.Language/RazorLanguageVersion.cs b/src/Microsoft.AspNetCore.Razor.Language/RazorLanguageVersion.cs index 721c84ff00..c200290878 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/RazorLanguageVersion.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/RazorLanguageVersion.cs @@ -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 + [DebuggerDisplay("{" + nameof(DebuggerToString) + "(),nq}")] + public sealed class RazorLanguageVersion : IEquatable, IComparable { 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}'"; } } diff --git a/src/Microsoft.AspNetCore.Razor.Language/RazorParserFeatureFlags.cs b/src/Microsoft.AspNetCore.Razor.Language/RazorParserFeatureFlags.cs index 19b1d54e80..0629eb9af8 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/RazorParserFeatureFlags.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/RazorParserFeatureFlags.cs @@ -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; } diff --git a/src/Microsoft.AspNetCore.Razor.Language/Resources.resx b/src/Microsoft.AspNetCore.Razor.Language/Resources.resx index 54df909c15..35b511066d 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/Resources.resx +++ b/src/Microsoft.AspNetCore.Razor.Language/Resources.resx @@ -291,4 +291,7 @@ SectionName + + The Razor language version '{0}' is unrecognized or not supported by this version of Razor. + \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Razor.Runtime/Hosting/RazorConfigurationNameAttribute.cs b/src/Microsoft.AspNetCore.Razor.Runtime/Hosting/RazorConfigurationNameAttribute.cs new file mode 100644 index 0000000000..034e64c309 --- /dev/null +++ b/src/Microsoft.AspNetCore.Razor.Runtime/Hosting/RazorConfigurationNameAttribute.cs @@ -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 +{ + /// + /// Specifies the name of a Razor configuration as defined by the Razor SDK. + /// + /// + /// 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. + /// + [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = false, Inherited = false)] + public sealed class RazorConfigurationNameAttribute : Attribute + { + /// + /// Creates a new instance of . + /// + /// The name of the Razor configuration. + public RazorConfigurationNameAttribute(string configurationName) + { + if (configurationName == null) + { + throw new ArgumentNullException(nameof(configurationName)); + } + + ConfigurationName = configurationName; + } + + /// + /// Gets the name of the Razor configuration. + /// + public string ConfigurationName { get; } + } +} \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Razor.Runtime/Hosting/RazorExtensionAssemblyNameAttribute.cs b/src/Microsoft.AspNetCore.Razor.Runtime/Hosting/RazorExtensionAssemblyNameAttribute.cs new file mode 100644 index 0000000000..92a9d1c6ec --- /dev/null +++ b/src/Microsoft.AspNetCore.Razor.Runtime/Hosting/RazorExtensionAssemblyNameAttribute.cs @@ -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 +{ + /// + /// Specifies the name of a Razor extension as defined by the Razor SDK. + /// + /// + /// 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. + /// + [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true, Inherited = false)] + public sealed class RazorExtensionAssemblyNameAttribute : Attribute + { + /// + /// Creates a new instance of . + /// + /// The name of the extension. + /// The assembly name of the extension. + 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; + } + + /// + /// Gets the assembly name of the extension. + /// + public string AssemblyName { get; } + + /// + /// Gets the name of the extension. + /// + public string ExtensionName { get; } + } +} \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Razor.Runtime/Hosting/RazorLanguageVersionAttribute.cs b/src/Microsoft.AspNetCore.Razor.Runtime/Hosting/RazorLanguageVersionAttribute.cs new file mode 100644 index 0000000000..8f261143d0 --- /dev/null +++ b/src/Microsoft.AspNetCore.Razor.Runtime/Hosting/RazorLanguageVersionAttribute.cs @@ -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 +{ + /// + /// Specifies the name of a Razor configuration as defined by the Razor SDK. + /// + /// + /// 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. + /// + [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = false, Inherited = false)] + public sealed class RazorLanguageVersionAttribute : Attribute + { + /// + /// Creates a new instance of . + /// + /// The language version of Razor + public RazorLanguageVersionAttribute(string languageVersion) + { + if (languageVersion == null) + { + throw new ArgumentNullException(nameof(languageVersion)); + } + + LanguageVersion = languageVersion; + } + + /// + /// Gets the Razor language version. + /// + public string LanguageVersion { get; } + } +} \ No newline at end of file diff --git a/src/Microsoft.VisualStudio.Editor.Razor/DefaultTemplateEngineFactoryService.cs b/src/Microsoft.VisualStudio.Editor.Razor/DefaultTemplateEngineFactoryService.cs index a82d1b8e94..ab5518bb46 100644 --- a/src/Microsoft.VisualStudio.Editor.Razor/DefaultTemplateEngineFactoryService.cs +++ b/src/Microsoft.VisualStudio.Editor.Razor/DefaultTemplateEngineFactoryService.cs @@ -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(), designTime: true); RazorEngine engine; if (razorLanguageVersion.Major == 1)