923 lines
28 KiB
C#
923 lines
28 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 System.Collections.Generic;
|
|
using System.Linq;
|
|
using Microsoft.AspNetCore.Razor.Language.Extensions;
|
|
using Xunit;
|
|
|
|
namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|
{
|
|
public class CSharpDirectivesTest : CsHtmlCodeParserTestBase
|
|
{
|
|
[Fact]
|
|
public void DirectiveDescriptor_FileScopedMultipleOccurring_CanHaveDuplicates()
|
|
{
|
|
// Arrange
|
|
var descriptor = DirectiveDescriptor.CreateDirective(
|
|
"custom",
|
|
DirectiveKind.SingleLine,
|
|
builder =>
|
|
{
|
|
builder.Usage = DirectiveUsage.FileScopedMultipleOccurring;
|
|
builder.AddTypeToken();
|
|
});
|
|
|
|
// Act & Assert
|
|
ParseDocumentTest(
|
|
@"@custom System.Text.Encoding.ASCIIEncoding
|
|
@custom System.Text.Encoding.UTF8Encoding",
|
|
new[] { descriptor });
|
|
}
|
|
|
|
[Fact]
|
|
public void DirectiveDescriptor_FileScopedSinglyOccurring_ErrorsIfDuplicate()
|
|
{
|
|
// Arrange
|
|
var descriptor = DirectiveDescriptor.CreateDirective(
|
|
"custom",
|
|
DirectiveKind.SingleLine,
|
|
builder =>
|
|
{
|
|
builder.Usage = DirectiveUsage.FileScopedSinglyOccurring;
|
|
builder.AddTypeToken();
|
|
});
|
|
|
|
// Act & Assert
|
|
ParseDocumentTest(
|
|
@"@custom System.Text.Encoding.ASCIIEncoding
|
|
@custom System.Text.Encoding.UTF8Encoding",
|
|
new[] { descriptor });
|
|
}
|
|
|
|
[Fact]
|
|
public void DirectiveDescriptor_FileScoped_CanBeBeneathOtherDirectives()
|
|
{
|
|
// Arrange
|
|
var customDescriptor = DirectiveDescriptor.CreateDirective(
|
|
"custom",
|
|
DirectiveKind.SingleLine,
|
|
builder =>
|
|
{
|
|
builder.Usage = DirectiveUsage.FileScopedSinglyOccurring;
|
|
builder.AddTypeToken();
|
|
});
|
|
var somethingDescriptor = DirectiveDescriptor.CreateDirective(
|
|
"something",
|
|
DirectiveKind.SingleLine,
|
|
builder =>
|
|
{
|
|
builder.Usage = DirectiveUsage.FileScopedMultipleOccurring;
|
|
builder.AddMemberToken();
|
|
});
|
|
|
|
// Act & Assert
|
|
ParseDocumentTest(
|
|
@"@custom System.Text.Encoding.ASCIIEncoding
|
|
@something Else",
|
|
new[] { customDescriptor, somethingDescriptor });
|
|
}
|
|
|
|
[Fact]
|
|
public void DirectiveDescriptor_FileScoped_CanBeBeneathOtherWhiteSpaceCommentsAndDirectives()
|
|
{
|
|
// Arrange
|
|
var customDescriptor = DirectiveDescriptor.CreateDirective(
|
|
"custom",
|
|
DirectiveKind.SingleLine,
|
|
builder =>
|
|
{
|
|
builder.Usage = DirectiveUsage.FileScopedSinglyOccurring;
|
|
builder.AddTypeToken();
|
|
});
|
|
var somethingDescriptor = DirectiveDescriptor.CreateDirective(
|
|
"something",
|
|
DirectiveKind.SingleLine,
|
|
builder =>
|
|
{
|
|
builder.Usage = DirectiveUsage.FileScopedMultipleOccurring;
|
|
builder.AddMemberToken();
|
|
});
|
|
|
|
// Act & Assert
|
|
ParseDocumentTest(
|
|
@"@* There are two directives beneath this *@
|
|
@custom System.Text.Encoding.ASCIIEncoding
|
|
|
|
@something Else
|
|
|
|
<p>This is extra</p>",
|
|
new[] { customDescriptor, somethingDescriptor });
|
|
}
|
|
|
|
[Fact]
|
|
public void DirectiveDescriptor_TokensMustBeSeparatedBySpace()
|
|
{
|
|
// Arrange
|
|
var descriptor = DirectiveDescriptor.CreateDirective(
|
|
"custom",
|
|
DirectiveKind.SingleLine,
|
|
b => b.AddStringToken().AddStringToken());
|
|
|
|
// Act & Assert
|
|
ParseCodeBlockTest(
|
|
"@custom \"string1\"\"string2\"",
|
|
new[] { descriptor });
|
|
}
|
|
|
|
[Fact]
|
|
public void DirectiveDescriptor_CanHandleEOFIncompleteNamespaceTokens()
|
|
{
|
|
// Arrange
|
|
var descriptor = DirectiveDescriptor.CreateDirective(
|
|
"custom",
|
|
DirectiveKind.SingleLine,
|
|
b => b.AddNamespaceToken());
|
|
|
|
// Act & Assert
|
|
ParseCodeBlockTest(
|
|
"@custom System.",
|
|
new[] { descriptor });
|
|
}
|
|
|
|
[Fact]
|
|
public void DirectiveDescriptor_CanHandleEOFInvalidNamespaceTokens()
|
|
{
|
|
// Arrange
|
|
var descriptor = DirectiveDescriptor.CreateDirective(
|
|
"custom",
|
|
DirectiveKind.SingleLine,
|
|
b => b.AddNamespaceToken());
|
|
|
|
// Act & Assert
|
|
ParseCodeBlockTest(
|
|
"@custom System<",
|
|
new[] { descriptor });
|
|
}
|
|
[Fact]
|
|
public void DirectiveDescriptor_CanHandleIncompleteNamespaceTokens()
|
|
{
|
|
// Arrange
|
|
var descriptor = DirectiveDescriptor.CreateDirective(
|
|
"custom",
|
|
DirectiveKind.SingleLine,
|
|
b => b.AddNamespaceToken());
|
|
|
|
// Act & Assert
|
|
ParseCodeBlockTest(
|
|
"@custom System." + Environment.NewLine,
|
|
new[] { descriptor });
|
|
}
|
|
|
|
[Fact]
|
|
public void DirectiveDescriptor_CanHandleInvalidNamespaceTokens()
|
|
{
|
|
// Arrange
|
|
var descriptor = DirectiveDescriptor.CreateDirective(
|
|
"custom",
|
|
DirectiveKind.SingleLine,
|
|
b => b.AddNamespaceToken());
|
|
|
|
// Act & Assert
|
|
ParseCodeBlockTest(
|
|
"@custom System<" + Environment.NewLine,
|
|
new[] { descriptor });
|
|
}
|
|
|
|
[Fact]
|
|
public void ExtensibleDirectiveDoesNotErorrIfNotAtStartOfLineBecauseOfWhitespace()
|
|
{
|
|
// Arrange
|
|
var descriptor = DirectiveDescriptor.CreateDirective(
|
|
"custom",
|
|
DirectiveKind.SingleLine,
|
|
b => b.AddTypeToken());
|
|
|
|
// Act & Assert
|
|
ParseCodeBlockTest(Environment.NewLine + " @custom System.Text.Encoding.ASCIIEncoding",
|
|
new[] { descriptor });
|
|
}
|
|
|
|
[Fact]
|
|
public void BuiltInDirectiveDoesNotErorrIfNotAtStartOfLineBecauseOfWhitespace()
|
|
{
|
|
// Act & Assert
|
|
ParseCodeBlockTest(Environment.NewLine + " @addTagHelper \"*, Foo\"");
|
|
}
|
|
|
|
[Fact]
|
|
public void BuiltInDirectiveErrorsIfNotAtStartOfLine()
|
|
{
|
|
// Act & Assert
|
|
ParseCodeBlockTest("{ @addTagHelper \"*, Foo\"" + Environment.NewLine + "}");
|
|
}
|
|
|
|
[Fact]
|
|
public void ExtensibleDirectiveErrorsIfNotAtStartOfLine()
|
|
{
|
|
// Arrange
|
|
var descriptor = DirectiveDescriptor.CreateDirective(
|
|
"custom",
|
|
DirectiveKind.SingleLine,
|
|
b => b.AddTypeToken());
|
|
|
|
// Act & Assert
|
|
ParseCodeBlockTest(
|
|
"{ @custom System.Text.Encoding.ASCIIEncoding" + Environment.NewLine + "}",
|
|
new[] { descriptor });
|
|
}
|
|
|
|
[Fact]
|
|
public void DirectiveDescriptor_UnderstandsTypeTokens()
|
|
{
|
|
// Arrange
|
|
var descriptor = DirectiveDescriptor.CreateDirective(
|
|
"custom",
|
|
DirectiveKind.SingleLine,
|
|
b => b.AddTypeToken());
|
|
|
|
// Act & Assert
|
|
ParseCodeBlockTest(
|
|
"@custom System.Text.Encoding.ASCIIEncoding",
|
|
new[] { descriptor });
|
|
}
|
|
|
|
[Fact]
|
|
public void DirectiveDescriptor_UnderstandsMemberTokens()
|
|
{
|
|
// Arrange
|
|
var descriptor = DirectiveDescriptor.CreateDirective(
|
|
"custom",
|
|
DirectiveKind.SingleLine,
|
|
b => b.AddMemberToken());
|
|
|
|
// Act & Assert
|
|
ParseCodeBlockTest(
|
|
"@custom Some_Member",
|
|
new[] { descriptor });
|
|
}
|
|
|
|
[Fact]
|
|
public void Parser_ParsesNamespaceDirectiveToken_WithSingleSegment()
|
|
{
|
|
// Arrange
|
|
var descriptor = DirectiveDescriptor.CreateDirective(
|
|
"custom",
|
|
DirectiveKind.SingleLine,
|
|
b => b.AddNamespaceToken());
|
|
|
|
// Act & Assert
|
|
ParseCodeBlockTest(
|
|
"@custom BaseNamespace",
|
|
new[] { descriptor });
|
|
}
|
|
|
|
[Fact]
|
|
public void Parser_ParsesNamespaceDirectiveToken_WithMultipleSegments()
|
|
{
|
|
// Arrange
|
|
var descriptor = DirectiveDescriptor.CreateDirective(
|
|
"custom",
|
|
DirectiveKind.SingleLine,
|
|
b => b.AddNamespaceToken());
|
|
|
|
// Act & Assert
|
|
ParseCodeBlockTest(
|
|
"@custom BaseNamespace.Foo.Bar",
|
|
new[] { descriptor });
|
|
}
|
|
|
|
[Fact]
|
|
public void DirectiveDescriptor_UnderstandsStringTokens()
|
|
{
|
|
// Arrange
|
|
var descriptor = DirectiveDescriptor.CreateDirective(
|
|
"custom",
|
|
DirectiveKind.SingleLine,
|
|
b => b.AddStringToken());
|
|
|
|
// Act & Assert
|
|
ParseCodeBlockTest(
|
|
"@custom \"AString\"",
|
|
new[] { descriptor });
|
|
}
|
|
|
|
[Fact]
|
|
public void DirectiveDescriptor_StringToken_ParserErrorForUnquotedValue()
|
|
{
|
|
// Arrange
|
|
var descriptor = DirectiveDescriptor.CreateDirective(
|
|
"custom",
|
|
DirectiveKind.SingleLine,
|
|
b => b.AddStringToken());
|
|
|
|
// Act & Assert
|
|
ParseCodeBlockTest(
|
|
"@custom AString",
|
|
new[] { descriptor });
|
|
}
|
|
|
|
[Fact]
|
|
public void DirectiveDescriptor_StringToken_ParserErrorForNonStringValue()
|
|
{
|
|
// Arrange
|
|
var descriptor = DirectiveDescriptor.CreateDirective(
|
|
"custom",
|
|
DirectiveKind.SingleLine,
|
|
b => b.AddStringToken());
|
|
|
|
// Act & Assert
|
|
ParseCodeBlockTest(
|
|
"@custom {foo?}",
|
|
new[] { descriptor });
|
|
}
|
|
|
|
[Fact]
|
|
public void DirectiveDescriptor_StringToken_ParserErrorForSingleQuotedValue()
|
|
{
|
|
// Arrange
|
|
var descriptor = DirectiveDescriptor.CreateDirective(
|
|
"custom",
|
|
DirectiveKind.SingleLine,
|
|
b => b.AddStringToken());
|
|
|
|
// Act & Assert
|
|
ParseCodeBlockTest(
|
|
"@custom 'AString'",
|
|
new[] { descriptor });
|
|
}
|
|
|
|
[Fact]
|
|
public void DirectiveDescriptor_StringToken_ParserErrorForPartialQuotedValue()
|
|
{
|
|
// Arrange
|
|
var descriptor = DirectiveDescriptor.CreateDirective(
|
|
"custom",
|
|
DirectiveKind.SingleLine,
|
|
b => b.AddStringToken());
|
|
|
|
// Act & Assert
|
|
ParseCodeBlockTest(
|
|
"@custom AString\"",
|
|
new[] { descriptor });
|
|
}
|
|
|
|
[Fact]
|
|
public void DirectiveDescriptor_UnderstandsMultipleTokens()
|
|
{
|
|
// Arrange
|
|
var descriptor = DirectiveDescriptor.CreateDirective(
|
|
"custom",
|
|
DirectiveKind.SingleLine,
|
|
b => b.AddTypeToken().AddMemberToken().AddStringToken());
|
|
|
|
// Act & Assert
|
|
ParseCodeBlockTest(
|
|
"@custom System.Text.Encoding.ASCIIEncoding Some_Member \"AString\"",
|
|
new[] { descriptor });
|
|
}
|
|
|
|
[Fact]
|
|
public void DirectiveDescriptor_UnderstandsRazorBlocks()
|
|
{
|
|
// Arrange
|
|
var descriptor = DirectiveDescriptor.CreateDirective(
|
|
"custom",
|
|
DirectiveKind.RazorBlock,
|
|
b => b.AddStringToken());
|
|
|
|
// Act & Assert
|
|
ParseCodeBlockTest(
|
|
"@custom \"Header\" { <p>F{o}o</p> }",
|
|
new[] { descriptor });
|
|
}
|
|
|
|
[Fact]
|
|
public void DirectiveDescriptor_UnderstandsCodeBlocks()
|
|
{
|
|
// Arrange
|
|
var descriptor = DirectiveDescriptor.CreateDirective(
|
|
"custom",
|
|
DirectiveKind.CodeBlock,
|
|
b => b.AddStringToken());
|
|
|
|
// Act & Assert
|
|
ParseCodeBlockTest(
|
|
"@custom \"Name\" { foo(); bar(); }",
|
|
new[] { descriptor });
|
|
}
|
|
|
|
[Fact]
|
|
public void DirectiveDescriptor_AllowsWhiteSpaceAroundTokens()
|
|
{
|
|
// Arrange
|
|
var descriptor = DirectiveDescriptor.CreateDirective(
|
|
"custom",
|
|
DirectiveKind.SingleLine,
|
|
b => b.AddTypeToken().AddMemberToken());
|
|
|
|
// Act & Assert
|
|
ParseCodeBlockTest(
|
|
"@custom System.Text.Encoding.ASCIIEncoding Some_Member ",
|
|
new[] { descriptor });
|
|
}
|
|
|
|
[Fact]
|
|
public void DirectiveDescriptor_ErrorsForInvalidMemberTokens()
|
|
{
|
|
// Arrange
|
|
var descriptor = DirectiveDescriptor.CreateDirective(
|
|
"custom",
|
|
DirectiveKind.SingleLine,
|
|
b => b.AddMemberToken());
|
|
|
|
// Act & Assert
|
|
ParseCodeBlockTest(
|
|
"@custom -Some_Member",
|
|
new[] { descriptor });
|
|
}
|
|
|
|
[Fact]
|
|
public void DirectiveDescriptor_NoErrorsSemicolonAfterDirective()
|
|
{
|
|
// Arrange
|
|
var descriptor = DirectiveDescriptor.CreateDirective(
|
|
"custom",
|
|
DirectiveKind.SingleLine,
|
|
b => b.AddStringToken());
|
|
|
|
// Act & Assert
|
|
ParseCodeBlockTest(
|
|
"@custom \"hello\" ; ",
|
|
new[] { descriptor });
|
|
}
|
|
|
|
[Fact]
|
|
public void DirectiveDescriptor_AllowsNullableTypes()
|
|
{
|
|
// Arrange
|
|
var variants = new[]
|
|
{
|
|
"string?",
|
|
"string?[]",
|
|
"global::System.Int32?",
|
|
"KeyValuePair<string, string>?",
|
|
"KeyValuePair<string, string>?[]",
|
|
"global::System.Collections.Generic.KeyValuePair<string, string>?[]",
|
|
};
|
|
|
|
var directiveName = "custom";
|
|
var source = $"@{directiveName}";
|
|
var descriptor = DirectiveDescriptor.CreateDirective(
|
|
directiveName,
|
|
DirectiveKind.SingleLine,
|
|
b =>
|
|
{
|
|
b.AddTypeToken();
|
|
b.AddTypeToken();
|
|
b.AddTypeToken();
|
|
b.AddTypeToken();
|
|
b.AddTypeToken();
|
|
b.AddTypeToken();
|
|
});
|
|
|
|
for (var i = 0; i < variants.Length; i++)
|
|
{
|
|
source += $" {variants[i]}";
|
|
}
|
|
|
|
// Act & Assert
|
|
ParseCodeBlockTest(source, new[] { descriptor });
|
|
}
|
|
|
|
[Fact]
|
|
public void DirectiveDescriptor_AllowsTupleTypes()
|
|
{
|
|
// Arrange
|
|
var variants = new[]
|
|
{
|
|
"(bool, int)",
|
|
"(int aa, string bb)?",
|
|
"( int? q , bool w )",
|
|
"( int ? q, bool ?w ,(long ? [])) ?",
|
|
"(List<(int, string)?> aa, string bb)",
|
|
"(string ss, (int u, List<(string, int)> k, (Char c, bool b, List<int> l)), global::System.Int32[] a)",
|
|
};
|
|
|
|
var directiveName = "custom";
|
|
var source = $"@{directiveName}";
|
|
var descriptor = DirectiveDescriptor.CreateDirective(
|
|
directiveName,
|
|
DirectiveKind.SingleLine,
|
|
b =>
|
|
{
|
|
b.AddTypeToken();
|
|
b.AddTypeToken();
|
|
b.AddTypeToken();
|
|
b.AddTypeToken();
|
|
b.AddTypeToken();
|
|
b.AddTypeToken();
|
|
});
|
|
|
|
for (var i = 0; i < variants.Length; i++)
|
|
{
|
|
source += $" {variants[i]}";
|
|
}
|
|
|
|
// Act & Assert
|
|
ParseCodeBlockTest(source, new[] { descriptor });
|
|
}
|
|
|
|
[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 });
|
|
}
|
|
|
|
[Fact]
|
|
public void DirectiveDescriptor_ErrorsExtraContentAfterDirective()
|
|
{
|
|
// Arrange
|
|
var descriptor = DirectiveDescriptor.CreateDirective(
|
|
"custom",
|
|
DirectiveKind.SingleLine,
|
|
b => b.AddStringToken());
|
|
|
|
// Act & Assert
|
|
ParseCodeBlockTest(
|
|
"@custom \"hello\" \"world\"",
|
|
new[] { descriptor });
|
|
}
|
|
|
|
[Fact]
|
|
public void DirectiveDescriptor_ErrorsWhenExtraContentBeforeBlockStart()
|
|
{
|
|
// Arrange
|
|
var descriptor = DirectiveDescriptor.CreateDirective(
|
|
"custom",
|
|
DirectiveKind.CodeBlock,
|
|
b => b.AddStringToken());
|
|
|
|
// Act & Assert
|
|
ParseCodeBlockTest(
|
|
"@custom \"Hello\" World { foo(); bar(); }",
|
|
new[] { descriptor });
|
|
}
|
|
|
|
[Fact]
|
|
public void DirectiveDescriptor_ErrorsWhenEOFBeforeDirectiveBlockStart()
|
|
{
|
|
// Arrange
|
|
var descriptor = DirectiveDescriptor.CreateDirective(
|
|
"custom",
|
|
DirectiveKind.CodeBlock,
|
|
b => b.AddStringToken());
|
|
|
|
// Act & Assert
|
|
ParseCodeBlockTest(
|
|
"@custom \"Hello\"",
|
|
new[] { descriptor });
|
|
}
|
|
|
|
[Fact]
|
|
public void DirectiveDescriptor_ErrorsWhenMissingEndBrace()
|
|
{
|
|
// Arrange
|
|
var descriptor = DirectiveDescriptor.CreateDirective(
|
|
"custom",
|
|
DirectiveKind.CodeBlock,
|
|
b => b.AddStringToken());
|
|
|
|
// Act & Assert
|
|
ParseCodeBlockTest(
|
|
"@custom \"Hello\" {",
|
|
new[] { descriptor });
|
|
}
|
|
|
|
[Fact]
|
|
public void TagHelperPrefixDirective_NoValueSucceeds()
|
|
{
|
|
ParseBlockTest("@tagHelperPrefix \"\"");
|
|
}
|
|
|
|
[Fact]
|
|
public void TagHelperPrefixDirective_Succeeds()
|
|
{
|
|
ParseBlockTest("@tagHelperPrefix Foo");
|
|
}
|
|
|
|
[Fact]
|
|
public void TagHelperPrefixDirective_WithQuotes_Succeeds()
|
|
{
|
|
ParseBlockTest("@tagHelperPrefix \"Foo\"");
|
|
}
|
|
|
|
[Fact]
|
|
public void TagHelperPrefixDirective_RequiresValue()
|
|
{
|
|
ParseBlockTest("@tagHelperPrefix ");
|
|
}
|
|
|
|
[Fact]
|
|
public void TagHelperPrefixDirective_StartQuoteRequiresDoubleQuotesAroundValue()
|
|
{
|
|
ParseBlockTest("@tagHelperPrefix \"Foo");
|
|
}
|
|
|
|
[Fact]
|
|
public void TagHelperPrefixDirective_EndQuoteRequiresDoubleQuotesAroundValue()
|
|
{
|
|
ParseBlockTest("@tagHelperPrefix Foo \"");
|
|
}
|
|
|
|
[Fact]
|
|
public void RemoveTagHelperDirective_NoValue_Invalid()
|
|
{
|
|
ParseBlockTest("@removeTagHelper \"\"");
|
|
}
|
|
|
|
[Fact]
|
|
public void RemoveTagHelperDirective_InvalidLookupText_AddsError()
|
|
{
|
|
ParseBlockTest("@removeTagHelper Foo");
|
|
}
|
|
|
|
[Fact]
|
|
public void RemoveTagHelperDirective_SingleQuotes_AddsError()
|
|
{
|
|
ParseBlockTest("@removeTagHelper '*, Foo'");
|
|
}
|
|
|
|
[Fact]
|
|
public void RemoveTagHelperDirective_WithQuotes_InvalidLookupText_AddsError()
|
|
{
|
|
ParseBlockTest("@removeTagHelper \"Foo\"");
|
|
}
|
|
|
|
[Fact]
|
|
public void RemoveTagHelperDirective_SupportsSpaces()
|
|
{
|
|
ParseBlockTest("@removeTagHelper Foo, Bar ");
|
|
}
|
|
|
|
[Fact]
|
|
public void RemoveTagHelperDirective_RequiresValue()
|
|
{
|
|
ParseBlockTest("@removeTagHelper ");
|
|
}
|
|
|
|
[Fact]
|
|
public void RemoveTagHelperDirective_StartQuoteRequiresDoubleQuotesAroundValue()
|
|
{
|
|
// Arrange
|
|
ParseBlockTest("@removeTagHelper \"Foo");
|
|
}
|
|
|
|
[Fact]
|
|
public void RemoveTagHelperDirective_EndQuoteRequiresDoubleQuotesAroundValue()
|
|
{
|
|
ParseBlockTest("@removeTagHelper Foo\"");
|
|
}
|
|
|
|
[Fact]
|
|
public void AddTagHelperDirective_NoValue_Invalid()
|
|
{
|
|
ParseBlockTest("@addTagHelper \"\"");
|
|
}
|
|
|
|
[Fact]
|
|
public void AddTagHelperDirective_InvalidLookupText_AddsError()
|
|
{
|
|
ParseBlockTest("@addTagHelper Foo");
|
|
}
|
|
|
|
[Fact]
|
|
public void AddTagHelperDirective_WithQuotes_InvalidLookupText_AddsError()
|
|
{
|
|
ParseBlockTest("@addTagHelper \"Foo\"");
|
|
}
|
|
|
|
[Fact]
|
|
public void AddTagHelperDirective_SingleQuotes_AddsError()
|
|
{
|
|
ParseBlockTest("@addTagHelper '*, Foo'");
|
|
}
|
|
|
|
[Fact]
|
|
public void AddTagHelperDirective_SupportsSpaces()
|
|
{
|
|
ParseBlockTest("@addTagHelper Foo, Bar ");
|
|
}
|
|
|
|
[Fact]
|
|
public void AddTagHelperDirective_RequiresValue()
|
|
{
|
|
ParseBlockTest("@addTagHelper ");
|
|
}
|
|
|
|
[Fact]
|
|
public void AddTagHelperDirective_StartQuoteRequiresDoubleQuotesAroundValue()
|
|
{
|
|
ParseBlockTest("@addTagHelper \"Foo");
|
|
}
|
|
|
|
[Fact]
|
|
public void AddTagHelperDirective_EndQuoteRequiresDoubleQuotesAroundValue()
|
|
{
|
|
ParseBlockTest("@addTagHelper Foo\"");
|
|
}
|
|
|
|
[Fact]
|
|
public void InheritsDirectiveSupportsArrays()
|
|
{
|
|
ParseDocumentTest(
|
|
"@inherits string[[]][]",
|
|
new[] { InheritsDirective.Directive, });
|
|
}
|
|
|
|
[Fact]
|
|
public void InheritsDirectiveSupportsNestedGenerics()
|
|
{
|
|
ParseDocumentTest(
|
|
"@inherits System.Web.Mvc.WebViewPage<IEnumerable<MvcApplication2.Models.RegisterModel>>",
|
|
new[] { InheritsDirective.Directive, });
|
|
}
|
|
|
|
[Fact]
|
|
public void InheritsDirectiveSupportsTypeKeywords()
|
|
{
|
|
ParseDocumentTest(
|
|
"@inherits string",
|
|
new[] { InheritsDirective.Directive, });
|
|
}
|
|
|
|
[Fact]
|
|
public void Parse_FunctionsDirective()
|
|
{
|
|
ParseCodeBlockTest(
|
|
"@functions { foo(); bar(); }",
|
|
new[] { FunctionsDirective.Directive, });
|
|
}
|
|
|
|
[Fact]
|
|
public void EmptyFunctionsDirective()
|
|
{
|
|
ParseCodeBlockTest(
|
|
"@functions { }",
|
|
new[] { FunctionsDirective.Directive, });
|
|
}
|
|
|
|
[Fact]
|
|
public void Parse_SectionDirective()
|
|
{
|
|
ParseCodeBlockTest(
|
|
"@section Header { <p>F{o}o</p> }",
|
|
new[] { SectionDirective.Directive, });
|
|
}
|
|
|
|
[Fact]
|
|
public void OptionalDirectiveTokens_AreSkipped()
|
|
{
|
|
// Arrange
|
|
var descriptor = DirectiveDescriptor.CreateDirective(
|
|
"custom",
|
|
DirectiveKind.SingleLine,
|
|
b => b.AddOptionalStringToken());
|
|
|
|
// Act & Assert
|
|
ParseCodeBlockTest(
|
|
"@custom ",
|
|
new[] { descriptor });
|
|
}
|
|
|
|
[Fact]
|
|
public void OptionalDirectiveTokens_WithSimpleTokens_AreParsed()
|
|
{
|
|
// Arrange
|
|
var descriptor = DirectiveDescriptor.CreateDirective(
|
|
"custom",
|
|
DirectiveKind.SingleLine,
|
|
b => b.AddOptionalStringToken());
|
|
|
|
// Act & Assert
|
|
ParseCodeBlockTest(
|
|
"@custom \"simple-value\"",
|
|
new[] { descriptor });
|
|
}
|
|
|
|
[Fact]
|
|
public void OptionalDirectiveTokens_WithBraces_AreParsed()
|
|
{
|
|
// Arrange
|
|
var descriptor = DirectiveDescriptor.CreateDirective(
|
|
"custom",
|
|
DirectiveKind.SingleLine,
|
|
b => b.AddOptionalStringToken());
|
|
|
|
// Act & Assert
|
|
ParseCodeBlockTest(
|
|
"@custom \"{formaction}?/{id}?\"",
|
|
new[] { descriptor });
|
|
}
|
|
|
|
[Fact]
|
|
public void OptionalDirectiveTokens_WithMultipleOptionalTokens_AreParsed()
|
|
{
|
|
// Arrange
|
|
var descriptor = DirectiveDescriptor.CreateDirective(
|
|
"custom",
|
|
DirectiveKind.SingleLine,
|
|
b => b.AddOptionalStringToken().AddOptionalTypeToken());
|
|
|
|
// Act & Assert
|
|
ParseCodeBlockTest(
|
|
"@custom \"{formaction}?/{id}?\" System.String",
|
|
new[] { descriptor });
|
|
}
|
|
|
|
[Fact]
|
|
public void OptionalMemberTokens_WithMissingMember_IsParsed()
|
|
{
|
|
// Arrange
|
|
var descriptor = DirectiveDescriptor.CreateDirective(
|
|
"TestDirective",
|
|
DirectiveKind.SingleLine,
|
|
b => b.AddOptionalMemberToken().AddOptionalStringToken());
|
|
|
|
// Act & Assert
|
|
ParseCodeBlockTest(
|
|
"@TestDirective ",
|
|
new[] { descriptor });
|
|
}
|
|
|
|
[Fact]
|
|
public void OptionalMemberTokens_WithMemberSpecified_IsParsed()
|
|
{
|
|
// Arrange
|
|
var descriptor = DirectiveDescriptor.CreateDirective(
|
|
"TestDirective",
|
|
DirectiveKind.SingleLine,
|
|
b => b.AddOptionalMemberToken().AddOptionalStringToken());
|
|
|
|
// Act & Assert
|
|
ParseCodeBlockTest(
|
|
"@TestDirective PropertyName",
|
|
new[] { descriptor });
|
|
}
|
|
|
|
[Fact]
|
|
public void Directives_CanUseReservedWord_Class()
|
|
{
|
|
// Arrange
|
|
var descriptor = DirectiveDescriptor.CreateDirective(
|
|
"class",
|
|
DirectiveKind.SingleLine);
|
|
|
|
// Act & Assert
|
|
ParseCodeBlockTest(
|
|
"@class",
|
|
new[] { descriptor });
|
|
}
|
|
|
|
[Fact]
|
|
public void Directives_CanUseReservedWord_Namespace()
|
|
{
|
|
// Arrange
|
|
var descriptor = DirectiveDescriptor.CreateDirective(
|
|
"namespace",
|
|
DirectiveKind.SingleLine);
|
|
|
|
// Act & Assert
|
|
ParseCodeBlockTest(
|
|
"@namespace",
|
|
new[] { descriptor });
|
|
}
|
|
|
|
internal virtual void ParseCodeBlockTest(string document)
|
|
{
|
|
ParseCodeBlockTest(document, Array.Empty<DirectiveDescriptor>());
|
|
}
|
|
|
|
internal virtual void ParseCodeBlockTest(
|
|
string document,
|
|
IEnumerable<DirectiveDescriptor> descriptors,
|
|
Block expected = null,
|
|
params RazorDiagnostic[] expectedErrors)
|
|
{
|
|
var result = ParseCodeBlock(RazorLanguageVersion.Latest, document, descriptors, designTime: false);
|
|
|
|
BaselineTest(result);
|
|
}
|
|
}
|
|
}
|