* Refactoring RazorFileInfoCollectionGenerator to not be instantiated.
* Adding CompilerGeneratedAttribute to generated code. * Adding unit tests for RazorFileInfoCollectionGenerator.
This commit is contained in:
parent
1723ef0e97
commit
c631d533c4
|
|
@ -0,0 +1,71 @@
|
||||||
|
// 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.Runtime.CompilerServices;
|
||||||
|
using System.Text;
|
||||||
|
using Microsoft.AspNet.Mvc.Razor.Precompilation;
|
||||||
|
using Microsoft.Dnx.Runtime;
|
||||||
|
using Microsoft.Framework.Internal;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Mvc.Razor.Internal
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Utility type to code generate <see cref="RazorFileInfoCollection"/> types.
|
||||||
|
/// </summary>
|
||||||
|
public static class RazorFileInfoCollectionGenerator
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Generates CSharp code for the specified <paramref name="fileInfoCollection"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="fileInfoCollection">The <see cref="RazorFileInfoCollection"/>.</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static string GenerateCode([NotNull] RazorFileInfoCollection fileInfoCollection)
|
||||||
|
{
|
||||||
|
var builder = new StringBuilder();
|
||||||
|
|
||||||
|
builder.Append(
|
||||||
|
$@"namespace __ASP_ASSEMBLY
|
||||||
|
{{
|
||||||
|
[{typeof(CompilerGeneratedAttribute).FullName}]
|
||||||
|
public class __PreGeneratedViewCollection : {typeof(RazorFileInfoCollection).FullName}
|
||||||
|
{{
|
||||||
|
public __PreGeneratedViewCollection()
|
||||||
|
{{
|
||||||
|
{nameof(RazorFileInfoCollection.AssemblyResourceName)} = @""{fileInfoCollection.AssemblyResourceName}"";
|
||||||
|
{nameof(RazorFileInfoCollection.SymbolsResourceName)} = @""{fileInfoCollection.SymbolsResourceName}"";
|
||||||
|
FileInfos = new System.Collections.Generic.List<{typeof(RazorFileInfo).FullName}>
|
||||||
|
{{");
|
||||||
|
|
||||||
|
foreach (var fileInfo in fileInfoCollection.FileInfos)
|
||||||
|
{
|
||||||
|
builder.Append(
|
||||||
|
$@"
|
||||||
|
new {typeof(RazorFileInfo).FullName}
|
||||||
|
{{
|
||||||
|
{nameof(RazorFileInfo.FullTypeName)} = @""{fileInfo.FullTypeName}"",
|
||||||
|
{nameof(RazorFileInfo.RelativePath)} = @""{fileInfo.RelativePath}""
|
||||||
|
}},");
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.Append(
|
||||||
|
$@"
|
||||||
|
}};
|
||||||
|
}}
|
||||||
|
|
||||||
|
private static {typeof(System.Reflection.Assembly).FullName} _loadedAssembly;
|
||||||
|
|
||||||
|
public override {typeof(System.Reflection.Assembly).FullName} LoadAssembly(
|
||||||
|
{typeof(IAssemblyLoadContext).FullName} loadContext)
|
||||||
|
{{
|
||||||
|
if (_loadedAssembly == null)
|
||||||
|
{{
|
||||||
|
_loadedAssembly = base.LoadAssembly(loadContext);
|
||||||
|
}}
|
||||||
|
return _loadedAssembly;
|
||||||
|
}}
|
||||||
|
}}
|
||||||
|
}}");
|
||||||
|
return builder.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,129 +0,0 @@
|
||||||
// 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.Globalization;
|
|
||||||
using System.Text;
|
|
||||||
using Microsoft.AspNet.Mvc.Razor.Compilation;
|
|
||||||
using Microsoft.CodeAnalysis;
|
|
||||||
using Microsoft.Dnx.Compilation.CSharp;
|
|
||||||
using Microsoft.Dnx.Runtime;
|
|
||||||
using Microsoft.Framework.Internal;
|
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Mvc.Razor.Precompilation
|
|
||||||
{
|
|
||||||
public class RazorFileInfoCollectionGenerator
|
|
||||||
{
|
|
||||||
private string _fileFormat;
|
|
||||||
|
|
||||||
public RazorFileInfoCollectionGenerator([NotNull] RazorFileInfoCollection fileInfoCollection,
|
|
||||||
[NotNull] CompilationSettings compilationSettings)
|
|
||||||
{
|
|
||||||
RazorFileInfoCollection = fileInfoCollection;
|
|
||||||
CompilationSettings = compilationSettings;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected RazorFileInfoCollection RazorFileInfoCollection { get; }
|
|
||||||
|
|
||||||
protected CompilationSettings CompilationSettings { get; }
|
|
||||||
|
|
||||||
public virtual SyntaxTree GenerateCollection()
|
|
||||||
{
|
|
||||||
var builder = new StringBuilder();
|
|
||||||
builder.AppendFormat(CultureInfo.InvariantCulture,
|
|
||||||
TopFormat,
|
|
||||||
RazorFileInfoCollection.AssemblyResourceName,
|
|
||||||
RazorFileInfoCollection.SymbolsResourceName);
|
|
||||||
|
|
||||||
foreach (var fileInfo in RazorFileInfoCollection.FileInfos)
|
|
||||||
{
|
|
||||||
var perFileEntry = GenerateFile(fileInfo);
|
|
||||||
builder.Append(perFileEntry);
|
|
||||||
}
|
|
||||||
|
|
||||||
builder.Append(Bottom);
|
|
||||||
|
|
||||||
var sourceCode = builder.ToString();
|
|
||||||
var syntaxTree = SyntaxTreeGenerator.Generate(sourceCode,
|
|
||||||
"__AUTO__GeneratedViewsCollection.cs",
|
|
||||||
CompilationSettings);
|
|
||||||
|
|
||||||
return syntaxTree;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual string GenerateFile([NotNull] RazorFileInfo fileInfo)
|
|
||||||
{
|
|
||||||
return string.Format(FileFormat,
|
|
||||||
fileInfo.RelativePath,
|
|
||||||
fileInfo.FullTypeName);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual string TopFormat
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return
|
|
||||||
$@"using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Reflection;
|
|
||||||
using {typeof(RazorFileInfoCollection).Namespace};
|
|
||||||
|
|
||||||
namespace __ASP_ASSEMBLY
|
|
||||||
{{{{
|
|
||||||
public class __PreGeneratedViewCollection : {nameof(RazorFileInfoCollection)}
|
|
||||||
{{{{
|
|
||||||
public __PreGeneratedViewCollection()
|
|
||||||
{{{{
|
|
||||||
{nameof(RazorFileInfoCollection.AssemblyResourceName)} = ""{{0}}"";
|
|
||||||
{nameof(RazorFileInfoCollection.SymbolsResourceName)} = ""{{1}}"";
|
|
||||||
var fileInfos = new List<{nameof(RazorFileInfo)}>();
|
|
||||||
{nameof(RazorFileInfoCollection.FileInfos)} = fileInfos;
|
|
||||||
{nameof(RazorFileInfo)} info;
|
|
||||||
";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual string Bottom
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return
|
|
||||||
$@"
|
|
||||||
}}
|
|
||||||
private static Assembly _loadedAssembly;
|
|
||||||
|
|
||||||
public override Assembly LoadAssembly({typeof(IAssemblyLoadContext).FullName} loadContext)
|
|
||||||
{{
|
|
||||||
if (_loadedAssembly == null)
|
|
||||||
{{
|
|
||||||
_loadedAssembly = base.LoadAssembly(loadContext);
|
|
||||||
}}
|
|
||||||
return _loadedAssembly;
|
|
||||||
}}
|
|
||||||
}}
|
|
||||||
}}
|
|
||||||
";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual string FileFormat
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (_fileFormat == null)
|
|
||||||
{
|
|
||||||
_fileFormat =
|
|
||||||
$@"
|
|
||||||
info = new {nameof(RazorFileInfo)}
|
|
||||||
{{{{
|
|
||||||
{nameof(RazorFileInfo.RelativePath)} = @""{{0}}"",
|
|
||||||
{nameof(RazorFileInfo.FullTypeName)} = @""{{1}}""
|
|
||||||
}}}};
|
|
||||||
fileInfos.Add(info);
|
|
||||||
";
|
|
||||||
}
|
|
||||||
|
|
||||||
return _fileFormat;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -64,12 +64,11 @@ namespace Microsoft.AspNet.Mvc.Razor.Precompilation
|
||||||
var result = CreateFileInfoCollection();
|
var result = CreateFileInfoCollection();
|
||||||
if (result != null)
|
if (result != null)
|
||||||
{
|
{
|
||||||
var collectionGenerator = new RazorFileInfoCollectionGenerator(
|
var generatedCode = RazorFileInfoCollectionGenerator.GenerateCode(result);
|
||||||
result,
|
var syntaxTree = CSharpSyntaxTree.ParseText(
|
||||||
CompilationSettings);
|
generatedCode,
|
||||||
|
SyntaxTreeGenerator.GetParseOptions(CompilationSettings));
|
||||||
var tree = collectionGenerator.GenerateCollection();
|
CompileContext.Compilation = CompileContext.Compilation.AddSyntaxTrees(syntaxTree);
|
||||||
CompileContext.Compilation = CompileContext.Compilation.AddSyntaxTrees(tree);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,135 @@
|
||||||
|
// 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.Collections.Generic;
|
||||||
|
using Microsoft.AspNet.Mvc.Razor.Compilation;
|
||||||
|
using Microsoft.AspNet.Mvc.Razor.Precompilation;
|
||||||
|
using Microsoft.CodeAnalysis.CSharp;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Mvc.Razor.Internal
|
||||||
|
{
|
||||||
|
public class RazorFileInfoCollectionGeneratorTest
|
||||||
|
{
|
||||||
|
public static TheoryData GenerateCollection_ProducesExpectedCodeData
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var expected1 =
|
||||||
|
@"namespace __ASP_ASSEMBLY
|
||||||
|
{
|
||||||
|
[System.Runtime.CompilerServices.CompilerGeneratedAttribute]
|
||||||
|
public class __PreGeneratedViewCollection : Microsoft.AspNet.Mvc.Razor.Precompilation.RazorFileInfoCollection
|
||||||
|
{
|
||||||
|
public __PreGeneratedViewCollection()
|
||||||
|
{
|
||||||
|
AssemblyResourceName = @""EmptyAssembly"";
|
||||||
|
SymbolsResourceName = @"""";
|
||||||
|
FileInfos = new System.Collections.Generic.List<Microsoft.AspNet.Mvc.Razor.Precompilation.RazorFileInfo>
|
||||||
|
{
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static System.Reflection.Assembly _loadedAssembly;
|
||||||
|
|
||||||
|
public override System.Reflection.Assembly LoadAssembly(
|
||||||
|
Microsoft.Dnx.Runtime.IAssemblyLoadContext loadContext)
|
||||||
|
{
|
||||||
|
if (_loadedAssembly == null)
|
||||||
|
{
|
||||||
|
_loadedAssembly = base.LoadAssembly(loadContext);
|
||||||
|
}
|
||||||
|
return _loadedAssembly;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}";
|
||||||
|
var expected2 =
|
||||||
|
@"namespace __ASP_ASSEMBLY
|
||||||
|
{
|
||||||
|
[System.Runtime.CompilerServices.CompilerGeneratedAttribute]
|
||||||
|
public class __PreGeneratedViewCollection : Microsoft.AspNet.Mvc.Razor.Precompilation.RazorFileInfoCollection
|
||||||
|
{
|
||||||
|
public __PreGeneratedViewCollection()
|
||||||
|
{
|
||||||
|
AssemblyResourceName = @""TestAssembly"";
|
||||||
|
SymbolsResourceName = @""SymbolsResource"";
|
||||||
|
FileInfos = new System.Collections.Generic.List<Microsoft.AspNet.Mvc.Razor.Precompilation.RazorFileInfo>
|
||||||
|
{
|
||||||
|
new Microsoft.AspNet.Mvc.Razor.Precompilation.RazorFileInfo
|
||||||
|
{
|
||||||
|
FullTypeName = @""SomeType.Name"",
|
||||||
|
RelativePath = @""Views/Home/Index.cshtml""
|
||||||
|
},
|
||||||
|
new Microsoft.AspNet.Mvc.Razor.Precompilation.RazorFileInfo
|
||||||
|
{
|
||||||
|
FullTypeName = @""Different.Name"",
|
||||||
|
RelativePath = @""Views/Home/Different.cshtml""
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static System.Reflection.Assembly _loadedAssembly;
|
||||||
|
|
||||||
|
public override System.Reflection.Assembly LoadAssembly(
|
||||||
|
Microsoft.Dnx.Runtime.IAssemblyLoadContext loadContext)
|
||||||
|
{
|
||||||
|
if (_loadedAssembly == null)
|
||||||
|
{
|
||||||
|
_loadedAssembly = base.LoadAssembly(loadContext);
|
||||||
|
}
|
||||||
|
return _loadedAssembly;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}";
|
||||||
|
|
||||||
|
return new TheoryData<RazorFileInfoCollection, string>
|
||||||
|
{
|
||||||
|
{ new EmptyCollection(), expected1 },
|
||||||
|
{ new TestCollection(), expected2 },
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[MemberData(nameof(GenerateCollection_ProducesExpectedCodeData))]
|
||||||
|
public void GenerateCollection_ProducesExpectedCode(RazorFileInfoCollection collection, string expected)
|
||||||
|
{
|
||||||
|
// Act
|
||||||
|
var actual = RazorFileInfoCollectionGenerator.GenerateCode(collection);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class EmptyCollection : RazorFileInfoCollection
|
||||||
|
{
|
||||||
|
public EmptyCollection()
|
||||||
|
{
|
||||||
|
AssemblyResourceName = "EmptyAssembly";
|
||||||
|
FileInfos = new List<RazorFileInfo>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class TestCollection : RazorFileInfoCollection
|
||||||
|
{
|
||||||
|
public TestCollection()
|
||||||
|
{
|
||||||
|
AssemblyResourceName = "TestAssembly";
|
||||||
|
SymbolsResourceName = "SymbolsResource";
|
||||||
|
FileInfos = new List<RazorFileInfo>
|
||||||
|
{
|
||||||
|
new RazorFileInfo
|
||||||
|
{
|
||||||
|
FullTypeName = "SomeType.Name",
|
||||||
|
RelativePath = @"Views/Home/Index.cshtml"
|
||||||
|
},
|
||||||
|
new RazorFileInfo
|
||||||
|
{
|
||||||
|
FullTypeName = "Different.Name",
|
||||||
|
RelativePath = @"Views/Home/Different.cshtml"
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue