private static IReadOnlyList <IntermediateToken> GetAttributeContent(TagHelperPropertyIntermediateNode node) { var template = node.FindDescendantNodes <TemplateIntermediateNode>().FirstOrDefault(); if (template != null) { // See comments in TemplateDiagnosticPass node.Diagnostics.Add(BlazorDiagnosticFactory.Create_TemplateInvalidLocation(template.Source)); return(new[] { new IntermediateToken() { Kind = TokenKind.CSharp, Content = string.Empty, }, }); } if (node.Children.Count == 1 && node.Children[0] is HtmlContentIntermediateNode htmlContentNode) { // This case can be hit for a 'string' attribute. We want to turn it into // an expression. var tokens = htmlContentNode.FindDescendantNodes <IntermediateToken>(); var content = "\"" + string.Join(string.Empty, tokens.Select(t => t.Content)) + "\""; return(new[] { new IntermediateToken() { Content = content, Kind = TokenKind.CSharp, } }); } else { return(node.FindDescendantNodes <IntermediateToken>()); } }
protected override void ExecuteCore(RazorCodeDocument codeDocument, DocumentIntermediateNode documentNode) { var visitor = new Visitor(); visitor.Visit(documentNode); for (var i = 0; i < visitor.Candidates.Count; i++) { var candidate = visitor.Candidates[i]; candidate.Parent.Diagnostics.Add(BlazorDiagnosticFactory.Create_TemplateInvalidLocation(candidate.Node.Source)); // Remove the offending node since we don't know how to render it. This means that the user won't get C# // completion at this location, which is fine because it's inside an HTML attribute. candidate.Remove(); } }
private static IntermediateToken GetAttributeContent(TagHelperPropertyIntermediateNode node) { var template = node.FindDescendantNodes <TemplateIntermediateNode>().FirstOrDefault(); if (template != null) { // See comments in TemplateDiagnosticPass node.Diagnostics.Add(BlazorDiagnosticFactory.Create_TemplateInvalidLocation(template.Source)); return(new IntermediateToken() { Kind = TokenKind.CSharp, Content = string.Empty, }); } if (node.Children[0] is HtmlContentIntermediateNode htmlContentNode) { // This case can be hit for a 'string' attribute. We want to turn it into // an expression. var content = "\"" + string.Join(string.Empty, htmlContentNode.Children.OfType <IntermediateToken>().Select(t => t.Content)) + "\""; return(new IntermediateToken() { Kind = TokenKind.CSharp, Content = content }); } else if (node.Children[0] is CSharpExpressionIntermediateNode cSharpNode) { // This case can be hit when the attribute has an explicit @ inside, which // 'escapes' any special sugar we provide for codegen. return(GetToken(cSharpNode)); } else { // This is the common case for 'mixed' content return(GetToken(node)); } // In error cases we won't have a single token, but we still want to generate the code. IntermediateToken GetToken(IntermediateNode parent) { return (parent.Children.Count == 1 ? (IntermediateToken)parent.Children[0] : new IntermediateToken() { Kind = TokenKind.CSharp, Content = string.Join(string.Empty, parent.Children.OfType <IntermediateToken>().Select(t => t.Content)), }); } }