Refactoring CSharpCodeWriter
* Using CodeGeneratorContext to pass around metadata. * Tweaks in CSharpCodeWriter to use the right type name * Adding a sample unit test
This commit is contained in:
parent
68bb44d73e
commit
57854b2cc0
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using Microsoft.AspNet.Razor.Generator;
|
using Microsoft.AspNet.Razor.Generator;
|
||||||
|
using Microsoft.AspNet.Razor.Generator.Compiler;
|
||||||
|
using Microsoft.AspNet.Razor.Generator.Compiler.CSharp;
|
||||||
using Microsoft.AspNet.Razor.Parser;
|
using Microsoft.AspNet.Razor.Parser;
|
||||||
using Microsoft.CSharp;
|
using Microsoft.CSharp;
|
||||||
|
|
||||||
|
|
@ -47,5 +49,10 @@ namespace Microsoft.AspNet.Razor
|
||||||
{
|
{
|
||||||
return new CSharpRazorCodeGenerator(className, rootNamespaceName, sourceFileName, host);
|
return new CSharpRazorCodeGenerator(className, rootNamespaceName, sourceFileName, host);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override CodeBuilder CreateBuilder(CodeGeneratorContext codeGeneratorContext)
|
||||||
|
{
|
||||||
|
return new CSharpCodeBuilder(codeGeneratorContext);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,8 @@ namespace Microsoft.AspNet.Razor.Generator
|
||||||
// It's way safer to make them internal for now, especially with the code generator stuff in a bit of flux.
|
// 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; }
|
internal ExpressionRenderingMode ExpressionRenderingMode { get; set; }
|
||||||
public string SourceFile { get; internal set; }
|
public string SourceFile { get; internal set; }
|
||||||
|
public string RootNamespace { get; private set; }
|
||||||
|
public string ClassName { get; private set; }
|
||||||
|
|
||||||
#region deletable
|
#region deletable
|
||||||
#if NET45
|
#if NET45
|
||||||
|
|
@ -46,6 +48,7 @@ namespace Microsoft.AspNet.Razor.Generator
|
||||||
public CodeCompileUnit CompileUnit { get; internal set; }
|
public CodeCompileUnit CompileUnit { get; internal set; }
|
||||||
|
|
||||||
public CodeNamespace Namespace { get; internal set; }
|
public CodeNamespace Namespace { get; internal set; }
|
||||||
|
|
||||||
public CodeTypeDeclaration GeneratedClass { get; internal set; }
|
public CodeTypeDeclaration GeneratedClass { get; internal set; }
|
||||||
public CodeMemberMethod TargetMethod { get; set; }
|
public CodeMemberMethod TargetMethod { get; set; }
|
||||||
public IDictionary<int, GeneratedCodeMapping> CodeMappings { get; private set; }
|
public IDictionary<int, GeneratedCodeMapping> CodeMappings { get; private set; }
|
||||||
|
|
@ -320,6 +323,8 @@ namespace Microsoft.AspNet.Razor.Generator
|
||||||
CodeTreeBuilder = new CodeTreeBuilder(),
|
CodeTreeBuilder = new CodeTreeBuilder(),
|
||||||
Host = host,
|
Host = host,
|
||||||
SourceFile = shouldGenerateLinePragmas ? sourceFile : null,
|
SourceFile = shouldGenerateLinePragmas ? sourceFile : null,
|
||||||
|
RootNamespace = rootNamespace,
|
||||||
|
ClassName = className,
|
||||||
#if NET45
|
#if NET45
|
||||||
// This section is #if'd because it contains SOME incompatible pieces but also will not be needed once we transition over
|
// This section is #if'd because it contains SOME incompatible pieces but also will not be needed once we transition over
|
||||||
// to using the CodeTree
|
// to using the CodeTree
|
||||||
|
|
|
||||||
|
|
@ -1,72 +1,53 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Razor.Generator.Compiler.CSharp
|
namespace Microsoft.AspNet.Razor.Generator.Compiler.CSharp
|
||||||
{
|
{
|
||||||
public class CSharpCodeBuilder : CodeBuilder
|
public class CSharpCodeBuilder : CodeBuilder
|
||||||
{
|
{
|
||||||
public CSharpCodeBuilder(CodeTree codeTree, string rootNamespace, RazorEngineHost host, string sourceFile)
|
public CSharpCodeBuilder(CodeGeneratorContext context)
|
||||||
: base(codeTree)
|
: base(context)
|
||||||
{
|
{
|
||||||
Host = host;
|
|
||||||
RootNamespace = rootNamespace;
|
|
||||||
SourceFile = sourceFile;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public RazorEngineHost Host { get; private set; }
|
private CodeTree Tree { get { return Context.CodeTreeBuilder.CodeTree; } }
|
||||||
public string RootNamespace { get; private set; }
|
public RazorEngineHost Host { get { return Context.Host; } }
|
||||||
public string SourceFile { get; private set; }
|
|
||||||
|
|
||||||
public override CodeBuilderResult Build()
|
public override CodeBuilderResult Build()
|
||||||
{
|
{
|
||||||
var writer = new CSharpCodeWriter();
|
var writer = new CSharpCodeWriter();
|
||||||
|
|
||||||
// TODO: Combine into one string (perf)
|
using (writer.BuildNamespace(Context.RootNamespace))
|
||||||
writer.WriteComment(new string('-', 78))
|
|
||||||
.WriteComment("<auto-generated>")
|
|
||||||
.WriteComment(" This code was generated by a tool.")
|
|
||||||
.WriteComment("")
|
|
||||||
.WriteComment(" Changes to this file may cause incorrect behavior and will be lost if")
|
|
||||||
.WriteComment(" the code is regenerated.")
|
|
||||||
.WriteComment("</auto-generated>")
|
|
||||||
.WriteComment(new string('-', 78))
|
|
||||||
.WriteLine();
|
|
||||||
|
|
||||||
using (writer.BuildNamespace(RootNamespace))
|
|
||||||
{
|
{
|
||||||
// Write out using directives
|
// Write out using directives
|
||||||
AddImports(Tree, writer, Host.NamespaceImports);
|
AddImports(Tree, writer, Host.NamespaceImports);
|
||||||
|
|
||||||
// TODO: Include current projects namespace? Does that happen to be included in the namespace imports?
|
|
||||||
|
|
||||||
var baseTypeVisitor = new CSharpBaseTypeVisitor(writer);
|
|
||||||
|
|
||||||
baseTypeVisitor.Accept(Tree.Chunks);
|
|
||||||
|
|
||||||
string baseType = baseTypeVisitor.CurrentBaseType ?? Host.DefaultBaseClass;
|
|
||||||
|
|
||||||
// Separate the usings and the class
|
// Separate the usings and the class
|
||||||
writer.WriteLine();
|
writer.WriteLine();
|
||||||
|
|
||||||
|
var baseTypeVisitor = new CSharpBaseTypeVisitor(writer);
|
||||||
|
baseTypeVisitor.Accept(Tree.Chunks);
|
||||||
|
|
||||||
|
string baseType = baseTypeVisitor.CurrentBaseType ?? Host.DefaultBaseClass;
|
||||||
new CSharpClassAttributeVisitor(writer).Accept(Tree.Chunks);
|
new CSharpClassAttributeVisitor(writer).Accept(Tree.Chunks);
|
||||||
|
|
||||||
using (writer.BuildClassDeclaration("public", Host.DefaultClassName, String.IsNullOrEmpty(baseType) ? new string[0] : new string[] { baseType }))
|
IEnumerable<string> baseTypes = String.IsNullOrEmpty(baseType) ? Enumerable.Empty<string>() :
|
||||||
|
new string[] { baseType };
|
||||||
|
using (writer.BuildClassDeclaration("public", Context.ClassName, baseTypes))
|
||||||
{
|
{
|
||||||
if (Host.DesignTimeMode)
|
if (Host.DesignTimeMode)
|
||||||
{
|
{
|
||||||
writer.WriteLine("private static object @__o;");
|
writer.WriteLine("private static object @__o;");
|
||||||
}
|
}
|
||||||
|
|
||||||
new CSharpHelperVisitor(writer, Host, SourceFile).Accept(Tree.Chunks);
|
new CSharpHelperVisitor(writer, Context).Accept(Tree.Chunks);
|
||||||
new CSharpTypeMemberVisitor(writer, SourceFile).Accept(Tree.Chunks);
|
new CSharpTypeMemberVisitor(writer, Context).Accept(Tree.Chunks);
|
||||||
new CSharpDesignTimeHelpersVisitor(writer, Host, SourceFile).Accept(Tree);
|
new CSharpDesignTimeHelpersVisitor(writer, Context).Accept(Tree.Chunks);
|
||||||
|
|
||||||
// TODO: resolve variable declarations
|
// TODO: resolve variable declarations
|
||||||
|
|
||||||
writer.WriteLineHiddenDirective();
|
writer.WriteLineHiddenDirective();
|
||||||
using (writer.BuildConstructor(Host.DefaultClassName))
|
using (writer.BuildConstructor(Context.ClassName))
|
||||||
{
|
{
|
||||||
// Any constructor based logic that we need to add?
|
// Any constructor based logic that we need to add?
|
||||||
};
|
};
|
||||||
|
|
@ -76,7 +57,7 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler.CSharp
|
||||||
|
|
||||||
using (writer.BuildMethodDeclaration("public override", "void", Host.GeneratedClassContext.ExecuteMethodName))
|
using (writer.BuildMethodDeclaration("public override", "void", Host.GeneratedClassContext.ExecuteMethodName))
|
||||||
{
|
{
|
||||||
new CSharpCodeVisitor(writer, Host, SourceFile).Accept(Tree.Chunks);
|
new CSharpCodeVisitor(writer, Context).Accept(Tree.Chunks);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -87,7 +68,7 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler.CSharp
|
||||||
private void AddImports(CodeTree codeTree, CSharpCodeWriter writer, IEnumerable<string> defaultImports)
|
private void AddImports(CodeTree codeTree, CSharpCodeWriter writer, IEnumerable<string> defaultImports)
|
||||||
{
|
{
|
||||||
// Write out using directives
|
// Write out using directives
|
||||||
var usingVisitor = new CSharpUsingVisitor(writer, SourceFile);
|
var usingVisitor = new CSharpUsingVisitor(writer, Context.SourceFile);
|
||||||
foreach (Chunk chunk in Tree.Chunks)
|
foreach (Chunk chunk in Tree.Chunks)
|
||||||
{
|
{
|
||||||
usingVisitor.Accept(chunk);
|
usingVisitor.Accept(chunk);
|
||||||
|
|
|
||||||
|
|
@ -8,23 +8,20 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler.CSharp
|
||||||
{
|
{
|
||||||
private const string ValueWriterName = "__razor_attribute_value_writer";
|
private const string ValueWriterName = "__razor_attribute_value_writer";
|
||||||
|
|
||||||
private CSharpCodeWriter _writer;
|
private readonly CSharpCodeWriter _writer;
|
||||||
// TODO: No need for the entire host
|
private readonly CodeGeneratorContext _context;
|
||||||
private RazorEngineHost _host;
|
|
||||||
private string _sourceFile;
|
|
||||||
|
|
||||||
public CSharpCodeVisitor(CSharpCodeWriter writer, RazorEngineHost host, string sourceFile)
|
public CSharpCodeVisitor(CSharpCodeWriter writer, CodeGeneratorContext context)
|
||||||
{
|
{
|
||||||
_writer = writer;
|
_writer = writer;
|
||||||
_host = host;
|
_context = context;
|
||||||
_sourceFile = sourceFile;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void Visit(SetLayoutChunk chunk)
|
protected override void Visit(SetLayoutChunk chunk)
|
||||||
{
|
{
|
||||||
if (!_host.DesignTimeMode && !String.IsNullOrEmpty(_host.GeneratedClassContext.LayoutPropertyName))
|
if (!_context.Host.DesignTimeMode && !String.IsNullOrEmpty(_context.Host.GeneratedClassContext.LayoutPropertyName))
|
||||||
{
|
{
|
||||||
_writer.Write(_host.GeneratedClassContext.LayoutPropertyName)
|
_writer.Write(_context.Host.GeneratedClassContext.LayoutPropertyName)
|
||||||
.Write(" = ")
|
.Write(" = ")
|
||||||
.WriteStringLiteral(chunk.Layout)
|
.WriteStringLiteral(chunk.Layout)
|
||||||
.WriteLine(";");
|
.WriteLine(";");
|
||||||
|
|
@ -34,7 +31,7 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler.CSharp
|
||||||
protected override void Visit(TemplateChunk chunk)
|
protected override void Visit(TemplateChunk chunk)
|
||||||
{
|
{
|
||||||
_writer.Write(TemplateBlockCodeGenerator.ItemParameterName).Write(" => ")
|
_writer.Write(TemplateBlockCodeGenerator.ItemParameterName).Write(" => ")
|
||||||
.WriteStartNewObject(_host.GeneratedClassContext.TemplateTypeName);
|
.WriteStartNewObject(_context.Host.GeneratedClassContext.TemplateTypeName);
|
||||||
|
|
||||||
using (_writer.BuildLambda(endLine: false, parameterNames: TemplateBlockCodeGenerator.TemplateWriterName))
|
using (_writer.BuildLambda(endLine: false, parameterNames: TemplateBlockCodeGenerator.TemplateWriterName))
|
||||||
{
|
{
|
||||||
|
|
@ -46,30 +43,30 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler.CSharp
|
||||||
|
|
||||||
protected override void Visit(ResolveUrlChunk chunk)
|
protected override void Visit(ResolveUrlChunk chunk)
|
||||||
{
|
{
|
||||||
if (!_host.DesignTimeMode && String.IsNullOrEmpty(chunk.Url))
|
if (!_context.Host.DesignTimeMode && String.IsNullOrEmpty(chunk.Url))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Add instrumentation
|
// TODO: Add instrumentation
|
||||||
|
|
||||||
if (!String.IsNullOrEmpty(chunk.Url) && !_host.DesignTimeMode)
|
if (!String.IsNullOrEmpty(chunk.Url) && !_context.Host.DesignTimeMode)
|
||||||
{
|
{
|
||||||
if (chunk.RenderingMode == ExpressionRenderingMode.WriteToOutput)
|
if (chunk.RenderingMode == ExpressionRenderingMode.WriteToOutput)
|
||||||
{
|
{
|
||||||
if (!String.IsNullOrEmpty(chunk.WriterName))
|
if (!String.IsNullOrEmpty(chunk.WriterName))
|
||||||
{
|
{
|
||||||
_writer.WriteStartMethodInvocation(_host.GeneratedClassContext.WriteLiteralToMethodName)
|
_writer.WriteStartMethodInvocation(_context.Host.GeneratedClassContext.WriteLiteralToMethodName)
|
||||||
.Write(chunk.WriterName)
|
.Write(chunk.WriterName)
|
||||||
.WriteParameterSeparator();
|
.WriteParameterSeparator();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_writer.WriteStartMethodInvocation(_host.GeneratedClassContext.WriteLiteralMethodName);
|
_writer.WriteStartMethodInvocation(_context.Host.GeneratedClassContext.WriteLiteralMethodName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_writer.WriteStartMethodInvocation(_host.GeneratedClassContext.ResolveUrlMethodName)
|
_writer.WriteStartMethodInvocation(_context.Host.GeneratedClassContext.ResolveUrlMethodName)
|
||||||
.WriteStringLiteral(chunk.Url)
|
.WriteStringLiteral(chunk.Url)
|
||||||
.WriteEndMethodInvocation(endLine: false);
|
.WriteEndMethodInvocation(endLine: false);
|
||||||
|
|
||||||
|
|
@ -82,24 +79,24 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler.CSharp
|
||||||
|
|
||||||
protected override void Visit(LiteralChunk chunk)
|
protected override void Visit(LiteralChunk chunk)
|
||||||
{
|
{
|
||||||
if (!_host.DesignTimeMode && String.IsNullOrEmpty(chunk.Text))
|
if (!_context.Host.DesignTimeMode && String.IsNullOrEmpty(chunk.Text))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Add instrumentation
|
// TODO: Add instrumentation
|
||||||
|
|
||||||
if (!String.IsNullOrEmpty(chunk.Text) && !_host.DesignTimeMode)
|
if (!String.IsNullOrEmpty(chunk.Text) && !_context.Host.DesignTimeMode)
|
||||||
{
|
{
|
||||||
if (!String.IsNullOrEmpty(chunk.WriterName))
|
if (!String.IsNullOrEmpty(chunk.WriterName))
|
||||||
{
|
{
|
||||||
_writer.WriteStartMethodInvocation(_host.GeneratedClassContext.WriteLiteralToMethodName)
|
_writer.WriteStartMethodInvocation(_context.Host.GeneratedClassContext.WriteLiteralToMethodName)
|
||||||
.Write(chunk.WriterName)
|
.Write(chunk.WriterName)
|
||||||
.WriteParameterSeparator();
|
.WriteParameterSeparator();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_writer.WriteStartMethodInvocation(_host.GeneratedClassContext.WriteLiteralMethodName);
|
_writer.WriteStartMethodInvocation(_context.Host.GeneratedClassContext.WriteLiteralMethodName);
|
||||||
}
|
}
|
||||||
|
|
||||||
_writer.WriteStringLiteral(chunk.Text)
|
_writer.WriteStringLiteral(chunk.Text)
|
||||||
|
|
@ -114,13 +111,13 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler.CSharp
|
||||||
// TODO: Handle instrumentation
|
// TODO: Handle instrumentation
|
||||||
// TODO: Refactor
|
// TODO: Refactor
|
||||||
|
|
||||||
if (!_host.DesignTimeMode && chunk.RenderingMode == ExpressionRenderingMode.InjectCode)
|
if (!_context.Host.DesignTimeMode && chunk.RenderingMode == ExpressionRenderingMode.InjectCode)
|
||||||
{
|
{
|
||||||
Visit((ChunkBlock)chunk);
|
Visit((ChunkBlock)chunk);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (_host.DesignTimeMode)
|
if (_context.Host.DesignTimeMode)
|
||||||
{
|
{
|
||||||
_writer.WriteStartAssignment("__o");
|
_writer.WriteStartAssignment("__o");
|
||||||
}
|
}
|
||||||
|
|
@ -130,19 +127,19 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler.CSharp
|
||||||
|
|
||||||
if (!String.IsNullOrEmpty(chunk.WriterName))
|
if (!String.IsNullOrEmpty(chunk.WriterName))
|
||||||
{
|
{
|
||||||
_writer.WriteStartMethodInvocation(_host.GeneratedClassContext.WriteToMethodName)
|
_writer.WriteStartMethodInvocation(_context.Host.GeneratedClassContext.WriteToMethodName)
|
||||||
.Write(chunk.WriterName)
|
.Write(chunk.WriterName)
|
||||||
.WriteParameterSeparator();
|
.WriteParameterSeparator();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_writer.WriteStartMethodInvocation(_host.GeneratedClassContext.WriteMethodName);
|
_writer.WriteStartMethodInvocation(_context.Host.GeneratedClassContext.WriteMethodName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Visit((ChunkBlock)chunk);
|
Visit((ChunkBlock)chunk);
|
||||||
|
|
||||||
if (_host.DesignTimeMode)
|
if (_context.Host.DesignTimeMode)
|
||||||
{
|
{
|
||||||
_writer.WriteLine(";");
|
_writer.WriteLine(";");
|
||||||
}
|
}
|
||||||
|
|
@ -155,7 +152,7 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler.CSharp
|
||||||
|
|
||||||
protected override void Visit(ExpressionChunk chunk)
|
protected override void Visit(ExpressionChunk chunk)
|
||||||
{
|
{
|
||||||
using (_writer.BuildLineMapping(chunk.Start, chunk.Code.Value.Length, _sourceFile))
|
using (_writer.BuildLineMapping(chunk.Start, chunk.Code.Value.Length, _context.SourceFile))
|
||||||
{
|
{
|
||||||
_writer.Indent(chunk.Start.CharacterIndex)
|
_writer.Indent(chunk.Start.CharacterIndex)
|
||||||
.Write(chunk.Code.Value);
|
.Write(chunk.Code.Value);
|
||||||
|
|
@ -166,7 +163,7 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler.CSharp
|
||||||
{
|
{
|
||||||
foreach (Snippet snippet in chunk.Code)
|
foreach (Snippet snippet in chunk.Code)
|
||||||
{
|
{
|
||||||
using (_writer.BuildLineMapping(chunk.Start, snippet.Value.Length, _sourceFile))
|
using (_writer.BuildLineMapping(chunk.Start, snippet.Value.Length, _context.SourceFile))
|
||||||
{
|
{
|
||||||
_writer.Indent(chunk.Start.CharacterIndex);
|
_writer.Indent(chunk.Start.CharacterIndex);
|
||||||
_writer.WriteLine(snippet.Value);
|
_writer.WriteLine(snippet.Value);
|
||||||
|
|
@ -176,7 +173,7 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler.CSharp
|
||||||
|
|
||||||
protected override void Visit(DynamicCodeAttributeChunk chunk)
|
protected override void Visit(DynamicCodeAttributeChunk chunk)
|
||||||
{
|
{
|
||||||
if (_host.DesignTimeMode)
|
if (_context.Host.DesignTimeMode)
|
||||||
{
|
{
|
||||||
return; // Don't generate anything!
|
return; // Don't generate anything!
|
||||||
}
|
}
|
||||||
|
|
@ -208,7 +205,7 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler.CSharp
|
||||||
.WriteLocationTaggedString(chunk.Prefix)
|
.WriteLocationTaggedString(chunk.Prefix)
|
||||||
.WriteParameterSeparator()
|
.WriteParameterSeparator()
|
||||||
.WriteStartMethodInvocation("Tuple.Create", new string[] { "System.Object", "System.Int32" })
|
.WriteStartMethodInvocation("Tuple.Create", new string[] { "System.Object", "System.Int32" })
|
||||||
.WriteStartNewObject(_host.GeneratedClassContext.TemplateTypeName);
|
.WriteStartNewObject(_context.Host.GeneratedClassContext.TemplateTypeName);
|
||||||
|
|
||||||
using (_writer.BuildLambda(endLine: false, parameterNames: ValueWriterName))
|
using (_writer.BuildLambda(endLine: false, parameterNames: ValueWriterName))
|
||||||
{
|
{
|
||||||
|
|
@ -227,7 +224,7 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler.CSharp
|
||||||
|
|
||||||
protected override void Visit(LiteralCodeAttributeChunk chunk)
|
protected override void Visit(LiteralCodeAttributeChunk chunk)
|
||||||
{
|
{
|
||||||
if (_host.DesignTimeMode)
|
if (_context.Host.DesignTimeMode)
|
||||||
{
|
{
|
||||||
return; // Don't generate anything!
|
return; // Don't generate anything!
|
||||||
}
|
}
|
||||||
|
|
@ -262,20 +259,20 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler.CSharp
|
||||||
|
|
||||||
protected override void Visit(CodeAttributeChunk chunk)
|
protected override void Visit(CodeAttributeChunk chunk)
|
||||||
{
|
{
|
||||||
if (_host.DesignTimeMode)
|
if (_context.Host.DesignTimeMode)
|
||||||
{
|
{
|
||||||
return; // Don't generate anything!
|
return; // Don't generate anything!
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!String.IsNullOrEmpty(chunk.WriterName))
|
if (!String.IsNullOrEmpty(chunk.WriterName))
|
||||||
{
|
{
|
||||||
_writer.WriteStartMethodInvocation(_host.GeneratedClassContext.WriteAttributeToMethodName)
|
_writer.WriteStartMethodInvocation(_context.Host.GeneratedClassContext.WriteAttributeToMethodName)
|
||||||
.Write(chunk.WriterName)
|
.Write(chunk.WriterName)
|
||||||
.WriteParameterSeparator();
|
.WriteParameterSeparator();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_writer.WriteStartMethodInvocation(_host.GeneratedClassContext.WriteAttributeMethodName);
|
_writer.WriteStartMethodInvocation(_context.Host.GeneratedClassContext.WriteAttributeMethodName);
|
||||||
}
|
}
|
||||||
|
|
||||||
_writer.WriteStringLiteral(chunk.Attribute)
|
_writer.WriteStringLiteral(chunk.Attribute)
|
||||||
|
|
@ -291,7 +288,7 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler.CSharp
|
||||||
|
|
||||||
protected override void Visit(SectionChunk chunk)
|
protected override void Visit(SectionChunk chunk)
|
||||||
{
|
{
|
||||||
_writer.WriteStartMethodInvocation(_host.GeneratedClassContext.DefineSectionMethodName)
|
_writer.WriteStartMethodInvocation(_context.Host.GeneratedClassContext.DefineSectionMethodName)
|
||||||
.WriteStringLiteral(chunk.Name)
|
.WriteStringLiteral(chunk.Name)
|
||||||
.WriteParameterSeparator();
|
.WriteParameterSeparator();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,27 +5,24 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler.CSharp
|
||||||
{
|
{
|
||||||
internal const string InheritsHelper = "__inheritsHelper";
|
internal const string InheritsHelper = "__inheritsHelper";
|
||||||
|
|
||||||
private CSharpCodeWriter _writer;
|
private readonly CSharpCodeWriter _writer;
|
||||||
// TODO: No need for the entire host
|
private readonly CodeGeneratorContext _context;
|
||||||
private RazorEngineHost _host;
|
|
||||||
private string _sourceFile;
|
|
||||||
|
|
||||||
public CSharpDesignTimeHelpersVisitor(CSharpCodeWriter writer, RazorEngineHost host, string sourceFile)
|
public CSharpDesignTimeHelpersVisitor(CSharpCodeWriter writer, CodeGeneratorContext context)
|
||||||
{
|
{
|
||||||
_writer = writer;
|
_writer = writer;
|
||||||
_host = host;
|
_context = context;
|
||||||
_sourceFile = sourceFile;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Accept(CodeTree tree)
|
public override void Accept(System.Collections.Generic.IList<Chunk> chunks)
|
||||||
{
|
{
|
||||||
if(_host.DesignTimeMode)
|
if (_context.Host.DesignTimeMode)
|
||||||
{
|
{
|
||||||
using(_writer.BuildMethodDeclaration("private","void", "@"+CodeGeneratorContext.DesignTimeHelperMethodName))
|
using (_writer.BuildMethodDeclaration("private", "void", "@" + CodeGeneratorContext.DesignTimeHelperMethodName))
|
||||||
{
|
{
|
||||||
using (_writer.BuildDisableWarningScope())
|
using (_writer.BuildDisableWarningScope())
|
||||||
{
|
{
|
||||||
Accept(tree.Chunks);
|
Accept(chunks);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -33,9 +30,9 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler.CSharp
|
||||||
|
|
||||||
protected override void Visit(SetBaseTypeChunk chunk)
|
protected override void Visit(SetBaseTypeChunk chunk)
|
||||||
{
|
{
|
||||||
if (_host.DesignTimeMode)
|
if (_context.Host.DesignTimeMode)
|
||||||
{
|
{
|
||||||
using (CSharpLineMappingWriter lineMappingWriter = _writer.BuildLineMapping(chunk.Start, chunk.TypeName.Length, _sourceFile))
|
using (CSharpLineMappingWriter lineMappingWriter = _writer.BuildLineMapping(chunk.Start, chunk.TypeName.Length, _context.SourceFile))
|
||||||
{
|
{
|
||||||
_writer.Indent(chunk.Start.CharacterIndex);
|
_writer.Indent(chunk.Start.CharacterIndex);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,28 +6,26 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler.CSharp
|
||||||
{
|
{
|
||||||
private const string HelperWriterName = "__razor_helper_writer";
|
private const string HelperWriterName = "__razor_helper_writer";
|
||||||
|
|
||||||
private CSharpCodeWriter _writer;
|
private readonly CSharpCodeWriter _writer;
|
||||||
private string _sourceFile;
|
private readonly CodeGeneratorContext _context;
|
||||||
private RazorEngineHost _host;
|
|
||||||
private CSharpCodeVisitor _codeVisitor;
|
private CSharpCodeVisitor _codeVisitor;
|
||||||
|
|
||||||
public CSharpHelperVisitor(CSharpCodeWriter writer, RazorEngineHost host, string sourceFile)
|
public CSharpHelperVisitor(CSharpCodeWriter writer, CodeGeneratorContext context)
|
||||||
{
|
{
|
||||||
_writer = writer;
|
_writer = writer;
|
||||||
_sourceFile = sourceFile;
|
_context = context;
|
||||||
_host = host;
|
_codeVisitor = new CSharpCodeVisitor(writer, context);
|
||||||
_codeVisitor = new CSharpCodeVisitor(writer, host, sourceFile);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void Visit(HelperChunk chunk)
|
protected override void Visit(HelperChunk chunk)
|
||||||
{
|
{
|
||||||
IDisposable lambdaScope = null;
|
IDisposable lambdaScope = null;
|
||||||
|
|
||||||
using (CSharpLineMappingWriter mappingWriter = _writer.BuildLineMapping(chunk.Signature.Location, chunk.Signature.Value.Length, _sourceFile))
|
using (CSharpLineMappingWriter mappingWriter = _writer.BuildLineMapping(chunk.Signature.Location, chunk.Signature.Value.Length, _context.SourceFile))
|
||||||
{
|
{
|
||||||
string accessibility = "public " + (_host.StaticHelpers ? "static" : String.Empty);
|
string accessibility = "public " + (_context.Host.StaticHelpers ? "static" : String.Empty);
|
||||||
|
|
||||||
_writer.Write(accessibility).Write(" ").Write(_host.GeneratedClassContext.TemplateTypeName).Write(" ");
|
_writer.Write(accessibility).Write(" ").Write(_context.Host.GeneratedClassContext.TemplateTypeName).Write(" ");
|
||||||
mappingWriter.MarkLineMappingStart();
|
mappingWriter.MarkLineMappingStart();
|
||||||
_writer.Write(chunk.Signature);
|
_writer.Write(chunk.Signature);
|
||||||
mappingWriter.MarkLineMappingEnd();
|
mappingWriter.MarkLineMappingEnd();
|
||||||
|
|
@ -36,7 +34,7 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler.CSharp
|
||||||
if(chunk.HeaderComplete)
|
if(chunk.HeaderComplete)
|
||||||
{
|
{
|
||||||
_writer.WriteStartReturn()
|
_writer.WriteStartReturn()
|
||||||
.WriteStartNewObject(_host.GeneratedClassContext.TemplateTypeName);
|
.WriteStartNewObject(_context.Host.GeneratedClassContext.TemplateTypeName);
|
||||||
|
|
||||||
lambdaScope = _writer.BuildLambda(endLine: false, parameterNames: HelperWriterName);
|
lambdaScope = _writer.BuildLambda(endLine: false, parameterNames: HelperWriterName);
|
||||||
}
|
}
|
||||||
|
|
@ -52,7 +50,7 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler.CSharp
|
||||||
|
|
||||||
if(chunk.Footer != null && !String.IsNullOrEmpty(chunk.Footer.Value))
|
if(chunk.Footer != null && !String.IsNullOrEmpty(chunk.Footer.Value))
|
||||||
{
|
{
|
||||||
using(_writer.BuildLineMapping(chunk.Footer.Location, chunk.Footer.Value.Length, _sourceFile))
|
using(_writer.BuildLineMapping(chunk.Footer.Location, chunk.Footer.Value.Length, _context.SourceFile))
|
||||||
{
|
{
|
||||||
_writer.Write(chunk.Footer);
|
_writer.Write(chunk.Footer);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,12 +5,12 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler.CSharp
|
||||||
public class CSharpTypeMemberVisitor : CodeVisitor
|
public class CSharpTypeMemberVisitor : CodeVisitor
|
||||||
{
|
{
|
||||||
private CSharpCodeWriter _writer;
|
private CSharpCodeWriter _writer;
|
||||||
private string _sourceFile;
|
private CodeGeneratorContext _context;
|
||||||
|
|
||||||
public CSharpTypeMemberVisitor(CSharpCodeWriter writer, string sourceFile)
|
public CSharpTypeMemberVisitor(CSharpCodeWriter writer, CodeGeneratorContext context)
|
||||||
{
|
{
|
||||||
_writer = writer;
|
_writer = writer;
|
||||||
_sourceFile = sourceFile;
|
_context = context;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void Visit(TypeMemberChunk chunk)
|
protected override void Visit(TypeMemberChunk chunk)
|
||||||
|
|
@ -19,7 +19,7 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler.CSharp
|
||||||
|
|
||||||
if (code != null)
|
if (code != null)
|
||||||
{
|
{
|
||||||
using (_writer.BuildLineMapping(chunk.Start, code.Value.Length, _sourceFile))
|
using (_writer.BuildLineMapping(chunk.Start, code.Value.Length, _context.SourceFile))
|
||||||
{
|
{
|
||||||
_writer.WriteLine(code.Value);
|
_writer.WriteLine(code.Value);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler
|
||||||
{
|
{
|
||||||
public abstract class ChunkVisitor : IChunkVisitor
|
public abstract class ChunkVisitor : IChunkVisitor
|
||||||
{
|
{
|
||||||
public void Accept(IList<Chunk> chunks)
|
public virtual void Accept(IList<Chunk> chunks)
|
||||||
{
|
{
|
||||||
if (chunks == null)
|
if (chunks == null)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,20 @@
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Razor.Generator.Compiler
|
namespace Microsoft.AspNet.Razor.Generator.Compiler
|
||||||
{
|
{
|
||||||
public class CodeBuilder
|
public abstract class CodeBuilder
|
||||||
{
|
{
|
||||||
protected CodeTree Tree;
|
private readonly CodeGeneratorContext _context;
|
||||||
|
|
||||||
public CodeBuilder(CodeTree codeTree)
|
public CodeBuilder(CodeGeneratorContext context)
|
||||||
{
|
{
|
||||||
Tree = codeTree;
|
_context = context;
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual CodeBuilderResult Build()
|
protected CodeGeneratorContext Context
|
||||||
{
|
{
|
||||||
return null;
|
get { return _context; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public abstract CodeBuilderResult Build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,8 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler
|
||||||
{
|
{
|
||||||
public class CodeTreeBuilder
|
public class CodeTreeBuilder
|
||||||
{
|
{
|
||||||
|
private readonly Stack<ChunkBlock> _blockChain;
|
||||||
private Chunk _lastChunk;
|
private Chunk _lastChunk;
|
||||||
private Stack<ChunkBlock> _blockChain;
|
|
||||||
|
|
||||||
public CodeTreeBuilder()
|
public CodeTreeBuilder()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Microsoft.AspNet.Razor.Generator;
|
using Microsoft.AspNet.Razor.Generator;
|
||||||
|
using Microsoft.AspNet.Razor.Generator.Compiler;
|
||||||
using Microsoft.AspNet.Razor.Parser;
|
using Microsoft.AspNet.Razor.Parser;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Razor
|
namespace Microsoft.AspNet.Razor
|
||||||
|
|
@ -59,5 +60,7 @@ namespace Microsoft.AspNet.Razor
|
||||||
/// Constructs the code generator. Must return a new instance on EVERY call to ensure thread-safety
|
/// Constructs the code generator. Must return a new instance on EVERY call to ensure thread-safety
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract RazorCodeGenerator CreateCodeGenerator(string className, string rootNamespaceName, string sourceFileName, RazorEngineHost host);
|
public abstract RazorCodeGenerator CreateCodeGenerator(string className, string rootNamespaceName, string sourceFileName, RazorEngineHost host);
|
||||||
|
|
||||||
|
public abstract CodeBuilder CreateBuilder(CodeGeneratorContext codeGeneratorContext);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -184,7 +184,7 @@ namespace Microsoft.AspNet.Razor
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
var builder = new CSharpCodeBuilder(generator.Context.CodeTreeBuilder.CodeTree, rootNamespace, Host, sourceFileName);
|
var builder = new CSharpCodeBuilder(generator.Context);
|
||||||
CodeBuilderResult builderResult = builder.Build();
|
CodeBuilderResult builderResult = builder.Build();
|
||||||
|
|
||||||
// Collect results and return
|
// Collect results and return
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,52 @@
|
||||||
|
using Microsoft.AspNet.Razor.Generator;
|
||||||
|
using Microsoft.AspNet.Razor.Generator.Compiler;
|
||||||
|
using Microsoft.AspNet.Razor.Generator.Compiler.CSharp;
|
||||||
|
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||||
|
using Microsoft.TestCommon;
|
||||||
|
using Moq;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Razor.Test.Generator.CodeTree
|
||||||
|
{
|
||||||
|
public class CSharpCodeBuilderTests
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void CodeTreeWithUsings()
|
||||||
|
{
|
||||||
|
var syntaxTreeNode = Mock.Of<SyntaxTreeNode>();
|
||||||
|
var language = new CSharpRazorCodeLanguage();
|
||||||
|
RazorEngineHost host = new RazorEngineHost(language);
|
||||||
|
var context = CodeGeneratorContext.Create(host, "TestClass", "TestNamespace", "Foo.cs", shouldGenerateLinePragmas: false);
|
||||||
|
context.CodeTreeBuilder.AddUsingChunk("FakeNamespace1", syntaxTreeNode, context);
|
||||||
|
context.CodeTreeBuilder.AddUsingChunk("FakeNamespace2.SubNamespace", syntaxTreeNode, context);
|
||||||
|
CodeBuilder codeBuilder = language.CreateBuilder(context);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
CodeBuilderResult result = codeBuilder.Build();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(@"namespace TestNamespace
|
||||||
|
{
|
||||||
|
#line 1 """"
|
||||||
|
using FakeNamespace1;
|
||||||
|
#line default
|
||||||
|
#line hidden
|
||||||
|
#line 1 """"
|
||||||
|
using FakeNamespace2.SubNamespace;
|
||||||
|
#line default
|
||||||
|
#line hidden
|
||||||
|
|
||||||
|
public class TestClass
|
||||||
|
{
|
||||||
|
#line hidden
|
||||||
|
public TestClass()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Execute()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}", result.Code.TrimEnd());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -6,7 +6,7 @@ using Microsoft.TestCommon;
|
||||||
namespace Microsoft.AspNet.Razor.Test.Generator
|
namespace Microsoft.AspNet.Razor.Test.Generator
|
||||||
{
|
{
|
||||||
public class CodeTreeGenerationTest : CSharpRazorCodeGeneratorTest
|
public class CodeTreeGenerationTest : CSharpRazorCodeGeneratorTest
|
||||||
{
|
{
|
||||||
[Fact]
|
[Fact]
|
||||||
public void CodeTreeComparisonTest()
|
public void CodeTreeComparisonTest()
|
||||||
{
|
{
|
||||||
|
|
@ -16,6 +16,6 @@ namespace Microsoft.AspNet.Razor.Test.Generator
|
||||||
File.WriteAllText("./testfile_ct.cs", results.GeneratedCode);
|
File.WriteAllText("./testfile_ct.cs", results.GeneratedCode);
|
||||||
File.WriteAllText("./testfile_cd.cs", codDOMOutput);
|
File.WriteAllText("./testfile_cd.cs", codDOMOutput);
|
||||||
}, designTimeMode: true);
|
}, designTimeMode: true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,7 @@
|
||||||
<Compile Include="Framework\TestSpanBuilder.cs" />
|
<Compile Include="Framework\TestSpanBuilder.cs" />
|
||||||
<Compile Include="Generator\CodeTree\CodeTreeGenerationTest.cs" />
|
<Compile Include="Generator\CodeTree\CodeTreeGenerationTest.cs" />
|
||||||
<Compile Include="Generator\CodeTree\CodeTreeOutputValidator.cs" />
|
<Compile Include="Generator\CodeTree\CodeTreeOutputValidator.cs" />
|
||||||
|
<Compile Include="Generator\CodeTree\CSharpCodeBuilderTests.cs" />
|
||||||
<Compile Include="Generator\GeneratedCodeMappingTest.cs" />
|
<Compile Include="Generator\GeneratedCodeMappingTest.cs" />
|
||||||
<Compile Include="Generator\PaddingTest.cs" />
|
<Compile Include="Generator\PaddingTest.cs" />
|
||||||
<Compile Include="Generator\TabTest.cs" />
|
<Compile Include="Generator\TabTest.cs" />
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue