From 3b53f045186b735d28955064cabd21717b0aee68 Mon Sep 17 00:00:00 2001 From: "N. Taylor Mullen" Date: Tue, 23 May 2017 10:53:13 -0700 Subject: [PATCH] Change ParserContext to take a RazorSourceDocument. - This moves ParserContext closer to operating on a RazorSourceDocument and exposes it at the parsing layer. - Was not able to replace the `ITextDocument` property on `ParserContext` due to its current wiring. Our tokenizers rely on a single reader that iterates over the document and take turns tokenizing characters from that reader. The reader that the tokenizers pull from is also highly coupled with the parsers implementations; they end up moving the readers pointer frequently. --- .../Legacy/ParserContext.cs | 10 +++- .../Legacy/RazorParser.cs | 8 +-- .../RazorSourceLineCollection.cs | 2 - .../Legacy/ParserTestBase.cs | 58 ++++++++----------- 4 files changed, 33 insertions(+), 45 deletions(-) diff --git a/src/Microsoft.AspNetCore.Razor.Language/Legacy/ParserContext.cs b/src/Microsoft.AspNetCore.Razor.Language/Legacy/ParserContext.cs index 80de5cba27..cfe4e6d04c 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/Legacy/ParserContext.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/Legacy/ParserContext.cs @@ -9,14 +9,18 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy { internal partial class ParserContext { - public ParserContext(ITextDocument source, RazorParserOptions options) + public ParserContext(RazorSourceDocument source, RazorParserOptions options) { if (source == null) { throw new ArgumentNullException(nameof(source)); } - Source = source; + SourceDocument = source; + var chars = new char[source.Length]; + source.CopyTo(0, chars, 0, source.Length); + + Source = new SeekableTextReader(chars, source.FileName); DesignTimeMode = options.DesignTime; ParseOnlyLeadingDirectives = options.ParseOnlyLeadingDirectives; Builder = new SyntaxTreeBuilder(); @@ -29,6 +33,8 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy public ITextDocument Source { get; } + public RazorSourceDocument SourceDocument { get; } + public bool DesignTimeMode { get; } public bool ParseOnlyLeadingDirectives { get; } diff --git a/src/Microsoft.AspNetCore.Razor.Language/Legacy/RazorParser.cs b/src/Microsoft.AspNetCore.Razor.Language/Legacy/RazorParser.cs index edc019caf0..2823ffd69d 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/Legacy/RazorParser.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/Legacy/RazorParser.cs @@ -32,13 +32,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy throw new ArgumentNullException(nameof(source)); } - var chars = new char[source.Length]; - source.CopyTo(0, chars, 0, source.Length); - - var reader = new SeekableTextReader(chars, source.FileName); - - var context = new ParserContext(reader, Options); - + var context = new ParserContext(source, Options); var codeParser = new CSharpCodeParser(Options.Directives, context); var markupParser = new HtmlMarkupParser(context); diff --git a/src/Microsoft.AspNetCore.Razor.Language/RazorSourceLineCollection.cs b/src/Microsoft.AspNetCore.Razor.Language/RazorSourceLineCollection.cs index bfaac27f07..211ea39ad0 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/RazorSourceLineCollection.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/RazorSourceLineCollection.cs @@ -1,8 +1,6 @@ // 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 Microsoft.AspNetCore.Razor.Language.Legacy; - namespace Microsoft.AspNetCore.Razor.Language { public abstract class RazorSourceLineCollection diff --git a/test/Microsoft.AspNetCore.Razor.Language.Test/Legacy/ParserTestBase.cs b/test/Microsoft.AspNetCore.Razor.Language.Test/Legacy/ParserTestBase.cs index 58a093b944..4b1cf56d78 100644 --- a/test/Microsoft.AspNetCore.Razor.Language.Test/Legacy/ParserTestBase.cs +++ b/test/Microsoft.AspNetCore.Razor.Language.Test/Legacy/ParserTestBase.cs @@ -34,11 +34,9 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy internal virtual RazorSyntaxTree ParseDocument(string document, bool designTime = false) { - var source = TestRazorSourceDocument.Create(document); - var reader = new SeekableTextReader(document, filePath: null); - + var source = TestRazorSourceDocument.Create(document, fileName: null); var options = RazorParserOptions.Create(Array.Empty(), designTime); - var context = new ParserContext(reader, options); + var context = new ParserContext(source, options); var codeParser = new CSharpCodeParser(context); var markupParser = new HtmlMarkupParser(context); @@ -64,26 +62,22 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy internal virtual RazorSyntaxTree ParseHtmlBlock(string document, bool designTime = false) { - var source = TestRazorSourceDocument.Create(document); + var source = TestRazorSourceDocument.Create(document, fileName: null); + var options = RazorParserOptions.Create(Array.Empty(), designTime); + var context = new ParserContext(source, options); - using (var reader = new SeekableTextReader(document, filePath: null)) + var parser = new HtmlMarkupParser(context); + parser.CodeParser = new CSharpCodeParser(context) { - var options = RazorParserOptions.Create(Array.Empty(), designTime); - var context = new ParserContext(reader, options); + HtmlParser = parser, + }; - var parser = new HtmlMarkupParser(context); - parser.CodeParser = new CSharpCodeParser(context) - { - HtmlParser = parser, - }; + parser.ParseBlock(); - parser.ParseBlock(); + var root = context.Builder.Build(); + var diagnostics = context.ErrorSink.Errors?.Select(error => RazorDiagnostic.Create(error)); - var root = context.Builder.Build(); - var diagnostics = context.ErrorSink.Errors?.Select(error => RazorDiagnostic.Create(error)); - - return RazorSyntaxTree.Create(root, source, diagnostics, options); - } + return RazorSyntaxTree.Create(root, source, diagnostics, options); } internal virtual RazorSyntaxTree ParseCodeBlock(string document, bool designTime = false) @@ -96,26 +90,22 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy IEnumerable descriptors, bool designTime) { - var source = TestRazorSourceDocument.Create(document); + var source = TestRazorSourceDocument.Create(document, fileName: null); + var options = RazorParserOptions.Create(descriptors, designTime); + var context = new ParserContext(source, options); - using (var reader = new SeekableTextReader(document, filePath: null)) + var parser = new CSharpCodeParser(descriptors, context); + parser.HtmlParser = new HtmlMarkupParser(context) { - var options = RazorParserOptions.Create(descriptors, designTime); - var context = new ParserContext(reader, options); + CodeParser = parser, + }; - var parser = new CSharpCodeParser(descriptors, context); - parser.HtmlParser = new HtmlMarkupParser(context) - { - CodeParser = parser, - }; + parser.ParseBlock(); - parser.ParseBlock(); + var root = context.Builder.Build(); + var diagnostics = context.ErrorSink.Errors?.Select(error => RazorDiagnostic.Create(error)); - var root = context.Builder.Build(); - var diagnostics = context.ErrorSink.Errors?.Select(error => RazorDiagnostic.Create(error)); - - return RazorSyntaxTree.Create(root, source, diagnostics, options); - } + return RazorSyntaxTree.Create(root, source, diagnostics, options); } internal SpanFactory CreateSpanFactory()