From b0e2dc2addb46661ac39fdce3253193eab40c33d Mon Sep 17 00:00:00 2001 From: Ajay Bhargav Baaskaran Date: Thu, 10 Jan 2019 13:55:28 -0800 Subject: [PATCH] Added check to ensure we generate syntax tree with full fidelity (dotnet/aspnetcore-tooling#111) * Added check to ensure we generate syntax tree with full fidelity * Better check * Feedback \n\nCommit migrated from https://github.com/dotnet/aspnetcore-tooling/commit/88653fc34823633fbad1e7e9b7dffbbce8e27a36 --- .../Language/Legacy/ParserTestBase.cs | 130 +++--------------- .../Language/SyntaxTreeVerifier.cs | 29 +++- 2 files changed, 44 insertions(+), 115 deletions(-) diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common/Language/Legacy/ParserTestBase.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common/Language/Legacy/ParserTestBase.cs index 80287a2f9e..522fa00289 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common/Language/Legacy/ParserTestBase.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common/Language/Legacy/ParserTestBase.cs @@ -4,16 +4,13 @@ using System; using System.Collections.Generic; -using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; +using System.Text.RegularExpressions; using System.Threading; -using System.Text; using Xunit; using Xunit.Sdk; -using System.Text.RegularExpressions; -using Microsoft.AspNetCore.Razor.Language.Syntax; namespace Microsoft.AspNetCore.Razor.Language.Legacy { @@ -175,44 +172,19 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy return Regex.Replace(content, "(? directives, bool designTime) - { - return ParseBlock(RazorLanguageVersion.Latest, document, directives, designTime); - } - internal abstract RazorSyntaxTree ParseBlock(RazorLanguageVersion version, string document, IEnumerable directives, bool designTime); - internal RazorSyntaxTree ParseDocument(string document, bool designTime = false, RazorParserFeatureFlags featureFlags = null) - { - return ParseDocument(RazorLanguageVersion.Latest, document, designTime, featureFlags); - } - - internal RazorSyntaxTree ParseDocument(RazorLanguageVersion version, string document, bool designTime = false, RazorParserFeatureFlags featureFlags = null) - { - return ParseDocument(version, document, null, designTime, featureFlags); - } - - internal RazorSyntaxTree ParseDocument(string document, IEnumerable directives, bool designTime = false, RazorParserFeatureFlags featureFlags = null) + internal RazorSyntaxTree ParseDocument(string document, bool designTime = false, IEnumerable directives = null, RazorParserFeatureFlags featureFlags = null) { return ParseDocument(RazorLanguageVersion.Latest, document, directives, designTime, featureFlags); } @@ -271,11 +243,6 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy return syntaxTree; } - internal RazorSyntaxTree ParseCodeBlock(string document, bool designTime = false) - { - return ParseCodeBlock(RazorLanguageVersion.Latest, document, Enumerable.Empty(), designTime); - } - internal virtual RazorSyntaxTree ParseCodeBlock( RazorLanguageVersion version, string document, @@ -306,86 +273,39 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy internal virtual void ParseBlockTest(string document) { - ParseBlockTest(document, null, false, new RazorDiagnostic[0]); + ParseBlockTest(document, null, false); } - internal virtual void ParseBlockTest(string document, IEnumerable directives) + internal virtual void ParseBlockTest(string document, bool designTime) { - ParseBlockTest(document, directives, null); - } - - internal virtual void ParseBlockTest(string document, params RazorDiagnostic[] expectedErrors) - { - ParseBlockTest(document, false, expectedErrors); - } - - internal virtual void ParseBlockTest(string document, bool designTime, params RazorDiagnostic[] expectedErrors) - { - ParseBlockTest(document, null, designTime, expectedErrors); + ParseBlockTest(document, null, designTime); } internal virtual void ParseBlockTest(RazorLanguageVersion version, string document) { - ParseBlockTest(version, document, false, null); + ParseBlockTest(version, document, false); } - internal virtual void ParseBlockTest(string document, IEnumerable directives, params RazorDiagnostic[] expectedErrors) + internal virtual void ParseBlockTest(string document, IEnumerable directives) { - ParseBlockTest(document, directives, false, expectedErrors); + ParseBlockTest(document, directives, false); } - internal virtual void ParseBlockTest(RazorLanguageVersion version, string document, bool designTime, params RazorDiagnostic[] expectedErrors) + internal virtual void ParseBlockTest(RazorLanguageVersion version, string document, bool designTime) { - ParseBlockTest(version, document, null, designTime, expectedErrors); + ParseBlockTest(version, document, null, designTime); } - internal virtual void ParseBlockTest(string document, IEnumerable directives, bool designTime, params RazorDiagnostic[] expectedErrors) + internal virtual void ParseBlockTest(string document, IEnumerable directives, bool designTime) { - ParseBlockTest(RazorLanguageVersion.Latest, document, directives, designTime, expectedErrors); + ParseBlockTest(RazorLanguageVersion.Latest, document, directives, designTime); } - internal virtual void ParseBlockTest(RazorLanguageVersion version, string document, IEnumerable directives, bool designTime, params RazorDiagnostic[] expectedErrors) + internal virtual void ParseBlockTest(RazorLanguageVersion version, string document, IEnumerable directives, bool designTime) { var result = ParseBlock(version, document, directives, designTime); - BaselineTest(result); - } - - internal virtual void SingleSpanBlockTest(string document) - { - SingleSpanBlockTest(document, default, default); - } - - internal virtual void SingleSpanBlockTest(string document, BlockKindInternal blockKind, SpanKindInternal spanType, AcceptedCharactersInternal acceptedCharacters = AcceptedCharactersInternal.Any) - { - SingleSpanBlockTest(document, blockKind, spanType, acceptedCharacters, expectedError: null); - } - - internal virtual void SingleSpanBlockTest(string document, string spanContent, BlockKindInternal blockKind, SpanKindInternal spanType, AcceptedCharactersInternal acceptedCharacters = AcceptedCharactersInternal.Any) - { - SingleSpanBlockTest(document, spanContent, blockKind, spanType, acceptedCharacters, expectedErrors: null); - } - - internal virtual void SingleSpanBlockTest(string document, BlockKindInternal blockKind, SpanKindInternal spanType, params RazorDiagnostic[] expectedError) - { - SingleSpanBlockTest(document, document, blockKind, spanType, expectedError); - } - - internal virtual void SingleSpanBlockTest(string document, string spanContent, BlockKindInternal blockKind, SpanKindInternal spanType, params RazorDiagnostic[] expectedErrors) - { - SingleSpanBlockTest(document, spanContent, blockKind, spanType, AcceptedCharactersInternal.Any, expectedErrors ?? new RazorDiagnostic[0]); - } - - internal virtual void SingleSpanBlockTest(string document, BlockKindInternal blockKind, SpanKindInternal spanType, AcceptedCharactersInternal acceptedCharacters, params RazorDiagnostic[] expectedError) - { - SingleSpanBlockTest(document, document, blockKind, spanType, acceptedCharacters, expectedError); - } - - internal virtual void SingleSpanBlockTest(string document, string spanContent, BlockKindInternal blockKind, SpanKindInternal spanType, AcceptedCharactersInternal acceptedCharacters, params RazorDiagnostic[] expectedErrors) - { - var result = ParseBlock(document, designTime: false); - - BaselineTest(result); + BaselineTest(result, ensureFullFidelity: false); } internal virtual void ParseDocumentTest(string document) @@ -393,14 +313,9 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy ParseDocumentTest(document, null, false); } - internal virtual void ParseDocumentTest(string document, params RazorDiagnostic[] expectedErrors) + internal virtual void ParseDocumentTest(string document, IEnumerable directives) { - ParseDocumentTest(document, false, expectedErrors); - } - - internal virtual void ParseDocumentTest(string document, IEnumerable directives, params RazorDiagnostic[] expectedErrors) - { - ParseDocumentTest(document, directives, false, expectedErrors); + ParseDocumentTest(document, directives, false); } internal virtual void ParseDocumentTest(string document, bool designTime) @@ -408,14 +323,9 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy ParseDocumentTest(document, null, designTime); } - internal virtual void ParseDocumentTest(string document, bool designTime, params RazorDiagnostic[] expectedErrors) + internal virtual void ParseDocumentTest(string document, IEnumerable directives, bool designTime) { - ParseDocumentTest(document, null, designTime, expectedErrors); - } - - internal virtual void ParseDocumentTest(string document, IEnumerable directives, bool designTime, params RazorDiagnostic[] expectedErrors) - { - var result = ParseDocument(document, directives, designTime); + var result = ParseDocument(document, designTime, directives); BaselineTest(result); } diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common/Language/SyntaxTreeVerifier.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common/Language/SyntaxTreeVerifier.cs index fee17d1368..f4f416616c 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common/Language/SyntaxTreeVerifier.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common/Language/SyntaxTreeVerifier.cs @@ -2,20 +2,37 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Text; using Microsoft.AspNetCore.Razor.Language.Legacy; using Microsoft.AspNetCore.Razor.Language.Syntax; +using Xunit; namespace Microsoft.AspNetCore.Razor.Language { // Verifies recursively that a syntax tree has no gaps in terms of position/location. internal class SyntaxTreeVerifier { - public static void Verify(RazorSyntaxTree syntaxTree) + public static void Verify(RazorSyntaxTree syntaxTree, bool ensureFullFidelity = true) { - new Verifier(syntaxTree.Source).Visit(syntaxTree.Root); + var verifier = new Verifier(syntaxTree.Source); + verifier.Visit(syntaxTree.Root); + + if (ensureFullFidelity) + { + var syntaxTreeString = syntaxTree.Root.ToFullString(); + var builder = new StringBuilder(syntaxTree.Source.Length); + for (var i = 0; i < syntaxTree.Source.Length; i++) + { + builder.Append(syntaxTree.Source[i]); + } + var sourceString = builder.ToString(); + + // Make sure the syntax tree contains all of the text in the document. + Assert.Equal(sourceString, syntaxTreeString); + } } - private class Verifier : SyntaxRewriter + private class Verifier : SyntaxWalker { private readonly SourceLocationTracker _tracker; private readonly RazorSourceDocument _source; @@ -26,7 +43,9 @@ namespace Microsoft.AspNetCore.Razor.Language _source = source; } - public override SyntaxNode VisitToken(SyntaxToken token) + public SourceLocationTracker SourceLocationTracker => _tracker; + + public override void VisitToken(SyntaxToken token) { if (token != null && !token.IsMissing && token.Kind != SyntaxKind.Marker) { @@ -39,7 +58,7 @@ namespace Microsoft.AspNetCore.Razor.Language _tracker.UpdateLocation(token.Content); } - return base.VisitToken(token); + base.VisitToken(token); } } }