Flow RootNamespace from MSBuild (dotnet/aspnetcore-tooling#331)

- Flow Root namespace through in command line builds

- Flow Root namespace through in design time builds

- Feedback\n\nCommit migrated from 057d4f3570
This commit is contained in:
Ajay Bhargav Baaskaran 2019-03-13 14:18:07 -07:00 committed by GitHub
parent eeabe9ee71
commit 2c39457306
16 changed files with 106 additions and 27 deletions

View File

@ -1,6 +1,6 @@
// <auto-generated/> // <auto-generated/>
#pragma warning disable 1591 #pragma warning disable 1591
namespace __BlazorGenerated namespace __GeneratedComponent
{ {
#line hidden #line hidden
using TModel = global::System.Object; using TModel = global::System.Object;

View File

@ -1,5 +1,5 @@
Document - Document -
NamespaceDeclaration - - __BlazorGenerated NamespaceDeclaration - - __GeneratedComponent
UsingDirective - - TModel = global::System.Object UsingDirective - - TModel = global::System.Object
UsingDirective - (1:0,1 [12] ) - System UsingDirective - (1:0,1 [12] ) - System
UsingDirective - (16:1,1 [32] ) - System.Collections.Generic UsingDirective - (16:1,1 [32] ) - System.Collections.Generic

View File

@ -1,23 +1,23 @@
Source Location: (12:0,12 [11] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/BasicComponent.cshtml) Source Location: (12:0,12 [11] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/BasicComponent.cshtml)
|IDisposable| |IDisposable|
Generated Location: (662:17,0 [11] ) Generated Location: (665:17,0 [11] )
|IDisposable| |IDisposable|
Source Location: (38:1,13 [15] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/BasicComponent.cshtml) Source Location: (38:1,13 [15] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/BasicComponent.cshtml)
|this.ToString()| |this.ToString()|
Generated Location: (1258:33,13 [15] ) Generated Location: (1261:33,13 [15] )
|this.ToString()| |this.ToString()|
Source Location: (79:3,5 [29] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/BasicComponent.cshtml) Source Location: (79:3,5 [29] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/BasicComponent.cshtml)
|string.Format("{0}", "Hello")| |string.Format("{0}", "Hello")|
Generated Location: (1403:38,6 [29] ) Generated Location: (1406:38,6 [29] )
|string.Format("{0}", "Hello")| |string.Format("{0}", "Hello")|
Source Location: (132:6,12 [37] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/BasicComponent.cshtml) Source Location: (132:6,12 [37] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/BasicComponent.cshtml)
| |
void IDisposable.Dispose(){ } void IDisposable.Dispose(){ }
| |
Generated Location: (1617:45,12 [37] ) Generated Location: (1620:45,12 [37] )
| |
void IDisposable.Dispose(){ } void IDisposable.Dispose(){ }
| |

View File

@ -1,7 +1,7 @@
#pragma checksum "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/BasicComponent.cshtml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "d3c3d6059615673cb46fc4974164d61eabadb890" #pragma checksum "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/BasicComponent.cshtml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "d3c3d6059615673cb46fc4974164d61eabadb890"
// <auto-generated/> // <auto-generated/>
#pragma warning disable 1591 #pragma warning disable 1591
namespace __BlazorGenerated namespace __GeneratedComponent
{ {
#line hidden #line hidden
using System; using System;

View File

@ -1,5 +1,5 @@
Document - Document -
NamespaceDeclaration - - __BlazorGenerated NamespaceDeclaration - - __GeneratedComponent
UsingDirective - (1:0,1 [14] ) - System UsingDirective - (1:0,1 [14] ) - System
UsingDirective - (16:1,1 [34] ) - System.Collections.Generic UsingDirective - (16:1,1 [34] ) - System.Collections.Generic
UsingDirective - (51:2,1 [19] ) - System.Linq UsingDirective - (51:2,1 [19] ) - System.Linq

View File

@ -18,11 +18,10 @@ namespace Microsoft.AspNetCore.Razor.Language.Components
private static readonly char[] NamespaceSeparators = new char[] { '.' }; private static readonly char[] NamespaceSeparators = new char[] { '.' };
/// <summary> /// <summary>
/// The base namespace. /// The fallback value of the root namespace. Only used if the fallback root namespace
/// was not passed in.
/// </summary> /// </summary>
// This is a fallback value and will only be used if we can't compute public string FallbackRootNamespace { get; set; } = "__GeneratedComponent";
// a reasonable namespace.
public string BaseNamespace { get; set; } = "__BlazorGenerated";
/// <summary> /// <summary>
/// Gets or sets whether to mangle class names. /// Gets or sets whether to mangle class names.
@ -58,7 +57,9 @@ namespace Microsoft.AspNetCore.Razor.Language.Components
ClassDeclarationIntermediateNode @class, ClassDeclarationIntermediateNode @class,
MethodDeclarationIntermediateNode method) MethodDeclarationIntermediateNode method)
{ {
var options = codeDocument.GetDocumentIntermediateNode().Options;
if (!TryComputeNamespaceAndClass( if (!TryComputeNamespaceAndClass(
options,
codeDocument.Source.FilePath, codeDocument.Source.FilePath,
codeDocument.Source.RelativePath, codeDocument.Source.RelativePath,
out var computedNamespace, out var computedNamespace,
@ -66,7 +67,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Components
{ {
// If we can't compute a nice namespace (no relative path) then just generate something // If we can't compute a nice namespace (no relative path) then just generate something
// mangled. // mangled.
computedNamespace = BaseNamespace; computedNamespace = FallbackRootNamespace;
var checksum = Checksum.BytesToString(codeDocument.Source.GetChecksum()); var checksum = Checksum.BytesToString(codeDocument.Source.GetChecksum());
computedClass = $"AspNetCore_{checksum}"; computedClass = $"AspNetCore_{checksum}";
} }
@ -125,7 +126,12 @@ namespace Microsoft.AspNetCore.Razor.Language.Components
// //
// However all kinds of thing are possible in tools. We shouldn't barf here if the document isn't // However all kinds of thing are possible in tools. We shouldn't barf here if the document isn't
// set up correctly. // set up correctly.
private bool TryComputeNamespaceAndClass(string filePath, string relativePath, out string @namespace, out string @class) private bool TryComputeNamespaceAndClass(
RazorCodeGenerationOptions options,
string filePath,
string relativePath,
out string @namespace,
out string @class)
{ {
if (filePath == null || relativePath == null || filePath.Length <= relativePath.Length) if (filePath == null || relativePath == null || filePath.Length <= relativePath.Length)
{ {
@ -134,14 +140,8 @@ namespace Microsoft.AspNetCore.Razor.Language.Components
return false; return false;
} }
// Try and infer a namespace from the project directory. We don't yet have the ability to pass var rootNamespace = options.RootNamespace;
// the namespace through from the project. if (string.IsNullOrEmpty(rootNamespace))
var trimLength = relativePath.Length + (relativePath.StartsWith("/") ? 0 : 1);
var baseDirectory = filePath.Substring(0, filePath.Length - trimLength);
var lastSlash = baseDirectory.LastIndexOfAny(PathSeparators);
var baseNamespace = lastSlash == -1 ? baseDirectory : baseDirectory.Substring(lastSlash + 1);
if (string.IsNullOrEmpty(baseNamespace))
{ {
@namespace = null; @namespace = null;
@class = null; @class = null;
@ -151,7 +151,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Components
var builder = new StringBuilder(); var builder = new StringBuilder();
// Sanitize the base namespace, but leave the dots. // Sanitize the base namespace, but leave the dots.
var segments = baseNamespace.Split(NamespaceSeparators, StringSplitOptions.RemoveEmptyEntries); var segments = rootNamespace.Split(NamespaceSeparators, StringSplitOptions.RemoveEmptyEntries);
builder.Append(CSharpIdentifier.SanitizeIdentifier(segments[0])); builder.Append(CSharpIdentifier.SanitizeIdentifier(segments[0]));
for (var i = 1; i < segments.Length; i++) for (var i = 1; i < segments.Length; i++)
{ {

View File

@ -9,6 +9,7 @@ namespace Microsoft.AspNetCore.Razor.Language
bool indentWithTabs, bool indentWithTabs,
int indentSize, int indentSize,
bool designTime, bool designTime,
string rootNamespace,
bool suppressChecksum, bool suppressChecksum,
bool supressMetadataAttributes, bool supressMetadataAttributes,
bool suppressPrimaryMethodBody) bool suppressPrimaryMethodBody)
@ -16,6 +17,7 @@ namespace Microsoft.AspNetCore.Razor.Language
IndentWithTabs = indentWithTabs; IndentWithTabs = indentWithTabs;
IndentSize = indentSize; IndentSize = indentSize;
DesignTime = designTime; DesignTime = designTime;
RootNamespace = rootNamespace;
SuppressChecksum = suppressChecksum; SuppressChecksum = suppressChecksum;
SuppressMetadataAttributes = supressMetadataAttributes; SuppressMetadataAttributes = supressMetadataAttributes;
SuppressPrimaryMethodBody = suppressPrimaryMethodBody; SuppressPrimaryMethodBody = suppressPrimaryMethodBody;
@ -27,6 +29,8 @@ namespace Microsoft.AspNetCore.Razor.Language
public override int IndentSize { get; } public override int IndentSize { get; }
public override string RootNamespace { get; }
public override bool SuppressChecksum { get; } public override bool SuppressChecksum { get; }
} }
} }

View File

@ -43,6 +43,7 @@ namespace Microsoft.AspNetCore.Razor.Language
IndentWithTabs, IndentWithTabs,
IndentSize, IndentSize,
DesignTime, DesignTime,
RootNamespace,
SuppressChecksum, SuppressChecksum,
SuppressMetadataAttributes, SuppressMetadataAttributes,
SuppressPrimaryMethodBody); SuppressPrimaryMethodBody);

View File

@ -14,6 +14,7 @@ namespace Microsoft.AspNetCore.Razor.Language
indentSize: 4, indentSize: 4,
designTime: false, designTime: false,
suppressChecksum: false, suppressChecksum: false,
rootNamespace: null,
supressMetadataAttributes: false, supressMetadataAttributes: false,
suppressPrimaryMethodBody: false); suppressPrimaryMethodBody: false);
} }
@ -24,6 +25,7 @@ namespace Microsoft.AspNetCore.Razor.Language
indentWithTabs: false, indentWithTabs: false,
indentSize: 4, indentSize: 4,
designTime: true, designTime: true,
rootNamespace: null,
suppressChecksum: false, suppressChecksum: false,
supressMetadataAttributes: true, supressMetadataAttributes: true,
suppressPrimaryMethodBody: false); suppressPrimaryMethodBody: false);
@ -67,6 +69,11 @@ namespace Microsoft.AspNetCore.Razor.Language
public abstract int IndentSize { get; } public abstract int IndentSize { get; }
/// <summary>
/// Gets the root namespace for the generated code.
/// </summary>
public virtual string RootNamespace { get; }
/// <summary> /// <summary>
/// Gets a value that indicates whether to suppress the default <c>#pragma checksum</c> directive in the /// Gets a value that indicates whether to suppress the default <c>#pragma checksum</c> directive in the
/// generated C# code. If <c>false</c> the checkum directive will be included, otherwise it will not be /// generated C# code. If <c>false</c> the checkum directive will be included, otherwise it will not be

View File

@ -15,6 +15,11 @@ namespace Microsoft.AspNetCore.Razor.Language
public abstract bool IndentWithTabs { get; set; } public abstract bool IndentWithTabs { get; set; }
/// <summary>
/// Gets or sets the root namespace of the generated code.
/// </summary>
public virtual string RootNamespace { get; set; }
/// <summary> /// <summary>
/// Gets or sets a value that indicates whether to suppress the default <c>#pragma checksum</c> directive in the /// Gets or sets a value that indicates whether to suppress the default <c>#pragma checksum</c> directive in the
/// generated C# code. If <c>false</c> the checkum directive will be included, otherwise it will not be /// generated C# code. If <c>false</c> the checkum directive will be included, otherwise it will not be

View File

@ -75,6 +75,23 @@ namespace Microsoft.AspNetCore.Razor.Language
return builder; return builder;
} }
/// <summary>
/// Sets the root namespace for the generated code.
/// </summary>
/// <param name="builder">The <see cref="RazorProjectEngineBuilder"/>.</param>
/// <param name="rootNamespace">The root namespace.</param>
/// <returns>The <see cref="RazorProjectEngineBuilder"/>.</returns>
public static RazorProjectEngineBuilder SetRootNamespace(this RazorProjectEngineBuilder builder, string rootNamespace)
{
if (builder == null)
{
throw new ArgumentNullException(nameof(builder));
}
builder.Features.Add(new ConfigureRootNamespaceFeature(rootNamespace));
return builder;
}
public static void SetImportFeature(this RazorProjectEngineBuilder builder, IImportProjectFeature feature) public static void SetImportFeature(this RazorProjectEngineBuilder builder, IImportProjectFeature feature)
{ {
if (builder == null) if (builder == null)
@ -281,5 +298,29 @@ namespace Microsoft.AspNetCore.Razor.Language
public override Stream Read() => new MemoryStream(_importBytes); public override Stream Read() => new MemoryStream(_importBytes);
} }
} }
private class ConfigureRootNamespaceFeature : IConfigureRazorCodeGenerationOptionsFeature
{
private readonly string _rootNamespace;
public ConfigureRootNamespaceFeature(string rootNamespace)
{
_rootNamespace = rootNamespace;
}
public int Order { get; set; }
public RazorEngine Engine { get; set; }
public void Configure(RazorCodeGenerationOptionsBuilder options)
{
if (options == null)
{
throw new ArgumentNullException(nameof(options));
}
options.RootNamespace = _rootNamespace;
}
}
} }
} }

View File

@ -29,6 +29,7 @@ namespace Microsoft.AspNetCore.Razor.Tools
Configuration = Option("-c", "Razor configuration name", CommandOptionType.SingleValue); Configuration = Option("-c", "Razor configuration name", CommandOptionType.SingleValue);
ExtensionNames = Option("-n", "extension name", CommandOptionType.MultipleValue); ExtensionNames = Option("-n", "extension name", CommandOptionType.MultipleValue);
ExtensionFilePaths = Option("-e", "extension file path", CommandOptionType.MultipleValue); ExtensionFilePaths = Option("-e", "extension file path", CommandOptionType.MultipleValue);
RootNamespace = Option("--root-namespace", "root namespace for generated code", CommandOptionType.SingleValue);
GenerateDeclaration = Option("--generate-declaration", "Generate declaration", CommandOptionType.NoValue); GenerateDeclaration = Option("--generate-declaration", "Generate declaration", CommandOptionType.NoValue);
} }
@ -52,6 +53,8 @@ namespace Microsoft.AspNetCore.Razor.Tools
public CommandOption ExtensionFilePaths { get; } public CommandOption ExtensionFilePaths { get; }
public CommandOption RootNamespace { get; }
public CommandOption GenerateDeclaration { get; } public CommandOption GenerateDeclaration { get; }
protected override Task<int> ExecuteCoreAsync() protected override Task<int> ExecuteCoreAsync()
@ -176,6 +179,11 @@ namespace Microsoft.AspNetCore.Razor.Tools
{ {
b.Features.Add(new SetSuppressPrimaryMethodBodyOptionFeature()); b.Features.Add(new SetSuppressPrimaryMethodBodyOptionFeature());
} }
if (RootNamespace.HasValue())
{
b.SetRootNamespace(RootNamespace.Value());
}
}); });
var results = GenerateCode(engine, sourceItems); var results = GenerateCode(engine, sourceItems);

View File

@ -24,6 +24,8 @@ namespace Microsoft.AspNetCore.Razor.Tasks
private const string AssemblyName = "AssemblyName"; private const string AssemblyName = "AssemblyName";
private const string AssemblyFilePath = "AssemblyFilePath"; private const string AssemblyFilePath = "AssemblyFilePath";
public string RootNamespace { get; set; }
[Required] [Required]
public string Version { get; set; } public string Version { get; set; }
@ -135,6 +137,13 @@ namespace Microsoft.AspNetCore.Razor.Tasks
builder.AppendLine("-c"); builder.AppendLine("-c");
builder.AppendLine(Configuration[0].GetMetadata(Identity)); builder.AppendLine(Configuration[0].GetMetadata(Identity));
// Added in 3.0
if (parsedVersion.Major >= 3 && !string.IsNullOrEmpty(RootNamespace))
{
builder.AppendLine("--root-namespace");
builder.AppendLine(RootNamespace);
}
// Added in 3.0 // Added in 3.0
if (parsedVersion.Major >= 3 && GenerateDeclaration) if (parsedVersion.Major >= 3 && GenerateDeclaration)
{ {

View File

@ -155,6 +155,7 @@ Copyright (c) .NET Foundation. All rights reserved.
ForceServer="$(_RazorForceBuildServer)" ForceServer="$(_RazorForceBuildServer)"
PipeName="$(_RazorBuildServerPipeName)" PipeName="$(_RazorBuildServerPipeName)"
Version="$(RazorLangVersion)" Version="$(RazorLangVersion)"
RootNamespace="$(RootNamespace)"
Configuration="@(ResolvedRazorConfiguration)" Configuration="@(ResolvedRazorConfiguration)"
Extensions="@(ResolvedRazorExtension)" Extensions="@(ResolvedRazorExtension)"
Sources="@(RazorGenerateWithTargetPath)" Sources="@(RazorGenerateWithTargetPath)"

View File

@ -98,6 +98,7 @@ Copyright (c) .NET Foundation. All rights reserved.
ForceServer="$(_RazorForceBuildServer)" ForceServer="$(_RazorForceBuildServer)"
PipeName="$(_RazorBuildServerPipeName)" PipeName="$(_RazorBuildServerPipeName)"
Version="$(RazorLangVersion)" Version="$(RazorLangVersion)"
RootNamespace="$(RootNamespace)"
Configuration="@(ResolvedRazorConfiguration)" Configuration="@(ResolvedRazorConfiguration)"
Extensions="@(ResolvedRazorExtension)" Extensions="@(ResolvedRazorExtension)"
Sources="@(_RazorComponentDeclarationSources)" Sources="@(_RazorComponentDeclarationSources)"

View File

@ -66,7 +66,7 @@ namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests
PathSeparator = Path.DirectorySeparatorChar.ToString(); PathSeparator = Path.DirectorySeparatorChar.ToString();
WorkingDirectory = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? ArbitraryWindowsPath : ArbitraryMacLinuxPath; WorkingDirectory = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? ArbitraryWindowsPath : ArbitraryMacLinuxPath;
DefaultBaseNamespace = "Test"; // Matches the default working directory DefaultRootNamespace = "Test"; // Matches the default working directory
DefaultFileName = "TestComponent.cshtml"; DefaultFileName = "TestComponent.cshtml";
} }
@ -78,7 +78,7 @@ namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests
internal virtual RazorConfiguration Configuration { get; } internal virtual RazorConfiguration Configuration { get; }
internal virtual string DefaultBaseNamespace { get; } internal virtual string DefaultRootNamespace { get; }
internal virtual string DefaultFileName { get; } internal virtual string DefaultFileName { get; }
@ -113,6 +113,8 @@ namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests
{ {
return RazorProjectEngine.Create(configuration, FileSystem, b => return RazorProjectEngine.Create(configuration, FileSystem, b =>
{ {
b.SetRootNamespace(DefaultRootNamespace);
// Turn off checksums, we're testing code generation. // Turn off checksums, we're testing code generation.
b.Features.Add(new SuppressChecksum()); b.Features.Add(new SuppressChecksum());
@ -320,7 +322,7 @@ namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests
{ {
var assemblyResult = CompileToAssembly(DefaultFileName, cshtmlSource); var assemblyResult = CompileToAssembly(DefaultFileName, cshtmlSource);
var componentFullTypeName = $"{DefaultBaseNamespace}.{Path.GetFileNameWithoutExtension(DefaultFileName)}"; var componentFullTypeName = $"{DefaultRootNamespace}.{Path.GetFileNameWithoutExtension(DefaultFileName)}";
return CompileToComponent(assemblyResult, componentFullTypeName); return CompileToComponent(assemblyResult, componentFullTypeName);
} }