// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; using System.Linq; using System.Text; using Microsoft.AspNetCore.Razor.Language.Intermediate; namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration { internal class DefaultDocumentWriter : DocumentWriter { private readonly CodeTarget _codeTarget; private readonly RazorCodeGenerationOptions _options; public DefaultDocumentWriter(CodeTarget codeTarget, RazorCodeGenerationOptions options) { _codeTarget = codeTarget; _options = options; } public override RazorCSharpDocument WriteDocument(RazorCodeDocument codeDocument, DocumentIntermediateNode documentNode) { if (codeDocument == null) { throw new ArgumentNullException(nameof(codeDocument)); } if (documentNode == null) { throw new ArgumentNullException(nameof(documentNode)); } var context = new DefaultCodeRenderingContext( new CodeWriter(), _codeTarget.CreateNodeWriter(), codeDocument, documentNode, _options); context.Visitor = new Visitor(_codeTarget, context); context.Visitor.VisitDocument(documentNode); var cSharp = context.CodeWriter.GenerateCode(); return new DefaultRazorCSharpDocument( cSharp, _options, context.Diagnostics.ToArray(), context.LineMappings.ToArray()); } private class Visitor : IntermediateNodeVisitor { private readonly DefaultCodeRenderingContext _context; private readonly CodeTarget _target; public Visitor(CodeTarget target, DefaultCodeRenderingContext context) { _target = target; _context = context; } private DefaultCodeRenderingContext Context => _context; public override void VisitDocument(DocumentIntermediateNode node) { if (!Context.Options.SuppressChecksum) { // See http://msdn.microsoft.com/en-us/library/system.codedom.codechecksumpragma.checksumalgorithmid.aspx const string Sha1AlgorithmId = "{ff1816ec-aa5e-4d10-87f7-6f4963833460}"; var sourceDocument = Context.SourceDocument; var checksum = sourceDocument.GetChecksum(); var fileHashBuilder = new StringBuilder(checksum.Length * 2); foreach (var value in checksum) { fileHashBuilder.Append(value.ToString("x2")); } var bytes = fileHashBuilder.ToString(); if (!string.IsNullOrEmpty(bytes)) { Context.CodeWriter .Write("#pragma checksum \"") .Write(sourceDocument.FilePath) .Write("\" \"") .Write(Sha1AlgorithmId) .Write("\" \"") .Write(bytes) .WriteLine("\""); } } Context.CodeWriter .WriteLine("// ") .WriteLine("#pragma warning disable 1591"); VisitDefault(node); Context.CodeWriter.WriteLine("#pragma warning restore 1591"); } public override void VisitUsingDirective(UsingDirectiveIntermediateNode node) { Context.NodeWriter.WriteUsingDirective(Context, node); } public override void VisitNamespaceDeclaration(NamespaceDeclarationIntermediateNode node) { using (Context.CodeWriter.BuildNamespace(node.Content)) { Context.CodeWriter.WriteLine("#line hidden"); VisitDefault(node); } } public override void VisitClassDeclaration(ClassDeclarationIntermediateNode node) { using (Context.CodeWriter.BuildClassDeclaration(node.Modifiers, node.Name, node.BaseType, node.Interfaces)) { VisitDefault(node); } } public override void VisitMethodDeclaration(MethodDeclarationIntermediateNode node) { Context.CodeWriter.WriteLine("#pragma warning disable 1998"); for (var i = 0; i < node.Modifiers.Count; i++) { Context.CodeWriter.Write(node.Modifiers[i]); Context.CodeWriter.Write(" "); } Context.CodeWriter .Write(node.ReturnType) .Write(" ") .Write(node.Name) .WriteLine("()"); using (Context.CodeWriter.BuildScope()) { VisitDefault(node); } Context.CodeWriter.WriteLine("#pragma warning restore 1998"); } public override void VisitFieldDeclaration(FieldDeclarationIntermediateNode node) { Context.CodeWriter.WriteField(node.Modifiers, node.Type, node.Name); } public override void VisitPropertyDeclaration(PropertyDeclarationIntermediateNode node) { Context.CodeWriter.WriteAutoPropertyDeclaration(node.Modifiers, node.Type, node.Name); } public override void VisitExtension(ExtensionIntermediateNode node) { node.WriteNode(_target, Context); } public override void VisitCSharpExpression(CSharpExpressionIntermediateNode node) { Context.NodeWriter.WriteCSharpExpression(Context, node); } public override void VisitCSharpCode(CSharpCodeIntermediateNode node) { Context.NodeWriter.WriteCSharpCode(Context, node); } public override void VisitHtmlAttribute(HtmlAttributeIntermediateNode node) { Context.NodeWriter.WriteHtmlAttribute(Context, node); } public override void VisitHtmlAttributeValue(HtmlAttributeValueIntermediateNode node) { Context.NodeWriter.WriteHtmlAttributeValue(Context, node); } public override void VisitCSharpExpressionAttributeValue(CSharpExpressionAttributeValueIntermediateNode node) { Context.NodeWriter.WriteCSharpExpressionAttributeValue(Context, node); } public override void VisitCSharpCodeAttributeValue(CSharpCodeAttributeValueIntermediateNode node) { Context.NodeWriter.WriteCSharpCodeAttributeValue(Context, node); } public override void VisitHtml(HtmlContentIntermediateNode node) { Context.NodeWriter.WriteHtmlContent(Context, node); } public override void VisitTagHelper(TagHelperIntermediateNode node) { var tagHelperRenderingContext = new TagHelperRenderingContext(); using (Context.Push(tagHelperRenderingContext)) { VisitDefault(node); } } public override void VisitDefault(IntermediateNode node) { Context.RenderChildren(node); } } } }