Support tuples for type directive tokens

This commit is contained in:
Ajay Bhargav Baaskaran 2017-08-11 17:07:43 -07:00
parent 655a693e4a
commit 8d2a9e5929
2 changed files with 89 additions and 1 deletions

View File

@ -957,7 +957,34 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
protected bool NamespaceOrTypeName()
{
if (Optional(CSharpSymbolType.Identifier) || Optional(CSharpSymbolType.Keyword))
if (Optional(CSharpSymbolType.LeftParenthesis))
{
while (!Optional(CSharpSymbolType.RightParenthesis) && !EndOfFile)
{
Optional(CSharpSymbolType.WhiteSpace);
if (!NamespaceOrTypeName())
{
return false;
}
Optional(CSharpSymbolType.WhiteSpace);
Optional(CSharpSymbolType.Identifier);
Optional(CSharpSymbolType.WhiteSpace);
Optional(CSharpSymbolType.Comma);
}
if (At(CSharpSymbolType.WhiteSpace) && NextIs(CSharpSymbolType.QuestionMark))
{
// Only accept the whitespace if we are going to consume the next token.
AcceptAndMoveNext();
}
Optional(CSharpSymbolType.QuestionMark); // Nullable
return true;
}
else if (Optional(CSharpSymbolType.Identifier) || Optional(CSharpSymbolType.Keyword))
{
if (Optional(CSharpSymbolType.DoubleColon))
{
@ -975,8 +1002,20 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
NamespaceOrTypeName();
}
if (At(CSharpSymbolType.WhiteSpace) && NextIs(CSharpSymbolType.QuestionMark))
{
// Only accept the whitespace if we are going to consume the next token.
AcceptAndMoveNext();
}
Optional(CSharpSymbolType.QuestionMark); // Nullable
if (At(CSharpSymbolType.WhiteSpace) && NextIs(CSharpSymbolType.LeftBracket))
{
// Only accept the whitespace if we are going to consume the next token.
AcceptAndMoveNext();
}
while (At(CSharpSymbolType.LeftBracket))
{
Balance(BalancingModes.None);

View File

@ -811,6 +811,55 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
Factory.Span(SpanKindInternal.Code, expectedType, markup: false).AsDirectiveToken(descriptor.Tokens[0])));
}
[Theory]
[InlineData("(bool, int)")]
[InlineData("(int aa, string bb)?")]
[InlineData("( int? q , bool w )")]
[InlineData("( int ? q, bool ?w ,(long ? [])) ?")]
[InlineData("(List<(int, string)?> aa, string bb)")]
[InlineData("(string ss, (int u, List<(string, int)> k, (Char c, bool b, List<int> l)), global::System.Int32[] a)")]
public void DirectiveDescriptor_AllowsTupleTypes(string expectedType)
{
// Arrange
var descriptor = DirectiveDescriptor.CreateDirective(
"custom",
DirectiveKind.SingleLine,
b => b.AddTypeToken());
// Act & Assert
ParseCodeBlockTest(
$"@custom {expectedType}",
new[] { descriptor },
new DirectiveBlock(
new DirectiveChunkGenerator(descriptor),
Factory.CodeTransition(),
Factory.MetaCode("custom").Accepts(AcceptedCharactersInternal.None),
Factory.Span(SpanKindInternal.Code, " ", markup: false).Accepts(AcceptedCharactersInternal.WhiteSpace),
Factory.Span(SpanKindInternal.Code, expectedType, markup: false).AsDirectiveToken(descriptor.Tokens[0])));
}
[Fact]
public void DirectiveDescriptor_AllowsTupleTypes_IgnoresTrailingWhitespace()
{
// Arrange
var descriptor = DirectiveDescriptor.CreateDirective(
"custom",
DirectiveKind.SingleLine,
b => b.AddTypeToken());
// Act & Assert
ParseCodeBlockTest(
$"@custom (bool, int?) ",
new[] { descriptor },
new DirectiveBlock(
new DirectiveChunkGenerator(descriptor),
Factory.CodeTransition(),
Factory.MetaCode("custom").Accepts(AcceptedCharactersInternal.None),
Factory.Span(SpanKindInternal.Code, " ", markup: false).Accepts(AcceptedCharactersInternal.WhiteSpace),
Factory.Span(SpanKindInternal.Code, "(bool, int?)", markup: false).AsDirectiveToken(descriptor.Tokens[0]),
Factory.MetaCode(" ").Accepts(AcceptedCharactersInternal.WhiteSpace)));
}
[Fact]
public void DirectiveDescriptor_ErrorsExtraContentAfterDirective()
{