Refactored CodeGeneratorContext to CodeBuilderContext.
- Needed to separate the context's of "generation" and "building" to enable the communication of the TagHelperProvider.
This commit is contained in:
parent
20824f37e0
commit
950828cbab
|
|
@ -42,7 +42,7 @@ namespace Microsoft.AspNet.Razor
|
|||
return new CSharpRazorCodeGenerator(className, rootNamespaceName, sourceFileName, host);
|
||||
}
|
||||
|
||||
public override CodeBuilder CreateCodeBuilder(CodeGeneratorContext context)
|
||||
public override CodeBuilder CreateCodeBuilder(CodeBuilderContext context)
|
||||
{
|
||||
return new CSharpCodeBuilder(context);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,54 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Generator
|
||||
{
|
||||
/// <summary>
|
||||
/// Context object with information used to generate a Razor page.
|
||||
/// </summary>
|
||||
public class CodeBuilderContext : CodeGeneratorContext
|
||||
{
|
||||
/// <summary>
|
||||
/// Instantiates a new instance of the <see cref="CodeBuilderContext"/> object.
|
||||
/// </summary>
|
||||
/// <param name="generatorContext">A <see cref="CodeGeneratorContext"/> to copy information from.</param>
|
||||
public CodeBuilderContext(CodeGeneratorContext generatorContext)
|
||||
: base(generatorContext)
|
||||
{
|
||||
ExpressionRenderingMode = ExpressionRenderingMode.WriteToOutput;
|
||||
}
|
||||
|
||||
// Internal for testing.
|
||||
internal CodeBuilderContext(RazorEngineHost host,
|
||||
string className,
|
||||
string rootNamespace,
|
||||
string sourceFile,
|
||||
bool shouldGenerateLinePragmas)
|
||||
: base(host, className, rootNamespace, sourceFile, shouldGenerateLinePragmas)
|
||||
{
|
||||
ExpressionRenderingMode = ExpressionRenderingMode.WriteToOutput;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The current C# rendering mode.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <see cref="ExpressionRenderingMode.WriteToOutput"/> forces C# generation to write
|
||||
/// <see cref="Compiler.Chunk"/>s to the output page, i.e. WriteLiteral("Hello World").
|
||||
/// <see cref="ExpressionRenderingMode.InjectCode"/> writes <see cref="Compiler.Chunk"/> values in their
|
||||
/// rawest form, i.g. "Hello World".
|
||||
/// </remarks>
|
||||
public ExpressionRenderingMode ExpressionRenderingMode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The C# writer to write <see cref="Compiler.Chunk"/> information to.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If <see cref="TargetWriterName"/> is <c>null</c> values will be written using a default write method
|
||||
/// i.e. WriteLiteral("Hello World").
|
||||
/// If <see cref="TargetWriterName"/> is not <c>null</c> values will be written to the given
|
||||
/// <see cref="TargetWriterName"/>, i.e. WriteLiteralTo(myWriter, "Hello World").
|
||||
/// </remarks>
|
||||
public string TargetWriterName { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -7,37 +7,43 @@ namespace Microsoft.AspNet.Razor.Generator
|
|||
{
|
||||
public class CodeGeneratorContext
|
||||
{
|
||||
private CodeGeneratorContext()
|
||||
protected CodeGeneratorContext(CodeGeneratorContext context)
|
||||
: this(context.Host,
|
||||
context.ClassName,
|
||||
context.RootNamespace,
|
||||
context.SourceFile,
|
||||
// True because we're pulling from the provided context's source file.
|
||||
shouldGenerateLinePragmas: true)
|
||||
{
|
||||
ExpressionRenderingMode = ExpressionRenderingMode.WriteToOutput;
|
||||
CodeTreeBuilder = context.CodeTreeBuilder;
|
||||
}
|
||||
|
||||
public CodeGeneratorContext(RazorEngineHost host,
|
||||
string className,
|
||||
string rootNamespace,
|
||||
string sourceFile,
|
||||
bool shouldGenerateLinePragmas)
|
||||
{
|
||||
CodeTreeBuilder = new CodeTreeBuilder();
|
||||
Host = host;
|
||||
SourceFile = shouldGenerateLinePragmas ? sourceFile : null;
|
||||
RootNamespace = rootNamespace;
|
||||
ClassName = className;
|
||||
}
|
||||
|
||||
// Internal/Private state. Technically consumers might want to use some of these but they can implement them independently if necessary.
|
||||
// It's way safer to make them internal for now, especially with the code generator stuff in a bit of flux.
|
||||
internal ExpressionRenderingMode ExpressionRenderingMode { get; set; }
|
||||
public string SourceFile { get; internal set; }
|
||||
|
||||
public string RootNamespace { get; private set; }
|
||||
|
||||
public string ClassName { get; private set; }
|
||||
|
||||
public RazorEngineHost Host { get; private set; }
|
||||
public string TargetWriterName { get; set; }
|
||||
|
||||
public CodeTreeBuilder CodeTreeBuilder { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the <c>SHA1</c> based checksum for the file whose location is defined by <see cref="SourceFile"/>.
|
||||
/// </summary>
|
||||
public string Checksum { get; set; }
|
||||
|
||||
public static CodeGeneratorContext Create(RazorEngineHost host, string className, string rootNamespace, string sourceFile, bool shouldGenerateLinePragmas)
|
||||
{
|
||||
return new CodeGeneratorContext()
|
||||
{
|
||||
CodeTreeBuilder = new CodeTreeBuilder(),
|
||||
Host = host,
|
||||
SourceFile = shouldGenerateLinePragmas ? sourceFile : null,
|
||||
RootNamespace = rootNamespace,
|
||||
ClassName = className
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler.CSharp
|
|||
private const string Sha1AlgorithmId = "{ff1816ec-aa5e-4d10-87f7-6f4963833460}";
|
||||
private const int DisableAsyncWarning = 1998;
|
||||
|
||||
public CSharpCodeBuilder(CodeGeneratorContext context)
|
||||
public CSharpCodeBuilder(CodeBuilderContext context)
|
||||
: base(context)
|
||||
{
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler.CSharp
|
|||
{
|
||||
public class CSharpBaseTypeVisitor : CodeVisitor<CSharpCodeWriter>
|
||||
{
|
||||
public CSharpBaseTypeVisitor(CSharpCodeWriter writer, CodeGeneratorContext context)
|
||||
public CSharpBaseTypeVisitor(CSharpCodeWriter writer, CodeBuilderContext context)
|
||||
: base(writer, context) { }
|
||||
|
||||
public string CurrentBaseType { get; set; }
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler.CSharp
|
|||
{
|
||||
public class CSharpClassAttributeVisitor : CodeVisitor<CSharpCodeWriter>
|
||||
{
|
||||
public CSharpClassAttributeVisitor(CSharpCodeWriter writer, CodeGeneratorContext context)
|
||||
public CSharpClassAttributeVisitor(CSharpCodeWriter writer, CodeBuilderContext context)
|
||||
: base(writer, context) { }
|
||||
|
||||
protected override void Visit(SessionStateChunk chunk)
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler.CSharp
|
|||
|
||||
private CSharpPaddingBuilder _paddingBuilder;
|
||||
|
||||
public CSharpCodeVisitor(CSharpCodeWriter writer, CodeGeneratorContext context)
|
||||
public CSharpCodeVisitor(CSharpCodeWriter writer, CodeBuilderContext context)
|
||||
: base(writer, context)
|
||||
{
|
||||
_paddingBuilder = new CSharpPaddingBuilder(context.Host);
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler.CSharp
|
|||
|
||||
private const int DisableVariableNamingWarnings = 219;
|
||||
|
||||
public CSharpDesignTimeHelpersVisitor(CSharpCodeWriter writer, CodeGeneratorContext context)
|
||||
public CSharpDesignTimeHelpersVisitor(CSharpCodeWriter writer, CodeBuilderContext context)
|
||||
: base(writer, context) { }
|
||||
|
||||
public void AcceptTree(CodeTree tree)
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler.CSharp
|
|||
|
||||
private CSharpCodeVisitor _codeVisitor;
|
||||
|
||||
public CSharpHelperVisitor(CSharpCodeWriter writer, CodeGeneratorContext context)
|
||||
public CSharpHelperVisitor(CSharpCodeWriter writer, CodeBuilderContext context)
|
||||
: base(writer, context)
|
||||
{
|
||||
_codeVisitor = new CSharpCodeVisitor(writer, context);
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler.CSharp
|
|||
{
|
||||
private CSharpCodeVisitor _csharpCodeVisitor;
|
||||
|
||||
public CSharpTypeMemberVisitor(CSharpCodeWriter writer, CodeGeneratorContext context)
|
||||
public CSharpTypeMemberVisitor(CSharpCodeWriter writer, CodeBuilderContext context)
|
||||
: base(writer, context)
|
||||
{
|
||||
_csharpCodeVisitor = new CSharpCodeVisitor(writer, context);
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler.CSharp
|
|||
{
|
||||
public class CSharpUsingVisitor : CodeVisitor<CSharpCodeWriter>
|
||||
{
|
||||
public CSharpUsingVisitor(CSharpCodeWriter writer, CodeGeneratorContext context)
|
||||
public CSharpUsingVisitor(CSharpCodeWriter writer, CodeBuilderContext context)
|
||||
: base(writer, context)
|
||||
{
|
||||
ImportedUsings = new List<string>();
|
||||
|
|
|
|||
|
|
@ -8,14 +8,14 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler
|
|||
{
|
||||
public abstract class ChunkVisitor<T> : IChunkVisitor where T : CodeWriter
|
||||
{
|
||||
public ChunkVisitor(T writer, CodeGeneratorContext context)
|
||||
public ChunkVisitor(T writer, CodeBuilderContext context)
|
||||
{
|
||||
Writer = writer;
|
||||
Context = context;
|
||||
}
|
||||
|
||||
protected T Writer { get; private set; }
|
||||
protected CodeGeneratorContext Context { get; private set; }
|
||||
protected CodeBuilderContext Context { get; private set; }
|
||||
|
||||
public void Accept(IList<Chunk> chunks)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -5,14 +5,14 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler
|
|||
{
|
||||
public abstract class CodeBuilder
|
||||
{
|
||||
private readonly CodeGeneratorContext _context;
|
||||
private readonly CodeBuilderContext _context;
|
||||
|
||||
public CodeBuilder(CodeGeneratorContext context)
|
||||
public CodeBuilder(CodeBuilderContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
protected CodeGeneratorContext Context
|
||||
protected CodeBuilderContext Context
|
||||
{
|
||||
get { return _context; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler
|
|||
{
|
||||
public class CodeVisitor<T> : ChunkVisitor<T> where T : CodeWriter
|
||||
{
|
||||
public CodeVisitor(T writer, CodeGeneratorContext context)
|
||||
public CodeVisitor(T writer, CodeBuilderContext context)
|
||||
: base(writer, context) { }
|
||||
|
||||
protected override void Visit(LiteralChunk chunk)
|
||||
|
|
|
|||
|
|
@ -71,7 +71,11 @@ namespace Microsoft.AspNet.Razor.Generator
|
|||
{
|
||||
if (_context == null)
|
||||
{
|
||||
_context = CodeGeneratorContext.Create(Host, ClassName, RootNamespaceName, SourceFileName, GenerateLinePragmas);
|
||||
_context = new CodeGeneratorContext(Host,
|
||||
ClassName,
|
||||
RootNamespaceName,
|
||||
SourceFileName,
|
||||
GenerateLinePragmas);
|
||||
Initialize(_context);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,9 +9,10 @@ namespace Microsoft.AspNet.Razor
|
|||
{
|
||||
public class GeneratorResults : ParserResults
|
||||
{
|
||||
public GeneratorResults(ParserResults parserResults,
|
||||
CodeBuilderResult codeBuilderResult)
|
||||
: this(parserResults.Document, parserResults.ParserErrors, codeBuilderResult)
|
||||
public GeneratorResults(ParserResults parserResults, CodeBuilderResult codeBuilderResult)
|
||||
: this(parserResults.Document,
|
||||
parserResults.ParserErrors,
|
||||
codeBuilderResult)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -33,6 +34,7 @@ namespace Microsoft.AspNet.Razor
|
|||
}
|
||||
|
||||
public string GeneratedCode { get; private set; }
|
||||
|
||||
public IList<LineMapping> DesignTimeLineMappings { get; private set; }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -54,6 +54,6 @@ namespace Microsoft.AspNet.Razor
|
|||
/// </summary>
|
||||
public abstract RazorCodeGenerator CreateCodeGenerator(string className, string rootNamespaceName, string sourceFileName, RazorEngineHost host);
|
||||
|
||||
public abstract CodeBuilder CreateCodeBuilder(CodeGeneratorContext codeGeneratorContext);
|
||||
public abstract CodeBuilder CreateCodeBuilder(CodeBuilderContext codeGeneratorContext);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -207,7 +207,7 @@ namespace Microsoft.AspNet.Razor
|
|||
/// </summary>
|
||||
/// <param name="incomingBuilder">The code builder</param>
|
||||
/// <returns>Either the same code builder, after modifications, or a different code builder.</returns>
|
||||
public virtual CodeBuilder DecorateCodeBuilder(CodeBuilder incomingBuilder, CodeGeneratorContext context)
|
||||
public virtual CodeBuilder DecorateCodeBuilder(CodeBuilder incomingBuilder, CodeBuilderContext context)
|
||||
{
|
||||
if (incomingBuilder == null)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -252,8 +252,8 @@ namespace Microsoft.AspNet.Razor
|
|||
generator.DesignTimeMode = Host.DesignTimeMode;
|
||||
generator.Visit(results);
|
||||
|
||||
|
||||
var codeGenerationContext = generator.Context;
|
||||
var codeBuilderContext = new CodeBuilderContext(generator.Context);
|
||||
var builder = CreateCodeBuilder(codeBuilderContext);
|
||||
codeGenerationContext.Checksum = checksum;
|
||||
|
||||
var builder = CreateCodeBuilder(codeGenerationContext);
|
||||
|
|
@ -281,7 +281,7 @@ namespace Microsoft.AspNet.Razor
|
|||
};
|
||||
}
|
||||
|
||||
protected internal virtual CodeBuilder CreateCodeBuilder(CodeGeneratorContext context)
|
||||
protected internal virtual CodeBuilder CreateCodeBuilder(CodeBuilderContext context)
|
||||
{
|
||||
return Host.DecorateCodeBuilder(Host.CodeLanguage.CreateCodeBuilder(context),
|
||||
context);
|
||||
|
|
|
|||
|
|
@ -48,15 +48,16 @@ namespace Microsoft.AspNet.Razor.Test
|
|||
{
|
||||
// Arrange
|
||||
var language = new CSharpRazorCodeLanguage();
|
||||
var host = new RazorEngineHost(language);
|
||||
var context = CodeGeneratorContext.Create(host,
|
||||
"myclass",
|
||||
"myns",
|
||||
string.Empty,
|
||||
shouldGenerateLinePragmas: false);
|
||||
var host = new RazorEngineHost(language);
|
||||
var codeBuilderContext = new CodeBuilderContext(
|
||||
host,
|
||||
"myclass",
|
||||
"myns",
|
||||
string.Empty,
|
||||
shouldGenerateLinePragmas: false);
|
||||
|
||||
// Act
|
||||
var generator = language.CreateCodeBuilder(context);
|
||||
var generator = language.CreateCodeBuilder(codeBuilderContext);
|
||||
|
||||
// Assert
|
||||
Assert.IsType<CSharpCodeBuilder>(generator);
|
||||
|
|
|
|||
|
|
@ -17,15 +17,22 @@ namespace Microsoft.AspNet.Razor.Test.Generator.CodeTree
|
|||
var syntaxTreeNode = new Mock<Span>(new SpanBuilder());
|
||||
var language = new CSharpRazorCodeLanguage();
|
||||
var host = new RazorEngineHost(language);
|
||||
var context = CodeGeneratorContext.Create(host, "TestClass", "TestNamespace", "Foo.cs", shouldGenerateLinePragmas: false);
|
||||
context.CodeTreeBuilder.AddUsingChunk("FakeNamespace1", syntaxTreeNode.Object);
|
||||
context.CodeTreeBuilder.AddUsingChunk("FakeNamespace2.SubNamespace", syntaxTreeNode.Object);
|
||||
var codeBuilder = language.CreateCodeBuilder(context);
|
||||
var codeBuilderContext = new CodeBuilderContext(
|
||||
host,
|
||||
"TestClass",
|
||||
"TestNamespace",
|
||||
"Foo.cs",
|
||||
shouldGenerateLinePragmas: false);
|
||||
codeBuilderContext.CodeTreeBuilder.AddUsingChunk("FakeNamespace1", syntaxTreeNode.Object);
|
||||
codeBuilderContext.CodeTreeBuilder.AddUsingChunk("FakeNamespace2.SubNamespace", syntaxTreeNode.Object);
|
||||
var codeBuilder = language.CreateCodeBuilder(codeBuilderContext);
|
||||
|
||||
// Act
|
||||
var result = codeBuilder.Build();
|
||||
|
||||
BaselineWriter.WriteBaseline(@"test\Microsoft.AspNet.Razor.Test\TestFiles\CodeGenerator\CS\Output\CSharpCodeBuilder.cs", result.Code);
|
||||
BaselineWriter.WriteBaseline(
|
||||
@"test\Microsoft.AspNet.Razor.Test\TestFiles\CodeGenerator\CS\Output\CSharpCodeBuilder.cs",
|
||||
result.Code);
|
||||
|
||||
var expectedOutput = TestFile.Create("TestFiles/CodeGenerator/CS/Output/CSharpCodeBuilder.cs").ReadAllText();
|
||||
|
||||
|
|
|
|||
|
|
@ -25,13 +25,14 @@ namespace Microsoft.AspNet.Razor
|
|||
|
||||
private static Mock<ChunkVisitor<CodeWriter>> CreateVisitor()
|
||||
{
|
||||
var context = CodeGeneratorContext.Create(new RazorEngineHost(new CSharpRazorCodeLanguage()),
|
||||
"myclass",
|
||||
"myns",
|
||||
string.Empty,
|
||||
shouldGenerateLinePragmas: false);
|
||||
var codeBuilderContext = new CodeBuilderContext(
|
||||
new RazorEngineHost(new CSharpRazorCodeLanguage()),
|
||||
"myclass",
|
||||
"myns",
|
||||
string.Empty,
|
||||
shouldGenerateLinePragmas: false);
|
||||
var writer = Mock.Of<CodeWriter>();
|
||||
return new Mock<ChunkVisitor<CodeWriter>>(writer, context);
|
||||
return new Mock<ChunkVisitor<CodeWriter>>(writer, codeBuilderContext);
|
||||
}
|
||||
|
||||
private class MyTestChunk : Chunk
|
||||
|
|
|
|||
|
|
@ -114,19 +114,21 @@ namespace Microsoft.AspNet.Razor.Test
|
|||
{
|
||||
// Arrange
|
||||
var mockHost = new Mock<RazorEngineHost>(new CSharpRazorCodeLanguage()) { CallBase = true };
|
||||
var context = CodeGeneratorContext.Create(mockHost.Object,
|
||||
"different-class",
|
||||
"different-ns",
|
||||
string.Empty,
|
||||
shouldGenerateLinePragmas: true);
|
||||
var expected = new CSharpCodeBuilder(context);
|
||||
var codeBuilderContext = new CodeBuilderContext(
|
||||
mockHost.Object,
|
||||
"different-class",
|
||||
"different-ns",
|
||||
string.Empty,
|
||||
shouldGenerateLinePragmas: true);
|
||||
|
||||
mockHost.Setup(h => h.DecorateCodeBuilder(It.IsAny<CSharpCodeBuilder>(), context))
|
||||
var expected = new CSharpCodeBuilder(codeBuilderContext);
|
||||
|
||||
mockHost.Setup(h => h.DecorateCodeBuilder(It.IsAny<CSharpCodeBuilder>(), codeBuilderContext))
|
||||
.Returns(expected);
|
||||
var engine = new RazorTemplateEngine(mockHost.Object);
|
||||
|
||||
// Act
|
||||
var actual = engine.CreateCodeBuilder(context);
|
||||
var actual = engine.CreateCodeBuilder(codeBuilderContext);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expected, actual);
|
||||
|
|
|
|||
Loading…
Reference in New Issue