/// <inheritdoc/> protected override async Task WriteAsync(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); var sectionContent = (await renderer.RenderAsync(obj, context.Push(innerType, param))) as List <Expression>; if (sectionContent.Count > 0) { expression = WriteIEnumerable(value, param, innerType, sectionContent); } } else if (typeof(IEnumerator).IsAssignableFrom(value.Type)) { var innerType = value.Type.GetElementTypeOfIEnumerable() ?? typeof(object); var param = Expression.Parameter(innerType); var sectionContent = (await renderer.RenderAsync(obj, context.Push(innerType, param))) as List <Expression>; if (sectionContent.Count > 0) { expression = WriteIEnumerator(value, param, innerType, sectionContent); } } else if (typeof(IDictionary).IsAssignableFrom(value.Type) || value != null) { var param = Expression.Parameter(value.Type); var assignment = Expression.Assign(param, value); var sectionContent = await renderer.RenderAsync(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); } }
/// <inheritdoc/> protected override async Task WriteAsync(CompilationRenderer renderer, PartialToken obj, CompilerContext context) { var partialName = obj.Content; string template = null; if (context.PartialLoader != null) { template = await context.PartialLoader.LoadAsync(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 = await renderer.RenderAsync(context.CompilerSettings.Parser.Parse(template, lineIndent: obj.LineIndent), context) as List <Expression>; renderer.AddExpressionToScope(AddLambdaDefinition(definition, partialContent, actionType, sourceDatas)); } }
/// <inheritdoc/> protected override async Task WriteAsync(CompilationRenderer renderer, InvertedSectionToken obj, CompilerContext context) { Expression expression = null; if (await renderer.RenderAsync(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); } }