aspnetcore/test/Microsoft.AspNetCore.Razor..../Legacy/CSharpStatementTest.cs

425 lines
18 KiB
C#

// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using Xunit;
namespace Microsoft.AspNetCore.Razor.Language.Legacy
{
// Basic Tests for C# Statements:
// * Basic case for each statement
// * Basic case for ALL clauses
// This class DOES NOT contain
// * Error cases
// * Tests for various types of nested statements
// * Comment tests
public class CSharpStatementTest : CsHtmlCodeParserTestBase
{
[Fact]
public void ForStatement()
{
ParseBlockTest("@for(int i = 0; i++; i < length) { foo(); }",
new StatementBlock(
Factory.CodeTransition(),
Factory.Code("for(int i = 0; i++; i < length) { foo(); }")
.AsStatement()
.Accepts(AcceptedCharactersInternal.None)
));
}
[Fact]
public void ForEachStatement()
{
ParseBlockTest("@foreach(var foo in bar) { foo(); }",
new StatementBlock(
Factory.CodeTransition(),
Factory.Code("foreach(var foo in bar) { foo(); }")
.AsStatement()
.Accepts(AcceptedCharactersInternal.None)
));
}
[Fact]
public void WhileStatement()
{
ParseBlockTest("@while(true) { foo(); }",
new StatementBlock(
Factory.CodeTransition(),
Factory.Code("while(true) { foo(); }")
.AsStatement()
.Accepts(AcceptedCharactersInternal.None)
));
}
[Fact]
public void SwitchStatement()
{
ParseBlockTest("@switch(foo) { foo(); }",
new StatementBlock(
Factory.CodeTransition(),
Factory.Code("switch(foo) { foo(); }")
.AsStatement()
.Accepts(AcceptedCharactersInternal.None)
));
}
[Fact]
public void LockStatement()
{
ParseBlockTest("@lock(baz) { foo(); }",
new StatementBlock(
Factory.CodeTransition(),
Factory.Code("lock(baz) { foo(); }")
.AsStatement()
.Accepts(AcceptedCharactersInternal.None)
));
}
[Fact]
public void IfStatement()
{
ParseBlockTest("@if(true) { foo(); }",
new StatementBlock(
Factory.CodeTransition(),
Factory.Code("if(true) { foo(); }")
.AsStatement()
));
}
[Fact]
public void ElseIfClause()
{
ParseBlockTest("@if(true) { foo(); } else if(false) { foo(); } else if(!false) { foo(); }",
new StatementBlock(
Factory.CodeTransition(),
Factory.Code("if(true) { foo(); } else if(false) { foo(); } else if(!false) { foo(); }")
.AsStatement()
));
}
[Fact]
public void ElseClause()
{
ParseBlockTest("@if(true) { foo(); } else { foo(); }",
new StatementBlock(
Factory.CodeTransition(),
Factory.Code("if(true) { foo(); } else { foo(); }")
.AsStatement()
.Accepts(AcceptedCharactersInternal.None)
));
}
[Fact]
public void TryStatement()
{
ParseBlockTest("@try { foo(); }",
new StatementBlock(
Factory.CodeTransition(),
Factory.Code("try { foo(); }")
.AsStatement()
));
}
[Fact]
public void CatchClause()
{
ParseBlockTest("@try { foo(); } catch(IOException ioex) { handleIO(); } catch(Exception ex) { handleOther(); }",
new StatementBlock(
Factory.CodeTransition(),
Factory.Code("try { foo(); } catch(IOException ioex) { handleIO(); } catch(Exception ex) { handleOther(); }")
.AsStatement()
));
}
public static TheoryData ExceptionFilterData
{
get
{
var factory = new SpanFactory();
// document, expectedStatement
return new TheoryData<string, StatementBlock>
{
{
"@try { someMethod(); } catch(Exception) when (true) { handleIO(); }",
new StatementBlock(
factory.CodeTransition(),
factory
.Code("try { someMethod(); } catch(Exception) when (true) { handleIO(); }")
.AsStatement())
},
{
"@try { A(); } catch(Exception) when (true) { B(); } finally { C(); }",
new StatementBlock(
factory.CodeTransition(),
factory
.Code("try { A(); } catch(Exception) when (true) { B(); } finally { C(); }")
.AsStatement()
.Accepts(AcceptedCharactersInternal.None))
},
{
"@try { A(); } catch(Exception) when (true) { B(); } catch(IOException) when (false) { C(); }",
new StatementBlock(
factory.CodeTransition(),
factory
.Code("try { A(); } catch(Exception) when (true) { B(); } catch(IOException) " +
"when (false) { C(); }")
.AsStatement())
},
{
string.Format("@try{0}{{{0} A();{0}}}{0}catch(Exception) when (true)", Environment.NewLine) +
string.Format("{0}{{{0} B();{0}}}{0}catch(IOException) when (false)", Environment.NewLine) +
string.Format("{0}{{{0} C();{0}}}", Environment.NewLine),
new StatementBlock(
factory.CodeTransition(),
factory
.Code(
string.Format("try{0}{{{0} A();{0}}}{0}catch(Exception) ", Environment.NewLine) +
string.Format("when (true){0}{{{0} B();{0}}}{0}", Environment.NewLine) +
string.Format("catch(IOException) when (false){0}{{{0} ", Environment.NewLine) +
string.Format("C();{0}}}", Environment.NewLine))
.AsStatement())
},
// Wrapped in @{ block.
{
"@{try { someMethod(); } catch(Exception) when (true) { handleIO(); }}",
new StatementBlock(
factory.CodeTransition(),
factory.MetaCode("{").Accepts(AcceptedCharactersInternal.None),
factory
.Code("try { someMethod(); } catch(Exception) when (true) { handleIO(); }")
.AsStatement()
.AutoCompleteWith(autoCompleteString: null),
factory.MetaCode("}").Accepts(AcceptedCharactersInternal.None))
},
// Partial exception filter data
{
"@try { someMethod(); } catch(Exception) when",
new StatementBlock(
factory.CodeTransition(),
factory
.Code("try { someMethod(); } catch(Exception) when")
.AsStatement())
},
{
"@try { someMethod(); } when",
new StatementBlock(
factory.CodeTransition(),
factory
.Code("try { someMethod(); }")
.AsStatement())
},
{
"@try { someMethod(); } catch(Exception) when { anotherMethod(); }",
new StatementBlock(
factory.CodeTransition(),
factory
.Code("try { someMethod(); } catch(Exception) when { anotherMethod(); }")
.AsStatement())
},
{
"@try { someMethod(); } catch(Exception) when (true)",
new StatementBlock(
factory.CodeTransition(),
factory
.Code("try { someMethod(); } catch(Exception) when (true)")
.AsStatement())
},
};
}
}
[Theory]
[MemberData(nameof(ExceptionFilterData))]
public void ExceptionFilters(string document, object expectedStatement)
{
FixupSpans = true;
// Act & Assert
ParseBlockTest(document, (StatementBlock)expectedStatement);
}
public static TheoryData ExceptionFilterErrorData
{
get
{
var factory = new SpanFactory();
var unbalancedParenErrorString = "An opening \"(\" is missing the corresponding closing \")\".";
var unbalancedBracketCatchErrorString = "The catch block is missing a closing \"}\" character. " +
"Make sure you have a matching \"}\" character for all the \"{\" characters within this block, " +
"and that none of the \"}\" characters are being interpreted as markup.";
// document, expectedStatement, expectedErrors
return new TheoryData<string, StatementBlock, RazorError[]>
{
{
"@try { someMethod(); } catch(Exception) when (",
new StatementBlock(
factory.CodeTransition(),
factory
.Code("try { someMethod(); } catch(Exception) when (")
.AsStatement()),
new[] { new RazorError(unbalancedParenErrorString, 45, 0, 45, 1) }
},
{
"@try { someMethod(); } catch(Exception) when (someMethod(",
new StatementBlock(
factory.CodeTransition(),
factory
.Code("try { someMethod(); } catch(Exception) when (someMethod(")
.AsStatement()),
new[] { new RazorError(unbalancedParenErrorString, 45, 0, 45, 1) }
},
{
"@try { someMethod(); } catch(Exception) when (true) {",
new StatementBlock(
factory.CodeTransition(),
factory
.Code("try { someMethod(); } catch(Exception) when (true) {")
.AsStatement()),
new[] { new RazorError(unbalancedBracketCatchErrorString, 23, 0, 23, 1) }
},
};
}
}
[Theory]
[MemberData(nameof(ExceptionFilterErrorData))]
public void ExceptionFilterErrors(
string document,
object expectedStatement,
object expectedErrors)
{
FixupSpans = true;
// Act & Assert
ParseBlockTest(document, (StatementBlock)expectedStatement, (RazorError[])expectedErrors);
}
[Fact]
public void FinallyClause()
{
ParseBlockTest("@try { foo(); } finally { Dispose(); }",
new StatementBlock(
Factory.CodeTransition(),
Factory.Code("try { foo(); } finally { Dispose(); }")
.AsStatement()
.Accepts(AcceptedCharactersInternal.None)
));
}
public static TheoryData StaticUsingData
{
get
{
var factory = new SpanFactory();
Func<string, string, DirectiveBlock> createUsing = (code, import) =>
new DirectiveBlock(
factory.CodeTransition(),
factory.Code(code)
.AsNamespaceImport(import)
.Accepts(AcceptedCharactersInternal.AnyExceptNewline));
// document, expectedResult
return new TheoryData<string, DirectiveBlock>
{
{ "@using static", createUsing("using static", " static") },
{ "@using static ", createUsing("using static ", " static ") },
{ "@using static ", createUsing("using static ", " static ") },
{ "@using static System", createUsing("using static System", " static System") },
{
"@using static System",
createUsing("using static System", " static System")
},
{
"@using static System.Console",
createUsing("using static System.Console", " static System.Console")
},
{
"@using static global::System.Console",
createUsing("using static global::System.Console", " static global::System.Console")
},
{
"@using static global::System.Console ",
createUsing("using static global::System.Console", " static global::System.Console")
},
};
}
}
[Theory]
[MemberData(nameof(StaticUsingData))]
public void StaticUsingImport(string document, object expectedResult)
{
FixupSpans = true;
// Act & Assert
ParseBlockTest(document, (DirectiveBlock)expectedResult);
}
[Fact]
public void UsingStatement()
{
ParseBlockTest("@using(var foo = new Foo()) { foo.Bar(); }",
new StatementBlock(
Factory.CodeTransition(),
Factory.Code("using(var foo = new Foo()) { foo.Bar(); }")
.AsStatement()
.Accepts(AcceptedCharactersInternal.None)
));
}
[Fact]
public void UsingTypeAlias()
{
ParseBlockTest("@using StringDictionary = System.Collections.Generic.Dictionary<string, string>",
new DirectiveBlock(
Factory.CodeTransition(),
Factory.Code("using StringDictionary = System.Collections.Generic.Dictionary<string, string>")
.AsNamespaceImport(" StringDictionary = System.Collections.Generic.Dictionary<string, string>")
.Accepts(AcceptedCharactersInternal.AnyExceptNewline)
));
}
[Fact]
public void UsingNamespaceImport()
{
ParseBlockTest("@using System.Text.Encoding.ASCIIEncoding",
new DirectiveBlock(
Factory.CodeTransition(),
Factory.Code("using System.Text.Encoding.ASCIIEncoding")
.AsNamespaceImport(" System.Text.Encoding.ASCIIEncoding")
.Accepts(AcceptedCharactersInternal.AnyExceptNewline)
));
}
[Fact]
public void DoStatement()
{
ParseBlockTest("@do { foo(); } while(true);",
new StatementBlock(
Factory.CodeTransition(),
Factory.Code("do { foo(); } while(true);")
.AsStatement()
.Accepts(AcceptedCharactersInternal.None)
));
}
[Fact]
public void NonBlockKeywordTreatedAsImplicitExpression()
{
ParseBlockTest("@is foo",
new ExpressionBlock(new ExpressionChunkGenerator(),
Factory.CodeTransition(),
Factory.Code("is")
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
.Accepts(AcceptedCharactersInternal.NonWhiteSpace)
));
}
}
}