Split the functions/section/inherits directives

This commit is contained in:
Ryan Nowak 2017-06-09 18:13:44 -07:00
parent 27ac5da6d5
commit 22d52f2a3c
30 changed files with 716 additions and 415 deletions

View File

@ -15,6 +15,10 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
NamespaceDirective.Register(builder);
PageDirective.Register(builder);
FunctionsDirective.Register(builder);
InheritsDirective.Register(builder);
SectionDirective.Register(builder);
builder.AddTargetExtension(new InjectDirectiveTargetExtension());
builder.AddTargetExtension(new TemplateTargetExtension()
{

View File

@ -3,6 +3,7 @@
using System;
using System.Linq;
using Microsoft.AspNetCore.Razor.Language.Extensions;
using Microsoft.AspNetCore.Razor.Language.Legacy;
namespace Microsoft.AspNetCore.Razor.Language
@ -55,7 +56,7 @@ namespace Microsoft.AspNetCore.Razor.Language
if (_nestedLevel > 0)
{
var directiveStart = block.Children.First(child => !child.IsBlock && ((Span)child).Kind == SpanKindInternal.Transition).Start;
var errorLength = /* @ */ 1 + CSharpCodeParser.SectionDirectiveDescriptor.Directive.Length;
var errorLength = /* @ */ 1 + SectionDirective.Directive.Directive.Length;
_errorSink.OnError(
directiveStart,
LegacyResources.FormatParseError_Sections_Cannot_Be_Nested(LegacyResources.SectionExample_CS),

View File

@ -0,0 +1,20 @@
// 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 Microsoft.AspNetCore.Razor.Language.Legacy;
namespace Microsoft.AspNetCore.Razor.Language.Extensions
{
public static class FunctionsDirective
{
public static readonly DirectiveDescriptor Directive = DirectiveDescriptor.CreateDirective(
SyntaxConstants.CSharp.FunctionsKeyword,
DirectiveKind.CodeBlock);
public static void Register(IRazorEngineBuilder builder)
{
builder.AddDirective(Directive);
builder.Features.Add(new FunctionsDirectivePass());
}
}
}

View File

@ -0,0 +1,29 @@
// 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 Microsoft.AspNetCore.Razor.Language.Intermediate;
namespace Microsoft.AspNetCore.Razor.Language.Extensions
{
public class FunctionsDirectivePass : RazorIRPassBase, IRazorDirectiveClassifierPass
{
protected override void ExecuteCore(RazorCodeDocument codeDocument, DocumentIRNode irDocument)
{
var @class = irDocument.FindPrimaryClass();
if (@class == null)
{
return;
}
foreach (var functions in irDocument.FindDirectiveReferences(FunctionsDirective.Directive))
{
functions.Remove();
for (var i = 0; i < functions.Node.Children.Count; i++)
{
@class.Children.Add(functions.Node.Children[i]);
}
}
}
}
}

View File

@ -0,0 +1,21 @@
// 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 Microsoft.AspNetCore.Razor.Language.Legacy;
namespace Microsoft.AspNetCore.Razor.Language.Extensions
{
public static class InheritsDirective
{
public static readonly DirectiveDescriptor Directive = DirectiveDescriptor.CreateDirective(
SyntaxConstants.CSharp.InheritsKeyword,
DirectiveKind.SingleLine,
builder => builder.AddTypeToken());
public static void Register(IRazorEngineBuilder builder)
{
builder.AddDirective(Directive);
builder.Features.Add(new InheritsDirectivePass());
}
}
}

View File

@ -0,0 +1,34 @@
// 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.Linq;
using Microsoft.AspNetCore.Razor.Language.Intermediate;
namespace Microsoft.AspNetCore.Razor.Language.Extensions
{
public class InheritsDirectivePass : RazorIRPassBase, IRazorDirectiveClassifierPass
{
protected override void ExecuteCore(RazorCodeDocument codeDocument, DocumentIRNode irDocument)
{
var @class = irDocument.FindPrimaryClass();
if (@class == null)
{
return;
}
foreach (var inherits in irDocument.FindDirectiveReferences(InheritsDirective.Directive))
{
inherits.Remove();
var token = ((DirectiveIRNode)inherits.Node).Tokens.FirstOrDefault();
if (token != null)
{
@class.BaseType = token.Content;
break;
}
}
}
}
}

View File

@ -0,0 +1,21 @@
// 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 Microsoft.AspNetCore.Razor.Language.Legacy;
namespace Microsoft.AspNetCore.Razor.Language.Extensions
{
public static class SectionDirective
{
public static readonly DirectiveDescriptor Directive = DirectiveDescriptor.CreateDirective(
SyntaxConstants.CSharp.SectionKeyword,
DirectiveKind.RazorBlock,
builder => builder.AddMemberToken());
public static void Register(IRazorEngineBuilder builder)
{
builder.AddDirective(Directive);
builder.Features.Add(new SectionDirectivePass());
}
}
}

View File

@ -1,53 +1,25 @@
// 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.Intermediate;
using Microsoft.AspNetCore.Razor.Language.Legacy;
namespace Microsoft.AspNetCore.Razor.Language
namespace Microsoft.AspNetCore.Razor.Language.Extensions
{
internal class DefaultDirectiveIRPass : RazorIRPassBase, IRazorDirectiveClassifierPass
public class SectionDirectivePass : RazorIRPassBase, IRazorDirectiveClassifierPass
{
protected override void ExecuteCore(RazorCodeDocument codeDocument, DocumentIRNode irDocument)
{
var parserOptions = irDocument.Options;
var designTime = parserOptions.DesignTime;
var classNode = irDocument.FindPrimaryClass();
if (classNode == null)
var @class = irDocument.FindPrimaryClass();
if (@class == null)
{
return;
}
foreach (var functions in irDocument.FindDirectiveReferences(CSharpCodeParser.FunctionsDirectiveDescriptor))
foreach (var section in irDocument.FindDirectiveReferences(SectionDirective.Directive))
{
functions.Remove();
for (var i =0; i < functions.Node.Children.Count; i++)
{
classNode.Children.Add(functions.Node.Children[i]);
}
}
foreach (var inherits in irDocument.FindDirectiveReferences(CSharpCodeParser.InheritsDirectiveDescriptor).Reverse())
{
inherits.Remove();
var token = ((DirectiveIRNode)inherits.Node).Tokens.FirstOrDefault();
if (token != null)
{
classNode.BaseType = token.Content;
break;
}
}
foreach (var section in irDocument.FindDirectiveReferences(CSharpCodeParser.SectionDirectiveDescriptor))
{
var lambdaContent = designTime ? "__razor_section_writer" : string.Empty;
var lambdaContent = irDocument.Options.DesignTime ? "__razor_section_writer" : string.Empty;
var sectionName = ((DirectiveIRNode)section.Node).Tokens.FirstOrDefault()?.Content;
var builder = RazorIRBuilder.Create(new CSharpCodeIRNode());
@ -57,7 +29,7 @@ namespace Microsoft.AspNetCore.Razor.Language
Content = $"DefineSection(\"{sectionName}\", async ({lambdaContent}) => {{"
});
section.InsertBefore(builder.Build());
section.InsertBefore(section.Node.Children.Except(((DirectiveIRNode)section.Node).Tokens));
builder = RazorIRBuilder.Create(new CSharpCodeIRNode());

View File

@ -13,20 +13,6 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
private static readonly Func<CSharpSymbol, bool> IsValidStatementSpacingSymbol =
IsSpacingToken(includeNewLines: true, includeComments: true);
internal static readonly DirectiveDescriptor SectionDirectiveDescriptor = DirectiveDescriptor.CreateDirective(
SyntaxConstants.CSharp.SectionKeyword,
DirectiveKind.RazorBlock,
builder => builder.AddMemberToken());
internal static readonly DirectiveDescriptor FunctionsDirectiveDescriptor = DirectiveDescriptor.CreateDirective(
SyntaxConstants.CSharp.FunctionsKeyword,
DirectiveKind.CodeBlock);
internal static readonly DirectiveDescriptor InheritsDirectiveDescriptor = DirectiveDescriptor.CreateDirective(
SyntaxConstants.CSharp.InheritsKeyword,
DirectiveKind.SingleLine,
builder => builder.AddTypeToken());
internal static readonly DirectiveDescriptor AddTagHelperDirectiveDescriptor = DirectiveDescriptor.CreateDirective(
SyntaxConstants.CSharp.AddTagHelperKeyword,
DirectiveKind.SingleLine,
@ -42,11 +28,8 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
DirectiveKind.SingleLine,
builder => builder.AddStringToken());
internal static readonly IEnumerable<DirectiveDescriptor> DefaultDirectiveDescriptors = new[]
internal static readonly IEnumerable<DirectiveDescriptor> DefaultDirectiveDescriptors = new DirectiveDescriptor[]
{
SectionDirectiveDescriptor,
FunctionsDirectiveDescriptor,
InheritsDirectiveDescriptor,
};
internal static ISet<string> DefaultKeywords = new HashSet<string>()
@ -63,9 +46,6 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
"switch",
"lock",
"using",
"section",
"inherits",
"functions",
"namespace",
"class",
};
@ -76,16 +56,26 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
private Dictionary<CSharpKeyword, Action<bool>> _keywordParsers = new Dictionary<CSharpKeyword, Action<bool>>();
public CSharpCodeParser(ParserContext context)
: this(directiveDescriptors: Enumerable.Empty<DirectiveDescriptor>(), context: context)
: this(directives: Enumerable.Empty<DirectiveDescriptor>(), context: context)
{
}
public CSharpCodeParser(IEnumerable<DirectiveDescriptor> directiveDescriptors, ParserContext context)
public CSharpCodeParser(IEnumerable<DirectiveDescriptor> directives, ParserContext context)
: base(context.ParseOnlyLeadingDirectives ? FirstDirectiveCSharpLanguageCharacteristics.Instance : CSharpLanguageCharacteristics.Instance, context)
{
if (directives == null)
{
throw new ArgumentNullException(nameof(directives));
}
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
Keywords = new HashSet<string>();
SetUpKeywords();
SetupDirectives(directiveDescriptors);
SetupDirectives(directives);
SetUpExpressions();
}

View File

@ -47,7 +47,6 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
{
var other = obj as ImplicitExpressionEditHandler;
return base.Equals(other) &&
_keywords.SetEquals(other._keywords) &&
AcceptTrailingDot == other.AcceptTrailingDot;
}
@ -55,7 +54,6 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
{
// Hash code should include only immutable properties and base has none.
var hashCodeCombiner = HashCodeCombiner.Start();
hashCodeCombiner.Add(Keywords);
hashCodeCombiner.Add(AcceptTrailingDot);
return hashCodeCombiner;

View File

@ -70,7 +70,6 @@ namespace Microsoft.AspNetCore.Razor.Language
// IR Passes
builder.Features.Add(new DefaultDocumentClassifierPass());
builder.Features.Add(new DefaultDirectiveIRPass());
builder.Features.Add(new DirectiveRemovalIROptimizationPass());
// Default Runtime Targets

View File

@ -5,6 +5,7 @@ using System;
using System.IO;
using System.Text;
using Microsoft.AspNetCore.Razor.Language;
using Microsoft.AspNetCore.Razor.Language.Extensions;
using Microsoft.AspNetCore.Razor.Language.Intermediate;
using Xunit;
@ -239,6 +240,9 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
{
// Notice we're not registering the ModelDirective.Pass here so we can run it on demand.
b.AddDirective(ModelDirective.Directive);
// There's some special interaction with the inherits directive
InheritsDirective.Register(b);
});
}

View File

@ -1,127 +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.Linq;
using Microsoft.AspNetCore.Razor.Language.Legacy;
using Xunit;
namespace Microsoft.AspNetCore.Razor.Language
{
public class DefaultDirectiveSyntaxTreePassTest
{
[Fact]
public void Execute_DoesNotRecreateSyntaxTreeWhenNoErrors()
{
// Arrange
var engine = RazorEngine.Create();
var pass = new DefaultDirectiveSyntaxTreePass()
{
Engine = engine,
};
var content =
@"
@section Foo {
}";
var sourceDocument = TestRazorSourceDocument.Create(content);
var codeDocument = RazorCodeDocument.Create(sourceDocument);
var originalTree = RazorSyntaxTree.Parse(sourceDocument);
// Act
var outputTree = pass.Execute(codeDocument, originalTree);
// Assert
Assert.Empty(originalTree.Diagnostics);
Assert.Same(originalTree, outputTree);
Assert.Empty(outputTree.Diagnostics);
}
[Fact]
public void Execute_LogsErrorsForNestedSections()
{
// Arrange
var expectedErrors = new[] {
new RazorError(
LegacyResources.FormatParseError_Sections_Cannot_Be_Nested(LegacyResources.SectionExample_CS),
new SourceLocation(18 + Environment.NewLine.Length * 2, 2, 4),
length: 8),
new RazorError(
LegacyResources.FormatParseError_Sections_Cannot_Be_Nested(LegacyResources.SectionExample_CS),
new SourceLocation(41 + Environment.NewLine.Length * 4, 4, 4),
length: 8),
};
var expectedDiagnostics = expectedErrors.Select(error => RazorDiagnostic.Create(error));
var engine = RazorEngine.Create();
var pass = new DefaultDirectiveSyntaxTreePass()
{
Engine = engine,
};
var content =
@"
@section Foo {
@section Bar {
}
@section Baz {
}
}";
var sourceDocument = TestRazorSourceDocument.Create(content, fileName: null);
var codeDocument = RazorCodeDocument.Create(sourceDocument);
var originalTree = RazorSyntaxTree.Parse(sourceDocument);
// Act
var outputTree = pass.Execute(codeDocument, originalTree);
// Assert
Assert.Empty(originalTree.Diagnostics);
Assert.NotSame(originalTree, outputTree);
Assert.Equal(expectedDiagnostics, outputTree.Diagnostics);
}
[Fact]
public void Execute_CombinesErrorsWhenNestedSections()
{
// Arrange
var expectedErrors = new[] {
new RazorError("Test Error", SourceLocation.Zero, 3),
new RazorError(
LegacyResources.FormatParseError_Sections_Cannot_Be_Nested(LegacyResources.SectionExample_CS),
new SourceLocation(18 + Environment.NewLine.Length * 2, 2, 4),
length: 8),
new RazorError(
LegacyResources.FormatParseError_Sections_Cannot_Be_Nested(LegacyResources.SectionExample_CS),
new SourceLocation(41 + Environment.NewLine.Length * 4, 4, 4),
length: 8),
};
var expectedDiagnostics = expectedErrors.Select(error => RazorDiagnostic.Create(error)).ToList();
var engine = RazorEngine.Create();
var pass = new DefaultDirectiveSyntaxTreePass()
{
Engine = engine,
};
var content =
@"
@section Foo {
@section Bar {
}
@section Baz {
}
}";
var sourceDocument = TestRazorSourceDocument.Create(content, fileName: null);
var codeDocument = RazorCodeDocument.Create(sourceDocument);
var originalTree = RazorSyntaxTree.Parse(sourceDocument);
var erroredOriginalTree = RazorSyntaxTree.Create(
originalTree.Root,
originalTree.Source,
new[] { expectedDiagnostics[0] },
originalTree.Options);
// Act
var outputTree = pass.Execute(codeDocument, erroredOriginalTree);
// Assert
Assert.Empty(originalTree.Diagnostics);
Assert.NotSame(originalTree, outputTree);
Assert.Equal(expectedDiagnostics, outputTree.Diagnostics);
}
}
}

View File

@ -8,6 +8,7 @@ using Microsoft.AspNetCore.Razor.Language.Intermediate;
using Xunit;
using static Microsoft.AspNetCore.Razor.Language.Intermediate.RazorIRAssert;
using Moq;
using Microsoft.AspNetCore.Razor.Language.Extensions;
namespace Microsoft.AspNetCore.Razor.Language
{
@ -459,6 +460,8 @@ namespace Microsoft.AspNetCore.Razor.Language
{
builder?.Invoke(b);
FunctionsDirective.Register(b);
SectionDirective.Register(b);
b.AddTagHelpers(tagHelpers);
});

View File

@ -0,0 +1,103 @@
// 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 Microsoft.AspNetCore.Razor.Language.Intermediate;
using Xunit;
using static Microsoft.AspNetCore.Razor.Language.Intermediate.RazorIRAssert;
namespace Microsoft.AspNetCore.Razor.Language.Extensions
{
public class FunctionsDirectivePassTest
{
[Fact]
public void Execute_SkipsDocumentWithNoClassNode()
{
// Arrange
var engine = CreateEngine();
var pass = new FunctionsDirectivePass()
{
Engine = engine,
};
var sourceDocument = TestRazorSourceDocument.Create("@functions { var value = true; }");
var codeDocument = RazorCodeDocument.Create(sourceDocument);
var irDocument = new DocumentIRNode();
irDocument.Children.Add(new DirectiveIRNode() { Descriptor = FunctionsDirective.Directive, });
// Act
pass.Execute(codeDocument, irDocument);
// Assert
Children(
irDocument,
node => Assert.IsType<DirectiveIRNode>(node));
}
[Fact]
public void Execute_MovesStatementsToClassLevel()
{
// Arrange
var engine = CreateEngine();
var pass = new FunctionsDirectivePass()
{
Engine = engine,
};
var sourceDocument = TestRazorSourceDocument.Create("@functions { var value = true; }");
var codeDocument = RazorCodeDocument.Create(sourceDocument);
var irDocument = Lower(codeDocument, engine);
// Act
pass.Execute(codeDocument, irDocument);
// Assert
Children(
irDocument,
node => Assert.IsType<ChecksumIRNode>(node),
node => Assert.IsType<NamespaceDeclarationIRNode>(node));
var @namespace = irDocument.Children[1];
Children(
@namespace,
node => Assert.IsType<ClassDeclarationIRNode>(node));
var @class = @namespace.Children[0];
Children(
@class,
node => Assert.IsType<MethodDeclarationIRNode>(node),
node => CSharpCode(" var value = true; ", node));
var method = (MethodDeclarationIRNode)@class.Children[0];
Assert.Empty(method.Children);
}
private static RazorEngine CreateEngine()
{
return RazorEngine.Create(b =>
{
FunctionsDirective.Register(b);
});
}
private static DocumentIRNode Lower(RazorCodeDocument codeDocument, RazorEngine engine)
{
for (var i = 0; i < engine.Phases.Count; i++)
{
var phase = engine.Phases[i];
phase.Execute(codeDocument);
if (phase is IRazorDocumentClassifierPhase)
{
break;
}
}
var irDocument = codeDocument.GetIRDocument();
Assert.NotNull(irDocument);
return irDocument;
}
}
}

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 Microsoft.AspNetCore.Razor.Language.Intermediate;
using Xunit;
using static Microsoft.AspNetCore.Razor.Language.Intermediate.RazorIRAssert;
namespace Microsoft.AspNetCore.Razor.Language.Extensions
{
public class InheritsDirectivePassTest
{
[Fact]
public void Execute_SkipsDocumentWithNoClassNode()
{
// Arrange
var engine = CreateEngine();
var pass = new InheritsDirectivePass()
{
Engine = engine,
};
var sourceDocument = TestRazorSourceDocument.Create("@inherits Hello<World[]>");
var codeDocument = RazorCodeDocument.Create(sourceDocument);
var irDocument = new DocumentIRNode();
irDocument.Children.Add(new DirectiveIRNode() { Descriptor = FunctionsDirective.Directive, });
// Act
pass.Execute(codeDocument, irDocument);
// Assert
Children(
irDocument,
node => Assert.IsType<DirectiveIRNode>(node));
}
[Fact]
public void Execute_Inherits_SetsClassDeclarationBaseType()
{
// Arrange
var engine = CreateEngine();
var pass = new InheritsDirectivePass()
{
Engine = engine,
};
var content = "@inherits Hello<World[]>";
var sourceDocument = TestRazorSourceDocument.Create(content);
var codeDocument = RazorCodeDocument.Create(sourceDocument);
var irDocument = Lower(codeDocument, engine);
// Act
pass.Execute(codeDocument, irDocument);
// Assert
Children(
irDocument,
node => Assert.IsType<ChecksumIRNode>(node),
node => Assert.IsType<NamespaceDeclarationIRNode>(node));
var @namespace = irDocument.Children[1];
Children(
@namespace,
node => Assert.IsType<ClassDeclarationIRNode>(node));
var @class = (ClassDeclarationIRNode)@namespace.Children[0];
Assert.Equal("Hello<World[]>", @class.BaseType);
}
private static RazorEngine CreateEngine()
{
return RazorEngine.Create(b =>
{
InheritsDirective.Register(b);
});
}
private static DocumentIRNode Lower(RazorCodeDocument codeDocument, RazorEngine engine)
{
for (var i = 0; i < engine.Phases.Count; i++)
{
var phase = engine.Phases[i];
phase.Execute(codeDocument);
if (phase is IRazorDocumentClassifierPhase)
{
break;
}
}
var irDocument = codeDocument.GetIRDocument();
Assert.NotNull(irDocument);
return irDocument;
}
}
}

View File

@ -5,140 +5,127 @@ using Microsoft.AspNetCore.Razor.Language.Intermediate;
using Xunit;
using static Microsoft.AspNetCore.Razor.Language.Intermediate.RazorIRAssert;
namespace Microsoft.AspNetCore.Razor.Language
namespace Microsoft.AspNetCore.Razor.Language.Extensions
{
public class DefaultDirectiveIRPassTest
public class SectionDirectivePassTest
{
[Fact]
public void Execute_Inherits_SetsClassDeclarationBaseType()
public void Execute_SkipsDocumentWithNoClassNode()
{
// Arrange
var content = "@inherits Hello<World[]>";
var sourceDocument = TestRazorSourceDocument.Create(content);
var codeDocument = RazorCodeDocument.Create(sourceDocument);
var irDocument = Lower(codeDocument);
var defaultEngine = RazorEngine.Create();
var pass = new DefaultDirectiveIRPass()
var engine = CreateEngine();
var pass = new SectionDirectivePass()
{
Engine = defaultEngine,
Engine = engine,
};
var sourceDocument = TestRazorSourceDocument.Create("@section Header { <p>Hello World</p> }");
var codeDocument = RazorCodeDocument.Create(sourceDocument);
var irDocument = new DocumentIRNode();
irDocument.Children.Add(new DirectiveIRNode() { Descriptor = SectionDirective.Directive, });
// Act
pass.Execute(codeDocument, irDocument);
// Assert
Children(irDocument,
node => Assert.IsType<ChecksumIRNode>(node),
node => Assert.IsType<NamespaceDeclarationIRNode>(node));
var @namespace = irDocument.Children[1];
Children(@namespace,
node => Assert.IsType<ClassDeclarationIRNode>(node));
var @class = (ClassDeclarationIRNode)@namespace.Children[0];
Assert.Equal("Hello<World[]>", @class.BaseType);
Children(
irDocument,
node => Assert.IsType<DirectiveIRNode>(node));
}
[Fact]
public void Execute_Functions_MovesStatementToClassLevel()
public void Execute_WrapsStatementInDefineSection()
{
// Arrange
var content = "@functions { var value = true; }";
var sourceDocument = TestRazorSourceDocument.Create(content);
var codeDocument = RazorCodeDocument.Create(sourceDocument);
var irDocument = Lower(codeDocument);
var defaultEngine = RazorEngine.Create();
var pass = new DefaultDirectiveIRPass()
var engine = CreateEngine();
var pass = new SectionDirectivePass()
{
Engine = defaultEngine,
Engine = engine,
};
// Act
pass.Execute(codeDocument, irDocument);
// Assert
Children(irDocument,
node => Assert.IsType<ChecksumIRNode>(node),
node => Assert.IsType<NamespaceDeclarationIRNode>(node));
var @namespace = irDocument.Children[1];
Children(@namespace,
node => Assert.IsType<ClassDeclarationIRNode>(node));
var @class = @namespace.Children[0];
Children(@class,
node => Assert.IsType<MethodDeclarationIRNode>(node),
node => CSharpCode(" var value = true; ", node));
var method = (MethodDeclarationIRNode)@class.Children[0];
Assert.Empty(method.Children);
}
[Fact]
public void Execute_Section_WrapsStatementInDefineSection()
{
// Arrange
var content = "@section Header { <p>Hello World</p> }";
var sourceDocument = TestRazorSourceDocument.Create(content);
var codeDocument = RazorCodeDocument.Create(sourceDocument);
var irDocument = Lower(codeDocument);
var defaultEngine = RazorEngine.Create();
var pass = new DefaultDirectiveIRPass()
{
Engine = defaultEngine,
};
var irDocument = Lower(codeDocument, engine);
// Act
pass.Execute(codeDocument, irDocument);
// Assert
Children(irDocument,
Children(
irDocument,
node => Assert.IsType<ChecksumIRNode>(node),
node => Assert.IsType<NamespaceDeclarationIRNode>(node));
var @namespace = irDocument.Children[1];
Children(@namespace,
Children(
@namespace,
node => Assert.IsType<ClassDeclarationIRNode>(node));
var @class = @namespace.Children[0];
var method = SingleChild<MethodDeclarationIRNode>(@class);
Children(method,
Children(
method,
node => CSharpCode("DefineSection(\"Header\", async () => {", node),
node => Html(" <p>Hello World</p> ", node),
node => CSharpCode("});", node));
}
[Fact]
public void Execute_Section_DesignTime_WrapsStatementInBackwardsCompatibleDefineSection()
public void Execute_DesignTime_WrapsStatementInBackwardsCompatibleDefineSection()
{
// Arrange
var engine = CreateDesignTimeEngine();
var pass = new SectionDirectivePass()
{
Engine = engine,
};
var content = "@section Header { <p>Hello World</p> }";
var designTimeEngine = RazorEngine.CreateDesignTime();
var sourceDocument = TestRazorSourceDocument.Create(content);
var codeDocument = RazorCodeDocument.Create(sourceDocument);
var irDocument = Lower(codeDocument, designTimeEngine);
var defaultEngine = RazorEngine.Create();
var pass = new DefaultDirectiveIRPass()
{
Engine = defaultEngine,
};
var irDocument = Lower(codeDocument, engine);
// Act
pass.Execute(codeDocument, irDocument);
// Assert
Children(irDocument,
Children(
irDocument,
node => Assert.IsType<ChecksumIRNode>(node),
node => Assert.IsType<NamespaceDeclarationIRNode>(node));
var @namespace = irDocument.Children[1];
Children(@namespace,
Children(
@namespace,
node => Assert.IsType<ClassDeclarationIRNode>(node));
var @class = @namespace.Children[0];
var method = SingleChild<MethodDeclarationIRNode>(@class);
Children(method,
Children(
method,
node => CSharpCode("DefineSection(\"Header\", async (__razor_section_writer) => {", node),
node => Html(" <p>Hello World</p> ", node),
node => CSharpCode("});", node));
}
private static DocumentIRNode Lower(RazorCodeDocument codeDocument)
private static RazorEngine CreateEngine()
{
var engine = RazorEngine.Create();
return RazorEngine.Create(b =>
{
SectionDirective.Register(b);
});
}
return Lower(codeDocument, engine);
private static RazorEngine CreateDesignTimeEngine()
{
return RazorEngine.CreateDesignTime(b =>
{
SectionDirective.Register(b);
});
}
private static DocumentIRNode Lower(RazorCodeDocument codeDocument, RazorEngine engine)

View File

@ -4,6 +4,7 @@
using Microsoft.AspNetCore.Razor.Language.CodeGeneration;
using Microsoft.AspNetCore.Razor.Language.Legacy;
using Xunit;
using static Microsoft.AspNetCore.Razor.Language.Intermediate.RazorIRAssert;
namespace Microsoft.AspNetCore.Razor.Language.Extensions
{

View File

@ -889,6 +889,10 @@ namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests
// Some of these tests use templates
builder.AddTargetExtension(new TemplateTargetExtension());
FunctionsDirective.Register(builder);
InheritsDirective.Register(builder);
SectionDirective.Register(builder);
});
var document = CreateCodeDocument();
@ -911,6 +915,10 @@ namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests
// Some of these tests use templates
builder.AddTargetExtension(new TemplateTargetExtension());
FunctionsDirective.Register(builder);
InheritsDirective.Register(builder);
SectionDirective.Register(builder);
});
var document = CreateCodeDocument();
@ -933,6 +941,10 @@ namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests
// Some of these tests use templates
builder.AddTargetExtension(new TemplateTargetExtension());
FunctionsDirective.Register(builder);
InheritsDirective.Register(builder);
SectionDirective.Register(builder);
});
var document = CreateCodeDocument();
@ -955,6 +967,10 @@ namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests
// Some of these tests use templates
builder.AddTargetExtension(new TemplateTargetExtension());
FunctionsDirective.Register(builder);
InheritsDirective.Register(builder);
SectionDirective.Register(builder);
});
var document = CreateCodeDocument();

View File

@ -3,6 +3,7 @@
using System;
using System.Linq;
using Microsoft.AspNetCore.Razor.Language.Extensions;
using Xunit;
namespace Microsoft.AspNetCore.Razor.Language.Legacy
@ -14,12 +15,13 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
{
ParseBlockTest(
"@functions{",
new DirectiveBlock(new DirectiveChunkGenerator(CSharpCodeParser.FunctionsDirectiveDescriptor),
new[] { FunctionsDirective.Directive, },
new DirectiveBlock(new DirectiveChunkGenerator(FunctionsDirective.Directive),
Factory.CodeTransition(),
Factory.MetaCode("functions").Accepts(AcceptedCharactersInternal.None),
Factory.MetaCode("{").AutoCompleteWith("}", atEndOfSpan: true).Accepts(AcceptedCharactersInternal.None)),
new RazorError(
LegacyResources.FormatParseError_Expected_EndOfBlock_Before_EOF(CSharpCodeParser.FunctionsDirectiveDescriptor.Directive, "}", "{"),
LegacyResources.FormatParseError_Expected_EndOfBlock_Before_EOF(FunctionsDirective.Directive.Directive, "}", "{"),
new SourceLocation(10, 0, 10),
length: 1));
}
@ -28,12 +30,13 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
public void SectionDirectiveAutoCompleteAtEOF()
{
ParseBlockTest("@section Header {",
new DirectiveBlock(new DirectiveChunkGenerator(CSharpCodeParser.SectionDirectiveDescriptor),
new[] { SectionDirective.Directive, },
new DirectiveBlock(new DirectiveChunkGenerator(SectionDirective.Directive),
Factory.CodeTransition(),
Factory.MetaCode("section").Accepts(AcceptedCharactersInternal.None),
Factory.Span(SpanKindInternal.Code, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.WhiteSpace),
Factory.Span(SpanKindInternal.Code, "Header", CSharpSymbolType.Identifier)
.AsDirectiveToken(CSharpCodeParser.SectionDirectiveDescriptor.Tokens.First()),
.AsDirectiveToken(SectionDirective.Directive.Tokens.First()),
Factory.Span(SpanKindInternal.Markup, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.AllWhiteSpace),
Factory.MetaCode("{").AutoCompleteWith("}", atEndOfSpan: true).Accepts(AcceptedCharactersInternal.None),
new MarkupBlock(
@ -65,8 +68,10 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
[Fact]
public void FunctionsDirectiveAutoCompleteAtStartOfFile()
{
ParseBlockTest("@functions{" + Environment.NewLine + "foo",
new DirectiveBlock(new DirectiveChunkGenerator(CSharpCodeParser.FunctionsDirectiveDescriptor),
ParseBlockTest(
"@functions{" + Environment.NewLine + "foo",
new[] { FunctionsDirective.Directive, },
new DirectiveBlock(new DirectiveChunkGenerator(FunctionsDirective.Directive),
Factory.CodeTransition(),
Factory.MetaCode("functions").Accepts(AcceptedCharactersInternal.None),
Factory.MetaCode("{").AutoCompleteWith("}", atEndOfSpan: true).Accepts(AcceptedCharactersInternal.None),
@ -82,11 +87,12 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
{
ParseBlockTest("@section Header {" + Environment.NewLine
+ "<p>Foo</p>",
new DirectiveBlock(new DirectiveChunkGenerator(CSharpCodeParser.SectionDirectiveDescriptor),
new[] { SectionDirective.Directive, },
new DirectiveBlock(new DirectiveChunkGenerator(SectionDirective.Directive),
Factory.CodeTransition(),
Factory.MetaCode("section").Accepts(AcceptedCharactersInternal.None),
Factory.Span(SpanKindInternal.Code, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.WhiteSpace),
Factory.Span(SpanKindInternal.Code, "Header", CSharpSymbolType.Identifier).AsDirectiveToken(CSharpCodeParser.SectionDirectiveDescriptor.Tokens.First()),
Factory.Span(SpanKindInternal.Code, "Header", CSharpSymbolType.Identifier).AsDirectiveToken(SectionDirective.Directive.Tokens.First()),
Factory.Span(SpanKindInternal.Markup, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.AllWhiteSpace),
Factory.MetaCode("{").AutoCompleteWith("}", atEndOfSpan: true).Accepts(AcceptedCharactersInternal.None),
new MarkupBlock(

View File

@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Razor.Language.Extensions;
using Xunit;
namespace Microsoft.AspNetCore.Razor.Language.Legacy
@ -987,56 +988,66 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
}
[Fact]
public void InheritsDirective()
public void ParseBlock_InheritsDirective()
{
ParseBlockTest("@inherits System.Web.WebPages.WebPage",
new DirectiveBlock(new DirectiveChunkGenerator(CSharpCodeParser.InheritsDirectiveDescriptor),
ParseCodeBlockTest(
"@inherits System.Web.WebPages.WebPage",
new[] { InheritsDirective.Directive, },
new DirectiveBlock(new DirectiveChunkGenerator(InheritsDirective.Directive),
Factory.CodeTransition(),
Factory.MetaCode("inherits").Accepts(AcceptedCharactersInternal.None),
Factory.Span(SpanKindInternal.Code, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.WhiteSpace),
Factory.Span(SpanKindInternal.Code, "System.Web.WebPages.WebPage", markup: false).AsDirectiveToken(CSharpCodeParser.InheritsDirectiveDescriptor.Tokens.First())));
Factory.Span(SpanKindInternal.Code, "System.Web.WebPages.WebPage", markup: false).AsDirectiveToken(InheritsDirective.Directive.Tokens.First())));
}
[Fact]
public void InheritsDirectiveSupportsArrays()
{
ParseBlockTest("@inherits string[[]][]",
new DirectiveBlock(new DirectiveChunkGenerator(CSharpCodeParser.InheritsDirectiveDescriptor),
ParseCodeBlockTest(
"@inherits string[[]][]",
new[] { InheritsDirective.Directive, },
new DirectiveBlock(new DirectiveChunkGenerator(InheritsDirective.Directive),
Factory.CodeTransition(),
Factory.MetaCode("inherits").Accepts(AcceptedCharactersInternal.None),
Factory.Span(SpanKindInternal.Code, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.WhiteSpace),
Factory.Span(SpanKindInternal.Code, "string[[]][]", markup: false).AsDirectiveToken(CSharpCodeParser.InheritsDirectiveDescriptor.Tokens.First())));
Factory.Span(SpanKindInternal.Code, "string[[]][]", markup: false).AsDirectiveToken(InheritsDirective.Directive.Tokens.First())));
}
[Fact]
public void InheritsDirectiveSupportsNestedGenerics()
{
ParseBlockTest("@inherits System.Web.Mvc.WebViewPage<IEnumerable<MvcApplication2.Models.RegisterModel>>",
new DirectiveBlock(new DirectiveChunkGenerator(CSharpCodeParser.InheritsDirectiveDescriptor),
ParseCodeBlockTest(
"@inherits System.Web.Mvc.WebViewPage<IEnumerable<MvcApplication2.Models.RegisterModel>>",
new[] { InheritsDirective.Directive, },
new DirectiveBlock(new DirectiveChunkGenerator(InheritsDirective.Directive),
Factory.CodeTransition(),
Factory.MetaCode("inherits").Accepts(AcceptedCharactersInternal.None),
Factory.Span(SpanKindInternal.Code, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.WhiteSpace),
Factory.Span(SpanKindInternal.Code, "System.Web.Mvc.WebViewPage<IEnumerable<MvcApplication2.Models.RegisterModel>>", markup: false)
.AsDirectiveToken(CSharpCodeParser.InheritsDirectiveDescriptor.Tokens.First())));
.AsDirectiveToken(InheritsDirective.Directive.Tokens.First())));
}
[Fact]
public void InheritsDirectiveSupportsTypeKeywords()
{
ParseBlockTest("@inherits string",
new DirectiveBlock(new DirectiveChunkGenerator(CSharpCodeParser.InheritsDirectiveDescriptor),
ParseCodeBlockTest(
"@inherits string",
new[] { InheritsDirective.Directive, },
new DirectiveBlock(new DirectiveChunkGenerator(InheritsDirective.Directive),
Factory.CodeTransition(),
Factory.MetaCode("inherits").Accepts(AcceptedCharactersInternal.None),
Factory.Span(SpanKindInternal.Code, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.WhiteSpace),
Factory.Span(SpanKindInternal.Code, "string", markup: false)
.AsDirectiveToken(CSharpCodeParser.InheritsDirectiveDescriptor.Tokens.First())));
.AsDirectiveToken(InheritsDirective.Directive.Tokens.First())));
}
[Fact]
public void FunctionsDirective()
public void Parse_FunctionsDirective()
{
ParseBlockTest("@functions { foo(); bar(); }",
new DirectiveBlock(new DirectiveChunkGenerator(CSharpCodeParser.FunctionsDirectiveDescriptor),
ParseCodeBlockTest(
"@functions { foo(); bar(); }",
new[] { FunctionsDirective.Directive, },
new DirectiveBlock(new DirectiveChunkGenerator(FunctionsDirective.Directive),
Factory.CodeTransition(),
Factory.MetaCode("functions").Accepts(AcceptedCharactersInternal.None),
Factory.Span(SpanKindInternal.Markup, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.AllWhiteSpace),
@ -1048,8 +1059,10 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
[Fact]
public void EmptyFunctionsDirective()
{
ParseBlockTest("@functions { }",
new DirectiveBlock(new DirectiveChunkGenerator(CSharpCodeParser.FunctionsDirectiveDescriptor),
ParseCodeBlockTest(
"@functions { }",
new[] { FunctionsDirective.Directive, },
new DirectiveBlock(new DirectiveChunkGenerator(FunctionsDirective.Directive),
Factory.CodeTransition(),
Factory.MetaCode("functions").Accepts(AcceptedCharactersInternal.None),
Factory.Span(SpanKindInternal.Markup, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.AllWhiteSpace),
@ -1059,15 +1072,17 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
}
[Fact]
public void SectionDirective()
public void Parse_SectionDirective()
{
ParseBlockTest("@section Header { <p>F{o}o</p> }",
new DirectiveBlock(new DirectiveChunkGenerator(CSharpCodeParser.SectionDirectiveDescriptor),
ParseCodeBlockTest(
"@section Header { <p>F{o}o</p> }",
new[] { SectionDirective.Directive, },
new DirectiveBlock(new DirectiveChunkGenerator(SectionDirective.Directive),
Factory.CodeTransition(),
Factory.MetaCode("section").Accepts(AcceptedCharactersInternal.None),
Factory.Span(SpanKindInternal.Code, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.WhiteSpace),
Factory.Span(SpanKindInternal.Code, "Header", CSharpSymbolType.Identifier)
.AsDirectiveToken(CSharpCodeParser.SectionDirectiveDescriptor.Tokens.First()),
.AsDirectiveToken(SectionDirective.Directive.Tokens.First()),
Factory.Span(SpanKindInternal.Markup, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.AllWhiteSpace),
Factory.MetaCode("{").AutoCompleteWith(null, atEndOfSpan: true).Accepts(AcceptedCharactersInternal.None),
new MarkupBlock(

View File

@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using Microsoft.AspNetCore.Razor.Language.Extensions;
using Xunit;
namespace Microsoft.AspNetCore.Razor.Language.Legacy
@ -298,8 +299,10 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
[Fact]
public void ParseBlockReportsErrorIfClassBlockUnterminatedAtEOF()
{
ParseBlockTest("functions { var foo = bar; if(foo != null) { bar(); } ",
new DirectiveBlock(new DirectiveChunkGenerator(CSharpCodeParser.FunctionsDirectiveDescriptor),
ParseBlockTest(
"functions { var foo = bar; if(foo != null) { bar(); } ",
new[] { FunctionsDirective.Directive, },
new DirectiveBlock(new DirectiveChunkGenerator(FunctionsDirective.Directive),
Factory.MetaCode("functions").Accepts(AcceptedCharactersInternal.None),
Factory.Span(SpanKindInternal.Markup, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.AllWhiteSpace),
Factory.MetaCode("{").AutoCompleteWith("}", atEndOfSpan: true).Accepts(AcceptedCharactersInternal.None),

View File

@ -2,7 +2,7 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Linq;
using Microsoft.AspNetCore.Razor.Language.Extensions;
using Xunit;
namespace Microsoft.AspNetCore.Razor.Language.Legacy
@ -12,15 +12,17 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
[Fact]
public void ParseSectionBlockCapturesNewlineImmediatelyFollowing()
{
ParseDocumentTest("@section" + Environment.NewLine,
ParseDocumentTest(
"@section" + Environment.NewLine,
new[] { SectionDirective.Directive, },
new MarkupBlock(
Factory.EmptyHtml(),
new DirectiveBlock(new DirectiveChunkGenerator(CSharpCodeParser.SectionDirectiveDescriptor),
new DirectiveBlock(new DirectiveChunkGenerator(SectionDirective.Directive),
Factory.CodeTransition(),
Factory.MetaCode("section").Accepts(AcceptedCharactersInternal.None)),
Factory.Markup(Environment.NewLine)),
new RazorError(
LegacyResources.FormatDirectiveExpectsIdentifier(CSharpCodeParser.SectionDirectiveDescriptor.Directive),
LegacyResources.FormatDirectiveExpectsIdentifier(SectionDirective.Directive.Directive),
new SourceLocation(8, 0, 8),
length: Environment.NewLine.Length));
}
@ -28,18 +30,20 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
[Fact]
public void ParseSectionBlockCapturesWhitespaceToEndOfLineInSectionStatementMissingOpenBrace()
{
ParseDocumentTest("@section Foo " + Environment.NewLine + " ",
ParseDocumentTest(
"@section Foo " + Environment.NewLine + " ",
new[] { SectionDirective.Directive, },
new MarkupBlock(
Factory.EmptyHtml(),
new DirectiveBlock(new DirectiveChunkGenerator(CSharpCodeParser.SectionDirectiveDescriptor),
new DirectiveBlock(new DirectiveChunkGenerator(SectionDirective.Directive),
Factory.CodeTransition(),
Factory.MetaCode("section").Accepts(AcceptedCharactersInternal.None),
Factory.Span(SpanKindInternal.Code, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.WhiteSpace),
Factory.Span(SpanKindInternal.Code, "Foo", CSharpSymbolType.Identifier).AsDirectiveToken(CSharpCodeParser.SectionDirectiveDescriptor.Tokens[0]),
Factory.Span(SpanKindInternal.Code, "Foo", CSharpSymbolType.Identifier).AsDirectiveToken(SectionDirective.Directive.Tokens[0]),
Factory.Span(SpanKindInternal.Markup, " " + Environment.NewLine + " ", markup: false).Accepts(AcceptedCharactersInternal.AllWhiteSpace)),
Factory.EmptyHtml()),
new RazorError(
LegacyResources.FormatUnexpectedEOFAfterDirective(CSharpCodeParser.SectionDirectiveDescriptor.Directive, "{"),
LegacyResources.FormatUnexpectedEOFAfterDirective(SectionDirective.Directive.Directive, "{"),
new SourceLocation(25 + Environment.NewLine.Length, 0, 25 + Environment.NewLine.Length),
length: 1));
}
@ -47,16 +51,18 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
[Fact]
public void ParseSectionBlockCapturesWhitespaceToEndOfLineInSectionStatementMissingName()
{
ParseDocumentTest("@section " + Environment.NewLine + " ",
ParseDocumentTest(
"@section " + Environment.NewLine + " ",
new[] { SectionDirective.Directive, },
new MarkupBlock(
Factory.EmptyHtml(),
new DirectiveBlock(new DirectiveChunkGenerator(CSharpCodeParser.SectionDirectiveDescriptor),
new DirectiveBlock(new DirectiveChunkGenerator(SectionDirective.Directive),
Factory.CodeTransition(),
Factory.MetaCode("section").Accepts(AcceptedCharactersInternal.None),
Factory.Span(SpanKindInternal.Code, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.WhiteSpace)),
Factory.Markup(Environment.NewLine + " ")),
new RazorError(
LegacyResources.FormatDirectiveExpectsIdentifier(CSharpCodeParser.SectionDirectiveDescriptor.Directive),
LegacyResources.FormatDirectiveExpectsIdentifier(SectionDirective.Directive.Directive),
new SourceLocation(17, 0, 17),
length: Environment.NewLine.Length));
}
@ -64,7 +70,9 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
[Fact]
public void ParseSectionBlockIgnoresSectionUnlessAllLowerCase()
{
ParseDocumentTest("@Section foo",
ParseDocumentTest(
"@Section foo",
new[] { SectionDirective.Directive, },
new MarkupBlock(
Factory.EmptyHtml(),
new ExpressionBlock(
@ -78,10 +86,12 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
[Fact]
public void ParseSectionBlockReportsErrorAndTerminatesSectionBlockIfKeywordNotFollowedByIdentifierStartCharacter()
{
ParseDocumentTest("@section 9 { <p>Foo</p> }",
ParseDocumentTest(
"@section 9 { <p>Foo</p> }",
new[] { SectionDirective.Directive, },
new MarkupBlock(
Factory.EmptyHtml(),
new DirectiveBlock(new DirectiveChunkGenerator(CSharpCodeParser.SectionDirectiveDescriptor),
new DirectiveBlock(new DirectiveChunkGenerator(SectionDirective.Directive),
Factory.CodeTransition(),
Factory.MetaCode("section").Accepts(AcceptedCharactersInternal.None),
Factory.Span(SpanKindInternal.Code, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.WhiteSpace)),
@ -93,7 +103,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
Factory.Markup("</p>")),
Factory.Markup(" }")),
new RazorError(
LegacyResources.FormatDirectiveExpectsIdentifier(CSharpCodeParser.SectionDirectiveDescriptor.Directive),
LegacyResources.FormatDirectiveExpectsIdentifier(SectionDirective.Directive.Directive),
new SourceLocation(9, 0, 9),
length: 1));
}
@ -101,14 +111,16 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
[Fact]
public void ParseSectionBlockReportsErrorAndTerminatesSectionBlockIfNameNotFollowedByOpenBrace()
{
ParseDocumentTest("@section foo-bar { <p>Foo</p> }",
ParseDocumentTest(
"@section foo-bar { <p>Foo</p> }",
new[] { SectionDirective.Directive, },
new MarkupBlock(
Factory.EmptyHtml(),
new DirectiveBlock(new DirectiveChunkGenerator(CSharpCodeParser.SectionDirectiveDescriptor),
new DirectiveBlock(new DirectiveChunkGenerator(SectionDirective.Directive),
Factory.CodeTransition(),
Factory.MetaCode("section").Accepts(AcceptedCharactersInternal.None),
Factory.Span(SpanKindInternal.Code, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.WhiteSpace),
Factory.Span(SpanKindInternal.Code, "foo", CSharpSymbolType.Identifier).AsDirectiveToken(CSharpCodeParser.SectionDirectiveDescriptor.Tokens[0])),
Factory.Span(SpanKindInternal.Code, "foo", CSharpSymbolType.Identifier).AsDirectiveToken(SectionDirective.Directive.Tokens[0])),
Factory.Markup("-bar { "),
new MarkupTagBlock(
Factory.Markup("<p>")),
@ -117,7 +129,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
Factory.Markup("</p>")),
Factory.Markup(" }")),
new RazorError(
LegacyResources.FormatUnexpectedDirectiveLiteral(CSharpCodeParser.SectionDirectiveDescriptor.Directive, "{"),
LegacyResources.FormatUnexpectedDirectiveLiteral(SectionDirective.Directive.Directive, "{"),
new SourceLocation(12, 0, 12),
length: 1));
}
@ -125,23 +137,25 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
[Fact]
public void ParserOutputsErrorOnNestedSections()
{
ParseDocumentTest("@section foo { @section bar { <p>Foo</p> } }",
ParseDocumentTest(
"@section foo { @section bar { <p>Foo</p> } }",
new[] { SectionDirective.Directive, },
new MarkupBlock(
Factory.EmptyHtml(),
new DirectiveBlock(new DirectiveChunkGenerator(CSharpCodeParser.SectionDirectiveDescriptor),
new DirectiveBlock(new DirectiveChunkGenerator(SectionDirective.Directive),
Factory.CodeTransition(),
Factory.MetaCode("section").Accepts(AcceptedCharactersInternal.None),
Factory.Span(SpanKindInternal.Code, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.WhiteSpace),
Factory.Span(SpanKindInternal.Code, "foo", CSharpSymbolType.Identifier).AsDirectiveToken(CSharpCodeParser.SectionDirectiveDescriptor.Tokens[0]),
Factory.Span(SpanKindInternal.Code, "foo", CSharpSymbolType.Identifier).AsDirectiveToken(SectionDirective.Directive.Tokens[0]),
Factory.Span(SpanKindInternal.Markup, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.AllWhiteSpace),
Factory.MetaCode("{").AutoCompleteWith(null, atEndOfSpan: true).Accepts(AcceptedCharactersInternal.None),
new MarkupBlock(
Factory.Markup(" "),
new DirectiveBlock(new DirectiveChunkGenerator(CSharpCodeParser.SectionDirectiveDescriptor),
new DirectiveBlock(new DirectiveChunkGenerator(SectionDirective.Directive),
Factory.CodeTransition(),
Factory.MetaCode("section").Accepts(AcceptedCharactersInternal.None),
Factory.Span(SpanKindInternal.Code, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.WhiteSpace),
Factory.Span(SpanKindInternal.Code, "bar", CSharpSymbolType.Identifier).AsDirectiveToken(CSharpCodeParser.SectionDirectiveDescriptor.Tokens[0]),
Factory.Span(SpanKindInternal.Code, "bar", CSharpSymbolType.Identifier).AsDirectiveToken(SectionDirective.Directive.Tokens[0]),
Factory.Span(SpanKindInternal.Markup, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.AllWhiteSpace),
Factory.MetaCode("{").AutoCompleteWith(null, atEndOfSpan: true).Accepts(AcceptedCharactersInternal.None),
new MarkupBlock(
@ -169,20 +183,22 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
[Fact]
public void ParseSectionBlockHandlesEOFAfterOpenBrace()
{
ParseDocumentTest("@section foo {",
ParseDocumentTest(
"@section foo {",
new[] { SectionDirective.Directive, },
new MarkupBlock(
Factory.EmptyHtml(),
new DirectiveBlock(new DirectiveChunkGenerator(CSharpCodeParser.SectionDirectiveDescriptor),
new DirectiveBlock(new DirectiveChunkGenerator(SectionDirective.Directive),
Factory.CodeTransition(),
Factory.MetaCode("section").Accepts(AcceptedCharactersInternal.None),
Factory.Span(SpanKindInternal.Code, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.WhiteSpace),
Factory.Span(SpanKindInternal.Code, "foo", CSharpSymbolType.Identifier).AsDirectiveToken(CSharpCodeParser.SectionDirectiveDescriptor.Tokens[0]),
Factory.Span(SpanKindInternal.Code, "foo", CSharpSymbolType.Identifier).AsDirectiveToken(SectionDirective.Directive.Tokens[0]),
Factory.Span(SpanKindInternal.Markup, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.AllWhiteSpace),
Factory.MetaCode("{").AutoCompleteWith("}", atEndOfSpan: true).Accepts(AcceptedCharactersInternal.None),
new MarkupBlock(
Factory.EmptyHtml()))),
new RazorError(
LegacyResources.FormatParseError_Expected_EndOfBlock_Before_EOF(CSharpCodeParser.SectionDirectiveDescriptor.Directive, "}", "{"),
LegacyResources.FormatParseError_Expected_EndOfBlock_Before_EOF(SectionDirective.Directive.Directive, "}", "{"),
new SourceLocation(13, 0, 13),
length: 1));
}
@ -194,14 +210,16 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
[InlineData(" \n abc")]
public void ParseSectionBlockHandlesEOFAfterOpenContent(string postStartBrace)
{
ParseDocumentTest("@section foo {" + postStartBrace,
ParseDocumentTest(
"@section foo {" + postStartBrace,
new[] { SectionDirective.Directive, },
new MarkupBlock(
Factory.EmptyHtml(),
new DirectiveBlock(new DirectiveChunkGenerator(CSharpCodeParser.SectionDirectiveDescriptor),
new DirectiveBlock(new DirectiveChunkGenerator(SectionDirective.Directive),
Factory.CodeTransition(),
Factory.MetaCode("section").Accepts(AcceptedCharactersInternal.None),
Factory.Span(SpanKindInternal.Code, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.WhiteSpace),
Factory.Span(SpanKindInternal.Code, "foo", CSharpSymbolType.Identifier).AsDirectiveToken(CSharpCodeParser.SectionDirectiveDescriptor.Tokens[0]),
Factory.Span(SpanKindInternal.Code, "foo", CSharpSymbolType.Identifier).AsDirectiveToken(SectionDirective.Directive.Tokens[0]),
Factory.Span(SpanKindInternal.Markup, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.AllWhiteSpace),
Factory.MetaCode("{").AutoCompleteWith("}", atEndOfSpan: true).Accepts(AcceptedCharactersInternal.None),
new MarkupBlock(
@ -215,14 +233,16 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
[Fact]
public void ParseSectionBlockHandlesUnterminatedSection()
{
ParseDocumentTest("@section foo { <p>Foo{}</p>",
ParseDocumentTest(
"@section foo { <p>Foo{}</p>",
new[] { SectionDirective.Directive, },
new MarkupBlock(
Factory.EmptyHtml(),
new DirectiveBlock(new DirectiveChunkGenerator(CSharpCodeParser.SectionDirectiveDescriptor),
new DirectiveBlock(new DirectiveChunkGenerator(SectionDirective.Directive),
Factory.CodeTransition(),
Factory.MetaCode("section").Accepts(AcceptedCharactersInternal.None),
Factory.Span(SpanKindInternal.Code, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.WhiteSpace),
Factory.Span(SpanKindInternal.Code, "foo", CSharpSymbolType.Identifier).AsDirectiveToken(CSharpCodeParser.SectionDirectiveDescriptor.Tokens[0]),
Factory.Span(SpanKindInternal.Code, "foo", CSharpSymbolType.Identifier).AsDirectiveToken(SectionDirective.Directive.Tokens[0]),
Factory.Span(SpanKindInternal.Markup, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.AllWhiteSpace),
Factory.MetaCode("{").AutoCompleteWith("}", atEndOfSpan: true).Accepts(AcceptedCharactersInternal.None),
new MarkupBlock(
@ -249,13 +269,14 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
"@section Test{0}{{{0}{1}@if(true){0}{1}{{{0}{1}{1}<p>Hello World</p>{0}{1}}}",
newLine,
spaces),
new[] { SectionDirective.Directive, },
new MarkupBlock(
Factory.EmptyHtml(),
new DirectiveBlock(new DirectiveChunkGenerator(CSharpCodeParser.SectionDirectiveDescriptor),
new DirectiveBlock(new DirectiveChunkGenerator(SectionDirective.Directive),
Factory.CodeTransition(),
Factory.MetaCode("section").Accepts(AcceptedCharactersInternal.None),
Factory.Span(SpanKindInternal.Code, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.WhiteSpace),
Factory.Span(SpanKindInternal.Code, "Test", CSharpSymbolType.Identifier).AsDirectiveToken(CSharpCodeParser.SectionDirectiveDescriptor.Tokens[0]),
Factory.Span(SpanKindInternal.Code, "Test", CSharpSymbolType.Identifier).AsDirectiveToken(SectionDirective.Directive.Tokens[0]),
Factory.Span(SpanKindInternal.Markup, Environment.NewLine, CSharpSymbolType.NewLine).Accepts(AcceptedCharactersInternal.AllWhiteSpace),
Factory.MetaCode("{").AutoCompleteWith("}", atEndOfSpan: true).Accepts(AcceptedCharactersInternal.None),
new MarkupBlock(
@ -280,18 +301,20 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
[Fact]
public void ParseSectionBlockReportsErrorAndAcceptsWhitespaceToEndOfLineIfSectionNotFollowedByOpenBrace()
{
ParseDocumentTest("@section foo " + Environment.NewLine,
ParseDocumentTest(
"@section foo " + Environment.NewLine,
new[] { SectionDirective.Directive, },
new MarkupBlock(
Factory.EmptyHtml(),
new DirectiveBlock(new DirectiveChunkGenerator(CSharpCodeParser.SectionDirectiveDescriptor),
new DirectiveBlock(new DirectiveChunkGenerator(SectionDirective.Directive),
Factory.CodeTransition(),
Factory.MetaCode("section").Accepts(AcceptedCharactersInternal.None),
Factory.Span(SpanKindInternal.Code, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.WhiteSpace),
Factory.Span(SpanKindInternal.Code, "foo", CSharpSymbolType.Identifier).AsDirectiveToken(CSharpCodeParser.SectionDirectiveDescriptor.Tokens[0]),
Factory.Span(SpanKindInternal.Code, "foo", CSharpSymbolType.Identifier).AsDirectiveToken(SectionDirective.Directive.Tokens[0]),
Factory.Span(SpanKindInternal.Markup, " " + Environment.NewLine, markup: false).Accepts(AcceptedCharactersInternal.AllWhiteSpace)),
Factory.EmptyHtml()),
new RazorError(
LegacyResources.FormatUnexpectedEOFAfterDirective(CSharpCodeParser.SectionDirectiveDescriptor.Directive, "{"),
LegacyResources.FormatUnexpectedEOFAfterDirective(SectionDirective.Directive.Directive, "{"),
new SourceLocation(18 + Environment.NewLine.Length, 0, 18 + Environment.NewLine.Length),
length: 1));
}
@ -308,13 +331,14 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
+ "{" + Environment.NewLine
+ "<p>Foo</p>" + Environment.NewLine
+ "}",
new[] { SectionDirective.Directive, },
new MarkupBlock(
Factory.EmptyHtml(),
new DirectiveBlock(new DirectiveChunkGenerator(CSharpCodeParser.SectionDirectiveDescriptor),
new DirectiveBlock(new DirectiveChunkGenerator(SectionDirective.Directive),
Factory.CodeTransition(),
Factory.MetaCode("section").Accepts(AcceptedCharactersInternal.None),
Factory.Span(SpanKindInternal.Code, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.WhiteSpace),
Factory.Span(SpanKindInternal.Code, "foo", CSharpSymbolType.Identifier).AsDirectiveToken(CSharpCodeParser.SectionDirectiveDescriptor.Tokens[0]),
Factory.Span(SpanKindInternal.Code, "foo", CSharpSymbolType.Identifier).AsDirectiveToken(SectionDirective.Directive.Tokens[0]),
Factory.Span(SpanKindInternal.Markup, " " + string.Format("{0}{0}{0}{0}{0}{0}", Environment.NewLine), markup: false).Accepts(AcceptedCharactersInternal.AllWhiteSpace),
Factory.MetaCode("{").AutoCompleteWith(null, atEndOfSpan: true).Accepts(AcceptedCharactersInternal.None),
new MarkupBlock(
@ -332,14 +356,16 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
[Fact]
public void ParseSectionBlockParsesNamedSectionCorrectly()
{
ParseDocumentTest("@section foo { <p>Foo</p> }",
ParseDocumentTest(
"@section foo { <p>Foo</p> }",
new[] { SectionDirective.Directive, },
new MarkupBlock(
Factory.EmptyHtml(),
new DirectiveBlock(new DirectiveChunkGenerator(CSharpCodeParser.SectionDirectiveDescriptor),
new DirectiveBlock(new DirectiveChunkGenerator(SectionDirective.Directive),
Factory.CodeTransition(),
Factory.MetaCode("section").Accepts(AcceptedCharactersInternal.None),
Factory.Span(SpanKindInternal.Code, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.WhiteSpace),
Factory.Span(SpanKindInternal.Code, "foo", CSharpSymbolType.Identifier).AsDirectiveToken(CSharpCodeParser.SectionDirectiveDescriptor.Tokens[0]),
Factory.Span(SpanKindInternal.Code, "foo", CSharpSymbolType.Identifier).AsDirectiveToken(SectionDirective.Directive.Tokens[0]),
Factory.Span(SpanKindInternal.Markup, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.AllWhiteSpace),
Factory.MetaCode("{").AutoCompleteWith(null, atEndOfSpan: true).Accepts(AcceptedCharactersInternal.None),
new MarkupBlock(
@ -357,14 +383,16 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
[Fact]
public void ParseSectionBlockDoesNotRequireSpaceBetweenSectionNameAndOpenBrace()
{
ParseDocumentTest("@section foo{ <p>Foo</p> }",
ParseDocumentTest(
"@section foo{ <p>Foo</p> }",
new[] { SectionDirective.Directive, },
new MarkupBlock(
Factory.EmptyHtml(),
new DirectiveBlock(new DirectiveChunkGenerator(CSharpCodeParser.SectionDirectiveDescriptor),
new DirectiveBlock(new DirectiveChunkGenerator(SectionDirective.Directive),
Factory.CodeTransition(),
Factory.MetaCode("section").Accepts(AcceptedCharactersInternal.None),
Factory.Span(SpanKindInternal.Code, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.WhiteSpace),
Factory.Span(SpanKindInternal.Code, "foo", CSharpSymbolType.Identifier).AsDirectiveToken(CSharpCodeParser.SectionDirectiveDescriptor.Tokens[0]),
Factory.Span(SpanKindInternal.Code, "foo", CSharpSymbolType.Identifier).AsDirectiveToken(SectionDirective.Directive.Tokens[0]),
Factory.MetaCode("{").AutoCompleteWith(null, atEndOfSpan: true).Accepts(AcceptedCharactersInternal.None),
new MarkupBlock(
Factory.Markup(" "),
@ -381,14 +409,16 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
[Fact]
public void ParseSectionBlockBalancesBraces()
{
ParseDocumentTest("@section foo { <script>(function foo() { return 1; })();</script> }",
ParseDocumentTest(
"@section foo { <script>(function foo() { return 1; })();</script> }",
new[] { SectionDirective.Directive, },
new MarkupBlock(
Factory.EmptyHtml(),
new DirectiveBlock(new DirectiveChunkGenerator(CSharpCodeParser.SectionDirectiveDescriptor),
new DirectiveBlock(new DirectiveChunkGenerator(SectionDirective.Directive),
Factory.CodeTransition(),
Factory.MetaCode("section").Accepts(AcceptedCharactersInternal.None),
Factory.Span(SpanKindInternal.Code, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.WhiteSpace),
Factory.Span(SpanKindInternal.Code, "foo", CSharpSymbolType.Identifier).AsDirectiveToken(CSharpCodeParser.SectionDirectiveDescriptor.Tokens[0]),
Factory.Span(SpanKindInternal.Code, "foo", CSharpSymbolType.Identifier).AsDirectiveToken(SectionDirective.Directive.Tokens[0]),
Factory.Span(SpanKindInternal.Markup, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.AllWhiteSpace),
Factory.MetaCode("{").AutoCompleteWith(null, atEndOfSpan: true).Accepts(AcceptedCharactersInternal.None),
new MarkupBlock(
@ -406,14 +436,16 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
[Fact]
public void ParseSectionBlockAllowsBracesInCSharpExpression()
{
ParseDocumentTest("@section foo { I really want to render a close brace, so here I go: @(\"}\") }",
ParseDocumentTest(
"@section foo { I really want to render a close brace, so here I go: @(\"}\") }",
new[] { SectionDirective.Directive, },
new MarkupBlock(
Factory.EmptyHtml(),
new DirectiveBlock(new DirectiveChunkGenerator(CSharpCodeParser.SectionDirectiveDescriptor),
new DirectiveBlock(new DirectiveChunkGenerator(SectionDirective.Directive),
Factory.CodeTransition(),
Factory.MetaCode("section").Accepts(AcceptedCharactersInternal.None),
Factory.Span(SpanKindInternal.Code, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.WhiteSpace),
Factory.Span(SpanKindInternal.Code, "foo", CSharpSymbolType.Identifier).AsDirectiveToken(CSharpCodeParser.SectionDirectiveDescriptor.Tokens[0]),
Factory.Span(SpanKindInternal.Code, "foo", CSharpSymbolType.Identifier).AsDirectiveToken(SectionDirective.Directive.Tokens[0]),
Factory.Span(SpanKindInternal.Markup, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.AllWhiteSpace),
Factory.MetaCode("{").AutoCompleteWith(null, atEndOfSpan: true).Accepts(AcceptedCharactersInternal.None),
new MarkupBlock(
@ -435,13 +467,14 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
+ "@if(true) {" + Environment.NewLine
+ "}" + Environment.NewLine
+ "}",
new[] { SectionDirective.Directive, },
new MarkupBlock(
Factory.EmptyHtml(),
new DirectiveBlock(new DirectiveChunkGenerator(CSharpCodeParser.SectionDirectiveDescriptor),
new DirectiveBlock(new DirectiveChunkGenerator(SectionDirective.Directive),
Factory.CodeTransition(),
Factory.MetaCode("section").Accepts(AcceptedCharactersInternal.None),
Factory.Span(SpanKindInternal.Code, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.WhiteSpace),
Factory.Span(SpanKindInternal.Code, "Foo", CSharpSymbolType.Identifier).AsDirectiveToken(CSharpCodeParser.SectionDirectiveDescriptor.Tokens[0]),
Factory.Span(SpanKindInternal.Code, "Foo", CSharpSymbolType.Identifier).AsDirectiveToken(SectionDirective.Directive.Tokens[0]),
Factory.Span(SpanKindInternal.Markup, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.AllWhiteSpace),
Factory.MetaCode("{").AutoCompleteWith(null, atEndOfSpan: true).Accepts(AcceptedCharactersInternal.None),
new MarkupBlock(
@ -460,13 +493,14 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
ParseDocumentTest("@section Foo {" + Environment.NewLine
+ "@if(true) {" + Environment.NewLine
+ "}}",
new[] { SectionDirective.Directive, },
new MarkupBlock(
Factory.EmptyHtml(),
new DirectiveBlock(new DirectiveChunkGenerator(CSharpCodeParser.SectionDirectiveDescriptor),
new DirectiveBlock(new DirectiveChunkGenerator(SectionDirective.Directive),
Factory.CodeTransition(),
Factory.MetaCode("section").Accepts(AcceptedCharactersInternal.None),
Factory.Span(SpanKindInternal.Code, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.WhiteSpace),
Factory.Span(SpanKindInternal.Code, "Foo", CSharpSymbolType.Identifier).AsDirectiveToken(CSharpCodeParser.SectionDirectiveDescriptor.Tokens[0]),
Factory.Span(SpanKindInternal.Code, "Foo", CSharpSymbolType.Identifier).AsDirectiveToken(SectionDirective.Directive.Tokens[0]),
Factory.Span(SpanKindInternal.Markup, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.AllWhiteSpace),
Factory.MetaCode("{").AutoCompleteWith(null, atEndOfSpan: true).Accepts(AcceptedCharactersInternal.None),
new MarkupBlock(
@ -482,14 +516,16 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
[Fact]
public void ParseSectionBlockCorrectlyTerminatesWhenCloseBraceImmediatelyFollowsMarkup()
{
ParseDocumentTest("@section foo {something}",
ParseDocumentTest(
"@section foo {something}",
new[] { SectionDirective.Directive, },
new MarkupBlock(
Factory.EmptyHtml(),
new DirectiveBlock(new DirectiveChunkGenerator(CSharpCodeParser.SectionDirectiveDescriptor),
new DirectiveBlock(new DirectiveChunkGenerator(SectionDirective.Directive),
Factory.CodeTransition(),
Factory.MetaCode("section").Accepts(AcceptedCharactersInternal.None),
Factory.Span(SpanKindInternal.Code, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.WhiteSpace),
Factory.Span(SpanKindInternal.Code, "foo", CSharpSymbolType.Identifier).AsDirectiveToken(CSharpCodeParser.SectionDirectiveDescriptor.Tokens[0]),
Factory.Span(SpanKindInternal.Code, "foo", CSharpSymbolType.Identifier).AsDirectiveToken(SectionDirective.Directive.Tokens[0]),
Factory.Span(SpanKindInternal.Markup, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.AllWhiteSpace),
Factory.MetaCode("{").AutoCompleteWith(null, atEndOfSpan: true).Accepts(AcceptedCharactersInternal.None),
new MarkupBlock(
@ -501,14 +537,16 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
[Fact]
public void ParseSectionBlockParsesComment()
{
ParseDocumentTest("@section s {<!-- -->}",
ParseDocumentTest(
"@section s {<!-- -->}",
new[] { SectionDirective.Directive, },
new MarkupBlock(
Factory.EmptyHtml(),
new DirectiveBlock(new DirectiveChunkGenerator(CSharpCodeParser.SectionDirectiveDescriptor),
new DirectiveBlock(new DirectiveChunkGenerator(SectionDirective.Directive),
Factory.CodeTransition(),
Factory.MetaCode("section").Accepts(AcceptedCharactersInternal.None),
Factory.Span(SpanKindInternal.Code, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.WhiteSpace),
Factory.Span(SpanKindInternal.Code, "s", CSharpSymbolType.Identifier).AsDirectiveToken(CSharpCodeParser.SectionDirectiveDescriptor.Tokens[0]),
Factory.Span(SpanKindInternal.Code, "s", CSharpSymbolType.Identifier).AsDirectiveToken(SectionDirective.Directive.Tokens[0]),
Factory.Span(SpanKindInternal.Markup, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.AllWhiteSpace),
Factory.MetaCode("{").AutoCompleteWith(null, atEndOfSpan: true).Accepts(AcceptedCharactersInternal.None),
new MarkupBlock(
@ -522,14 +560,16 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
[Fact]
public void ParseSectionBlockParsesCommentWithDelimiters()
{
ParseDocumentTest("@section s {<!-- > \" '-->}",
ParseDocumentTest(
"@section s {<!-- > \" '-->}",
new[] { SectionDirective.Directive, },
new MarkupBlock(
Factory.EmptyHtml(),
new DirectiveBlock(new DirectiveChunkGenerator(CSharpCodeParser.SectionDirectiveDescriptor),
new DirectiveBlock(new DirectiveChunkGenerator(SectionDirective.Directive),
Factory.CodeTransition(),
Factory.MetaCode("section").Accepts(AcceptedCharactersInternal.None),
Factory.Span(SpanKindInternal.Code, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.WhiteSpace),
Factory.Span(SpanKindInternal.Code, "s", CSharpSymbolType.Identifier).AsDirectiveToken(CSharpCodeParser.SectionDirectiveDescriptor.Tokens[0]),
Factory.Span(SpanKindInternal.Code, "s", CSharpSymbolType.Identifier).AsDirectiveToken(SectionDirective.Directive.Tokens[0]),
Factory.Span(SpanKindInternal.Markup, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.AllWhiteSpace),
Factory.MetaCode("{").AutoCompleteWith(null, atEndOfSpan: true).Accepts(AcceptedCharactersInternal.None),
new MarkupBlock(
@ -543,13 +583,14 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
{
ParseDocumentTest(
"@section s {" + Environment.NewLine + "<a" + Environment.NewLine + "<!-- > \" '-->}",
new[] { SectionDirective.Directive, },
new MarkupBlock(
Factory.EmptyHtml(),
new DirectiveBlock(new DirectiveChunkGenerator(CSharpCodeParser.SectionDirectiveDescriptor),
new DirectiveBlock(new DirectiveChunkGenerator(SectionDirective.Directive),
Factory.CodeTransition(),
Factory.MetaCode("section").Accepts(AcceptedCharactersInternal.None),
Factory.Span(SpanKindInternal.Code, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.WhiteSpace),
Factory.Span(SpanKindInternal.Code, "s", CSharpSymbolType.Identifier).AsDirectiveToken(CSharpCodeParser.SectionDirectiveDescriptor.Tokens[0]),
Factory.Span(SpanKindInternal.Code, "s", CSharpSymbolType.Identifier).AsDirectiveToken(SectionDirective.Directive.Tokens[0]),
Factory.Span(SpanKindInternal.Markup, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.AllWhiteSpace),
Factory.MetaCode("{").AutoCompleteWith(null, atEndOfSpan: true).Accepts(AcceptedCharactersInternal.None),
new MarkupBlock(
@ -566,13 +607,14 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
{
ParseDocumentTest(
"@section s { <? xml bleh ?>}",
new[] { SectionDirective.Directive, },
new MarkupBlock(
Factory.EmptyHtml(),
new DirectiveBlock(new DirectiveChunkGenerator(CSharpCodeParser.SectionDirectiveDescriptor),
new DirectiveBlock(new DirectiveChunkGenerator(SectionDirective.Directive),
Factory.CodeTransition(),
Factory.MetaCode("section").Accepts(AcceptedCharactersInternal.None),
Factory.Span(SpanKindInternal.Code, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.WhiteSpace),
Factory.Span(SpanKindInternal.Code, "s", CSharpSymbolType.Identifier).AsDirectiveToken(CSharpCodeParser.SectionDirectiveDescriptor.Tokens[0]),
Factory.Span(SpanKindInternal.Code, "s", CSharpSymbolType.Identifier).AsDirectiveToken(SectionDirective.Directive.Tokens[0]),
Factory.Span(SpanKindInternal.Markup, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.AllWhiteSpace),
Factory.MetaCode("{").AutoCompleteWith(null, atEndOfSpan: true).Accepts(AcceptedCharactersInternal.None),
new MarkupBlock(
@ -593,11 +635,11 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
"@section s {<span foo='@@' />}",
new MarkupBlock(
factory.EmptyHtml(),
new DirectiveBlock(new DirectiveChunkGenerator(CSharpCodeParser.SectionDirectiveDescriptor),
new DirectiveBlock(new DirectiveChunkGenerator(SectionDirective.Directive),
factory.CodeTransition(),
factory.MetaCode("section").Accepts(AcceptedCharactersInternal.None),
factory.Span(SpanKindInternal.Code, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.WhiteSpace),
factory.Span(SpanKindInternal.Code, "s", CSharpSymbolType.Identifier).AsDirectiveToken(CSharpCodeParser.SectionDirectiveDescriptor.Tokens[0]),
factory.Span(SpanKindInternal.Code, "s", CSharpSymbolType.Identifier).AsDirectiveToken(SectionDirective.Directive.Tokens[0]),
factory.Span(SpanKindInternal.Markup, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.AllWhiteSpace),
factory.MetaCode("{").AutoCompleteWith(null, atEndOfSpan: true).Accepts(AcceptedCharactersInternal.None),
new MarkupBlock(
@ -618,11 +660,11 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
"@section s {<span foo='@DateTime.Now @@' />}",
new MarkupBlock(
factory.EmptyHtml(),
new DirectiveBlock(new DirectiveChunkGenerator(CSharpCodeParser.SectionDirectiveDescriptor),
new DirectiveBlock(new DirectiveChunkGenerator(SectionDirective.Directive),
factory.CodeTransition(),
factory.MetaCode("section").Accepts(AcceptedCharactersInternal.None),
factory.Span(SpanKindInternal.Code, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.WhiteSpace),
factory.Span(SpanKindInternal.Code, "s", CSharpSymbolType.Identifier).AsDirectiveToken(CSharpCodeParser.SectionDirectiveDescriptor.Tokens[0]),
factory.Span(SpanKindInternal.Code, "s", CSharpSymbolType.Identifier).AsDirectiveToken(SectionDirective.Directive.Tokens[0]),
factory.Span(SpanKindInternal.Markup, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.AllWhiteSpace),
factory.MetaCode("{").AutoCompleteWith(null, atEndOfSpan: true).Accepts(AcceptedCharactersInternal.None),
new MarkupBlock(
@ -656,7 +698,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
{
FixupSpans = true;
ParseDocumentTest(input, (Block)expected);
ParseDocumentTest(input, new[] { SectionDirective.Directive, }, (Block)expected);
}
}
}

View File

@ -2,7 +2,7 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Linq;
using Microsoft.AspNetCore.Razor.Language.Extensions;
using Xunit;
namespace Microsoft.AspNetCore.Razor.Language.Legacy
@ -12,32 +12,38 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
[Fact]
public void ParseInheritsStatementMarksInheritsSpanAsCanGrowIfMissingTrailingSpace()
{
ParseBlockTest("inherits",
new DirectiveBlock(new DirectiveChunkGenerator(CSharpCodeParser.InheritsDirectiveDescriptor),
ParseBlockTest(
"inherits",
new[] { InheritsDirective.Directive, },
new DirectiveBlock(new DirectiveChunkGenerator(InheritsDirective.Directive),
Factory.MetaCode("inherits").Accepts(AcceptedCharactersInternal.None)),
new RazorError(
LegacyResources.FormatUnexpectedEOFAfterDirective(CSharpCodeParser.InheritsDirectiveDescriptor.Directive, "type"),
LegacyResources.FormatUnexpectedEOFAfterDirective(InheritsDirective.Directive.Directive, "type"),
new SourceLocation(8, 0, 8), 1));
}
[Fact]
public void InheritsBlockAcceptsMultipleGenericArguments()
{
ParseBlockTest("inherits Foo.Bar<Biz<Qux>, string, int>.Baz",
new DirectiveBlock(new DirectiveChunkGenerator(CSharpCodeParser.InheritsDirectiveDescriptor),
ParseBlockTest(
"inherits Foo.Bar<Biz<Qux>, string, int>.Baz",
new[] { InheritsDirective.Directive, },
new DirectiveBlock(new DirectiveChunkGenerator(InheritsDirective.Directive),
Factory.MetaCode("inherits").Accepts(AcceptedCharactersInternal.None),
Factory.Span(SpanKindInternal.Code, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.WhiteSpace),
Factory.Span(SpanKindInternal.Code, "Foo.Bar<Biz<Qux>, string, int>.Baz", markup: false).AsDirectiveToken(CSharpCodeParser.InheritsDirectiveDescriptor.Tokens[0])));
Factory.Span(SpanKindInternal.Code, "Foo.Bar<Biz<Qux>, string, int>.Baz", markup: false).AsDirectiveToken(InheritsDirective.Directive.Tokens[0])));
}
[Fact]
public void InheritsBlockOutputsErrorIfInheritsNotFollowedByTypeButAcceptsEntireLineAsCode()
{
ParseBlockTest("inherits " + Environment.NewLine + "foo",
new DirectiveBlock(new DirectiveChunkGenerator(CSharpCodeParser.InheritsDirectiveDescriptor),
ParseBlockTest(
"inherits " + Environment.NewLine + "foo",
new[] { InheritsDirective.Directive, },
new DirectiveBlock(new DirectiveChunkGenerator(InheritsDirective.Directive),
Factory.MetaCode("inherits").Accepts(AcceptedCharactersInternal.None),
Factory.Span(SpanKindInternal.Code, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.WhiteSpace)),
new RazorError(LegacyResources.FormatDirectiveExpectsTypeName(CSharpCodeParser.InheritsDirectiveDescriptor.Directive), 24, 0, 24, Environment.NewLine.Length));
new RazorError(LegacyResources.FormatDirectiveExpectsTypeName(InheritsDirective.Directive.Directive), 24, 0, 24, Environment.NewLine.Length));
}
[Fact]
@ -138,8 +144,10 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
public void ParseBlockBalancesBracesAndOutputsContentAsClassLevelCodeSpanIfFirstIdentifierIsFunctionsKeyword()
{
const string code = " foo(); \"bar}baz\" ";
ParseBlockTest("functions {" + code + "} zoop",
new DirectiveBlock(new DirectiveChunkGenerator(CSharpCodeParser.FunctionsDirectiveDescriptor),
ParseBlockTest(
"functions {" + code + "} zoop",
new[] { FunctionsDirective.Directive, },
new DirectiveBlock(new DirectiveChunkGenerator(FunctionsDirective.Directive),
Factory.MetaCode("functions").Accepts(AcceptedCharactersInternal.None),
Factory.Span(SpanKindInternal.Markup, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.AllWhiteSpace),
Factory.MetaCode("{").AutoCompleteWith(null, atEndOfSpan: true).Accepts(AcceptedCharactersInternal.None),
@ -150,8 +158,10 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
[Fact]
public void ParseBlockDoesNoErrorRecoveryForFunctionsBlock()
{
ParseBlockTest("functions { { { { { } zoop",
new DirectiveBlock(new DirectiveChunkGenerator(CSharpCodeParser.FunctionsDirectiveDescriptor),
ParseBlockTest(
"functions { { { { { } zoop",
new[] { FunctionsDirective.Directive, },
new DirectiveBlock(new DirectiveChunkGenerator(FunctionsDirective.Directive),
Factory.MetaCode("functions").Accepts(AcceptedCharactersInternal.None),
Factory.Span(SpanKindInternal.Markup, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.AllWhiteSpace),
Factory.MetaCode("{").AutoCompleteWith("}", atEndOfSpan: true).Accepts(AcceptedCharactersInternal.None),

View File

@ -9,9 +9,9 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
{
internal abstract ISet<string> KeywordSet { get; }
internal override RazorSyntaxTree ParseBlock(string document, bool designTime)
internal override RazorSyntaxTree ParseBlock(string document, IEnumerable<DirectiveDescriptor> directives, bool designTime)
{
return ParseCodeBlock(document, designTime);
return ParseCodeBlock(document, directives, designTime);
}
internal void ImplicitExpressionTest(string input, params RazorError[] errors)

View File

@ -3,6 +3,7 @@
using System;
using System.Linq;
using Microsoft.AspNetCore.Razor.Language.Extensions;
using Xunit;
namespace Microsoft.AspNetCore.Razor.Language.Legacy
@ -107,13 +108,14 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
ParseDocumentTest("@section Foo {" + Environment.NewLine
+ " <html></html>" + Environment.NewLine
+ "}",
new[] { SectionDirective.Directive, },
new MarkupBlock(
Factory.EmptyHtml(),
new DirectiveBlock(new DirectiveChunkGenerator(CSharpCodeParser.SectionDirectiveDescriptor),
new DirectiveBlock(new DirectiveChunkGenerator(SectionDirective.Directive),
Factory.CodeTransition(),
Factory.MetaCode("section").Accepts(AcceptedCharactersInternal.None),
Factory.Span(SpanKindInternal.Code, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.WhiteSpace),
Factory.Span(SpanKindInternal.Code, "Foo", CSharpSymbolType.Identifier).AsDirectiveToken(CSharpCodeParser.SectionDirectiveDescriptor.Tokens[0]),
Factory.Span(SpanKindInternal.Code, "Foo", CSharpSymbolType.Identifier).AsDirectiveToken(SectionDirective.Directive.Tokens[0]),
Factory.Span(SpanKindInternal.Markup, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.AllWhiteSpace),
Factory.MetaCode("{").AutoCompleteWith(null, atEndOfSpan: true).Accepts(AcceptedCharactersInternal.None),
new MarkupBlock(
@ -469,14 +471,16 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
[Fact]
public void ParseSectionIgnoresTagsInContentsOfScriptTag()
{
ParseDocumentTest(@"@section Foo { <script>foo<bar baz='@boz'></script> }",
ParseDocumentTest(
@"@section Foo { <script>foo<bar baz='@boz'></script> }",
new[] { SectionDirective.Directive, },
new MarkupBlock(
Factory.EmptyHtml(),
new DirectiveBlock(new DirectiveChunkGenerator(CSharpCodeParser.SectionDirectiveDescriptor),
new DirectiveBlock(new DirectiveChunkGenerator(SectionDirective.Directive),
Factory.CodeTransition(),
Factory.MetaCode("section").Accepts(AcceptedCharactersInternal.None),
Factory.Span(SpanKindInternal.Code, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.WhiteSpace),
Factory.Span(SpanKindInternal.Code, "Foo", CSharpSymbolType.Identifier).AsDirectiveToken(CSharpCodeParser.SectionDirectiveDescriptor.Tokens[0]),
Factory.Span(SpanKindInternal.Code, "Foo", CSharpSymbolType.Identifier).AsDirectiveToken(SectionDirective.Directive.Tokens[0]),
Factory.Span(SpanKindInternal.Markup, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.AllWhiteSpace),
Factory.MetaCode("{").AutoCompleteWith(null, atEndOfSpan: true).Accepts(AcceptedCharactersInternal.None),
new MarkupBlock(

View File

@ -3,6 +3,7 @@
using System;
using System.Linq;
using Microsoft.AspNetCore.Razor.Language.Extensions;
using Xunit;
namespace Microsoft.AspNetCore.Razor.Language.Legacy
@ -281,7 +282,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
[Fact]
public void SectionContextGivesWhitespacePreceedingAtToCodeIfThereIsNoMarkupOnThatLine()
{
var sectionDescriptor = CSharpCodeParser.SectionDirectiveDescriptor;
var sectionDescriptor = SectionDirective.Directive;
ParseDocumentTest("@section foo {" + Environment.NewLine
+ " <ul>" + Environment.NewLine
+ " @foreach(var p in Products) {" + Environment.NewLine
@ -289,13 +290,14 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
+ " }" + Environment.NewLine
+ " </ul>" + Environment.NewLine
+ "}",
new[] { SectionDirective.Directive, },
new MarkupBlock(
Factory.EmptyHtml(),
new DirectiveBlock(new DirectiveChunkGenerator(CSharpCodeParser.SectionDirectiveDescriptor),
new DirectiveBlock(new DirectiveChunkGenerator(SectionDirective.Directive),
Factory.CodeTransition(),
Factory.MetaCode("section").Accepts(AcceptedCharactersInternal.None),
Factory.Span(SpanKindInternal.Code, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.WhiteSpace),
Factory.Span(SpanKindInternal.Code, "foo", CSharpSymbolType.Identifier).AsDirectiveToken(CSharpCodeParser.SectionDirectiveDescriptor.Tokens[0]),
Factory.Span(SpanKindInternal.Code, "foo", CSharpSymbolType.Identifier).AsDirectiveToken(SectionDirective.Directive.Tokens[0]),
Factory.Span(SpanKindInternal.Markup, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.AllWhiteSpace),
Factory.MetaCode("{").AutoCompleteWith(null, atEndOfSpan: true).Accepts(AcceptedCharactersInternal.None),
new MarkupBlock(
@ -389,14 +391,16 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
[Fact]
public void SectionBodyTreatsTwoAtSignsAsEscapeSequence()
{
ParseDocumentTest("@section Foo { <foo>@@bar</foo> }",
ParseDocumentTest(
"@section Foo { <foo>@@bar</foo> }",
new[] { SectionDirective.Directive, },
new MarkupBlock(
Factory.EmptyHtml(),
new DirectiveBlock(new DirectiveChunkGenerator(CSharpCodeParser.SectionDirectiveDescriptor),
new DirectiveBlock(new DirectiveChunkGenerator(SectionDirective.Directive),
Factory.CodeTransition(),
Factory.MetaCode("section").Accepts(AcceptedCharactersInternal.None),
Factory.Span(SpanKindInternal.Code, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.WhiteSpace),
Factory.Span(SpanKindInternal.Code, "Foo", CSharpSymbolType.Identifier).AsDirectiveToken(CSharpCodeParser.SectionDirectiveDescriptor.Tokens[0]),
Factory.Span(SpanKindInternal.Code, "Foo", CSharpSymbolType.Identifier).AsDirectiveToken(SectionDirective.Directive.Tokens[0]),
Factory.Span(SpanKindInternal.Markup, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.AllWhiteSpace),
Factory.MetaCode("{").AutoCompleteWith(null, atEndOfSpan: true).Accepts(AcceptedCharactersInternal.None),
new MarkupBlock(
@ -415,14 +419,16 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
[Fact]
public void SectionBodyTreatsPairsOfAtSignsAsEscapeSequence()
{
ParseDocumentTest("@section Foo { <foo>@@@@@bar</foo> }",
ParseDocumentTest(
"@section Foo { <foo>@@@@@bar</foo> }",
new[] { SectionDirective.Directive, },
new MarkupBlock(
Factory.EmptyHtml(),
new DirectiveBlock(new DirectiveChunkGenerator(CSharpCodeParser.SectionDirectiveDescriptor),
new DirectiveBlock(new DirectiveChunkGenerator(SectionDirective.Directive),
Factory.CodeTransition(),
Factory.MetaCode("section").Accepts(AcceptedCharactersInternal.None),
Factory.Span(SpanKindInternal.Code, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.WhiteSpace),
Factory.Span(SpanKindInternal.Code, "Foo", CSharpSymbolType.Identifier).AsDirectiveToken(CSharpCodeParser.SectionDirectiveDescriptor.Tokens[0]),
Factory.Span(SpanKindInternal.Code, "Foo", CSharpSymbolType.Identifier).AsDirectiveToken(SectionDirective.Directive.Tokens[0]),
Factory.Span(SpanKindInternal.Markup, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.AllWhiteSpace),
Factory.MetaCode("{").AutoCompleteWith(null, atEndOfSpan: true).Accepts(AcceptedCharactersInternal.None),
new MarkupBlock(

View File

@ -2,13 +2,15 @@
// 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.Legacy
{
public abstract class MarkupParserTestBase : CodeParserTestBase
{
internal override RazorSyntaxTree ParseBlock(string document, bool designTime)
internal override RazorSyntaxTree ParseBlock(string document, IEnumerable<DirectiveDescriptor> directives, bool designTime)
{
return ParseHtmlBlock(document, designTime);
return ParseHtmlBlock(document, directives, designTime);
}
internal virtual void SingleSpanDocumentTest(string document, BlockKindInternal blockKind, SpanKindInternal spanType)

View File

@ -30,15 +30,27 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
internal BlockFactory BlockFactory { get; private set; }
internal abstract RazorSyntaxTree ParseBlock(string document, bool designTime);
internal RazorSyntaxTree ParseBlock(string document, bool designTime)
{
return ParseBlock(document, null, designTime);
}
internal abstract RazorSyntaxTree ParseBlock(string document, IEnumerable<DirectiveDescriptor> directives, bool designTime);
internal virtual RazorSyntaxTree ParseDocument(string document, bool designTime = false)
{
return ParseDocument(document, null, designTime);
}
internal virtual RazorSyntaxTree ParseDocument(string document, IEnumerable<DirectiveDescriptor> directives, bool designTime = false)
{
directives = directives ?? Array.Empty<DirectiveDescriptor>();
var source = TestRazorSourceDocument.Create(document, fileName: null);
var options = RazorParserOptions.Create(Array.Empty<DirectiveDescriptor>(), designTime);
var options = RazorParserOptions.Create(directives, designTime);
var context = new ParserContext(source, options);
var codeParser = new CSharpCodeParser(context);
var codeParser = new CSharpCodeParser(directives, context);
var markupParser = new HtmlMarkupParser(context);
codeParser.HtmlParser = markupParser;
@ -60,14 +72,16 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
return syntaxTree;
}
internal virtual RazorSyntaxTree ParseHtmlBlock(string document, bool designTime = false)
internal virtual RazorSyntaxTree ParseHtmlBlock(string document, IEnumerable<DirectiveDescriptor> directives, bool designTime = false)
{
directives = directives ?? Array.Empty<DirectiveDescriptor>();
var source = TestRazorSourceDocument.Create(document, fileName: null);
var options = RazorParserOptions.Create(Array.Empty<DirectiveDescriptor>(), designTime);
var options = RazorParserOptions.Create(directives, designTime);
var context = new ParserContext(source, options);
var parser = new HtmlMarkupParser(context);
parser.CodeParser = new CSharpCodeParser(context)
parser.CodeParser = new CSharpCodeParser(directives, context)
{
HtmlParser = parser,
};
@ -87,14 +101,16 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
internal virtual RazorSyntaxTree ParseCodeBlock(
string document,
IEnumerable<DirectiveDescriptor> descriptors,
IEnumerable<DirectiveDescriptor> directives,
bool designTime)
{
directives = directives ?? Array.Empty<DirectiveDescriptor>();
var source = TestRazorSourceDocument.Create(document, fileName: null);
var options = RazorParserOptions.Create(descriptors, designTime);
var options = RazorParserOptions.Create(directives, designTime);
var context = new ParserContext(source, options);
var parser = new CSharpCodeParser(descriptors, context);
var parser = new CSharpCodeParser(directives, context);
parser.HtmlParser = new HtmlMarkupParser(context)
{
CodeParser = parser,
@ -140,6 +156,11 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
ParseBlockTest(document, expectedRoot, false, null);
}
internal virtual void ParseBlockTest(string document, IEnumerable<DirectiveDescriptor> directives, Block expectedRoot)
{
ParseBlockTest(document, directives, expectedRoot, false, null);
}
internal virtual void ParseBlockTest(string document, Block expectedRoot, bool designTime)
{
ParseBlockTest(document, expectedRoot, designTime, null);
@ -150,9 +171,19 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
ParseBlockTest(document, expectedRoot, false, expectedErrors);
}
internal virtual void ParseBlockTest(string document, IEnumerable<DirectiveDescriptor> directives, Block expectedRoot, params RazorError[] expectedErrors)
{
ParseBlockTest(document, directives, expectedRoot, false, expectedErrors);
}
internal virtual void ParseBlockTest(string document, Block expected, bool designTime, params RazorError[] expectedErrors)
{
var result = ParseBlock(document, designTime);
ParseBlockTest(document, null, expected, designTime, expectedErrors);
}
internal virtual void ParseBlockTest(string document, IEnumerable<DirectiveDescriptor> directives, Block expected, bool designTime, params RazorError[] expectedErrors)
{
var result = ParseBlock(document, directives, designTime);
if (FixupSpans)
{
@ -236,6 +267,11 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
ParseDocumentTest(document, expectedRoot, false, expectedErrors);
}
internal virtual void ParseDocumentTest(string document, IEnumerable<DirectiveDescriptor> directives, Block expected, params RazorError[] expectedErrors)
{
ParseDocumentTest(document, directives, expected, false, expectedErrors);
}
internal virtual void ParseDocumentTest(string document, bool designTime)
{
ParseDocumentTest(document, null, designTime);
@ -248,7 +284,12 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
internal virtual void ParseDocumentTest(string document, Block expected, bool designTime, params RazorError[] expectedErrors)
{
var result = ParseDocument(document, designTime);
ParseDocumentTest(document, null, expected, designTime, expectedErrors);
}
internal virtual void ParseDocumentTest(string document, IEnumerable<DirectiveDescriptor> directives, Block expected, bool designTime, params RazorError[] expectedErrors)
{
var result = ParseDocument(document, directives, designTime);
if (FixupSpans)
{

View File

@ -150,7 +150,6 @@ namespace Microsoft.AspNetCore.Razor.Language
feature => Assert.IsType<DefaultDirectiveSyntaxTreePass>(feature),
feature => Assert.IsType<HtmlNodeOptimizationPass>(feature),
feature => Assert.IsType<DefaultDocumentClassifierPass>(feature),
feature => Assert.IsType<DefaultDirectiveIRPass>(feature),
feature => Assert.IsType<DirectiveRemovalIROptimizationPass>(feature),
feature => Assert.IsType<DefaultDocumentClassifierPassFeature>(feature),
feature => Assert.IsType<RazorPreallocatedTagHelperAttributeOptimizationPass>(feature));
@ -179,7 +178,6 @@ namespace Microsoft.AspNetCore.Razor.Language
feature => Assert.IsType<DefaultDirectiveSyntaxTreePass>(feature),
feature => Assert.IsType<HtmlNodeOptimizationPass>(feature),
feature => Assert.IsType<DefaultDocumentClassifierPass>(feature),
feature => Assert.IsType<DefaultDirectiveIRPass>(feature),
feature => Assert.IsType<DirectiveRemovalIROptimizationPass>(feature),
feature => Assert.IsType<DefaultDocumentClassifierPassFeature>(feature),
feature => Assert.IsType<DesignTimeOptionsFeature>(feature),