From 242ea0ee3fe3f14e8dd5777e76763290964c45ca Mon Sep 17 00:00:00 2001 From: Ryan Nowak Date: Fri, 13 Jan 2017 10:43:59 -0800 Subject: [PATCH] Add parsing of includes and imports Also adds the source document to the RazorSyntaxTree and does some cleanup related to this. This lets us verify which tree goes to which document and that seems important. Added basic tests to verify that parsing happens, though it's not being used for anything right now. --- .../DefaultDirectiveSyntaxTreePass.cs | 2 +- .../DefaultRazorParsingPhase.cs | 14 +++++ .../DefaultRazorSyntaxTree.cs | 9 ++- .../HtmlNodeOptimizationPass.cs | 2 +- .../Legacy/RazorParser.cs | 25 ++++---- .../RazorCodeDocumentExtensions.cs | 61 +++++++++++++++++++ .../RazorSyntaxTree.cs | 15 +++-- .../TagHelperBinderSyntaxTreePass.cs | 4 +- .../DefaultDirectiveSyntaxTreePassTest.cs | 6 +- .../DefaultRazorParsingPhaseTest.cs | 40 ++++++++++++ .../Legacy/ParserTestBase.cs | 10 ++- .../Legacy/RazorParserTest.cs | 8 +-- .../RazorCodeDocumentExtensionsTest.cs | 32 ++++++++++ .../TagHelperBinderSyntaxTreePassTest.cs | 8 ++- 14 files changed, 203 insertions(+), 33 deletions(-) diff --git a/src/Microsoft.AspNetCore.Razor.Evolution/DefaultDirectiveSyntaxTreePass.cs b/src/Microsoft.AspNetCore.Razor.Evolution/DefaultDirectiveSyntaxTreePass.cs index dddd26bfac..ed33aa4ae4 100644 --- a/src/Microsoft.AspNetCore.Razor.Evolution/DefaultDirectiveSyntaxTreePass.cs +++ b/src/Microsoft.AspNetCore.Razor.Evolution/DefaultDirectiveSyntaxTreePass.cs @@ -21,7 +21,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution if (errorSink.Errors.Count > 0) { var combinedErrors = syntaxTree.Diagnostics.Concat(errorSink.Errors).ToList(); - syntaxTree = RazorSyntaxTree.Create(syntaxTree.Root, combinedErrors, syntaxTree.Options); + syntaxTree = RazorSyntaxTree.Create(syntaxTree.Root, syntaxTree.Source, combinedErrors, syntaxTree.Options); } return syntaxTree; diff --git a/src/Microsoft.AspNetCore.Razor.Evolution/DefaultRazorParsingPhase.cs b/src/Microsoft.AspNetCore.Razor.Evolution/DefaultRazorParsingPhase.cs index bd1cba4fa5..2f005b0551 100644 --- a/src/Microsoft.AspNetCore.Razor.Evolution/DefaultRazorParsingPhase.cs +++ b/src/Microsoft.AspNetCore.Razor.Evolution/DefaultRazorParsingPhase.cs @@ -24,6 +24,20 @@ namespace Microsoft.AspNetCore.Razor.Evolution var syntaxTree = RazorSyntaxTree.Parse(codeDocument.Source, options); codeDocument.SetSyntaxTree(syntaxTree); + + var importSyntaxTrees = new RazorSyntaxTree[codeDocument.Imports.Count]; + for (var i = 0; i < codeDocument.Imports.Count; i++) + { + importSyntaxTrees[i] = RazorSyntaxTree.Parse(codeDocument.Imports[i], options); + } + codeDocument.SetImportSyntaxTrees(importSyntaxTrees); + + var includeSyntaxTrees = new RazorSyntaxTree[codeDocument.Includes.Count]; + for (var i = 0; i < codeDocument.Includes.Count; i++) + { + includeSyntaxTrees[i] = RazorSyntaxTree.Parse(codeDocument.Includes[i], options); + } + codeDocument.SetIncludeSyntaxTrees(includeSyntaxTrees); } } } diff --git a/src/Microsoft.AspNetCore.Razor.Evolution/DefaultRazorSyntaxTree.cs b/src/Microsoft.AspNetCore.Razor.Evolution/DefaultRazorSyntaxTree.cs index 81f7e264b9..51d74f66ca 100644 --- a/src/Microsoft.AspNetCore.Razor.Evolution/DefaultRazorSyntaxTree.cs +++ b/src/Microsoft.AspNetCore.Razor.Evolution/DefaultRazorSyntaxTree.cs @@ -8,9 +8,14 @@ namespace Microsoft.AspNetCore.Razor.Evolution { internal class DefaultRazorSyntaxTree : RazorSyntaxTree { - public DefaultRazorSyntaxTree(Block root, IReadOnlyList diagnostics, RazorParserOptions options) + public DefaultRazorSyntaxTree( + Block root, + RazorSourceDocument source, + IReadOnlyList diagnostics, + RazorParserOptions options) { Root = root; + Source = source; Diagnostics = diagnostics; Options = options; } @@ -20,5 +25,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution public override RazorParserOptions Options { get; } internal override Block Root { get; } + + public override RazorSourceDocument Source { get; } } } diff --git a/src/Microsoft.AspNetCore.Razor.Evolution/HtmlNodeOptimizationPass.cs b/src/Microsoft.AspNetCore.Razor.Evolution/HtmlNodeOptimizationPass.cs index 86169d3d67..72f41fe00a 100644 --- a/src/Microsoft.AspNetCore.Razor.Evolution/HtmlNodeOptimizationPass.cs +++ b/src/Microsoft.AspNetCore.Razor.Evolution/HtmlNodeOptimizationPass.cs @@ -19,7 +19,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution var whitespaceRewriter = new WhiteSpaceRewriter(); rewritten = whitespaceRewriter.Rewrite(rewritten); - var rewrittenSyntaxTree = RazorSyntaxTree.Create(rewritten, syntaxTree.Diagnostics, syntaxTree.Options); + var rewrittenSyntaxTree = RazorSyntaxTree.Create(rewritten, syntaxTree.Source, syntaxTree.Diagnostics, syntaxTree.Options); return rewrittenSyntaxTree; } } diff --git a/src/Microsoft.AspNetCore.Razor.Evolution/Legacy/RazorParser.cs b/src/Microsoft.AspNetCore.Razor.Evolution/Legacy/RazorParser.cs index ab0cda7fe0..2da299bf5e 100644 --- a/src/Microsoft.AspNetCore.Razor.Evolution/Legacy/RazorParser.cs +++ b/src/Microsoft.AspNetCore.Razor.Evolution/Legacy/RazorParser.cs @@ -2,7 +2,6 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; -using System.IO; namespace Microsoft.AspNetCore.Razor.Evolution.Legacy { @@ -25,17 +24,19 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy public RazorParserOptions Options { get; } - public virtual RazorSyntaxTree Parse(TextReader input) => Parse(input.ReadToEnd()); - - public virtual RazorSyntaxTree Parse(string input) => Parse(((ITextDocument)new SeekableTextReader(input))); - - public virtual RazorSyntaxTree Parse(char[] input) => Parse(((ITextDocument)new SeekableTextReader(input))); - - public virtual RazorSyntaxTree Parse(ITextDocument input) => ParseCore(input); - - private RazorSyntaxTree ParseCore(ITextDocument input) + public virtual RazorSyntaxTree Parse(RazorSourceDocument source) { - var context = new ParserContext(input, Options.DesignTimeMode); + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + var chars = new char[source.Length]; + source.CopyTo(0, chars, 0, source.Length); + + var reader = new SeekableTextReader(chars); + + var context = new ParserContext(reader, Options.DesignTimeMode); var codeParser = new CSharpCodeParser(Options.Directives, context); var markupParser = new HtmlMarkupParser(context); @@ -47,7 +48,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy var root = context.Builder.Build(); var diagnostics = context.ErrorSink.Errors; - return RazorSyntaxTree.Create(root, diagnostics, Options); + return RazorSyntaxTree.Create(root, source, diagnostics, Options); } } } diff --git a/src/Microsoft.AspNetCore.Razor.Evolution/RazorCodeDocumentExtensions.cs b/src/Microsoft.AspNetCore.Razor.Evolution/RazorCodeDocumentExtensions.cs index 9fde6ccc3a..fe91b166c3 100644 --- a/src/Microsoft.AspNetCore.Razor.Evolution/RazorCodeDocumentExtensions.cs +++ b/src/Microsoft.AspNetCore.Razor.Evolution/RazorCodeDocumentExtensions.cs @@ -3,6 +3,7 @@ using System; using Microsoft.AspNetCore.Razor.Evolution.Intermediate; +using System.Collections.Generic; namespace Microsoft.AspNetCore.Razor.Evolution { @@ -28,6 +29,46 @@ namespace Microsoft.AspNetCore.Razor.Evolution document.Items[typeof(RazorSyntaxTree)] = syntaxTree; } + public static IReadOnlyList GetImportSyntaxTrees(this RazorCodeDocument document) + { + if (document == null) + { + throw new ArgumentNullException(nameof(document)); + } + + return (document.Items[typeof(ImportSyntaxTreesHolder)] as ImportSyntaxTreesHolder)?.SyntaxTrees; + } + + public static void SetImportSyntaxTrees(this RazorCodeDocument document, IReadOnlyList syntaxTrees) + { + if (document == null) + { + throw new ArgumentNullException(nameof(document)); + } + + document.Items[typeof(ImportSyntaxTreesHolder)] = new ImportSyntaxTreesHolder(syntaxTrees); + } + + public static IReadOnlyList GetIncludeSyntaxTrees(this RazorCodeDocument document) + { + if (document == null) + { + throw new ArgumentNullException(nameof(document)); + } + + return (document.Items[typeof(IncludeSyntaxTreesHolder)] as IncludeSyntaxTreesHolder)?.SyntaxTrees; + } + + public static void SetIncludeSyntaxTrees(this RazorCodeDocument document, IReadOnlyList syntaxTrees) + { + if (document == null) + { + throw new ArgumentNullException(nameof(document)); + } + + document.Items[typeof(IncludeSyntaxTreesHolder)] = new IncludeSyntaxTreesHolder(syntaxTrees); + } + public static DocumentIRNode GetIRDocument(this RazorCodeDocument document) { if (document == null) @@ -67,5 +108,25 @@ namespace Microsoft.AspNetCore.Razor.Evolution document.Items[typeof(RazorCSharpDocument)] = csharp; } + + private class ImportSyntaxTreesHolder + { + public ImportSyntaxTreesHolder(IReadOnlyList syntaxTrees) + { + SyntaxTrees = syntaxTrees; + } + + public IReadOnlyList SyntaxTrees { get; } + } + + private class IncludeSyntaxTreesHolder + { + public IncludeSyntaxTreesHolder(IReadOnlyList syntaxTrees) + { + SyntaxTrees = syntaxTrees; + } + + public IReadOnlyList SyntaxTrees { get; } + } } } diff --git a/src/Microsoft.AspNetCore.Razor.Evolution/RazorSyntaxTree.cs b/src/Microsoft.AspNetCore.Razor.Evolution/RazorSyntaxTree.cs index ed5432f7e6..9ec849c11e 100644 --- a/src/Microsoft.AspNetCore.Razor.Evolution/RazorSyntaxTree.cs +++ b/src/Microsoft.AspNetCore.Razor.Evolution/RazorSyntaxTree.cs @@ -11,6 +11,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution { internal static RazorSyntaxTree Create( Block root, + RazorSourceDocument source, IEnumerable diagnostics, RazorParserOptions options) { @@ -19,6 +20,11 @@ namespace Microsoft.AspNetCore.Razor.Evolution throw new ArgumentNullException(nameof(root)); } + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + if (diagnostics == null) { throw new ArgumentNullException(nameof(diagnostics)); @@ -29,7 +35,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution throw new ArgumentNullException(nameof(options)); } - return new DefaultRazorSyntaxTree(root, new List(diagnostics), options); + return new DefaultRazorSyntaxTree(root, source, new List(diagnostics), options); } public static RazorSyntaxTree Parse(RazorSourceDocument source) @@ -50,10 +56,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution } var parser = new RazorParser(options ?? RazorParserOptions.CreateDefaultOptions()); - var sourceContent = new char[source.Length]; - source.CopyTo(0, sourceContent, 0, source.Length); - - return parser.Parse(sourceContent); + return parser.Parse(source); } internal abstract IReadOnlyList Diagnostics { get; } @@ -61,5 +64,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution public abstract RazorParserOptions Options { get; } internal abstract Block Root { get; } + + public abstract RazorSourceDocument Source { get; } } } diff --git a/src/Microsoft.AspNetCore.Razor.Evolution/TagHelperBinderSyntaxTreePass.cs b/src/Microsoft.AspNetCore.Razor.Evolution/TagHelperBinderSyntaxTreePass.cs index 7451d676bd..4bce049a7f 100644 --- a/src/Microsoft.AspNetCore.Razor.Evolution/TagHelperBinderSyntaxTreePass.cs +++ b/src/Microsoft.AspNetCore.Razor.Evolution/TagHelperBinderSyntaxTreePass.cs @@ -31,7 +31,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution if (errorSink.Errors.Count > 0) { var combinedErrors = CombineErrors(syntaxTree.Diagnostics, errorSink.Errors); - var erroredTree = RazorSyntaxTree.Create(syntaxTree.Root, combinedErrors, syntaxTree.Options); + var erroredTree = RazorSyntaxTree.Create(syntaxTree.Root, syntaxTree.Source, combinedErrors, syntaxTree.Options); return erroredTree; } @@ -49,7 +49,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution diagnostics = CombineErrors(diagnostics, errorSink.Errors); } - var newSyntaxTree = RazorSyntaxTree.Create(rewrittenRoot, diagnostics, syntaxTree.Options); + var newSyntaxTree = RazorSyntaxTree.Create(rewrittenRoot, syntaxTree.Source, diagnostics, syntaxTree.Options); return newSyntaxTree; } diff --git a/test/Microsoft.AspNetCore.Razor.Evolution.Test/DefaultDirectiveSyntaxTreePassTest.cs b/test/Microsoft.AspNetCore.Razor.Evolution.Test/DefaultDirectiveSyntaxTreePassTest.cs index 0e5fb63cba..0085646fbf 100644 --- a/test/Microsoft.AspNetCore.Razor.Evolution.Test/DefaultDirectiveSyntaxTreePassTest.cs +++ b/test/Microsoft.AspNetCore.Razor.Evolution.Test/DefaultDirectiveSyntaxTreePassTest.cs @@ -106,7 +106,11 @@ namespace Microsoft.AspNetCore.Razor.Evolution var sourceDocument = TestRazorSourceDocument.Create(content); var codeDocument = RazorCodeDocument.Create(sourceDocument); var originalTree = RazorSyntaxTree.Parse(sourceDocument); - var erroredOriginalTree = RazorSyntaxTree.Create(originalTree.Root, new[] { expectedErrors[0] }, originalTree.Options); + var erroredOriginalTree = RazorSyntaxTree.Create( + originalTree.Root, + originalTree.Source, + new[] { expectedErrors[0] }, + originalTree.Options); // Act var outputTree = pass.Execute(codeDocument, erroredOriginalTree); diff --git a/test/Microsoft.AspNetCore.Razor.Evolution.Test/DefaultRazorParsingPhaseTest.cs b/test/Microsoft.AspNetCore.Razor.Evolution.Test/DefaultRazorParsingPhaseTest.cs index 4eef9e3e1c..6b2a15e28b 100644 --- a/test/Microsoft.AspNetCore.Razor.Evolution.Test/DefaultRazorParsingPhaseTest.cs +++ b/test/Microsoft.AspNetCore.Razor.Evolution.Test/DefaultRazorParsingPhaseTest.cs @@ -46,6 +46,46 @@ namespace Microsoft.AspNetCore.Razor.Evolution Assert.Equal("test_directive", directive.Name); } + [Fact] + public void Execute_ParsesIncludesAndImports() + { + // Arrange + var phase = new DefaultRazorParsingPhase(); + var engine = RazorEngine.CreateEmpty((b) => + { + b.Phases.Add(phase); + b.Features.Add(new MyConfigureParserOptions()); + }); + + var imports = new[] + { + TestRazorSourceDocument.Create(), + TestRazorSourceDocument.Create(), + }; + + var includes = new[] + { + TestRazorSourceDocument.Create(), + TestRazorSourceDocument.Create(), + }; + + var codeDocument = TestRazorCodeDocument.Create(TestRazorSourceDocument.Create(), imports, includes); + + // Act + phase.Execute(codeDocument); + + // Assert + Assert.Collection( + codeDocument.GetImportSyntaxTrees(), + t => { Assert.Same(t.Source, imports[0]); Assert.Equal("test_directive", Assert.Single(t.Options.Directives).Name); }, + t => { Assert.Same(t.Source, imports[1]); Assert.Equal("test_directive", Assert.Single(t.Options.Directives).Name); }); + + Assert.Collection( + codeDocument.GetIncludeSyntaxTrees(), + t => { Assert.Same(t.Source, includes[0]); Assert.Equal("test_directive", Assert.Single(t.Options.Directives).Name); }, + t => { Assert.Same(t.Source, includes[1]); Assert.Equal("test_directive", Assert.Single(t.Options.Directives).Name); }); + } + private class MyConfigureParserOptions : IRazorConfigureParserFeature { public RazorEngine Engine { get; set; } diff --git a/test/Microsoft.AspNetCore.Razor.Evolution.Test/Legacy/ParserTestBase.cs b/test/Microsoft.AspNetCore.Razor.Evolution.Test/Legacy/ParserTestBase.cs index 84712fe8f5..fec20cc3d6 100644 --- a/test/Microsoft.AspNetCore.Razor.Evolution.Test/Legacy/ParserTestBase.cs +++ b/test/Microsoft.AspNetCore.Razor.Evolution.Test/Legacy/ParserTestBase.cs @@ -41,7 +41,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy var parser = new RazorParser(options); - var tree = parser.Parse((ITextDocument)reader); + var tree = parser.Parse(TestRazorSourceDocument.Create(document)); var defaultDirectivePass = new DefaultDirectiveSyntaxTreePass(); tree = defaultDirectivePass.Execute(codeDocument: null, syntaxTree: tree); @@ -51,6 +51,8 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy internal virtual RazorSyntaxTree ParseHtmlBlock(string document, bool designTime = false) { + var source = TestRazorSourceDocument.Create(document); + using (var reader = new SeekableTextReader(document)) { var context = new ParserContext(reader, designTime); @@ -68,7 +70,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy var options = RazorParserOptions.CreateDefaultOptions(); options.DesignTimeMode = designTime; - return RazorSyntaxTree.Create(root, diagnostics, options); + return RazorSyntaxTree.Create(root, source, diagnostics, options); } } @@ -82,6 +84,8 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy IEnumerable descriptors, bool designTime) { + var source = TestRazorSourceDocument.Create(document); + using (var reader = new SeekableTextReader(document)) { var context = new ParserContext(reader, designTime); @@ -106,7 +110,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy options.Directives.Add(directive); } - return RazorSyntaxTree.Create(root, diagnostics, options); + return RazorSyntaxTree.Create(root, source, diagnostics, options); } } diff --git a/test/Microsoft.AspNetCore.Razor.Evolution.Test/Legacy/RazorParserTest.cs b/test/Microsoft.AspNetCore.Razor.Evolution.Test/Legacy/RazorParserTest.cs index 3dbfed0a12..4bfc1333fc 100644 --- a/test/Microsoft.AspNetCore.Razor.Evolution.Test/Legacy/RazorParserTest.cs +++ b/test/Microsoft.AspNetCore.Razor.Evolution.Test/Legacy/RazorParserTest.cs @@ -13,9 +13,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy { var parser = new RazorParser(); var sourceDocument = TestRazorSourceDocument.CreateResource("TestFiles/Source/BasicMarkup.cshtml"); - var sourceContent = new char[sourceDocument.Length]; - sourceDocument.CopyTo(0, sourceContent, 0, sourceDocument.Length); - var output = parser.Parse(sourceContent); + var output = parser.Parse(sourceDocument); Assert.NotNull(output); } @@ -29,7 +27,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy var parser = new RazorParser(); // Act/Assert - ParserTestBase.EvaluateResults(parser.Parse(new StringReader("foo @bar baz")), + ParserTestBase.EvaluateResults(parser.Parse(TestRazorSourceDocument.Create("foo @bar baz")), new MarkupBlock( factory.Markup("foo "), new ExpressionBlock( @@ -49,7 +47,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy var parser = new RazorParser(); // Act - var results = parser.Parse(new StringReader("foo @bar baz")); + var results = parser.Parse(TestRazorSourceDocument.Create("foo @bar baz")); // Assert ParserTestBase.EvaluateResults(results, diff --git a/test/Microsoft.AspNetCore.Razor.Evolution.Test/RazorCodeDocumentExtensionsTest.cs b/test/Microsoft.AspNetCore.Razor.Evolution.Test/RazorCodeDocumentExtensionsTest.cs index b37ecc9a47..0b87e9c84e 100644 --- a/test/Microsoft.AspNetCore.Razor.Evolution.Test/RazorCodeDocumentExtensionsTest.cs +++ b/test/Microsoft.AspNetCore.Razor.Evolution.Test/RazorCodeDocumentExtensionsTest.cs @@ -39,6 +39,38 @@ namespace Microsoft.AspNetCore.Razor.Evolution Assert.Same(expected, codeDocument.Items[typeof(RazorSyntaxTree)]); } + [Fact] + public void GetAndSetImportSyntaxTrees_ReturnsSyntaxTrees() + { + // Arrange + var codeDocument = TestRazorCodeDocument.CreateEmpty(); + + var expected = new[] { RazorSyntaxTree.Parse(codeDocument.Source), }; + codeDocument.SetImportSyntaxTrees(expected); + + // Act + var actual = codeDocument.GetImportSyntaxTrees(); + + // Assert + Assert.Same(expected, actual); + } + + [Fact] + public void GetAndSetIncludeSyntaxTrees_ReturnsSyntaxTrees() + { + // Arrange + var codeDocument = TestRazorCodeDocument.CreateEmpty(); + + var expected = new[] { RazorSyntaxTree.Parse(codeDocument.Source), }; + codeDocument.SetIncludeSyntaxTrees(expected); + + // Act + var actual = codeDocument.GetIncludeSyntaxTrees(); + + // Assert + Assert.Same(expected, actual); + } + [Fact] public void GetIRDocument_ReturnsIRDocument() { diff --git a/test/Microsoft.AspNetCore.Razor.Evolution.Test/TagHelperBinderSyntaxTreePassTest.cs b/test/Microsoft.AspNetCore.Razor.Evolution.Test/TagHelperBinderSyntaxTreePassTest.cs index 73dcd91246..52bb9ed4f6 100644 --- a/test/Microsoft.AspNetCore.Razor.Evolution.Test/TagHelperBinderSyntaxTreePassTest.cs +++ b/test/Microsoft.AspNetCore.Razor.Evolution.Test/TagHelperBinderSyntaxTreePassTest.cs @@ -145,7 +145,11 @@ namespace Microsoft.AspNetCore.Razor.Evolution var codeDocument = RazorCodeDocument.Create(sourceDocument); var originalTree = RazorSyntaxTree.Parse(sourceDocument); var initialError = new RazorError("Initial test error", SourceLocation.Zero, length: 1); - var erroredOriginalTree = RazorSyntaxTree.Create(originalTree.Root, new[] { initialError }, originalTree.Options); + var erroredOriginalTree = RazorSyntaxTree.Create( + originalTree.Root, + originalTree.Source, + new[] { initialError }, + originalTree.Options); // Act var outputTree = pass.Execute(codeDocument, erroredOriginalTree); @@ -194,7 +198,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution LegacyResources.FormatTagHelpersParseTreeRewriter_FoundMalformedTagHelper("form"), new SourceLocation(Environment.NewLine.Length * 2 + 30, 2, 1), length: 4); - var erroredOriginalTree = RazorSyntaxTree.Create(originalTree.Root, new[] { initialError }, originalTree.Options); + var erroredOriginalTree = RazorSyntaxTree.Create(originalTree.Root, originalTree.Source, new[] { initialError }, originalTree.Options); // Act var outputTree = pass.Execute(codeDocument, erroredOriginalTree);