static void GenerateTransformMethod(CodeTypeDeclaration templateType, TemplateSettings settings, ParsedTemplate pt, string templateFile, bool isOverride) { string baseDirectory = Path.GetDirectoryName(templateFile); var transformMeth = Declare.Method("TransformText").Returns <string> ().AsVirtual(); if (isOverride) { transformMeth.AsOverride(); } transformMeth.WithStatements(Expression.This.SetProperty("GenerationEnvironment", Expression.Null)); CodeExpression toStringHelper = settings.IsPreprocessed ? Expression.This.Property("ToStringHelper") : TypeReference.Global(typeof(ToStringHelper)).AsExpression(); //method references that will need to be used multiple times var writeMeth = Expression.This.Method("Write"); var toStringMeth = toStringHelper.Method("ToStringWithCulture"); bool helperMode = false; //build the code from the segments foreach (TemplateSegment seg in pt.Content) { CodeStatement st = null; CodeLinePragma location = null; if (!settings.NoLinePragmas) { var f = seg.StartLocation.FileName ?? templateFile; if (!string.IsNullOrEmpty(f)) { // FIXME: we need to know where the output file will be to make this work properly if (settings.RelativeLinePragmas) { f = FileUtil.AbsoluteToRelativePath(baseDirectory, f); } else { f = Path.GetFullPath(f); } } location = new CodeLinePragma(f, seg.StartLocation.Line); } switch (seg.Type) { case SegmentType.Block: if (helperMode) { //TODO: are blocks permitted after helpers? pt.LogError("Blocks are not permitted after helpers", seg.TagStartLocation); } st = Statement.Snippet(seg.Text); break; case SegmentType.Expression: st = writeMeth.Invoke(toStringMeth.Invoke(Expression.Snippet(seg.Text))).AsStatement(); break; case SegmentType.Content: st = writeMeth.Invoke(Expression.Primitive(seg.Text)).AsStatement(); break; case SegmentType.Helper: if (!string.IsNullOrEmpty(seg.Text)) { templateType.AddSnippetMember(seg.Text, location); } helperMode = true; break; default: throw new InvalidOperationException(); } if (st != null) { if (helperMode) { //convert the statement into a snippet member and attach it to the top level type //TODO: is there a way to do this for languages that use indentation for blocks, e.g. python? using (var writer = new StringWriter()) { settings.Provider.GenerateCodeFromStatement(st, writer, null); var text = writer.ToString(); if (!string.IsNullOrEmpty(text)) { templateType.AddSnippetMember(text, location); } } } else { st.LinePragma = location; transformMeth.Statements.Add(st); continue; } } } transformMeth.WithStatements(Statement.Return(Expression.This.Property("GenerationEnvironment").InvokeMethod("ToString"))); templateType.AddMember(transformMeth); }