/// <inheritdoc/>
        protected override void Write(CompilationRenderer renderer, SectionToken obj, CompilerContext context)
        {
            var value = context.Lookup(obj.SectionName);

            if (value == null)
            {
                return;
            }

            Expression expression = null;

            if (typeof(IEnumerable).IsAssignableFrom(value.Type) && !EnumerableBlacklist.Any(x => x.IsAssignableFrom(value.Type)))
            {
                var innerType = value.Type.GetElementTypeOfIEnumerable();
                var param     = Expression.Parameter(innerType);
                expression = WriteIEnumerable(value, param, innerType, renderer.Render(obj, context.Push(innerType, param)) as List <Expression>);
            }
            else if (typeof(IEnumerator).IsAssignableFrom(value.Type))
            {
                var innerType = value.Type.GetElementTypeOfIEnumerable() ?? typeof(object);
                var param     = Expression.Parameter(innerType);
                expression = WriteIEnumerator(value, param, innerType, renderer.Render(obj, context.Push(innerType, param)) as List <Expression>);
            }
            else if (typeof(IDictionary).IsAssignableFrom(value.Type) || value != null)
            {
                var param      = Expression.Parameter(value.Type);
                var assignment = Expression.Assign(param, value);

                var sectionContent = renderer.Render(obj, context.Push(value.Type, param)) as List <Expression>;
                if (sectionContent.Count > 0)
                {
                    expression = Expression.Block(new[] { param }, new[] { assignment }.Concat(sectionContent));
                }
            }

            if (expression != null)
            {
                var truthy = context.GetTruthyExpression(value);

                var ex = truthy != null
                    ? Expression.IfThen(truthy, expression)
                    : expression;

                renderer.AddExpressionToScope(ex);
            }
        }
Example #2
0
        /// <inheritdoc/>
        protected override void Write(CompilationRenderer renderer, PartialToken obj, CompilerContext context)
        {
            var    partialName = obj.Content;
            string template    = null;

            if (context.PartialLoader != null)
            {
                template = context.PartialLoader.Load(partialName.ToString());
            }

            if (template != null)
            {
                var sourceDatas = context.GetNestedSourceData().ToArray();
                var key         = PartialLambdaExpressionDefinition.GetKey(template, context.SourceData.Type);

                // Recursive calls use the existing variable to call the partial lambda.
                if (renderer.PartialExpressionCache.TryGetValue(key, out var partialVariable))
                {
                    renderer.AddExpressionToScope(Expression.Invoke(partialVariable.Variable, context.SourceData));
                    return;
                }

                var sourceData = sourceDatas.Select(s => s.Type).ToArray();

                if (sourceData.Length > 16)
                {
                    throw new StubbleException("Cannot call a partial with more than 16 parameters.\nThis is likely due to a large amount of section scopes");
                }

                var actionType = Expression.GetActionType(sourceData);

                var definition = new PartialLambdaExpressionDefinition
                {
                    Variable = Expression.Parameter(actionType)
                };

                renderer.PartialExpressionCache.Add(key, definition);

                var partialContent = renderer.Render(context.CompilerSettings.Parser.Parse(template, lineIndent: obj.LineIndent), context) as List <Expression>;

                renderer.AddExpressionToScope(AddLambdaDefinition(definition, partialContent, actionType, sourceDatas));
            }
        }
Example #3
0
        /// <inheritdoc/>
        protected override void Write(CompilationRenderer renderer, InvertedSectionToken obj, CompilerContext context)
        {
            Expression expression = null;

            if (renderer.Render(obj, context) is List <Expression> sectionContent && sectionContent.Count > 0)
            {
                expression = Expression.Block(sectionContent);
            }

            var value = context.Lookup(obj.SectionName);

            if (value != null && expression != null)
            {
                expression = Expression.IfThen(Expression.Not(context.GetTruthyExpression(value)), expression);
            }

            if (expression != null)
            {
                renderer.AddExpressionToScope(expression);
            }
        }