aspnetcore/src/Microsoft.AspNetCore.Razor..../CodeGeneration/DefaultCodeRenderingContext.cs

193 lines
5.9 KiB
C#

// 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.Collections.Generic;
using Microsoft.AspNetCore.Razor.Language.Intermediate;
namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration
{
internal class DefaultCodeRenderingContext : CodeRenderingContext
{
private readonly Stack<IntermediateNode> _ancestors;
private readonly RazorCodeDocument _codeDocument;
private readonly DocumentIntermediateNode _documentNode;
private readonly List<ScopeInternal> _scopes;
public DefaultCodeRenderingContext(
CodeWriter codeWriter,
IntermediateNodeWriter nodeWriter,
RazorCodeDocument codeDocument,
DocumentIntermediateNode documentNode,
RazorCodeGenerationOptions options)
{
if (codeWriter == null)
{
throw new ArgumentNullException(nameof(codeWriter));
}
if (nodeWriter == null)
{
throw new ArgumentNullException(nameof(nodeWriter));
}
if (codeDocument == null)
{
throw new ArgumentNullException(nameof(codeDocument));
}
if (documentNode == null)
{
throw new ArgumentNullException(nameof(documentNode));
}
if (options == null)
{
throw new ArgumentNullException(nameof(options));
}
CodeWriter = codeWriter;
_codeDocument = codeDocument;
_documentNode = documentNode;
Options = options;
_ancestors = new Stack<IntermediateNode>();
Diagnostics = new RazorDiagnosticCollection();
Items = new ItemCollection();
LineMappings = new List<LineMapping>();
var diagnostics = _documentNode.GetAllDiagnostics();
for (var i = 0; i < diagnostics.Count; i++)
{
Diagnostics.Add(diagnostics[i]);
}
var newLineString = codeDocument.Items[NewLineString];
if (newLineString != null)
{
// Set new line character to a specific string regardless of platform, for testing purposes.
codeWriter.NewLine = (string)newLineString;
}
Items[NewLineString] = codeDocument.Items[NewLineString];
Items[SuppressUniqueIds] = codeDocument.Items[SuppressUniqueIds];
_scopes = new List<ScopeInternal>();
_scopes.Add(new ScopeInternal(nodeWriter));
}
// This will be initialized by the document writer when the context is 'live'.
public IntermediateNodeVisitor Visitor { get; set; }
public override IEnumerable<IntermediateNode> Ancestors => _ancestors;
internal Stack<IntermediateNode> AncestorsInternal => _ancestors;
public override CodeWriter CodeWriter { get; }
public override RazorDiagnosticCollection Diagnostics { get; }
public override string DocumentKind { get; }
public override ItemCollection Items { get; }
public List<LineMapping> LineMappings { get; }
public override IntermediateNodeWriter NodeWriter => Current.Writer;
public override RazorCodeGenerationOptions Options { get; }
public override IntermediateNode Parent => _ancestors.Count == 0 ? null : _ancestors.Peek();
public override RazorSourceDocument SourceDocument => _codeDocument.Source;
private ScopeInternal Current => _scopes[_scopes.Count - 1];
public override void AddLineMappingFor(IntermediateNode node)
{
if (node == null)
{
throw new ArgumentNullException(nameof(node));
}
if (node.Source == null)
{
return;
}
if (SourceDocument.FilePath != null &&
!string.Equals(SourceDocument.FilePath, node.Source.Value.FilePath, StringComparison.OrdinalIgnoreCase))
{
// We don't want to generate line mappings for imports.
return;
}
var source = node.Source.Value;
var generatedLocation = new SourceSpan(CodeWriter.Location, source.Length);
var lineMapping = new LineMapping(source, generatedLocation);
LineMappings.Add(lineMapping);
}
public override Scope CreateScope()
{
CreateScope(Current.Writer);
return new Scope(this);
}
public override Scope CreateScope(IntermediateNodeWriter writer)
{
if (writer == null)
{
throw new ArgumentNullException(nameof(writer));
}
_scopes.Add(new ScopeInternal(writer));
return new Scope(this);
}
public override void EndScope()
{
_scopes.RemoveAt(_scopes.Count - 1);
}
public override void RenderChildren(IntermediateNode node)
{
if (node == null)
{
throw new ArgumentNullException(nameof(node));
}
_ancestors.Push(node);
for (var i = 0; i < node.Children.Count; i++)
{
Visitor.Visit(node.Children[i]);
}
_ancestors.Pop();
}
public override void RenderNode(IntermediateNode node)
{
if (node == null)
{
throw new ArgumentNullException(nameof(node));
}
Visitor.Visit(node);
}
private struct ScopeInternal
{
public ScopeInternal(IntermediateNodeWriter writer)
{
Writer = writer;
}
public IntermediateNodeWriter Writer { get; }
}
}
}