175 lines
7.4 KiB
C#
Raw Normal View History

// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Web.Razor.Editor;
using System.Web.Razor.Parser;
using System.Web.Razor.Parser.SyntaxTree;
using System.Web.Razor.Resources;
using System.Web.Razor.Test.Framework;
using System.Web.Razor.Text;
using Xunit;
using Xunit.Extensions;
namespace System.Web.Razor.Test.Parser.VB
{
public class VBErrorTest : VBHtmlCodeParserTestBase
{
[Fact]
public void ParserOutputsErrorAndRecoversToEndOfLineIfExplicitExpressionUnterminated()
{
ParseBlockTest(@"(foo
bar",
new ExpressionBlock(
Factory.MetaCode("(").Accepts(AcceptedCharacters.None),
Factory.Code("foo").AsExpression()),
new RazorError(
String.Format(
RazorResources.ParseError_Expected_EndOfBlock_Before_EOF,
RazorResources.BlockName_ExplicitExpression,
")", "("),
SourceLocation.Zero));
}
[Fact]
public void ParserOutputsZeroLengthCodeSpanIfEofReachedAfterStartOfExplicitExpression()
{
ParseBlockTest("(",
new ExpressionBlock(
Factory.MetaCode("(").Accepts(AcceptedCharacters.None),
Factory.EmptyVB().AsExpression()),
new RazorError(
String.Format(RazorResources.ParseError_Expected_EndOfBlock_Before_EOF, "explicit expression", ")", "("),
SourceLocation.Zero));
}
[Fact]
public void ParserOutputsZeroLengthCodeSpanIfEofReachedAfterAtSign()
{
ParseBlockTest(String.Empty,
new ExpressionBlock(
Factory.EmptyVB().AsImplicitExpression(KeywordSet).Accepts(AcceptedCharacters.NonWhiteSpace)),
new RazorError(
RazorResources.ParseError_Unexpected_EndOfFile_At_Start_Of_CodeBlock,
SourceLocation.Zero));
}
[Fact]
public void ParserOutputsZeroLengthCodeSpanIfOnlyWhitespaceFoundAfterAtSign()
{
ParseBlockTest(" ",
new ExpressionBlock(
Factory.EmptyVB().AsImplicitExpression(KeywordSet).Accepts(AcceptedCharacters.NonWhiteSpace)),
new RazorError(
RazorResources.ParseError_Unexpected_WhiteSpace_At_Start_Of_CodeBlock_VB,
SourceLocation.Zero));
}
[Fact]
public void ParserOutputsZeroLengthCodeSpanIfInvalidCharacterFoundAfterAtSign()
{
ParseBlockTest("!!!",
new ExpressionBlock(
Factory.EmptyVB().AsImplicitExpression(KeywordSet).Accepts(AcceptedCharacters.NonWhiteSpace)),
new RazorError(
String.Format(RazorResources.ParseError_Unexpected_Character_At_Start_Of_CodeBlock_VB, "!"),
SourceLocation.Zero));
}
[Theory]
[InlineData("Code", "End Code", true, true)]
[InlineData("Do", "Loop", false, false)]
[InlineData("While", "End While", false, false)]
[InlineData("If", "End If", false, false)]
[InlineData("Select Case", "End Select", false, false)]
[InlineData("For", "Next", false, false)]
[InlineData("Try", "End Try", false, false)]
[InlineData("With", "End With", false, false)]
[InlineData("Using", "End Using", false, false)]
public void EofBlock(string keyword, string expectedTerminator, bool autoComplete, bool keywordIsMetaCode)
{
EofBlockCore(keyword, expectedTerminator, autoComplete, BlockType.Statement, keywordIsMetaCode, c => c.AsStatement());
}
[Fact]
public void EofFunctionsBlock()
{
EofBlockCore("Functions", "End Functions", true, BlockType.Functions, true, c => c.AsFunctionsBody());
}
private void EofBlockCore(string keyword, string expectedTerminator, bool autoComplete, BlockType blockType, bool keywordIsMetaCode, Func<UnclassifiedCodeSpanConstructor, SpanConstructor> classifier)
{
BlockBuilder expected = new BlockBuilder();
expected.Type = blockType;
if (keywordIsMetaCode)
{
expected.Children.Add(Factory.MetaCode(keyword).Accepts(AcceptedCharacters.None));
expected.Children.Add(
classifier(Factory.EmptyVB())
.With((SpanEditHandler)(
autoComplete ?
new AutoCompleteEditHandler(CSharpLanguageCharacteristics.Instance.TokenizeString) { AutoCompleteString = expectedTerminator } :
SpanEditHandler.CreateDefault())));
}
else
{
expected.Children.Add(
classifier(Factory.Code(keyword))
.With((SpanEditHandler)(
autoComplete ?
new AutoCompleteEditHandler(CSharpLanguageCharacteristics.Instance.TokenizeString) { AutoCompleteString = expectedTerminator } :
SpanEditHandler.CreateDefault())));
}
ParseBlockTest(keyword,
expected.Build(),
new RazorError(
String.Format(RazorResources.ParseError_BlockNotTerminated, keyword, expectedTerminator),
SourceLocation.Zero));
}
[Theory]
[InlineData("Code", "End Code", true)]
[InlineData("Do", "Loop", false)]
[InlineData("While", "End While", false)]
[InlineData("If", "End If", false)]
[InlineData("Select Case", "End Select", false)]
[InlineData("For", "Next", false)]
[InlineData("Try", "End Try", false)]
[InlineData("With", "End With", false)]
[InlineData("Using", "End Using", false)]
public void UnterminatedBlock(string keyword, string expectedTerminator, bool keywordIsMetaCode)
{
UnterminatedBlockCore(keyword, expectedTerminator, BlockType.Statement, keywordIsMetaCode, c => c.AsStatement());
}
[Fact]
public void UnterminatedFunctionsBlock()
{
UnterminatedBlockCore("Functions", "End Functions", BlockType.Functions, true, c => c.AsFunctionsBody());
}
private void UnterminatedBlockCore(string keyword, string expectedTerminator, BlockType blockType, bool keywordIsMetaCode, Func<UnclassifiedCodeSpanConstructor, SpanConstructor> classifier)
{
const string blockBody = @"
' This block is not correctly terminated!";
BlockBuilder expected = new BlockBuilder();
expected.Type = blockType;
if (keywordIsMetaCode)
{
expected.Children.Add(Factory.MetaCode(keyword).Accepts(AcceptedCharacters.None));
expected.Children.Add(classifier(Factory.Code(blockBody)));
}
else
{
expected.Children.Add(classifier(Factory.Code(keyword + blockBody)));
}
ParseBlockTest(keyword + blockBody,
expected.Build(),
new RazorError(
String.Format(RazorResources.ParseError_BlockNotTerminated, keyword, expectedTerminator),
SourceLocation.Zero));
}
}
}