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 88653fc348
This commit is contained in:
parent
b449a44440
commit
b0e2dc2add
|
|
@ -4,16 +4,13 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Text;
|
|
||||||
using Xunit;
|
using Xunit;
|
||||||
using Xunit.Sdk;
|
using Xunit.Sdk;
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
using Microsoft.AspNetCore.Razor.Language.Syntax;
|
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
{
|
{
|
||||||
|
|
@ -175,44 +172,19 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
return Regex.Replace(content, "(?<!\r)\n", "\r\n", RegexOptions.None, TimeSpan.FromSeconds(10));
|
return Regex.Replace(content, "(?<!\r)\n", "\r\n", RegexOptions.None, TimeSpan.FromSeconds(10));
|
||||||
}
|
}
|
||||||
|
|
||||||
internal virtual void BaselineTest(RazorSyntaxTree syntaxTree, bool verifySyntaxTree = true)
|
internal virtual void BaselineTest(RazorSyntaxTree syntaxTree, bool verifySyntaxTree = true, bool ensureFullFidelity = true)
|
||||||
{
|
{
|
||||||
if (verifySyntaxTree)
|
if (verifySyntaxTree)
|
||||||
{
|
{
|
||||||
SyntaxTreeVerifier.Verify(syntaxTree);
|
SyntaxTreeVerifier.Verify(syntaxTree, ensureFullFidelity);
|
||||||
}
|
}
|
||||||
|
|
||||||
AssertSyntaxTreeNodeMatchesBaseline(syntaxTree);
|
AssertSyntaxTreeNodeMatchesBaseline(syntaxTree);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal RazorSyntaxTree ParseBlock(string document, bool designTime)
|
|
||||||
{
|
|
||||||
return ParseBlock(RazorLanguageVersion.Latest, document, designTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal RazorSyntaxTree ParseBlock(RazorLanguageVersion version, string document, bool designTime)
|
|
||||||
{
|
|
||||||
return ParseBlock(version, document, null, designTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal RazorSyntaxTree ParseBlock(string document, IEnumerable<DirectiveDescriptor> directives, bool designTime)
|
|
||||||
{
|
|
||||||
return ParseBlock(RazorLanguageVersion.Latest, document, directives, designTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal abstract RazorSyntaxTree ParseBlock(RazorLanguageVersion version, string document, IEnumerable<DirectiveDescriptor> directives, bool designTime);
|
internal abstract RazorSyntaxTree ParseBlock(RazorLanguageVersion version, string document, IEnumerable<DirectiveDescriptor> directives, bool designTime);
|
||||||
|
|
||||||
internal RazorSyntaxTree ParseDocument(string document, bool designTime = false, RazorParserFeatureFlags featureFlags = null)
|
internal RazorSyntaxTree ParseDocument(string document, bool designTime = false, IEnumerable<DirectiveDescriptor> directives = null, 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<DirectiveDescriptor> directives, bool designTime = false, RazorParserFeatureFlags featureFlags = null)
|
|
||||||
{
|
{
|
||||||
return ParseDocument(RazorLanguageVersion.Latest, document, directives, designTime, featureFlags);
|
return ParseDocument(RazorLanguageVersion.Latest, document, directives, designTime, featureFlags);
|
||||||
}
|
}
|
||||||
|
|
@ -271,11 +243,6 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
return syntaxTree;
|
return syntaxTree;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal RazorSyntaxTree ParseCodeBlock(string document, bool designTime = false)
|
|
||||||
{
|
|
||||||
return ParseCodeBlock(RazorLanguageVersion.Latest, document, Enumerable.Empty<DirectiveDescriptor>(), designTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal virtual RazorSyntaxTree ParseCodeBlock(
|
internal virtual RazorSyntaxTree ParseCodeBlock(
|
||||||
RazorLanguageVersion version,
|
RazorLanguageVersion version,
|
||||||
string document,
|
string document,
|
||||||
|
|
@ -306,86 +273,39 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
|
|
||||||
internal virtual void ParseBlockTest(string document)
|
internal virtual void ParseBlockTest(string document)
|
||||||
{
|
{
|
||||||
ParseBlockTest(document, null, false, new RazorDiagnostic[0]);
|
ParseBlockTest(document, null, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal virtual void ParseBlockTest(string document, IEnumerable<DirectiveDescriptor> directives)
|
internal virtual void ParseBlockTest(string document, bool designTime)
|
||||||
{
|
{
|
||||||
ParseBlockTest(document, directives, null);
|
ParseBlockTest(document, null, designTime);
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal virtual void ParseBlockTest(RazorLanguageVersion version, string document)
|
internal virtual void ParseBlockTest(RazorLanguageVersion version, string document)
|
||||||
{
|
{
|
||||||
ParseBlockTest(version, document, false, null);
|
ParseBlockTest(version, document, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal virtual void ParseBlockTest(string document, IEnumerable<DirectiveDescriptor> directives, params RazorDiagnostic[] expectedErrors)
|
internal virtual void ParseBlockTest(string document, IEnumerable<DirectiveDescriptor> 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<DirectiveDescriptor> directives, bool designTime, params RazorDiagnostic[] expectedErrors)
|
internal virtual void ParseBlockTest(string document, IEnumerable<DirectiveDescriptor> 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<DirectiveDescriptor> directives, bool designTime, params RazorDiagnostic[] expectedErrors)
|
internal virtual void ParseBlockTest(RazorLanguageVersion version, string document, IEnumerable<DirectiveDescriptor> directives, bool designTime)
|
||||||
{
|
{
|
||||||
var result = ParseBlock(version, document, directives, designTime);
|
var result = ParseBlock(version, document, directives, designTime);
|
||||||
|
|
||||||
BaselineTest(result);
|
BaselineTest(result, ensureFullFidelity: false);
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal virtual void ParseDocumentTest(string document)
|
internal virtual void ParseDocumentTest(string document)
|
||||||
|
|
@ -393,14 +313,9 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
ParseDocumentTest(document, null, false);
|
ParseDocumentTest(document, null, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal virtual void ParseDocumentTest(string document, params RazorDiagnostic[] expectedErrors)
|
internal virtual void ParseDocumentTest(string document, IEnumerable<DirectiveDescriptor> directives)
|
||||||
{
|
{
|
||||||
ParseDocumentTest(document, false, expectedErrors);
|
ParseDocumentTest(document, directives, false);
|
||||||
}
|
|
||||||
|
|
||||||
internal virtual void ParseDocumentTest(string document, IEnumerable<DirectiveDescriptor> directives, params RazorDiagnostic[] expectedErrors)
|
|
||||||
{
|
|
||||||
ParseDocumentTest(document, directives, false, expectedErrors);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal virtual void ParseDocumentTest(string document, bool designTime)
|
internal virtual void ParseDocumentTest(string document, bool designTime)
|
||||||
|
|
@ -408,14 +323,9 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
ParseDocumentTest(document, null, designTime);
|
ParseDocumentTest(document, null, designTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal virtual void ParseDocumentTest(string document, bool designTime, params RazorDiagnostic[] expectedErrors)
|
internal virtual void ParseDocumentTest(string document, IEnumerable<DirectiveDescriptor> directives, bool designTime)
|
||||||
{
|
{
|
||||||
ParseDocumentTest(document, null, designTime, expectedErrors);
|
var result = ParseDocument(document, designTime, directives);
|
||||||
}
|
|
||||||
|
|
||||||
internal virtual void ParseDocumentTest(string document, IEnumerable<DirectiveDescriptor> directives, bool designTime, params RazorDiagnostic[] expectedErrors)
|
|
||||||
{
|
|
||||||
var result = ParseDocument(document, directives, designTime);
|
|
||||||
|
|
||||||
BaselineTest(result);
|
BaselineTest(result);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,20 +2,37 @@
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Text;
|
||||||
using Microsoft.AspNetCore.Razor.Language.Legacy;
|
using Microsoft.AspNetCore.Razor.Language.Legacy;
|
||||||
using Microsoft.AspNetCore.Razor.Language.Syntax;
|
using Microsoft.AspNetCore.Razor.Language.Syntax;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Razor.Language
|
namespace Microsoft.AspNetCore.Razor.Language
|
||||||
{
|
{
|
||||||
// Verifies recursively that a syntax tree has no gaps in terms of position/location.
|
// Verifies recursively that a syntax tree has no gaps in terms of position/location.
|
||||||
internal class SyntaxTreeVerifier
|
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 SourceLocationTracker _tracker;
|
||||||
private readonly RazorSourceDocument _source;
|
private readonly RazorSourceDocument _source;
|
||||||
|
|
@ -26,7 +43,9 @@ namespace Microsoft.AspNetCore.Razor.Language
|
||||||
_source = source;
|
_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)
|
if (token != null && !token.IsMissing && token.Kind != SyntaxKind.Marker)
|
||||||
{
|
{
|
||||||
|
|
@ -39,7 +58,7 @@ namespace Microsoft.AspNetCore.Razor.Language
|
||||||
_tracker.UpdateLocation(token.Content);
|
_tracker.UpdateLocation(token.Content);
|
||||||
}
|
}
|
||||||
|
|
||||||
return base.VisitToken(token);
|
base.VisitToken(token);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue