Convert CSharpSpecialBlockTest to use baselines.

#2263
This commit is contained in:
N. Taylor Mullen 2018-06-27 12:26:38 -07:00
parent a7fd53b3a3
commit 5950928baa
11 changed files with 202 additions and 197 deletions

View File

@ -2,245 +2,64 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using Microsoft.AspNetCore.Razor.Language.Extensions;
using Xunit;
namespace Microsoft.AspNetCore.Razor.Language.Legacy
{
public class CSharpSpecialBlockTest : CsHtmlCodeParserTestBase
{
[Fact]
public void ParseInheritsStatementMarksInheritsSpanAsCanGrowIfMissingTrailingSpace()
public CSharpSpecialBlockTest()
{
// Arrange
var chunkGenerator = new DirectiveChunkGenerator(InheritsDirective.Directive);
chunkGenerator.Diagnostics.Add(
RazorDiagnosticFactory.CreateParsing_UnexpectedEOFAfterDirective(
new SourceSpan(new SourceLocation(9, 0, 9), 1), InheritsDirective.Directive.Directive, "type"));
// Act & Assert
ParseDocumentTest(
"@inherits",
new[] { InheritsDirective.Directive },
new MarkupBlock(
Factory.EmptyHtml(),
new DirectiveBlock(chunkGenerator,
Factory.CodeTransition(),
Factory.MetaCode("inherits").Accepts(AcceptedCharactersInternal.None),
Factory.Span(SpanKindInternal.Code, string.Empty, CSharpSymbolType.Unknown)
.AsDirectiveToken(DirectiveTokenDescriptor.CreateToken(DirectiveTokenKind.Type))),
Factory.EmptyHtml()));
}
[Fact]
public void InheritsBlockAcceptsMultipleGenericArguments()
{
ParseDocumentTest(
"@inherits Foo.Bar<Biz<Qux>, string, int>.Baz",
new[] { InheritsDirective.Directive },
new MarkupBlock(
Factory.EmptyHtml(),
new DirectiveBlock(new DirectiveChunkGenerator(InheritsDirective.Directive),
Factory.CodeTransition(),
Factory.MetaCode("inherits").Accepts(AcceptedCharactersInternal.None),
Factory.Span(SpanKindInternal.Code, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.WhiteSpace),
Factory.Span(SpanKindInternal.Code, "Foo.Bar<Biz<Qux>, string, int>.Baz", markup: false).AsDirectiveToken(InheritsDirective.Directive.Tokens[0])),
Factory.EmptyHtml()));
}
[Fact]
public void InheritsBlockOutputsErrorIfInheritsNotFollowedByTypeButAcceptsEntireLineAsCode()
{
// Arrange
var chunkGenerator = new DirectiveChunkGenerator(InheritsDirective.Directive);
chunkGenerator.Diagnostics.Add(
RazorDiagnosticFactory.CreateParsing_DirectiveExpectsTypeName(
new SourceSpan(new SourceLocation(25, 0, 25), Environment.NewLine.Length),
InheritsDirective.Directive.Directive));
// Act & Assert
ParseDocumentTest(
"@inherits " + Environment.NewLine + "foo",
new[] { InheritsDirective.Directive },
new MarkupBlock(
Factory.EmptyHtml(),
new DirectiveBlock(chunkGenerator,
Factory.CodeTransition(),
Factory.MetaCode("inherits").Accepts(AcceptedCharactersInternal.None),
Factory.Span(SpanKindInternal.Code, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.WhiteSpace),
Factory.Span(SpanKindInternal.Code, string.Empty, CSharpSymbolType.Unknown)
.AsDirectiveToken(DirectiveTokenDescriptor.CreateToken(DirectiveTokenKind.Type))),
Factory.Markup(Environment.NewLine + "foo")));
UseBaselineTests = true;
}
[Fact]
public void NamespaceImportInsideCodeBlockCausesError()
{
ParseBlockTest("{ using Foo.Bar.Baz; var foo = bar; }",
new StatementBlock(
Factory.MetaCode("{").Accepts(AcceptedCharactersInternal.None),
Factory.Code(" using Foo.Bar.Baz; var foo = bar; ")
.AsStatement()
.AutoCompleteWith(autoCompleteString: null),
Factory.MetaCode("}").Accepts(AcceptedCharactersInternal.None)
),
RazorDiagnosticFactory.CreateParsing_NamespaceImportAndTypeAliasCannotExistWithinCodeBlock(
new SourceSpan(new SourceLocation(2, 0, 2), contentLength: 5)));
ParseBlockTest("{ using Foo.Bar.Baz; var foo = bar; }");
}
[Fact]
public void TypeAliasInsideCodeBlockIsNotHandledSpecially()
{
ParseBlockTest("{ using Foo = Bar.Baz; var foo = bar; }",
new StatementBlock(
Factory.MetaCode("{").Accepts(AcceptedCharactersInternal.None),
Factory.Code(" using Foo = Bar.Baz; var foo = bar; ")
.AsStatement()
.AutoCompleteWith(autoCompleteString: null),
Factory.MetaCode("}").Accepts(AcceptedCharactersInternal.None)
),
RazorDiagnosticFactory.CreateParsing_NamespaceImportAndTypeAliasCannotExistWithinCodeBlock(
new SourceSpan(new SourceLocation(2, 0, 2), contentLength: 5)));
}
[Fact]
public void Plan9FunctionsKeywordInsideCodeBlockIsNotHandledSpecially()
{
ParseBlockTest("{ functions Foo; }",
new StatementBlock(
Factory.MetaCode("{").Accepts(AcceptedCharactersInternal.None),
Factory.Code(" functions Foo; ")
.AsStatement()
.AutoCompleteWith(autoCompleteString: null),
Factory.MetaCode("}").Accepts(AcceptedCharactersInternal.None)
));
ParseBlockTest("{ using Foo = Bar.Baz; var foo = bar; }");
}
[Fact]
public void NonKeywordStatementInCodeBlockIsHandledCorrectly()
{
ParseBlockTest("{" + Environment.NewLine
+ " List<dynamic> photos = gallery.Photo.ToList();" + Environment.NewLine
+ "}",
new StatementBlock(
Factory.MetaCode("{").Accepts(AcceptedCharactersInternal.None),
Factory.Code($"{Environment.NewLine} List<dynamic> photos = gallery.Photo.ToList();{Environment.NewLine}")
.AsStatement()
.AutoCompleteWith(autoCompleteString: null),
Factory.MetaCode("}").Accepts(AcceptedCharactersInternal.None)
));
ParseBlockTest(
@"{
List<dynamic> photos = gallery.Photo.ToList();
}");
}
[Fact]
public void ParseBlockBalancesBracesOutsideStringsIfFirstCharacterIsBraceAndReturnsSpanOfTypeCode()
{
// Arrange
const string code = "foo\"b}ar\" if(condition) { string.Format(\"{0}\"); } ";
// Act/Assert
ParseBlockTest("{" + code + "}",
new StatementBlock(
Factory.MetaCode("{").Accepts(AcceptedCharactersInternal.None),
Factory.Code(code)
.AsStatement()
.AutoCompleteWith(autoCompleteString: null),
Factory.MetaCode("}").Accepts(AcceptedCharactersInternal.None)
));
ParseBlockTest("{foo\"b}ar\" if(condition) { string.Format(\"{0}\"); } }");
}
[Fact]
public void ParseBlockBalancesParensOutsideStringsIfFirstCharacterIsParenAndReturnsSpanOfTypeExpression()
{
// Arrange
const string code = "foo\"b)ar\" if(condition) { string.Format(\"{0}\"); } ";
// Act/Assert
ParseBlockTest("(" + code + ")",
new ExpressionBlock(
Factory.MetaCode("(").Accepts(AcceptedCharactersInternal.None),
Factory.Code(code).AsExpression(),
Factory.MetaCode(")").Accepts(AcceptedCharactersInternal.None)
));
}
[Fact]
public void ParseBlockBalancesBracesAndOutputsContentAsClassLevelCodeSpanIfFirstIdentifierIsFunctionsKeyword()
{
const string code = " foo(); \"bar}baz\" ";
ParseBlockTest(
"functions {" + code + "} zoop",
new[] { FunctionsDirective.Directive },
new DirectiveBlock(new DirectiveChunkGenerator(FunctionsDirective.Directive),
Factory.MetaCode("functions").Accepts(AcceptedCharactersInternal.None),
Factory.Span(SpanKindInternal.Markup, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.AllWhiteSpace),
Factory.MetaCode("{").AutoCompleteWith(null, atEndOfSpan: true).Accepts(AcceptedCharactersInternal.None),
Factory.Code(code).AsCodeBlock(),
Factory.MetaCode("}").Accepts(AcceptedCharactersInternal.None)));
}
[Fact]
public void ParseBlockDoesNoErrorRecoveryForFunctionsBlock()
{
// Arrange
var chunkGenerator = new DirectiveChunkGenerator(FunctionsDirective.Directive);
chunkGenerator.Diagnostics.Add(
RazorDiagnosticFactory.CreateParsing_ExpectedEndOfBlockBeforeEOF(
new SourceSpan(new SourceLocation(10, 0, 10), contentLength: 1), "functions", "}", "{"));
// Act & Assert
ParseBlockTest(
"functions { { { { { } zoop",
new[] { FunctionsDirective.Directive },
new DirectiveBlock(chunkGenerator,
Factory.MetaCode("functions").Accepts(AcceptedCharactersInternal.None),
Factory.Span(SpanKindInternal.Markup, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.AllWhiteSpace),
Factory.MetaCode("{").AutoCompleteWith("}", atEndOfSpan: true).Accepts(AcceptedCharactersInternal.None),
Factory.Code(" { { { { } zoop").AsCodeBlock()));
}
[Fact]
public void ParseBlockIgnoresFunctionsUnlessAllLowerCase()
{
ParseBlockTest("Functions { foo() }",
new ExpressionBlock(
Factory.Code("Functions")
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
.Accepts(AcceptedCharactersInternal.NonWhiteSpace)));
ParseBlockTest("(foo\"b)ar\" if(condition) { string.Format(\"{0}\"); } )");
}
[Fact]
public void ParseBlockIgnoresSingleSlashAtStart()
{
ParseBlockTest("@/ foo",
new ExpressionBlock(
Factory.CodeTransition(),
Factory.EmptyCSharp()
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
.Accepts(AcceptedCharactersInternal.NonWhiteSpace)),
RazorDiagnosticFactory.CreateParsing_UnexpectedCharacterAtStartOfCodeBlock(
new SourceSpan(new SourceLocation(1, 0, 1), contentLength: 1),
"/"));
ParseBlockTest("@/ foo");
}
[Fact]
public void ParseBlockTerminatesSingleLineCommentAtEndOfLine()
{
ParseBlockTest("if(!false) {" + Environment.NewLine
+ " // Foo" + Environment.NewLine
+ "\t<p>A real tag!</p>" + Environment.NewLine
+ "}",
new StatementBlock(
Factory.Code($"if(!false) {{{Environment.NewLine} // Foo{Environment.NewLine}").AsStatement(),
new MarkupBlock(
Factory.Markup("\t"),
new MarkupTagBlock(
Factory.Markup("<p>").Accepts(AcceptedCharactersInternal.None)),
Factory.Markup("A real tag!"),
new MarkupTagBlock(
Factory.Markup("</p>").Accepts(AcceptedCharactersInternal.None)),
Factory.Markup(Environment.NewLine).Accepts(AcceptedCharactersInternal.None)),
Factory.Code("}").AsStatement()
));
ParseBlockTest(
"if(!false) {" + Environment.NewLine +
" // Foo" + Environment.NewLine +
"\t<p>A real tag!</p>" + Environment.NewLine +
"}");
}
}
}

View File

@ -0,0 +1,6 @@
(1,3): Error RZ2004: Namespace imports and type aliases cannot be placed within code blocks. They must immediately follow an "@" character in markup. It is recommended that you put them at the top of the page, as in the following example:
@using System.Drawing;
@{
// OK here to use types from System.Drawing in the page.
}

View File

@ -0,0 +1,25 @@
Statement block - Gen<None> - 37 - (0:0,0)
MetaCode span - Gen<None> - [{] - SpanEditHandler;Accepts:None - (0:0,0) - Symbols:1
CSharpSymbolType.LeftBrace;[{];
Code span - Gen<Stmt> - [ using Foo.Bar.Baz; var foo = bar; ] - AutoCompleteEditHandler;Accepts:Any,AutoComplete:[<null>];AtEOL - (1:0,1) - Symbols:19
CSharpSymbolType.WhiteSpace;[ ];
CSharpSymbolType.Keyword;[using];
CSharpSymbolType.WhiteSpace;[ ];
CSharpSymbolType.Identifier;[Foo];
CSharpSymbolType.Dot;[.];
CSharpSymbolType.Identifier;[Bar];
CSharpSymbolType.Dot;[.];
CSharpSymbolType.Identifier;[Baz];
CSharpSymbolType.Semicolon;[;];
CSharpSymbolType.WhiteSpace;[ ];
CSharpSymbolType.Identifier;[var];
CSharpSymbolType.WhiteSpace;[ ];
CSharpSymbolType.Identifier;[foo];
CSharpSymbolType.WhiteSpace;[ ];
CSharpSymbolType.Assign;[=];
CSharpSymbolType.WhiteSpace;[ ];
CSharpSymbolType.Identifier;[bar];
CSharpSymbolType.Semicolon;[;];
CSharpSymbolType.WhiteSpace;[ ];
MetaCode span - Gen<None> - [}] - SpanEditHandler;Accepts:None - (36:0,36) - Symbols:1
CSharpSymbolType.RightBrace;[}];

View File

@ -0,0 +1,26 @@
Statement block - Gen<None> - 56 - (0:0,0)
MetaCode span - Gen<None> - [{] - SpanEditHandler;Accepts:None - (0:0,0) - Symbols:1
CSharpSymbolType.LeftBrace;[{];
Code span - Gen<Stmt> - [LF List<dynamic> photos = gallery.Photo.ToList();LF] - AutoCompleteEditHandler;Accepts:Any,AutoComplete:[<null>];AtEOL - (1:0,1) - Symbols:20
CSharpSymbolType.NewLine;[LF];
CSharpSymbolType.WhiteSpace;[ ];
CSharpSymbolType.Identifier;[List];
CSharpSymbolType.LessThan;[<];
CSharpSymbolType.Identifier;[dynamic];
CSharpSymbolType.GreaterThan;[>];
CSharpSymbolType.WhiteSpace;[ ];
CSharpSymbolType.Identifier;[photos];
CSharpSymbolType.WhiteSpace;[ ];
CSharpSymbolType.Assign;[=];
CSharpSymbolType.WhiteSpace;[ ];
CSharpSymbolType.Identifier;[gallery];
CSharpSymbolType.Dot;[.];
CSharpSymbolType.Identifier;[Photo];
CSharpSymbolType.Dot;[.];
CSharpSymbolType.Identifier;[ToList];
CSharpSymbolType.LeftParenthesis;[(];
CSharpSymbolType.RightParenthesis;[)];
CSharpSymbolType.Semicolon;[;];
CSharpSymbolType.NewLine;[LF];
MetaCode span - Gen<None> - [}] - SpanEditHandler;Accepts:None - (55:2,0) - Symbols:1
CSharpSymbolType.RightBrace;[}];

View File

@ -0,0 +1,26 @@
Statement block - Gen<None> - 52 - (0:0,0)
MetaCode span - Gen<None> - [{] - SpanEditHandler;Accepts:None - (0:0,0) - Symbols:1
CSharpSymbolType.LeftBrace;[{];
Code span - Gen<Stmt> - [foo"b}ar" if(condition) { string.Format("{0}"); } ] - AutoCompleteEditHandler;Accepts:Any,AutoComplete:[<null>];AtEOL - (1:0,1) - Symbols:20
CSharpSymbolType.Identifier;[foo];
CSharpSymbolType.StringLiteral;["b}ar"];
CSharpSymbolType.WhiteSpace;[ ];
CSharpSymbolType.Keyword;[if];
CSharpSymbolType.LeftParenthesis;[(];
CSharpSymbolType.Identifier;[condition];
CSharpSymbolType.RightParenthesis;[)];
CSharpSymbolType.WhiteSpace;[ ];
CSharpSymbolType.LeftBrace;[{];
CSharpSymbolType.WhiteSpace;[ ];
CSharpSymbolType.Keyword;[string];
CSharpSymbolType.Dot;[.];
CSharpSymbolType.Identifier;[Format];
CSharpSymbolType.LeftParenthesis;[(];
CSharpSymbolType.StringLiteral;["{0}"];
CSharpSymbolType.RightParenthesis;[)];
CSharpSymbolType.Semicolon;[;];
CSharpSymbolType.WhiteSpace;[ ];
CSharpSymbolType.RightBrace;[}];
CSharpSymbolType.WhiteSpace;[ ];
MetaCode span - Gen<None> - [}] - SpanEditHandler;Accepts:None - (51:0,51) - Symbols:1
CSharpSymbolType.RightBrace;[}];

View File

@ -0,0 +1,26 @@
Expression block - Gen<Expr> - 52 - (0:0,0)
MetaCode span - Gen<None> - [(] - SpanEditHandler;Accepts:None - (0:0,0) - Symbols:1
CSharpSymbolType.LeftParenthesis;[(];
Code span - Gen<Expr> - [foo"b)ar" if(condition) { string.Format("{0}"); } ] - SpanEditHandler;Accepts:Any - (1:0,1) - Symbols:20
CSharpSymbolType.Identifier;[foo];
CSharpSymbolType.StringLiteral;["b)ar"];
CSharpSymbolType.WhiteSpace;[ ];
CSharpSymbolType.Keyword;[if];
CSharpSymbolType.LeftParenthesis;[(];
CSharpSymbolType.Identifier;[condition];
CSharpSymbolType.RightParenthesis;[)];
CSharpSymbolType.WhiteSpace;[ ];
CSharpSymbolType.LeftBrace;[{];
CSharpSymbolType.WhiteSpace;[ ];
CSharpSymbolType.Keyword;[string];
CSharpSymbolType.Dot;[.];
CSharpSymbolType.Identifier;[Format];
CSharpSymbolType.LeftParenthesis;[(];
CSharpSymbolType.StringLiteral;["{0}"];
CSharpSymbolType.RightParenthesis;[)];
CSharpSymbolType.Semicolon;[;];
CSharpSymbolType.WhiteSpace;[ ];
CSharpSymbolType.RightBrace;[}];
CSharpSymbolType.WhiteSpace;[ ];
MetaCode span - Gen<None> - [)] - SpanEditHandler;Accepts:None - (51:0,51) - Symbols:1
CSharpSymbolType.RightParenthesis;[)];

View File

@ -0,0 +1 @@
(1,2): Error RZ1005: "/" is not valid at the start of a code block. Only identifiers, keywords, comments, "(" and "{" are valid.

View File

@ -0,0 +1,5 @@
Expression block - Gen<Expr> - 1 - (0:0,0)
Transition span - Gen<None> - [@] - SpanEditHandler;Accepts:None - (0:0,0) - Symbols:1
CSharpSymbolType.Transition;[@];
Code span - Gen<Expr> - [] - ImplicitExpressionEditHandler;Accepts:NonWhiteSpace;ImplicitExpression[RTD];K14 - (1:0,1) - Symbols:1
CSharpSymbolType.Unknown;[];

View File

@ -0,0 +1,38 @@
Statement block - Gen<None> - 48 - (0:0,0)
Code span - Gen<Stmt> - [if(!false) {LF // FooLF] - SpanEditHandler;Accepts:Any - (0:0,0) - Symbols:11
CSharpSymbolType.Keyword;[if];
CSharpSymbolType.LeftParenthesis;[(];
CSharpSymbolType.Not;[!];
CSharpSymbolType.Keyword;[false];
CSharpSymbolType.RightParenthesis;[)];
CSharpSymbolType.WhiteSpace;[ ];
CSharpSymbolType.LeftBrace;[{];
CSharpSymbolType.NewLine;[LF];
CSharpSymbolType.WhiteSpace;[ ];
CSharpSymbolType.Comment;[// Foo];
CSharpSymbolType.NewLine;[LF];
Markup block - Gen<None> - 21 - (26:2,0)
Markup span - Gen<Markup> - [ ] - SpanEditHandler;Accepts:Any - (26:2,0) - Symbols:1
HtmlSymbolType.WhiteSpace;[ ];
Tag block - Gen<None> - 3 - (27:2,1)
Markup span - Gen<Markup> - [<p>] - SpanEditHandler;Accepts:None - (27:2,1) - Symbols:3
HtmlSymbolType.OpenAngle;[<];
HtmlSymbolType.Text;[p];
HtmlSymbolType.CloseAngle;[>];
Markup span - Gen<Markup> - [A real tag!] - SpanEditHandler;Accepts:Any - (30:2,4) - Symbols:6
HtmlSymbolType.Text;[A];
HtmlSymbolType.WhiteSpace;[ ];
HtmlSymbolType.Text;[real];
HtmlSymbolType.WhiteSpace;[ ];
HtmlSymbolType.Text;[tag];
HtmlSymbolType.Bang;[!];
Tag block - Gen<None> - 4 - (41:2,15)
Markup span - Gen<Markup> - [</p>] - SpanEditHandler;Accepts:None - (41:2,15) - Symbols:4
HtmlSymbolType.OpenAngle;[<];
HtmlSymbolType.ForwardSlash;[/];
HtmlSymbolType.Text;[p];
HtmlSymbolType.CloseAngle;[>];
Markup span - Gen<Markup> - [LF] - SpanEditHandler;Accepts:None - (45:2,19) - Symbols:1
HtmlSymbolType.NewLine;[LF];
Code span - Gen<Stmt> - [}] - SpanEditHandler;Accepts:Any - (47:3,0) - Symbols:1
CSharpSymbolType.RightBrace;[}];

View File

@ -0,0 +1,6 @@
(1,3): Error RZ2004: Namespace imports and type aliases cannot be placed within code blocks. They must immediately follow an "@" character in markup. It is recommended that you put them at the top of the page, as in the following example:
@using System.Drawing;
@{
// OK here to use types from System.Drawing in the page.
}

View File

@ -0,0 +1,27 @@
Statement block - Gen<None> - 39 - (0:0,0)
MetaCode span - Gen<None> - [{] - SpanEditHandler;Accepts:None - (0:0,0) - Symbols:1
CSharpSymbolType.LeftBrace;[{];
Code span - Gen<Stmt> - [ using Foo = Bar.Baz; var foo = bar; ] - AutoCompleteEditHandler;Accepts:Any,AutoComplete:[<null>];AtEOL - (1:0,1) - Symbols:21
CSharpSymbolType.WhiteSpace;[ ];
CSharpSymbolType.Keyword;[using];
CSharpSymbolType.WhiteSpace;[ ];
CSharpSymbolType.Identifier;[Foo];
CSharpSymbolType.WhiteSpace;[ ];
CSharpSymbolType.Assign;[=];
CSharpSymbolType.WhiteSpace;[ ];
CSharpSymbolType.Identifier;[Bar];
CSharpSymbolType.Dot;[.];
CSharpSymbolType.Identifier;[Baz];
CSharpSymbolType.Semicolon;[;];
CSharpSymbolType.WhiteSpace;[ ];
CSharpSymbolType.Identifier;[var];
CSharpSymbolType.WhiteSpace;[ ];
CSharpSymbolType.Identifier;[foo];
CSharpSymbolType.WhiteSpace;[ ];
CSharpSymbolType.Assign;[=];
CSharpSymbolType.WhiteSpace;[ ];
CSharpSymbolType.Identifier;[bar];
CSharpSymbolType.Semicolon;[;];
CSharpSymbolType.WhiteSpace;[ ];
MetaCode span - Gen<None> - [}] - SpanEditHandler;Accepts:None - (38:0,38) - Symbols:1
CSharpSymbolType.RightBrace;[}];