2
// Based on TemplateCodeTransformer.cs from Razor Generator (http://razorgenerator.codeplex.com/)
3
// Licensed under the Microsoft Public License (MS-PL)
6
// Author: Michael Hutchinson <mhutch@xamarin.com>
7
// Copyright (c) 2012 Xamarin Inc (http://xamarin.com)
8
// Licensed under the Microsoft Public License (MS-PL)
12
using System.Collections.Generic;
16
namespace MonoDevelop.RazorGenerator
18
class PreprocessedTemplateCodeTransformers
20
public static void MakePartialAndRemoveCtor (RazorHost host, CodeCompileUnit codeCompileUnit, CodeNamespace generatedNamespace, CodeTypeDeclaration generatedClass, CodeMemberMethod executeMethod)
22
generatedClass.IsPartial = true;
23
// The generated class has a constructor in there by default.
24
generatedClass.Members.Remove (generatedClass.Members.OfType<CodeConstructor> ().Single ());
27
public static void AddGeneratedTemplateClassAttribute (RazorHost host, CodeCompileUnit codeCompileUnit, CodeNamespace generatedNamespace, CodeTypeDeclaration generatedClass, CodeMemberMethod executeMethod)
29
string tool = "RazorTemplatePreprocessor";
30
Version version = typeof (PreprocessedTemplateCodeTransformers).Assembly.GetName().Version;
31
generatedClass.CustomAttributes.Add(
32
new CodeAttributeDeclaration(typeof(System.CodeDom.Compiler.GeneratedCodeAttribute).FullName,
33
new CodeAttributeArgument(new CodePrimitiveExpression(tool)),
34
new CodeAttributeArgument(new CodePrimitiveExpression(version.ToString()))
38
static void AddComments (CodeTypeMember member, bool docComment, params string[] comments)
40
foreach (var c in comments) {
41
member.Comments.Add (new CodeCommentStatement (c, docComment));
45
public static void InjectBaseClass (RazorHost host, CodeCompileUnit codeCompileUnit, CodeNamespace generatedNamespace, CodeTypeDeclaration generatedClass, CodeMemberMethod executeMethod)
47
bool generateBaseClass = generatedClass.BaseTypes.Count == 0;
48
bool integrateHelpers = !generateBaseClass && generatedClass.BaseTypes [0].BaseType == "object";
49
if (!generateBaseClass && !integrateHelpers)
52
if (generateBaseClass) {
53
var baseName = generatedClass.Name + "Base";
54
generatedClass.BaseTypes.Add (new CodeTypeReference (baseName));
56
var baseClass = new CodeTypeDeclaration (baseName) {
57
TypeAttributes = generatedClass.TypeAttributes | System.Reflection.TypeAttributes.Abstract,
59
AddComments (baseClass, false,
60
"NOTE: this is the default generated helper class. You may choose to extract it to a separate file ",
61
"in order to customize it or share it between multiple templates, and specify the template's base ",
62
"class via the @inherits directive."
64
generatedNamespace.Types.Add (baseClass);
66
baseClass.Members.Add (new CodeSnippetTypeMember (baseMembersString));
67
baseClass.Members.Add (new CodeSnippetTypeMember (baseExecuteMethodString));
69
generatedClass.BaseTypes [0].BaseType = "System.Object";
70
executeMethod.Attributes = (executeMethod.Attributes & (~MemberAttributes.AccessMask | ~MemberAttributes.Override))
71
| MemberAttributes.Private | MemberAttributes.Final;
72
generatedClass.Members.Add (new CodeSnippetTypeMember (baseMembersString));
77
public System.Web.WebPages.HelperResult foo (int i)
79
return new System.Web.WebPages.HelperResult(__razor_helper_writer => {
80
WriteLiteralTo(__razor_helper_writer, "<p>");
81
WriteTo(__razor_helper_writer, i);
82
WriteLiteralTo(__razor_helper_writer, "</p>\n");
86
public static Action<TextWriter> foo (int i)
88
return __razor_helper_writer => {
89
__razor_helper_writer.Write("<p>");
90
WriteTo(__razor_helper_writer, i);
91
__razor_helper_writer.Write("</p>\n");
95
static string[,] replacements = new string [,] {
96
{ "public System.Web.WebPages.HelperResult " , "public static Action<System.IO.TextWriter> " },
97
{ "return new System.Web.WebPages.HelperResult(__razor_helper_writer" , "return __razor_helper_writer" },
98
{ "WriteLiteralTo(__razor_helper_writer," , "__razor_helper_writer.Write(" },
101
public static void SimplifyHelpers (RazorHost host, CodeCompileUnit codeCompileUnit, CodeNamespace generatedNamespace, CodeTypeDeclaration generatedClass, CodeMemberMethod executeMethod)
103
foreach (var method in generatedClass.Members.OfType<CodeSnippetTypeMember> ()) {
104
using (var writer = new System.IO.StringWriter (new System.Text.StringBuilder (method.Text.Length))) {
105
bool foundStart = false;
106
using (var reader = new System.IO.StringReader (method.Text)) {
107
bool lineHidden = false;
109
while ((line = reader.ReadLine ()) != null) {
111
if (line.StartsWith ("public System.Web.WebPages.HelperResult")) {
113
} else if (!string.IsNullOrWhiteSpace (line) && !line.StartsWith ("#line")) {
117
if (line.StartsWith ("#line")) {
118
lineHidden = line == "#line hidden";
120
if (lineHidden && line == "});") {
121
writer.WriteLine ("};");
124
var len = replacements.GetLength (0);
125
for (int i = 0; i < len; i++) {
126
var bad = replacements[i,0];
127
if (line.StartsWith (bad)) {
128
line = replacements[i,1] + line.Substring (bad.Length);
131
writer.WriteLine (line);
135
method.Text = writer.ToString ();
141
const string baseExecuteMethodString =
142
@" // This method is REQUIRED. The generated Razor subclass will override it with the generated code.
144
///<summary>Executes the template, writing output to the Write and WriteLiteral methods.</summary>.
145
///<remarks>Not intended to be called directly. Call the Generate method instead.</remarks>
146
public abstract void Execute ();
149
const string baseMembersString =
150
@" // This field is OPTIONAL, but used by the default implementation of Generate, Write and WriteLiteral
152
System.IO.TextWriter __razor_writer;
154
// This method is OPTIONAL
156
///<summary>Executes the template and returns the output as a string.</summary>
157
public string GenerateString ()
159
using (var sw = new System.IO.StringWriter ()) {
161
return sw.ToString();
165
// This method is OPTIONAL, you may choose to implement Write and WriteLiteral without use of __razor_writer
166
// and provide another means of invoking Execute.
168
///<summary>Executes the template, writing to the provided text writer.</summary>
169
public void Generate (System.IO.TextWriter writer)
171
__razor_writer = writer;
173
__razor_writer = null;
176
// This method is REQUIRED, but you may choose to implement it differently
178
///<summary>Writes literal values to the template output without HTML escaping them.</summary>
179
protected void WriteLiteral (string value)
181
__razor_writer.Write (value);
184
// This method is REQUIRED, but you may choose to implement it differently
186
///<summary>Writes values to the template output, HTML escaping them if necessary.</summary>
187
protected void Write (object value)
189
WriteTo (__razor_writer, value);
192
// This method is REQUIRED if the template uses any Razor helpers, but you may choose to implement it differently
194
///<summary>Invokes the action to write directly to the template output.</summary>
195
///<remarks>This is used for Razor helpers, which already perform any necessary HTML escaping.</remarks>
196
protected void Write (Action<System.IO.TextWriter> write)
198
write (__razor_writer);
201
// This method is REQUIRED if the template has any Razor helpers, but you may choose to implement it differently
203
///<remarks>Used by Razor helpers to HTML escape values.</remarks>
204
protected static void WriteTo (System.IO.TextWriter writer, object value)
207
writer.Write (System.Web.HttpUtility.HtmlEncode (value.ToString ()));
208
// NOTE: better version for .NET 4+, handles pre-escape HTML (IHtmlString)
209
// writer.Write (System.Web.HttpUtility.HtmlEncode (value));
b'\\ No newline at end of file'