Some API cleanup around directivest

This commit is contained in:
Ryan Nowak 2017-05-10 17:40:51 -07:00
parent ab98c5d837
commit b17e506ce8
27 changed files with 715 additions and 347 deletions

View File

@ -11,7 +11,10 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
{ {
public static class InjectDirective public static class InjectDirective
{ {
public static readonly DirectiveDescriptor Directive = DirectiveDescriptorBuilder.Create("inject").AddType().AddMember().Build(); public static readonly DirectiveDescriptor Directive = DirectiveDescriptor.CreateDirective(
"inject",
DirectiveKind.SingleLine,
builder => builder.AddTypeToken().AddMemberToken());
public static IRazorEngineBuilder Register(IRazorEngineBuilder builder) public static IRazorEngineBuilder Register(IRazorEngineBuilder builder)
{ {

View File

@ -11,7 +11,10 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
{ {
public static class ModelDirective public static class ModelDirective
{ {
public static readonly DirectiveDescriptor Directive = DirectiveDescriptorBuilder.Create("model").AddType().Build(); public static readonly DirectiveDescriptor Directive = DirectiveDescriptor.CreateDirective(
"model",
DirectiveKind.SingleLine,
builder => builder.AddTypeToken());
public static IRazorEngineBuilder Register(IRazorEngineBuilder builder) public static IRazorEngineBuilder Register(IRazorEngineBuilder builder)
{ {

View File

@ -12,9 +12,12 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
{ {
public static class NamespaceDirective public static class NamespaceDirective
{ {
private static readonly char[] Separators = new char[] { '\\', '/' }; private static readonly char[] Separators = new char[] { '\\', '/' };
public static readonly DirectiveDescriptor Directive = DirectiveDescriptorBuilder.Create("namespace").AddNamespace().Build(); public static readonly DirectiveDescriptor Directive = DirectiveDescriptor.CreateDirective(
"namespace",
DirectiveKind.SingleLine,
builder => builder.AddNamespaceToken());
public static void Register(IRazorEngineBuilder builder) public static void Register(IRazorEngineBuilder builder)
{ {

View File

@ -11,12 +11,10 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
{ {
public class PageDirective public class PageDirective
{ {
public static readonly DirectiveDescriptor DirectiveDescriptor = DirectiveDescriptorBuilder public static readonly DirectiveDescriptor Directive = DirectiveDescriptor.CreateDirective(
.Create("page") "page",
.BeginOptionals() DirectiveKind.SingleLine,
.AddString() // Route template builder => builder.AddOptionalStringToken());
.AddString() // Page Name
.Build();
private PageDirective(string routeTemplate, string pageName) private PageDirective(string routeTemplate, string pageName)
{ {
@ -30,7 +28,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
public static IRazorEngineBuilder Register(IRazorEngineBuilder builder) public static IRazorEngineBuilder Register(IRazorEngineBuilder builder)
{ {
builder.AddDirective(DirectiveDescriptor); builder.AddDirective(Directive);
return builder; return builder;
} }
@ -80,7 +78,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
public override void VisitDirective(DirectiveIRNode node) public override void VisitDirective(DirectiveIRNode node)
{ {
if (node.Descriptor == DirectiveDescriptor) if (node.Descriptor == Directive)
{ {
DirectiveNode = node; DirectiveNode = node;
} }

View File

@ -199,7 +199,7 @@ namespace Microsoft.AspNetCore.Razor.Language
public override void VisitDirectiveBlock(DirectiveChunkGenerator chunkGenerator, Block block) public override void VisitDirectiveBlock(DirectiveChunkGenerator chunkGenerator, Block block)
{ {
if (chunkGenerator.Descriptor.Kind == DirectiveDescriptorKind.SingleLine) if (chunkGenerator.Descriptor.Kind == DirectiveKind.SingleLine)
{ {
_insideLineDirective = true; _insideLineDirective = true;

View File

@ -1,16 +1,163 @@
// Copyright(c) .NET Foundation.All rights reserved. // 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. // 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.Collections.Generic;
using System.Linq;
namespace Microsoft.AspNetCore.Razor.Language namespace Microsoft.AspNetCore.Razor.Language
{ {
public class DirectiveDescriptor public abstract class DirectiveDescriptor
{ {
public string Name { get; set; } public abstract string Name { get; }
public DirectiveDescriptorKind Kind { get; set; } public abstract DirectiveKind Kind { get; }
public IReadOnlyList<DirectiveTokenDescriptor> Tokens { get; set; } public abstract IReadOnlyList<DirectiveTokenDescriptor> Tokens { get; }
public static DirectiveDescriptor CreateDirective(string name, DirectiveKind kind)
{
if (name == null)
{
throw new ArgumentNullException(nameof(name));
}
return CreateDirective(name, kind, configure: null);
}
public static DirectiveDescriptor CreateDirective(string name, DirectiveKind kind, Action<IDirectiveDescriptorBuilder> configure)
{
if (name == null)
{
throw new ArgumentNullException(nameof(name));
}
var builder = new DefaultDirectiveDescriptorBuilder(name, kind);
configure?.Invoke(builder);
return builder.Build();
}
public static DirectiveDescriptor CreateSingleLineDirective(string name)
{
if (name == null)
{
throw new ArgumentNullException(nameof(name));
}
return CreateDirective(name, DirectiveKind.SingleLine, configure: null);
}
public static DirectiveDescriptor CreateSingleLineDirective(string name, Action<IDirectiveDescriptorBuilder> configure)
{
if (name == null)
{
throw new ArgumentNullException(nameof(name));
}
return CreateDirective(name, DirectiveKind.SingleLine, configure);
}
public static DirectiveDescriptor CreateRazorBlockDirective(string name)
{
if (name == null)
{
throw new ArgumentNullException(nameof(name));
}
return CreateDirective(name, DirectiveKind.RazorBlock, configure: null);
}
public static DirectiveDescriptor CreateRazorBlockDirective(string name, Action<IDirectiveDescriptorBuilder> configure)
{
if (name == null)
{
throw new ArgumentNullException(nameof(name));
}
return CreateDirective(name, DirectiveKind.RazorBlock, configure);
}
public static DirectiveDescriptor CreateCodeBlockDirective(string name)
{
if (name == null)
{
throw new ArgumentNullException(nameof(name));
}
return CreateDirective(name, DirectiveKind.CodeBlock, configure: null);
}
public static DirectiveDescriptor CreateCodeBlockDirective(string name, Action<IDirectiveDescriptorBuilder> configure)
{
if (name == null)
{
throw new ArgumentNullException(nameof(name));
}
return CreateDirective(name, DirectiveKind.CodeBlock, configure);
}
private class DefaultDirectiveDescriptorBuilder : IDirectiveDescriptorBuilder
{
public DefaultDirectiveDescriptorBuilder(string name, DirectiveKind kind)
{
Name = name;
Kind = kind;
Tokens = new List<DirectiveTokenDescriptor>();
}
public string Name { get; }
public DirectiveKind Kind { get; }
public IList<DirectiveTokenDescriptor> Tokens { get; }
public DirectiveDescriptor Build()
{
if (Name.Length == 0)
{
throw new InvalidOperationException(Resources.FormatDirectiveDescriptor_InvalidDirectiveName(Name));
}
for (var i = 0; i < Name.Length; i++)
{
if (!char.IsLetter(Name[i]))
{
throw new InvalidOperationException(Resources.FormatDirectiveDescriptor_InvalidDirectiveName(Name));
}
}
var foundOptionalToken = false;
for (var i = 0; i < Tokens.Count; i++)
{
var token = Tokens[i];
foundOptionalToken |= token.Optional;
if (foundOptionalToken && !token.Optional)
{
throw new InvalidOperationException(Resources.DirectiveDescriptor_InvalidNonOptionalToken);
}
}
return new DefaultDirectiveDescriptor(Name, Kind, Tokens.ToArray());
}
}
private class DefaultDirectiveDescriptor : DirectiveDescriptor
{
public DefaultDirectiveDescriptor(string name, DirectiveKind kind, DirectiveTokenDescriptor[] tokens)
{
Name = name;
Kind = kind;
Tokens = tokens;
}
public override string Name { get; }
public override DirectiveKind Kind { get; }
public override IReadOnlyList<DirectiveTokenDescriptor> Tokens { get; }
}
} }
} }

View File

@ -1,113 +0,0 @@
// 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;
namespace Microsoft.AspNetCore.Razor.Language
{
public static class DirectiveDescriptorBuilder
{
public static IDirectiveDescriptorBuilder Create(string name)
{
return new DefaultDirectiveDescriptorBuilder(name, DirectiveDescriptorKind.SingleLine);
}
public static IDirectiveDescriptorBuilder CreateRazorBlock(string name)
{
return new DefaultDirectiveDescriptorBuilder(name, DirectiveDescriptorKind.RazorBlock);
}
public static IDirectiveDescriptorBuilder CreateCodeBlock(string name)
{
return new DefaultDirectiveDescriptorBuilder(name, DirectiveDescriptorKind.CodeBlock);
}
private class DefaultDirectiveDescriptorBuilder : IDirectiveDescriptorBuilder
{
private readonly List<DirectiveTokenDescriptor> _tokenDescriptors;
private readonly string _name;
private readonly DirectiveDescriptorKind _type;
private bool _optional;
public DefaultDirectiveDescriptorBuilder(string name, DirectiveDescriptorKind type)
{
_name = name;
_type = type;
_tokenDescriptors = new List<DirectiveTokenDescriptor>();
}
public IDirectiveDescriptorBuilder AddType()
{
var descriptor = new DirectiveTokenDescriptor()
{
Kind = DirectiveTokenKind.Type,
Optional = _optional,
};
_tokenDescriptors.Add(descriptor);
return this;
}
public IDirectiveDescriptorBuilder AddMember()
{
var descriptor = new DirectiveTokenDescriptor()
{
Kind = DirectiveTokenKind.Member,
Optional = _optional,
};
_tokenDescriptors.Add(descriptor);
return this;
}
public IDirectiveDescriptorBuilder AddNamespace()
{
var descriptor = new DirectiveTokenDescriptor()
{
Kind = DirectiveTokenKind.Namespace,
Optional = _optional,
};
_tokenDescriptors.Add(descriptor);
return this;
}
public IDirectiveDescriptorBuilder AddString()
{
var descriptor = new DirectiveTokenDescriptor()
{
Kind = DirectiveTokenKind.String,
Optional = _optional,
};
_tokenDescriptors.Add(descriptor);
return this;
}
public IDirectiveDescriptorBuilder BeginOptionals()
{
if (_optional)
{
throw new InvalidOperationException(
Resources.FormatDirectiveDescriptor_BeginOptionalsAlreadyInvoked(nameof(BeginOptionals)));
}
_optional = true;
return this;
}
public DirectiveDescriptor Build()
{
var descriptor = new DirectiveDescriptor
{
Name = _name,
Kind = _type,
Tokens = _tokenDescriptors,
};
return descriptor;
}
}
}
}

View File

@ -0,0 +1,98 @@
// 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;
namespace Microsoft.AspNetCore.Razor.Language
{
public static class DirectiveDescriptorBuilderExtensions
{
public static IDirectiveDescriptorBuilder AddMemberToken(this IDirectiveDescriptorBuilder builder)
{
if (builder == null)
{
throw new ArgumentNullException(nameof(builder));
}
builder.Tokens.Add(DirectiveTokenDescriptor.CreateToken(DirectiveTokenKind.Member));
return builder;
}
public static IDirectiveDescriptorBuilder AddNamespaceToken(this IDirectiveDescriptorBuilder builder)
{
if (builder == null)
{
throw new ArgumentNullException(nameof(builder));
}
builder.Tokens.Add(DirectiveTokenDescriptor.CreateToken(DirectiveTokenKind.Namespace));
return builder;
}
public static IDirectiveDescriptorBuilder AddStringToken(this IDirectiveDescriptorBuilder builder)
{
if (builder == null)
{
throw new ArgumentNullException(nameof(builder));
}
builder.Tokens.Add(DirectiveTokenDescriptor.CreateToken(DirectiveTokenKind.String));
return builder;
}
public static IDirectiveDescriptorBuilder AddTypeToken(this IDirectiveDescriptorBuilder builder)
{
if (builder == null)
{
throw new ArgumentNullException(nameof(builder));
}
builder.Tokens.Add(DirectiveTokenDescriptor.CreateToken(DirectiveTokenKind.Type));
return builder;
}
public static IDirectiveDescriptorBuilder AddOptionalMemberToken(this IDirectiveDescriptorBuilder builder)
{
if (builder == null)
{
throw new ArgumentNullException(nameof(builder));
}
builder.Tokens.Add(DirectiveTokenDescriptor.CreateToken(DirectiveTokenKind.Member, optional: true));
return builder;
}
public static IDirectiveDescriptorBuilder AddOptionalNamespaceToken(this IDirectiveDescriptorBuilder builder)
{
if (builder == null)
{
throw new ArgumentNullException(nameof(builder));
}
builder.Tokens.Add(DirectiveTokenDescriptor.CreateToken(DirectiveTokenKind.Namespace, optional: true));
return builder;
}
public static IDirectiveDescriptorBuilder AddOptionalStringToken(this IDirectiveDescriptorBuilder builder)
{
if (builder == null)
{
throw new ArgumentNullException(nameof(builder));
}
builder.Tokens.Add(DirectiveTokenDescriptor.CreateToken(DirectiveTokenKind.String, optional: true));
return builder;
}
public static IDirectiveDescriptorBuilder AddOptionalTypeToken(this IDirectiveDescriptorBuilder builder)
{
if (builder == null)
{
throw new ArgumentNullException(nameof(builder));
}
builder.Tokens.Add(DirectiveTokenDescriptor.CreateToken(DirectiveTokenKind.Type, optional: true));
return builder;
}
}
}

View File

@ -3,7 +3,7 @@
namespace Microsoft.AspNetCore.Razor.Language namespace Microsoft.AspNetCore.Razor.Language
{ {
public enum DirectiveDescriptorKind public enum DirectiveKind
{ {
SingleLine, SingleLine,
RazorBlock, RazorBlock,

View File

@ -3,10 +3,33 @@
namespace Microsoft.AspNetCore.Razor.Language namespace Microsoft.AspNetCore.Razor.Language
{ {
public class DirectiveTokenDescriptor public abstract class DirectiveTokenDescriptor
{ {
public DirectiveTokenKind Kind { get; set; } public abstract DirectiveTokenKind Kind { get; }
public bool Optional { get; set; } public abstract bool Optional { get; }
public static DirectiveTokenDescriptor CreateToken(DirectiveTokenKind kind)
{
return CreateToken(kind, optional: false);
}
public static DirectiveTokenDescriptor CreateToken(DirectiveTokenKind kind, bool optional)
{
return new DefaultDirectiveTokenDescriptor(kind, optional);
}
private class DefaultDirectiveTokenDescriptor : DirectiveTokenDescriptor
{
public DefaultDirectiveTokenDescriptor(DirectiveTokenKind kind, bool optional)
{
Kind = kind;
Optional = optional;
}
public override DirectiveTokenKind Kind { get; }
public override bool Optional { get; }
}
} }
} }

View File

@ -1,19 +1,17 @@
// Copyright(c) .NET Foundation.All rights reserved. // 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. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic;
namespace Microsoft.AspNetCore.Razor.Language namespace Microsoft.AspNetCore.Razor.Language
{ {
public interface IDirectiveDescriptorBuilder public interface IDirectiveDescriptorBuilder
{ {
IDirectiveDescriptorBuilder AddType(); string Name { get; }
IDirectiveDescriptorBuilder AddMember(); DirectiveKind Kind { get; }
IDirectiveDescriptorBuilder AddNamespace(); IList<DirectiveTokenDescriptor> Tokens { get; }
IDirectiveDescriptorBuilder AddString();
IDirectiveDescriptorBuilder BeginOptionals();
DirectiveDescriptor Build(); DirectiveDescriptor Build();
} }

View File

@ -13,40 +13,34 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
private static readonly Func<CSharpSymbol, bool> IsValidStatementSpacingSymbol = private static readonly Func<CSharpSymbol, bool> IsValidStatementSpacingSymbol =
IsSpacingToken(includeNewLines: true, includeComments: true); IsSpacingToken(includeNewLines: true, includeComments: true);
internal static readonly DirectiveDescriptor SectionDirectiveDescriptor = internal static readonly DirectiveDescriptor SectionDirectiveDescriptor = DirectiveDescriptor.CreateDirective(
DirectiveDescriptorBuilder SyntaxConstants.CSharp.SectionKeyword,
.CreateRazorBlock(SyntaxConstants.CSharp.SectionKeyword) DirectiveKind.RazorBlock,
.AddMember() builder => builder.AddMemberToken());
.Build();
internal static readonly DirectiveDescriptor FunctionsDirectiveDescriptor = internal static readonly DirectiveDescriptor FunctionsDirectiveDescriptor = DirectiveDescriptor.CreateDirective(
DirectiveDescriptorBuilder SyntaxConstants.CSharp.FunctionsKeyword,
.CreateCodeBlock(SyntaxConstants.CSharp.FunctionsKeyword) DirectiveKind.CodeBlock);
.Build();
internal static readonly DirectiveDescriptor InheritsDirectiveDescriptor = internal static readonly DirectiveDescriptor InheritsDirectiveDescriptor = DirectiveDescriptor.CreateDirective(
DirectiveDescriptorBuilder SyntaxConstants.CSharp.InheritsKeyword,
.Create(SyntaxConstants.CSharp.InheritsKeyword) DirectiveKind.SingleLine,
.AddType() builder => builder.AddTypeToken());
.Build();
internal static readonly DirectiveDescriptor AddTagHelperDirectiveDescriptor = internal static readonly DirectiveDescriptor AddTagHelperDirectiveDescriptor = DirectiveDescriptor.CreateDirective(
DirectiveDescriptorBuilder SyntaxConstants.CSharp.AddTagHelperKeyword,
.Create(SyntaxConstants.CSharp.AddTagHelperKeyword) DirectiveKind.SingleLine,
.AddString() builder => builder.AddStringToken());
.Build();
internal static readonly DirectiveDescriptor RemoveTagHelperDirectiveDescriptor = internal static readonly DirectiveDescriptor RemoveTagHelperDirectiveDescriptor = DirectiveDescriptor.CreateDirective(
DirectiveDescriptorBuilder SyntaxConstants.CSharp.RemoveTagHelperKeyword,
.Create(SyntaxConstants.CSharp.RemoveTagHelperKeyword) DirectiveKind.SingleLine,
.AddString() builder => builder.AddStringToken());
.Build();
internal static readonly DirectiveDescriptor TagHelperPrefixDirectiveDescriptor = internal static readonly DirectiveDescriptor TagHelperPrefixDirectiveDescriptor = DirectiveDescriptor.CreateDirective(
DirectiveDescriptorBuilder SyntaxConstants.CSharp.TagHelperPrefixKeyword,
.Create(SyntaxConstants.CSharp.TagHelperPrefixKeyword) DirectiveKind.SingleLine,
.AddString() builder => builder.AddStringToken());
.Build();
internal static readonly IEnumerable<DirectiveDescriptor> DefaultDirectiveDescriptors = new[] internal static readonly IEnumerable<DirectiveDescriptor> DefaultDirectiveDescriptors = new[]
{ {
@ -1638,7 +1632,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
switch (descriptor.Kind) switch (descriptor.Kind)
{ {
case DirectiveDescriptorKind.SingleLine: case DirectiveKind.SingleLine:
Optional(CSharpSymbolType.Semicolon); Optional(CSharpSymbolType.Semicolon);
AcceptWhile(IsSpacingToken(includeNewLines: false, includeComments: true)); AcceptWhile(IsSpacingToken(includeNewLines: false, includeComments: true));
@ -1656,7 +1650,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
Output(SpanKind.Markup, AcceptedCharacters.WhiteSpace); Output(SpanKind.Markup, AcceptedCharacters.WhiteSpace);
break; break;
case DirectiveDescriptorKind.RazorBlock: case DirectiveKind.RazorBlock:
AcceptWhile(IsSpacingToken(includeNewLines: true, includeComments: true)); AcceptWhile(IsSpacingToken(includeNewLines: true, includeComments: true));
Output(SpanKind.Markup, AcceptedCharacters.AllWhiteSpace); Output(SpanKind.Markup, AcceptedCharacters.AllWhiteSpace);
@ -1681,7 +1675,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
NextToken(); NextToken();
}); });
break; break;
case DirectiveDescriptorKind.CodeBlock: case DirectiveKind.CodeBlock:
AcceptWhile(IsSpacingToken(includeNewLines: true, includeComments: true)); AcceptWhile(IsSpacingToken(includeNewLines: true, includeComments: true));
Output(SpanKind.Markup, AcceptedCharacters.AllWhiteSpace); Output(SpanKind.Markup, AcceptedCharacters.AllWhiteSpace);

View File

@ -151,18 +151,18 @@ namespace Microsoft.AspNetCore.Razor.Language
=> GetString("RazorProject_PathMustStartWithForwardSlash"); => GetString("RazorProject_PathMustStartWithForwardSlash");
/// <summary> /// <summary>
/// The method '{0}' has already been invoked. /// A non-optional directive token cannot follow an optional directive token.
/// </summary> /// </summary>
internal static string DirectiveDescriptor_BeginOptionalsAlreadyInvoked internal static string DirectiveDescriptor_InvalidNonOptionalToken
{ {
get => GetString("DirectiveDescriptor_BeginOptionalsAlreadyInvoked"); get => GetString("DirectiveDescriptor_InvalidNonOptionalToken");
} }
/// <summary> /// <summary>
/// The method '{0}' has already been invoked. /// A non-optional directive token cannot follow an optional directive token.
/// </summary> /// </summary>
internal static string FormatDirectiveDescriptor_BeginOptionalsAlreadyInvoked(object p0) internal static string FormatDirectiveDescriptor_InvalidNonOptionalToken()
=> string.Format(CultureInfo.CurrentCulture, GetString("DirectiveDescriptor_BeginOptionalsAlreadyInvoked"), p0); => GetString("DirectiveDescriptor_InvalidNonOptionalToken");
/// <summary> /// <summary>
/// The document of kind '{0}' does not have a '{1}'. The document classifier must set a value for '{2}'. /// The document of kind '{0}' does not have a '{1}'. The document classifier must set a value for '{2}'.
@ -388,6 +388,20 @@ namespace Microsoft.AspNetCore.Razor.Language
internal static string FormatInvalidOperation_SpanIsNotChangeOwner(object p0, object p1) internal static string FormatInvalidOperation_SpanIsNotChangeOwner(object p0, object p1)
=> string.Format(CultureInfo.CurrentCulture, GetString("InvalidOperation_SpanIsNotChangeOwner"), p0, p1); => string.Format(CultureInfo.CurrentCulture, GetString("InvalidOperation_SpanIsNotChangeOwner"), p0, p1);
/// <summary>
/// Invalid directive name '{0}'. Directives must have a non-empty name that consists only of letters.
/// </summary>
internal static string DirectiveDescriptor_InvalidDirectiveName
{
get => GetString("DirectiveDescriptor_InvalidDirectiveName");
}
/// <summary>
/// Invalid directive name '{0}'. Directives must have a non-empty name that consists only of letters.
/// </summary>
internal static string FormatDirectiveDescriptor_InvalidDirectiveName(object p0)
=> string.Format(CultureInfo.CurrentCulture, GetString("DirectiveDescriptor_InvalidDirectiveName"), p0);
private static string GetString(string name, params string[] formatterNames) private static string GetString(string name, params string[] formatterNames)
{ {
var value = _resourceManager.GetString(name); var value = _resourceManager.GetString(name);

View File

@ -147,8 +147,8 @@
<data name="RazorProject_PathMustStartWithForwardSlash" xml:space="preserve"> <data name="RazorProject_PathMustStartWithForwardSlash" xml:space="preserve">
<value>Path must begin with a forward slash '/'.</value> <value>Path must begin with a forward slash '/'.</value>
</data> </data>
<data name="DirectiveDescriptor_BeginOptionalsAlreadyInvoked" xml:space="preserve"> <data name="DirectiveDescriptor_InvalidNonOptionalToken" xml:space="preserve">
<value>The method '{0}' has already been invoked.</value> <value>A non-optional directive token cannot follow an optional directive token.</value>
</data> </data>
<data name="DocumentMissingTarget" xml:space="preserve"> <data name="DocumentMissingTarget" xml:space="preserve">
<value>The document of kind '{0}' does not have a '{1}'. The document classifier must set a value for '{2}'.</value> <value>The document of kind '{0}' does not have a '{1}'. The document classifier must set a value for '{2}'.</value>
@ -198,4 +198,7 @@
<data name="InvalidOperation_SpanIsNotChangeOwner" xml:space="preserve"> <data name="InvalidOperation_SpanIsNotChangeOwner" xml:space="preserve">
<value>The node '{0}' is not the owner of change '{1}'.</value> <value>The node '{0}' is not the owner of change '{1}'.</value>
</data> </data>
<data name="DirectiveDescriptor_InvalidDirectiveName" xml:space="preserve">
<value>Invalid directive name '{0}'. Directives must have a non-empty name that consists only of letters.</value>
</data>
</root> </root>

View File

@ -102,25 +102,6 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
Assert.Null(pageDirective.PageName); Assert.Null(pageDirective.PageName);
} }
[Fact]
public void TryGetPageDirective_ParsesPageName()
{
// Arrange
var content = "@page \"some-route\" \"some name\"";
var sourceDocument = RazorSourceDocument.Create(content, "file");
var codeDocument = RazorCodeDocument.Create(sourceDocument);
var engine = CreateEngine();
var irDocument = CreateIRDocument(engine, codeDocument);
// Act
var result = PageDirective.TryGetPageDirective(irDocument, out var pageDirective);
// Assert
Assert.True(result);
Assert.Equal("some-route", pageDirective.RouteTemplate);
Assert.Equal("some name", pageDirective.PageName);
}
private RazorEngine CreateEngine() private RazorEngine CreateEngine()
{ {
return RazorEngine.Create(b => return RazorEngine.Create(b =>

View File

@ -52,10 +52,7 @@ private void __RazorDirectiveTokenHelpers__() {
{ {
Source = new SourceSpan("test.cshtml", 0, 0, 0, 5), Source = new SourceSpan("test.cshtml", 0, 0, 0, 5),
Content = "System.String", Content = "System.String",
Descriptor = new DirectiveTokenDescriptor() Descriptor = DirectiveTokenDescriptor.CreateToken(DirectiveTokenKind.Type),
{
Kind = DirectiveTokenKind.Type
}
}; };
node.Children.Add(token); node.Children.Add(token);
@ -94,10 +91,7 @@ System.String __typeHelper = null;
{ {
Source = new SourceSpan("test.cshtml", 0, 0, 0, 5), Source = new SourceSpan("test.cshtml", 0, 0, 0, 5),
Content = "System.Collections.Generic", Content = "System.Collections.Generic",
Descriptor = new DirectiveTokenDescriptor() Descriptor = DirectiveTokenDescriptor.CreateToken(DirectiveTokenKind.Namespace),
{
Kind = DirectiveTokenKind.Namespace
}
}; };
node.Children.Add(token); node.Children.Add(token);
@ -136,10 +130,7 @@ global::System.Object __typeHelper = nameof(System.Collections.Generic);
{ {
Source = new SourceSpan("test.cshtml", 0, 0, 0, 5), Source = new SourceSpan("test.cshtml", 0, 0, 0, 5),
Content = "Foo", Content = "Foo",
Descriptor = new DirectiveTokenDescriptor() Descriptor = DirectiveTokenDescriptor.CreateToken(DirectiveTokenKind.Member),
{
Kind = DirectiveTokenKind.Member
}
}; };
node.Children.Add(token); node.Children.Add(token);
@ -178,19 +169,13 @@ global::System.Object Foo = null;
{ {
Source = new SourceSpan("test.cshtml", 0, 0, 0, 5), Source = new SourceSpan("test.cshtml", 0, 0, 0, 5),
Content = "Value", Content = "Value",
Descriptor = new DirectiveTokenDescriptor() Descriptor = DirectiveTokenDescriptor.CreateToken(DirectiveTokenKind.String),
{
Kind = DirectiveTokenKind.String
}
}; };
var tokenWithQuotedContent = new DirectiveTokenIRNode() var tokenWithQuotedContent = new DirectiveTokenIRNode()
{ {
Source = new SourceSpan("test.cshtml", 0, 0, 0, 5), Source = new SourceSpan("test.cshtml", 0, 0, 0, 5),
Content = "\"Value\"", Content = "\"Value\"",
Descriptor = new DirectiveTokenDescriptor() Descriptor = DirectiveTokenDescriptor.CreateToken(DirectiveTokenKind.String),
{
Kind = DirectiveTokenKind.String
}
}; };
node.Children.Add(token); node.Children.Add(token);
node.Children.Add(tokenWithQuotedContent); node.Children.Add(tokenWithQuotedContent);
@ -233,10 +218,7 @@ global::System.Object __typeHelper = ""Value"";
var token = new DirectiveTokenIRNode() var token = new DirectiveTokenIRNode()
{ {
Content = "Value", Content = "Value",
Descriptor = new DirectiveTokenDescriptor() Descriptor = DirectiveTokenDescriptor.CreateToken(DirectiveTokenKind.String),
{
Kind = DirectiveTokenKind.String
}
}; };
node.Children.Add(token); node.Children.Add(token);

View File

@ -411,7 +411,7 @@ namespace Microsoft.AspNetCore.Razor.Language
// Act // Act
var irDocument = Lower(codeDocument, b => var irDocument = Lower(codeDocument, b =>
{ {
b.AddDirective(DirectiveDescriptorBuilder.Create("test").AddMember().Build()); b.AddDirective(DirectiveDescriptor.CreateDirective("test", DirectiveKind.SingleLine, d => d.AddMemberToken()));
}); });
// Assert // Assert
@ -440,7 +440,7 @@ namespace Microsoft.AspNetCore.Razor.Language
// Act // Act
var irDocument = Lower(codeDocument, b => var irDocument = Lower(codeDocument, b =>
{ {
b.AddDirective(DirectiveDescriptorBuilder.CreateRazorBlock("block").AddMember().Build()); b.AddDirective(DirectiveDescriptor.CreateDirective("block", DirectiveKind.RazorBlock, d => d.AddMemberToken()));
}); });
// Assert // Assert

View File

@ -1,7 +1,6 @@
// Copyright (c) .NET Foundation. All rights reserved. // 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. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using Xunit; using Xunit;
namespace Microsoft.AspNetCore.Razor.Language namespace Microsoft.AspNetCore.Razor.Language
@ -43,7 +42,7 @@ namespace Microsoft.AspNetCore.Razor.Language
// Assert // Assert
var syntaxTree = codeDocument.GetSyntaxTree(); var syntaxTree = codeDocument.GetSyntaxTree();
var directive = Assert.Single(syntaxTree.Options.Directives); var directive = Assert.Single(syntaxTree.Options.Directives);
Assert.Equal("test_directive", directive.Name); Assert.Equal("test", directive.Name);
} }
[Fact] [Fact]
@ -71,8 +70,8 @@ namespace Microsoft.AspNetCore.Razor.Language
// Assert // Assert
Assert.Collection( Assert.Collection(
codeDocument.GetImportSyntaxTrees(), codeDocument.GetImportSyntaxTrees(),
t => { Assert.Same(t.Source, imports[0]); Assert.Equal("test_directive", Assert.Single(t.Options.Directives).Name); }, t => { Assert.Same(t.Source, imports[0]); Assert.Equal("test", Assert.Single(t.Options.Directives).Name); },
t => { Assert.Same(t.Source, imports[1]); Assert.Equal("test_directive", Assert.Single(t.Options.Directives).Name); }); t => { Assert.Same(t.Source, imports[1]); Assert.Equal("test", Assert.Single(t.Options.Directives).Name); });
} }
private class MyParserOptionsFeature : IRazorParserOptionsFeature private class MyParserOptionsFeature : IRazorParserOptionsFeature
@ -83,7 +82,7 @@ namespace Microsoft.AspNetCore.Razor.Language
public void Configure(RazorParserOptions options) public void Configure(RazorParserOptions options)
{ {
options.Directives.Add(DirectiveDescriptorBuilder.Create("test_directive").Build()); options.Directives.Add(DirectiveDescriptor.CreateDirective("test", DirectiveKind.SingleLine));
} }
} }
} }

View File

@ -5,98 +5,102 @@ using Xunit;
namespace Microsoft.AspNetCore.Razor.Language namespace Microsoft.AspNetCore.Razor.Language
{ {
public class DirectiveDescriptorBuilderTest public class DirectiveDescriptorBuilderExtensionsTest
{ {
[Fact] [Fact]
public void Create_BuildsSingleLineDirectiveDescriptor() public void AddMemberToken_AddsToken()
{ {
// Act // Arrange & Act
var descriptor = DirectiveDescriptorBuilder.Create("custom").Build(); var descriptor = DirectiveDescriptor.CreateDirective("custom", DirectiveKind.SingleLine, b => b.AddMemberToken());
// Assert
Assert.Equal(DirectiveDescriptorKind.SingleLine, descriptor.Kind);
}
[Fact]
public void CreateRazorBlock_BuildsRazorBlockDirectiveDescriptor()
{
// Act
var descriptor = DirectiveDescriptorBuilder.CreateRazorBlock("custom").Build();
// Assert
Assert.Equal(DirectiveDescriptorKind.RazorBlock, descriptor.Kind);
}
[Fact]
public void CreateCodeBlock_BuildsCodeBlockDirectiveDescriptor()
{
// Act
var descriptor = DirectiveDescriptorBuilder.CreateCodeBlock("custom").Build();
// Assert
Assert.Equal(DirectiveDescriptorKind.CodeBlock, descriptor.Kind);
}
[Fact]
public void AddType_AddsToken()
{
// Arrange
var builder = DirectiveDescriptorBuilder.Create("custom");
// Act
var descriptor = builder.AddType().Build();
// Assert
var token = Assert.Single(descriptor.Tokens);
Assert.Equal(DirectiveTokenKind.Type, token.Kind);
}
[Fact]
public void AddMember_AddsToken()
{
// Arrange
var builder = DirectiveDescriptorBuilder.Create("custom");
// Act
var descriptor = builder.AddMember().Build();
// Assert // Assert
var token = Assert.Single(descriptor.Tokens); var token = Assert.Single(descriptor.Tokens);
Assert.Equal(DirectiveTokenKind.Member, token.Kind); Assert.Equal(DirectiveTokenKind.Member, token.Kind);
Assert.False(token.Optional);
} }
[Fact] [Fact]
public void AddString_AddsToken() public void AddNamespaceToken_AddsToken()
{ {
// Arrange // Arrange & Act
var builder = DirectiveDescriptorBuilder.Create("custom"); var descriptor = DirectiveDescriptor.CreateDirective("custom", DirectiveKind.SingleLine, b => b.AddNamespaceToken());
// Act // Assert
var descriptor = builder.AddString().Build(); var token = Assert.Single(descriptor.Tokens);
Assert.Equal(DirectiveTokenKind.Namespace, token.Kind);
Assert.False(token.Optional);
}
[Fact]
public void AddStringToken_AddsToken()
{
// Arrange & Act
var descriptor = DirectiveDescriptor.CreateDirective("custom", DirectiveKind.SingleLine, b => b.AddStringToken());
// Assert // Assert
var token = Assert.Single(descriptor.Tokens); var token = Assert.Single(descriptor.Tokens);
Assert.Equal(DirectiveTokenKind.String, token.Kind); Assert.Equal(DirectiveTokenKind.String, token.Kind);
Assert.False(token.Optional);
} }
[Fact] [Fact]
public void AddX_MaintainsMultipleTokens() public void AddTypeToken_AddsToken()
{ {
// Arrange // Arrange & Act
var builder = DirectiveDescriptorBuilder.Create("custom"); var descriptor = DirectiveDescriptor.CreateDirective("custom", DirectiveKind.SingleLine, b => b.AddTypeToken());
// Act
var descriptor = builder
.AddType()
.AddMember()
.AddString()
.Build();
// Assert // Assert
Assert.Collection(descriptor.Tokens, var token = Assert.Single(descriptor.Tokens);
token => Assert.Equal(DirectiveTokenKind.Type, token.Kind), Assert.Equal(DirectiveTokenKind.Type, token.Kind);
token => Assert.Equal(DirectiveTokenKind.Member, token.Kind), Assert.False(token.Optional);
token => Assert.Equal(DirectiveTokenKind.String, token.Kind)); }
[Fact]
public void AddOptionalTypeToken_AddsToken()
{
// Arrange & Act
var descriptor = DirectiveDescriptor.CreateDirective("custom", DirectiveKind.SingleLine, b => b.AddOptionalTypeToken());
// Assert
var token = Assert.Single(descriptor.Tokens);
Assert.Equal(DirectiveTokenKind.Type, token.Kind);
Assert.True(token.Optional);
}
[Fact]
public void AddOptionalMemberToken_AddsToken()
{
// Arrange & Act
var descriptor = DirectiveDescriptor.CreateDirective("custom", DirectiveKind.SingleLine, b => b.AddOptionalMemberToken());
// Assert
var token = Assert.Single(descriptor.Tokens);
Assert.Equal(DirectiveTokenKind.Member, token.Kind);
Assert.True(token.Optional);
}
[Fact]
public void AddOptionalNamespaceToken_AddsToken()
{
// Arrange & Act
var descriptor = DirectiveDescriptor.CreateDirective("custom", DirectiveKind.SingleLine, b => b.AddOptionalNamespaceToken());
// Assert
var token = Assert.Single(descriptor.Tokens);
Assert.Equal(DirectiveTokenKind.Namespace, token.Kind);
Assert.True(token.Optional);
}
[Fact]
public void AddOptionalStringToken_AddsToken()
{
// Arrange & Act
var descriptor = DirectiveDescriptor.CreateDirective("custom", DirectiveKind.SingleLine, b => b.AddOptionalStringToken());
// Assert
var token = Assert.Single(descriptor.Tokens);
Assert.Equal(DirectiveTokenKind.String, token.Kind);
Assert.True(token.Optional);
} }
} }
} }

View File

@ -0,0 +1,150 @@
// 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
{
public class DirectiveDescriptorTest
{
[Fact]
public void CreateDirective_CreatesDirective_WithProvidedKind()
{
// Arrange & Act
var directive = DirectiveDescriptor.CreateDirective("test", DirectiveKind.SingleLine);
// Assert
Assert.Equal("test", directive.Name);
Assert.Equal(DirectiveKind.SingleLine, directive.Kind);
}
[Fact]
public void CreateDirective_WithConfigure_CreatesDirective_WithProvidedKind()
{
// Arrange
var called = false;
Action<IDirectiveDescriptorBuilder> configure = b => { called = true; };
// Act
var directive = DirectiveDescriptor.CreateDirective("test", DirectiveKind.SingleLine, configure);
// Assert
Assert.Equal("test", directive.Name);
Assert.Equal(DirectiveKind.SingleLine, directive.Kind);
Assert.True(called);
}
[Fact]
public void CreateSingleLineDirective_CreatesSingleLineDirective()
{
// Arrange & Act
var directive = DirectiveDescriptor.CreateSingleLineDirective("test");
// Assert
Assert.Equal("test", directive.Name);
Assert.Equal(DirectiveKind.SingleLine, directive.Kind);
}
[Fact]
public void CreateSingleLineDirective_WithConfigure_CreatesSingleLineDirective()
{
// Arrange
var called = false;
Action<IDirectiveDescriptorBuilder> configure = b => { called = true; };
// Act
var directive = DirectiveDescriptor.CreateSingleLineDirective("test", configure);
// Assert
Assert.Equal("test", directive.Name);
Assert.Equal(DirectiveKind.SingleLine, directive.Kind);
Assert.True(called);
}
[Fact]
public void CreateRazorBlockDirective_CreatesRazorBlockDirective()
{
// Arrange & Act
var directive = DirectiveDescriptor.CreateRazorBlockDirective("test");
// Assert
Assert.Equal("test", directive.Name);
Assert.Equal(DirectiveKind.RazorBlock, directive.Kind);
}
[Fact]
public void CreateRazorBlockDirective_WithConfigure_CreatesRazorBlockDirective()
{
// Arrange
var called = false;
Action<IDirectiveDescriptorBuilder> configure = b => { called = true; };
// Act
var directive = DirectiveDescriptor.CreateRazorBlockDirective("test", configure);
// Assert
Assert.Equal("test", directive.Name);
Assert.Equal(DirectiveKind.RazorBlock, directive.Kind);
Assert.True(called);
}
[Fact]
public void CreateCodeBlockDirective_CreatesCodeBlockDirective()
{
// Arrange & Act
var directive = DirectiveDescriptor.CreateCodeBlockDirective("test");
// Assert
Assert.Equal("test", directive.Name);
Assert.Equal(DirectiveKind.CodeBlock, directive.Kind);
}
[Fact]
public void CreateCodeBlockDirective_WithConfigure_CreatesCodeBlockDirective()
{
// Arrange
var called = false;
Action<IDirectiveDescriptorBuilder> configure = b => { called = true; };
// Act
var directive = DirectiveDescriptor.CreateCodeBlockDirective("test", configure);
// Assert
Assert.Equal("test", directive.Name);
Assert.Equal(DirectiveKind.CodeBlock, directive.Kind);
Assert.True(called);
}
[Fact]
public void Build_ValidatesDirectiveName_EmptyIsInvalid()
{
// Arrange & Act
var ex = Assert.Throws<InvalidOperationException>(() => DirectiveDescriptor.CreateSingleLineDirective(""));
// Assert
Assert.Equal("Invalid directive name ''. Directives must have a non-empty name that consists only of letters.", ex.Message);
}
[Fact]
public void Build_ValidatesDirectiveName_InvalidCharacter()
{
// Arrange & Act
var ex = Assert.Throws<InvalidOperationException>(() => DirectiveDescriptor.CreateSingleLineDirective("test_directive"));
// Assert
Assert.Equal("Invalid directive name 'test_directive'. Directives must have a non-empty name that consists only of letters.", ex.Message);
}
[Fact]
public void Build_ValidatesDirectiveName_NonOptionalTokenFollowsOptionalToken()
{
// Arrange & Act
var ex = Assert.Throws<InvalidOperationException>(
() => DirectiveDescriptor.CreateSingleLineDirective("test", b => { b.AddOptionalMemberToken(); b.AddMemberToken(); }));
// Assert
Assert.Equal("A non-optional directive token cannot follow an optional directive token.", ex.Message);
}
}
}

View File

@ -19,8 +19,7 @@ namespace Microsoft.AspNetCore.Razor.Language
var codeDocument = RazorCodeDocument.Create(sourceDocument); var codeDocument = RazorCodeDocument.Create(sourceDocument);
var defaultEngine = RazorEngine.Create(b => var defaultEngine = RazorEngine.Create(b =>
{ {
var customDirective = DirectiveDescriptorBuilder.Create("custom").AddString().Build(); b.AddDirective(DirectiveDescriptor.CreateDirective("custom", DirectiveKind.SingleLine, d => d.AddStringToken()));
b.AddDirective(customDirective);
}); });
var irDocument = Lower(codeDocument, defaultEngine); var irDocument = Lower(codeDocument, defaultEngine);
var pass = new DirectiveRemovalIROptimizationPass() var pass = new DirectiveRemovalIROptimizationPass()
@ -54,8 +53,7 @@ namespace Microsoft.AspNetCore.Razor.Language
var codeDocument = RazorCodeDocument.Create(sourceDocument); var codeDocument = RazorCodeDocument.Create(sourceDocument);
var defaultEngine = RazorEngine.Create(b => var defaultEngine = RazorEngine.Create(b =>
{ {
var customDirective = DirectiveDescriptorBuilder.Create("custom").AddString().Build(); b.AddDirective(DirectiveDescriptor.CreateDirective("custom", DirectiveKind.SingleLine, d => d.AddStringToken()));
b.AddDirective(customDirective);
}); });
var irDocument = Lower(codeDocument, defaultEngine); var irDocument = Lower(codeDocument, defaultEngine);
var pass = new DirectiveRemovalIROptimizationPass() var pass = new DirectiveRemovalIROptimizationPass()

View File

@ -44,7 +44,7 @@ namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests
// Arrange // Arrange
var engine = RazorEngine.Create(b => var engine = RazorEngine.Create(b =>
{ {
b.AddDirective(DirectiveDescriptorBuilder.Create("test_directive").Build()); b.AddDirective(DirectiveDescriptor.CreateDirective("test", DirectiveKind.SingleLine));
}); });
var document = CreateCodeDocument(); var document = CreateCodeDocument();

View File

@ -16,7 +16,7 @@ namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests
{ {
builder.Features.Add(new ApiSetsIRTestAdapter()); builder.Features.Add(new ApiSetsIRTestAdapter());
builder.AddDirective(DirectiveDescriptorBuilder.Create("custom").AddNamespace().Build()); builder.AddDirective(DirectiveDescriptor.CreateDirective("custom", DirectiveKind.SingleLine, b => b.AddNamespaceToken()));
}); });
var document = CreateCodeDocument(); var document = CreateCodeDocument();

View File

@ -14,7 +14,10 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
public void DirectiveDescriptor_UnderstandsTypeTokens() public void DirectiveDescriptor_UnderstandsTypeTokens()
{ {
// Arrange // Arrange
var descriptor = DirectiveDescriptorBuilder.Create("custom").AddType().Build(); var descriptor = DirectiveDescriptor.CreateDirective(
"custom",
DirectiveKind.SingleLine,
b => b.AddTypeToken());
// Act & Assert // Act & Assert
ParseCodeBlockTest( ParseCodeBlockTest(
@ -34,7 +37,10 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
public void DirectiveDescriptor_UnderstandsMemberTokens() public void DirectiveDescriptor_UnderstandsMemberTokens()
{ {
// Arrange // Arrange
var descriptor = DirectiveDescriptorBuilder.Create("custom").AddMember().Build(); var descriptor = DirectiveDescriptor.CreateDirective(
"custom",
DirectiveKind.SingleLine,
b => b.AddMemberToken());
// Act & Assert // Act & Assert
ParseCodeBlockTest( ParseCodeBlockTest(
@ -54,7 +60,10 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
public void Parser_ParsesNamespaceDirectiveToken_WithSingleSegment() public void Parser_ParsesNamespaceDirectiveToken_WithSingleSegment()
{ {
// Arrange // Arrange
var descriptor = DirectiveDescriptorBuilder.Create("custom").AddNamespace().Build(); var descriptor = DirectiveDescriptor.CreateDirective(
"custom",
DirectiveKind.SingleLine,
b => b.AddNamespaceToken());
// Act & Assert // Act & Assert
ParseCodeBlockTest( ParseCodeBlockTest(
@ -74,7 +83,10 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
public void Parser_ParsesNamespaceDirectiveToken_WithMultipleSegments() public void Parser_ParsesNamespaceDirectiveToken_WithMultipleSegments()
{ {
// Arrange // Arrange
var descriptor = DirectiveDescriptorBuilder.Create("custom").AddNamespace().Build(); var descriptor = DirectiveDescriptor.CreateDirective(
"custom",
DirectiveKind.SingleLine,
b => b.AddNamespaceToken());
// Act & Assert // Act & Assert
ParseCodeBlockTest( ParseCodeBlockTest(
@ -94,7 +106,10 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
public void DirectiveDescriptor_UnderstandsStringTokens() public void DirectiveDescriptor_UnderstandsStringTokens()
{ {
// Arrange // Arrange
var descriptor = DirectiveDescriptorBuilder.Create("custom").AddString().Build(); var descriptor = DirectiveDescriptor.CreateDirective(
"custom",
DirectiveKind.SingleLine,
b => b.AddStringToken());
// Act & Assert // Act & Assert
ParseCodeBlockTest( ParseCodeBlockTest(
@ -114,7 +129,11 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
public void DirectiveDescriptor_StringToken_ParserErrorForUnquotedValue() public void DirectiveDescriptor_StringToken_ParserErrorForUnquotedValue()
{ {
// Arrange // Arrange
var descriptor = DirectiveDescriptorBuilder.Create("custom").AddString().Build(); var descriptor = DirectiveDescriptor.CreateDirective(
"custom",
DirectiveKind.SingleLine,
b => b.AddStringToken());
var expectedError = new RazorError( var expectedError = new RazorError(
LegacyResources.FormatDirectiveExpectsQuotedStringLiteral("custom"), LegacyResources.FormatDirectiveExpectsQuotedStringLiteral("custom"),
new SourceLocation(8, 0, 8), new SourceLocation(8, 0, 8),
@ -135,7 +154,11 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
public void DirectiveDescriptor_StringToken_ParserErrorForNonStringValue() public void DirectiveDescriptor_StringToken_ParserErrorForNonStringValue()
{ {
// Arrange // Arrange
var descriptor = DirectiveDescriptorBuilder.Create("custom").AddString().Build(); var descriptor = DirectiveDescriptor.CreateDirective(
"custom",
DirectiveKind.SingleLine,
b => b.AddStringToken());
var expectedError = new RazorError( var expectedError = new RazorError(
LegacyResources.FormatDirectiveExpectsQuotedStringLiteral("custom"), LegacyResources.FormatDirectiveExpectsQuotedStringLiteral("custom"),
new SourceLocation(8, 0, 8), new SourceLocation(8, 0, 8),
@ -156,7 +179,11 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
public void DirectiveDescriptor_StringToken_ParserErrorForSingleQuotedValue() public void DirectiveDescriptor_StringToken_ParserErrorForSingleQuotedValue()
{ {
// Arrange // Arrange
var descriptor = DirectiveDescriptorBuilder.Create("custom").AddString().Build(); var descriptor = DirectiveDescriptor.CreateDirective(
"custom",
DirectiveKind.SingleLine,
b => b.AddStringToken());
var expectedError = new RazorError( var expectedError = new RazorError(
LegacyResources.FormatDirectiveExpectsQuotedStringLiteral("custom"), LegacyResources.FormatDirectiveExpectsQuotedStringLiteral("custom"),
new SourceLocation(8, 0, 8), new SourceLocation(8, 0, 8),
@ -177,7 +204,11 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
public void DirectiveDescriptor_StringToken_ParserErrorForPartialQuotedValue() public void DirectiveDescriptor_StringToken_ParserErrorForPartialQuotedValue()
{ {
// Arrange // Arrange
var descriptor = DirectiveDescriptorBuilder.Create("custom").AddString().Build(); var descriptor = DirectiveDescriptor.CreateDirective(
"custom",
DirectiveKind.SingleLine,
b => b.AddStringToken());
var expectedError = new RazorError( var expectedError = new RazorError(
LegacyResources.FormatDirectiveExpectsQuotedStringLiteral("custom"), LegacyResources.FormatDirectiveExpectsQuotedStringLiteral("custom"),
new SourceLocation(8, 0, 8), new SourceLocation(8, 0, 8),
@ -199,11 +230,10 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
public void DirectiveDescriptor_UnderstandsMultipleTokens() public void DirectiveDescriptor_UnderstandsMultipleTokens()
{ {
// Arrange // Arrange
var descriptor = DirectiveDescriptorBuilder.Create("custom") var descriptor = DirectiveDescriptor.CreateDirective(
.AddType() "custom",
.AddMember() DirectiveKind.SingleLine,
.AddString() b => b.AddTypeToken().AddMemberToken().AddStringToken());
.Build();
// Act & Assert // Act & Assert
ParseCodeBlockTest( ParseCodeBlockTest(
@ -234,7 +264,10 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
public void DirectiveDescriptor_UnderstandsRazorBlocks() public void DirectiveDescriptor_UnderstandsRazorBlocks()
{ {
// Arrange // Arrange
var descriptor = DirectiveDescriptorBuilder.CreateRazorBlock("custom").AddString().Build(); var descriptor = DirectiveDescriptor.CreateDirective(
"custom",
DirectiveKind.RazorBlock,
b => b.AddStringToken());
// Act & Assert // Act & Assert
ParseCodeBlockTest( ParseCodeBlockTest(
@ -267,7 +300,10 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
public void DirectiveDescriptor_UnderstandsCodeBlocks() public void DirectiveDescriptor_UnderstandsCodeBlocks()
{ {
// Arrange // Arrange
var descriptor = DirectiveDescriptorBuilder.CreateCodeBlock("custom").AddString().Build(); var descriptor = DirectiveDescriptor.CreateDirective(
"custom",
DirectiveKind.CodeBlock,
b => b.AddStringToken());
// Act & Assert // Act & Assert
ParseCodeBlockTest( ParseCodeBlockTest(
@ -293,10 +329,10 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
public void DirectiveDescriptor_AllowsWhiteSpaceAroundTokens() public void DirectiveDescriptor_AllowsWhiteSpaceAroundTokens()
{ {
// Arrange // Arrange
var descriptor = DirectiveDescriptorBuilder.Create("custom") var descriptor = DirectiveDescriptor.CreateDirective(
.AddType() "custom",
.AddMember() DirectiveKind.SingleLine,
.Build(); b => b.AddTypeToken().AddMemberToken());
// Act & Assert // Act & Assert
ParseCodeBlockTest( ParseCodeBlockTest(
@ -325,7 +361,11 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
public void DirectiveDescriptor_ErrorsForInvalidMemberTokens() public void DirectiveDescriptor_ErrorsForInvalidMemberTokens()
{ {
// Arrange // Arrange
var descriptor = DirectiveDescriptorBuilder.Create("custom").AddMember().Build(); var descriptor = DirectiveDescriptor.CreateDirective(
"custom",
DirectiveKind.SingleLine,
b => b.AddMemberToken());
var expectedErorr = new RazorError( var expectedErorr = new RazorError(
LegacyResources.FormatDirectiveExpectsIdentifier("custom"), LegacyResources.FormatDirectiveExpectsIdentifier("custom"),
new SourceLocation(8, 0, 8), new SourceLocation(8, 0, 8),
@ -347,7 +387,10 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
public void DirectiveDescriptor_NoErrorsSemicolonAfterDirective() public void DirectiveDescriptor_NoErrorsSemicolonAfterDirective()
{ {
// Arrange // Arrange
var descriptor = DirectiveDescriptorBuilder.Create("custom").AddString().Build(); var descriptor = DirectiveDescriptor.CreateDirective(
"custom",
DirectiveKind.SingleLine,
b => b.AddStringToken());
// Act & Assert // Act & Assert
ParseCodeBlockTest( ParseCodeBlockTest(
@ -368,7 +411,11 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
public void DirectiveDescriptor_ErrorsExtraContentAfterDirective() public void DirectiveDescriptor_ErrorsExtraContentAfterDirective()
{ {
// Arrange // Arrange
var descriptor = DirectiveDescriptorBuilder.Create("custom").AddString().Build(); var descriptor = DirectiveDescriptor.CreateDirective(
"custom",
DirectiveKind.SingleLine,
b => b.AddStringToken());
var expectedErorr = new RazorError( var expectedErorr = new RazorError(
LegacyResources.FormatUnexpectedDirectiveLiteral("custom", "line break"), LegacyResources.FormatUnexpectedDirectiveLiteral("custom", "line break"),
new SourceLocation(16, 0, 16), new SourceLocation(16, 0, 16),
@ -395,7 +442,11 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
public void DirectiveDescriptor_ErrorsWhenExtraContentBeforeBlockStart() public void DirectiveDescriptor_ErrorsWhenExtraContentBeforeBlockStart()
{ {
// Arrange // Arrange
var descriptor = DirectiveDescriptorBuilder.CreateCodeBlock("custom").AddString().Build(); var descriptor = DirectiveDescriptor.CreateDirective(
"custom",
DirectiveKind.CodeBlock,
b => b.AddStringToken());
var expectedErorr = new RazorError( var expectedErorr = new RazorError(
LegacyResources.FormatUnexpectedDirectiveLiteral("custom", "{"), LegacyResources.FormatUnexpectedDirectiveLiteral("custom", "{"),
new SourceLocation(16, 0, 16), new SourceLocation(16, 0, 16),
@ -422,7 +473,11 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
public void DirectiveDescriptor_ErrorsWhenEOFBeforeDirectiveBlockStart() public void DirectiveDescriptor_ErrorsWhenEOFBeforeDirectiveBlockStart()
{ {
// Arrange // Arrange
var descriptor = DirectiveDescriptorBuilder.CreateCodeBlock("custom").AddString().Build(); var descriptor = DirectiveDescriptor.CreateDirective(
"custom",
DirectiveKind.CodeBlock,
b => b.AddStringToken());
var expectedErorr = new RazorError( var expectedErorr = new RazorError(
LegacyResources.FormatUnexpectedEOFAfterDirective("custom", "{"), LegacyResources.FormatUnexpectedEOFAfterDirective("custom", "{"),
new SourceLocation(15, 0, 15), new SourceLocation(15, 0, 15),
@ -447,7 +502,11 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
public void DirectiveDescriptor_ErrorsWhenMissingEndBrace() public void DirectiveDescriptor_ErrorsWhenMissingEndBrace()
{ {
// Arrange // Arrange
var descriptor = DirectiveDescriptorBuilder.CreateCodeBlock("custom").AddString().Build(); var descriptor = DirectiveDescriptor.CreateDirective(
"custom",
DirectiveKind.CodeBlock,
b => b.AddStringToken());
var expectedErorr = new RazorError( var expectedErorr = new RazorError(
LegacyResources.FormatParseError_Expected_EndOfBlock_Before_EOF("custom", "}", "{"), LegacyResources.FormatParseError_Expected_EndOfBlock_Before_EOF("custom", "}", "{"),
new SourceLocation(16, 0, 16), new SourceLocation(16, 0, 16),
@ -884,7 +943,10 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
public void OptionalDirectiveTokens_AreSkipped() public void OptionalDirectiveTokens_AreSkipped()
{ {
// Arrange // Arrange
var descriptor = DirectiveDescriptorBuilder.Create("custom").BeginOptionals().AddString().Build(); var descriptor = DirectiveDescriptor.CreateDirective(
"custom",
DirectiveKind.SingleLine,
b => b.AddOptionalStringToken());
// Act & Assert // Act & Assert
ParseCodeBlockTest( ParseCodeBlockTest(
@ -901,7 +963,11 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
public void OptionalDirectiveTokens_WithSimpleTokens_AreParsed() public void OptionalDirectiveTokens_WithSimpleTokens_AreParsed()
{ {
// Arrange // Arrange
var descriptor = DirectiveDescriptorBuilder.Create("custom").BeginOptionals().AddString().Build(); var descriptor = DirectiveDescriptor.CreateDirective(
"custom",
DirectiveKind.SingleLine,
b => b.AddOptionalStringToken());
var chunkGenerator = new DirectiveTokenChunkGenerator(descriptor.Tokens.First()); var chunkGenerator = new DirectiveTokenChunkGenerator(descriptor.Tokens.First());
// Act & Assert // Act & Assert
@ -922,7 +988,11 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
public void OptionalDirectiveTokens_WithBraces_AreParsed() public void OptionalDirectiveTokens_WithBraces_AreParsed()
{ {
// Arrange // Arrange
var descriptor = DirectiveDescriptorBuilder.Create("custom").BeginOptionals().AddString().Build(); var descriptor = DirectiveDescriptor.CreateDirective(
"custom",
DirectiveKind.SingleLine,
b => b.AddOptionalStringToken());
var chunkGenerator = new DirectiveTokenChunkGenerator(descriptor.Tokens.First()); var chunkGenerator = new DirectiveTokenChunkGenerator(descriptor.Tokens.First());
// Act & Assert // Act & Assert
@ -943,7 +1013,10 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
public void OptionalDirectiveTokens_WithMultipleOptionalTokens_AreParsed() public void OptionalDirectiveTokens_WithMultipleOptionalTokens_AreParsed()
{ {
// Arrange // Arrange
var descriptor = DirectiveDescriptorBuilder.Create("custom").BeginOptionals().AddString().AddType().Build(); var descriptor = DirectiveDescriptor.CreateDirective(
"custom",
DirectiveKind.SingleLine,
b => b.AddOptionalStringToken().AddOptionalTypeToken());
// Act & Assert // Act & Assert
ParseCodeBlockTest( ParseCodeBlockTest(
@ -967,7 +1040,10 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
public void OptionalMemberTokens_WithMissingMember_IsParsed() public void OptionalMemberTokens_WithMissingMember_IsParsed()
{ {
// Arrange // Arrange
var descriptor = DirectiveDescriptorBuilder.Create("TestDirective").BeginOptionals().AddMember().AddString().Build(); var descriptor = DirectiveDescriptor.CreateDirective(
"TestDirective",
DirectiveKind.SingleLine,
b => b.AddOptionalMemberToken().AddOptionalStringToken());
// Act & Assert // Act & Assert
ParseCodeBlockTest( ParseCodeBlockTest(
@ -984,7 +1060,10 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
public void OptionalMemberTokens_WithMemberSpecified_IsParsed() public void OptionalMemberTokens_WithMemberSpecified_IsParsed()
{ {
// Arrange // Arrange
var descriptor = DirectiveDescriptorBuilder.Create("TestDirective").BeginOptionals().AddMember().AddString().Build(); var descriptor = DirectiveDescriptor.CreateDirective(
"TestDirective",
DirectiveKind.SingleLine,
b => b.AddOptionalMemberToken().AddOptionalStringToken());
// Act & Assert // Act & Assert
ParseCodeBlockTest( ParseCodeBlockTest(
@ -1004,7 +1083,9 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
public void Directives_CanUseReservedWord_Class() public void Directives_CanUseReservedWord_Class()
{ {
// Arrange // Arrange
var descriptor = DirectiveDescriptorBuilder.Create("class").Build(); var descriptor = DirectiveDescriptor.CreateDirective(
"class",
DirectiveKind.SingleLine);
// Act & Assert // Act & Assert
ParseCodeBlockTest( ParseCodeBlockTest(
@ -1020,7 +1101,9 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
public void Directives_CanUseReservedWord_Namespace() public void Directives_CanUseReservedWord_Namespace()
{ {
// Arrange // Arrange
var descriptor = DirectiveDescriptorBuilder.Create("namespace").Build(); var descriptor = DirectiveDescriptor.CreateDirective(
"namespace",
DirectiveKind.SingleLine);
// Act & Assert // Act & Assert
ParseCodeBlockTest( ParseCodeBlockTest(

View File

@ -19,7 +19,7 @@ namespace Microsoft.AspNetCore.Razor.Language
b.Features.Add(expected); b.Features.Add(expected);
// Act // Act
b.AddDirective(DirectiveDescriptorBuilder.Create("test_directive").Build()); b.AddDirective(DirectiveDescriptor.CreateDirective("test", DirectiveKind.SingleLine));
}); });
// Assert // Assert
@ -27,7 +27,7 @@ namespace Microsoft.AspNetCore.Razor.Language
Assert.Same(expected, actual); Assert.Same(expected, actual);
var directive = Assert.Single(actual.Directives); var directive = Assert.Single(actual.Directives);
Assert.Equal("test_directive", directive.Name); Assert.Equal("test", directive.Name);
} }
[Fact] [Fact]
@ -37,7 +37,7 @@ namespace Microsoft.AspNetCore.Razor.Language
var engine = RazorEngine.CreateEmpty(b => var engine = RazorEngine.CreateEmpty(b =>
{ {
// Act // Act
b.AddDirective(DirectiveDescriptorBuilder.Create("test_directive").Build()); b.AddDirective(DirectiveDescriptor.CreateDirective("test", DirectiveKind.SingleLine));
}); });
// Assert // Assert
@ -45,7 +45,7 @@ namespace Microsoft.AspNetCore.Razor.Language
Assert.IsType<DefaultRazorDirectiveFeature>(actual); Assert.IsType<DefaultRazorDirectiveFeature>(actual);
var directive = Assert.Single(actual.Directives); var directive = Assert.Single(actual.Directives);
Assert.Equal("test_directive", directive.Name); Assert.Equal("test", directive.Name);
} }
[Fact] [Fact]

View File

@ -26,7 +26,7 @@ namespace Microsoft.VisualStudio.RazorExtension.RazorInfo
builder.Append(")"); builder.Append(")");
} }
if (directive.Kind == DirectiveDescriptorKind.CodeBlock || directive.Kind == DirectiveDescriptorKind.RazorBlock) if (directive.Kind == DirectiveKind.CodeBlock || directive.Kind == DirectiveKind.RazorBlock)
{ {
builder.Append("{ ... }"); builder.Append("{ ... }");
} }