Ejemplo n.º 1
0
        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);
        }