Skip to content
This repository was archived by the owner on Dec 19, 2018. It is now read-only.

Commit 88cca81

Browse files
committed
Bug fixes
1 parent 3532097 commit 88cca81

File tree

2 files changed

+77
-10
lines changed

2 files changed

+77
-10
lines changed

src/Microsoft.AspNetCore.Razor.Language/Legacy/HtmlParser.cs

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -981,6 +981,8 @@ private void ParseSingleLineMarkup(in SyntaxListBuilder<RazorSyntaxNode> builder
981981

982982
private void ParseTagBlock(in SyntaxListBuilder<RazorSyntaxNode> builder, Stack<Tuple<SyntaxToken, SourceLocation>> tags)
983983
{
984+
// TODO: This is really ugly and needs to be cleaned up.
985+
984986
// Skip Whitespace and Text
985987
var completeTag = false;
986988
var blockAlreadyBuilt = false;
@@ -991,22 +993,23 @@ private void ParseTagBlock(in SyntaxListBuilder<RazorSyntaxNode> builder, Stack<
991993
// Output everything prior to the OpenAngle into a markup span
992994
builder.Add(OutputTokensAsMarkupLiteral());
993995

994-
// Do not want to start a new tag block if we're at the end of the file.
995996
var tagBuilder = builder;
996-
IDisposable disposableTagBuilder = null;
997+
IDisposable tagBuilderDisposable = null;
997998
try
998999
{
9991000
if (EndOfFile)
10001001
{
1002+
// Do not want to start a new tag block if we're at the end of the file.
10011003
EndTagBlock(builder, tags, complete: true);
10021004
}
10031005
else
10041006
{
1005-
if (!AtSpecialTag)
1007+
var atSpecialTag = AtSpecialTag;
1008+
if (!atSpecialTag)
10061009
{
10071010
// Start a tag block. This is used to wrap things like <p> or <a class="btn"> etc.
10081011
var pooledResult = Pool.Allocate<RazorSyntaxNode>();
1009-
disposableTagBuilder = pooledResult;
1012+
tagBuilderDisposable = pooledResult;
10101013
tagBuilder = pooledResult.Builder;
10111014
}
10121015
_bufferedOpenAngle = null;
@@ -1019,10 +1022,11 @@ private void ParseTagBlock(in SyntaxListBuilder<RazorSyntaxNode> builder, Stack<
10191022
AcceptToken(_bufferedOpenAngle);
10201023
EndTagBlock(tagBuilder, tags, complete: false);
10211024
}
1022-
else if (AtSpecialTag && At(SyntaxKind.Bang))
1025+
else if (atSpecialTag && At(SyntaxKind.Bang))
10231026
{
10241027
AcceptToken(_bufferedOpenAngle);
10251028
completeTag = ParseBangTag(builder);
1029+
blockAlreadyBuilt = completeTag;
10261030
}
10271031
else
10281032
{
@@ -1043,8 +1047,9 @@ private void ParseTagBlock(in SyntaxListBuilder<RazorSyntaxNode> builder, Stack<
10431047
// Output the contents of the tag into its own markup span.
10441048
builder.Add(OutputTokensAsMarkupLiteral());
10451049
}
1046-
else
1050+
else if (tagBuilderDisposable != null)
10471051
{
1052+
// A new tag block was started. Build it.
10481053
// Output the contents of the tag into its own markup span.
10491054
tagBuilder.Add(OutputTokensAsMarkupLiteral());
10501055
var tagBlock = SyntaxFactory.MarkupTagBlock(tagBuilder.ToList());
@@ -1054,10 +1059,10 @@ private void ParseTagBlock(in SyntaxListBuilder<RazorSyntaxNode> builder, Stack<
10541059
finally
10551060
{
10561061
// Will be null if we were at end of file or special tag when initially created.
1057-
if (disposableTagBuilder != null)
1062+
if (tagBuilderDisposable != null)
10581063
{
10591064
// End tag block
1060-
disposableTagBuilder.Dispose();
1065+
tagBuilderDisposable.Dispose();
10611066
}
10621067
}
10631068
}
@@ -1083,7 +1088,10 @@ private Tuple<bool, bool> ParseAfterTagStart(
10831088
case SyntaxKind.QuestionMark:
10841089
// XML PI
10851090
AcceptToken(_bufferedOpenAngle);
1086-
return Tuple.Create(TryParseXmlPI(builder), blockAlreadyBuilt);
1091+
var complete = TryParseXmlPI(builder);
1092+
// No block is created for Xml PI. So return the same value as complete.
1093+
blockAlreadyBuilt = complete;
1094+
return Tuple.Create(complete, blockAlreadyBuilt);
10871095
default:
10881096
// Start Tag
10891097
return ParseStartTag(builder, parentBuilder, tags);
@@ -1489,7 +1497,7 @@ private void EndTagBlock(
14891497
var shouldAcceptWhitespaceAndNewLine = true;
14901498

14911499
// Check if the previous span was a transition.
1492-
var previousSpan = GetLastSpan(builder[builder.Count - 1]);
1500+
var previousSpan = builder.Count > 0 ? GetLastSpan(builder[builder.Count - 1]) : null;
14931501
if (previousSpan != null && previousSpan.Kind == SyntaxKind.MarkupTransition)
14941502
{
14951503
var tokens = ReadWhile(
@@ -1710,6 +1718,7 @@ private Syntax.GreenNode GetLastSpan(RazorSyntaxNode node)
17101718
return null;
17111719
}
17121720

1721+
// Find the last token of this node and return its immediate non-list parent.
17131722
var red = node.CreateRed();
17141723
var last = red.GetLastTerminal();
17151724
if (last == null)

test/Microsoft.AspNetCore.Razor.Test.Common/Language/Legacy/SyntaxNodeParserTestBase.cs

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,64 @@ internal override RazorSyntaxTree ParseDocument(RazorLanguageVersion version, st
5050
return syntaxTree;
5151
}
5252

53+
internal override RazorSyntaxTree ParseHtmlBlock(RazorLanguageVersion version, string document, IEnumerable<DirectiveDescriptor> directives, bool designTime = false)
54+
{
55+
if (!UseNewSyntaxTree)
56+
{
57+
return base.ParseHtmlBlock(version, document, directives, designTime);
58+
}
59+
60+
directives = directives ?? Array.Empty<DirectiveDescriptor>();
61+
62+
var source = TestRazorSourceDocument.Create(document, filePath: null, relativePath: null, normalizeNewLines: true);
63+
64+
var options = CreateParserOptions(version, directives, designTime);
65+
var context = new ParserContext(source, options);
66+
67+
var codeParser = new CSharpCodeParser(directives, context);
68+
var markupParser = new HtmlMarkupParser(context);
69+
70+
codeParser.HtmlParser = markupParser;
71+
markupParser.CodeParser = codeParser;
72+
73+
var root = markupParser.ParseBlock().CreateRed();
74+
75+
var diagnostics = context.ErrorSink.Errors;
76+
77+
var syntaxTree = RazorSyntaxTree.Create(root, source, diagnostics, options);
78+
79+
return syntaxTree;
80+
}
81+
82+
internal override RazorSyntaxTree ParseCodeBlock(RazorLanguageVersion version, string document, IEnumerable<DirectiveDescriptor> directives, bool designTime = false)
83+
{
84+
if (!UseNewSyntaxTree)
85+
{
86+
return base.ParseCodeBlock(version, document, directives, designTime);
87+
}
88+
89+
directives = directives ?? Array.Empty<DirectiveDescriptor>();
90+
91+
var source = TestRazorSourceDocument.Create(document, filePath: null, relativePath: null, normalizeNewLines: true);
92+
93+
var options = CreateParserOptions(version, directives, designTime);
94+
var context = new ParserContext(source, options);
95+
96+
var codeParser = new CSharpCodeParser(directives, context);
97+
var markupParser = new HtmlMarkupParser(context);
98+
99+
codeParser.HtmlParser = markupParser;
100+
markupParser.CodeParser = codeParser;
101+
102+
var root = codeParser.ParseBlock().CreateRed();
103+
104+
var diagnostics = context.ErrorSink.Errors;
105+
106+
var syntaxTree = RazorSyntaxTree.Create(root, source, diagnostics, options);
107+
108+
return syntaxTree;
109+
}
110+
53111
internal override void AssertSyntaxTreeNodeMatchesBaseline(RazorSyntaxTree syntaxTree)
54112
{
55113
if (!UseNewSyntaxTree)

0 commit comments

Comments
 (0)