Added tests project.
This commit is contained in:
parent
72e37d7ac6
commit
af14969b54
21
Razor.sln
21
Razor.sln
|
|
@ -5,6 +5,14 @@ VisualStudioVersion = 12.0.21005.1
|
|||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNet.Razor", "src\Microsoft.AspNet.Razor\Microsoft.AspNet.Razor.csproj", "{E75D8296-3BA6-4E67-AFEB-90FF77460B15}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{3C0D6505-79B3-49D0-B4C3-176F0F1836ED}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{92463391-81BE-462B-AC3C-78C6C760741F}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNet.Razor.Test", "test\Microsoft.AspNet.Razor.Test\Microsoft.AspNet.Razor.Test.csproj", "{0BB62A1D-E6B5-49FA-9E3C-6AF679A66DFE}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.TestCommon", "test\Microsoft.TestCommon\Microsoft.TestCommon.csproj", "{FCCC4CB7-BAF7-4A57-9F89-E5766FE536C0}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
|
|
@ -15,8 +23,21 @@ Global
|
|||
{E75D8296-3BA6-4E67-AFEB-90FF77460B15}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E75D8296-3BA6-4E67-AFEB-90FF77460B15}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{E75D8296-3BA6-4E67-AFEB-90FF77460B15}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{0BB62A1D-E6B5-49FA-9E3C-6AF679A66DFE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{0BB62A1D-E6B5-49FA-9E3C-6AF679A66DFE}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{0BB62A1D-E6B5-49FA-9E3C-6AF679A66DFE}.Release|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{0BB62A1D-E6B5-49FA-9E3C-6AF679A66DFE}.Release|Any CPU.Build.0 = Debug|Any CPU
|
||||
{FCCC4CB7-BAF7-4A57-9F89-E5766FE536C0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{FCCC4CB7-BAF7-4A57-9F89-E5766FE536C0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{FCCC4CB7-BAF7-4A57-9F89-E5766FE536C0}.Release|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{FCCC4CB7-BAF7-4A57-9F89-E5766FE536C0}.Release|Any CPU.Build.0 = Debug|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(NestedProjects) = preSolution
|
||||
{E75D8296-3BA6-4E67-AFEB-90FF77460B15} = {3C0D6505-79B3-49D0-B4C3-176F0F1836ED}
|
||||
{0BB62A1D-E6B5-49FA-9E3C-6AF679A66DFE} = {92463391-81BE-462B-AC3C-78C6C760741F}
|
||||
{FCCC4CB7-BAF7-4A57-9F89-E5766FE536C0} = {92463391-81BE-462B-AC3C-78C6C760741F}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
|
|
|||
|
|
@ -37,3 +37,5 @@ using System.Runtime.InteropServices;
|
|||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNet.Razor.Test")]
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNet.Razor.Generator;
|
||||
using Microsoft.AspNet.Razor.Parser;
|
||||
using Microsoft.CSharp;
|
||||
using Microsoft.TestCommon;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Test
|
||||
{
|
||||
public class CSharpRazorCodeLanguageTest
|
||||
{
|
||||
[Fact]
|
||||
public void CreateCodeParserReturnsNewCSharpCodeParser()
|
||||
{
|
||||
// Arrange
|
||||
RazorCodeLanguage service = new CSharpRazorCodeLanguage();
|
||||
|
||||
// Act
|
||||
ParserBase parser = service.CreateCodeParser();
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(parser);
|
||||
Assert.IsType<CSharpCodeParser>(parser);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CreateCodeGeneratorParserListenerReturnsNewCSharpCodeGeneratorParserListener()
|
||||
{
|
||||
// Arrange
|
||||
RazorCodeLanguage service = new CSharpRazorCodeLanguage();
|
||||
|
||||
// Act
|
||||
RazorEngineHost host = new RazorEngineHost(service);
|
||||
RazorCodeGenerator generator = service.CreateCodeGenerator("Foo", "Bar", "Baz", host);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(generator);
|
||||
Assert.IsType<CSharpRazorCodeGenerator>(generator);
|
||||
Assert.Equal("Foo", generator.ClassName);
|
||||
Assert.Equal("Bar", generator.RootNamespaceName);
|
||||
Assert.Equal("Baz", generator.SourceFileName);
|
||||
Assert.Same(host, generator.Host);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CodeDomProviderTypeReturnsVBCodeProvider()
|
||||
{
|
||||
// Arrange
|
||||
RazorCodeLanguage service = new CSharpRazorCodeLanguage();
|
||||
|
||||
// Assert
|
||||
Assert.Equal(typeof(CSharpCodeProvider), service.CodeDomProviderType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using System.CodeDom;
|
||||
using System.CodeDom.Compiler;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Test
|
||||
{
|
||||
internal static class CodeCompileUnitExtensions
|
||||
{
|
||||
public static string GenerateCode<T>(this CodeCompileUnit ccu) where T : CodeDomProvider, new()
|
||||
{
|
||||
StringBuilder output = new StringBuilder();
|
||||
using (StringWriter writer = new StringWriter(output))
|
||||
{
|
||||
T provider = new T();
|
||||
provider.GenerateCodeFromCompileUnit(ccu, writer, new CodeGeneratorOptions() { IndentString = " " });
|
||||
}
|
||||
|
||||
return output.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,193 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using System.Threading;
|
||||
using Microsoft.AspNet.Razor.Editor;
|
||||
using Microsoft.AspNet.Razor.Parser;
|
||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||
using Microsoft.AspNet.Razor.Resources;
|
||||
using Microsoft.AspNet.Razor.Test.Framework;
|
||||
using Microsoft.AspNet.Razor.Test.Utils;
|
||||
using Microsoft.AspNet.Razor.Text;
|
||||
using System.Web.WebPages.TestUtils;
|
||||
using Microsoft.CSharp;
|
||||
using Microsoft.TestCommon;
|
||||
using Moq;
|
||||
using System;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Test.Editor
|
||||
{
|
||||
public class RazorEditorParserTest
|
||||
{
|
||||
private static readonly TestFile SimpleCSHTMLDocument = TestFile.Create("DesignTime.Simple.cshtml");
|
||||
private static readonly TestFile SimpleCSHTMLDocumentGenerated = TestFile.Create("DesignTime.Simple.txt");
|
||||
private const string TestLinePragmaFileName = "C:\\This\\Path\\Is\\Just\\For\\Line\\Pragmas.cshtml";
|
||||
|
||||
[Fact]
|
||||
public void ConstructorRequiresNonNullHost()
|
||||
{
|
||||
Assert.ThrowsArgumentNull(() => new RazorEditorParser(null, TestLinePragmaFileName),
|
||||
"host");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ConstructorRequiresNonNullPhysicalPath()
|
||||
{
|
||||
Assert.ThrowsArgumentNullOrEmptyString(() => new RazorEditorParser(CreateHost(), null),
|
||||
"sourceFileName");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ConstructorRequiresNonEmptyPhysicalPath()
|
||||
{
|
||||
Assert.ThrowsArgumentNullOrEmptyString(() => new RazorEditorParser(CreateHost(), String.Empty),
|
||||
"sourceFileName");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TreesAreDifferentReturnsTrueIfTreeStructureIsDifferent()
|
||||
{
|
||||
var factory = SpanFactory.CreateCsHtml();
|
||||
Block original = new MarkupBlock(
|
||||
factory.Markup("<p>"),
|
||||
new ExpressionBlock(
|
||||
factory.CodeTransition()),
|
||||
factory.Markup("</p>"));
|
||||
Block modified = new MarkupBlock(
|
||||
factory.Markup("<p>"),
|
||||
new ExpressionBlock(
|
||||
factory.CodeTransition("@"),
|
||||
factory.Code("f")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords, acceptTrailingDot: false)),
|
||||
factory.Markup("</p>"));
|
||||
ITextBuffer oldBuffer = new StringTextBuffer("<p>@</p>");
|
||||
ITextBuffer newBuffer = new StringTextBuffer("<p>@f</p>");
|
||||
Assert.True(BackgroundParser.TreesAreDifferent(
|
||||
original, modified, new[] {
|
||||
new TextChange(position: 4, oldLength: 0, oldBuffer: oldBuffer, newLength: 1, newBuffer: newBuffer)
|
||||
}));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TreesAreDifferentReturnsFalseIfTreeStructureIsSame()
|
||||
{
|
||||
var factory = SpanFactory.CreateCsHtml();
|
||||
Block original = new MarkupBlock(
|
||||
factory.Markup("<p>"),
|
||||
new ExpressionBlock(
|
||||
factory.CodeTransition(),
|
||||
factory.Code("f")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords, acceptTrailingDot: false)),
|
||||
factory.Markup("</p>"));
|
||||
factory.Reset();
|
||||
Block modified = new MarkupBlock(
|
||||
factory.Markup("<p>"),
|
||||
new ExpressionBlock(
|
||||
factory.CodeTransition(),
|
||||
factory.Code("foo")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords, acceptTrailingDot: false)),
|
||||
factory.Markup("</p>"));
|
||||
original.LinkNodes();
|
||||
modified.LinkNodes();
|
||||
ITextBuffer oldBuffer = new StringTextBuffer("<p>@f</p>");
|
||||
ITextBuffer newBuffer = new StringTextBuffer("<p>@foo</p>");
|
||||
Assert.False(BackgroundParser.TreesAreDifferent(
|
||||
original, modified, new[] {
|
||||
new TextChange(position: 5, oldLength: 0, oldBuffer: oldBuffer, newLength: 2, newBuffer: newBuffer)
|
||||
}));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CheckForStructureChangesRequiresNonNullBufferInChange()
|
||||
{
|
||||
TextChange change = new TextChange();
|
||||
Assert.ThrowsArgument(
|
||||
() => new RazorEditorParser(
|
||||
CreateHost(),
|
||||
"C:\\Foo.cshtml").CheckForStructureChanges(change),
|
||||
"change",
|
||||
String.Format(RazorResources.Structure_Member_CannotBeNull, "Buffer", "TextChange"));
|
||||
}
|
||||
|
||||
private static RazorEngineHost CreateHost()
|
||||
{
|
||||
return new RazorEngineHost(new CSharpRazorCodeLanguage()) { DesignTimeMode = true };
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[ReplaceCulture]
|
||||
public void CheckForStructureChangesStartsReparseAndFiresDocumentParseCompletedEventIfNoAdditionalChangesQueued()
|
||||
{
|
||||
// Arrange
|
||||
using (RazorEditorParser parser = CreateClientParser())
|
||||
{
|
||||
StringTextBuffer input = new StringTextBuffer(SimpleCSHTMLDocument.ReadAllText());
|
||||
|
||||
DocumentParseCompleteEventArgs capturedArgs = null;
|
||||
ManualResetEventSlim parseComplete = new ManualResetEventSlim(false);
|
||||
|
||||
parser.DocumentParseComplete += (sender, args) =>
|
||||
{
|
||||
capturedArgs = args;
|
||||
parseComplete.Set();
|
||||
};
|
||||
|
||||
// Act
|
||||
parser.CheckForStructureChanges(new TextChange(0, 0, new StringTextBuffer(String.Empty), input.Length, input));
|
||||
|
||||
// Assert
|
||||
MiscUtils.DoWithTimeoutIfNotDebugging(parseComplete.Wait);
|
||||
|
||||
string generatedCode = capturedArgs.GeneratorResults.GeneratedCode.GenerateCode<CSharpCodeProvider>();
|
||||
|
||||
Assert.Equal(
|
||||
SimpleCSHTMLDocumentGenerated.ReadAllText(),
|
||||
MiscUtils.StripRuntimeVersion(generatedCode));
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CheckForStructureChangesStartsFullReparseIfChangeOverlapsMultipleSpans()
|
||||
{
|
||||
// Arrange
|
||||
RazorEditorParser parser = new RazorEditorParser(CreateHost(), TestLinePragmaFileName);
|
||||
ITextBuffer original = new StringTextBuffer("Foo @bar Baz");
|
||||
ITextBuffer changed = new StringTextBuffer("Foo @bap Daz");
|
||||
TextChange change = new TextChange(7, 3, original, 3, changed);
|
||||
|
||||
ManualResetEventSlim parseComplete = new ManualResetEventSlim();
|
||||
int parseCount = 0;
|
||||
parser.DocumentParseComplete += (sender, args) =>
|
||||
{
|
||||
Interlocked.Increment(ref parseCount);
|
||||
parseComplete.Set();
|
||||
};
|
||||
|
||||
Assert.Equal(PartialParseResult.Rejected, parser.CheckForStructureChanges(new TextChange(0, 0, new StringTextBuffer(String.Empty), 12, original)));
|
||||
MiscUtils.DoWithTimeoutIfNotDebugging(parseComplete.Wait); // Wait for the parse to finish
|
||||
parseComplete.Reset();
|
||||
|
||||
// Act
|
||||
PartialParseResult result = parser.CheckForStructureChanges(change);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(PartialParseResult.Rejected, result);
|
||||
MiscUtils.DoWithTimeoutIfNotDebugging(parseComplete.Wait);
|
||||
Assert.Equal(2, parseCount);
|
||||
}
|
||||
|
||||
private TextChange CreateDummyChange()
|
||||
{
|
||||
return new TextChange(0, 0, new StringTextBuffer(String.Empty), 3, new StringTextBuffer("foo"));
|
||||
}
|
||||
|
||||
private static Mock<RazorEditorParser> CreateMockParser()
|
||||
{
|
||||
return new Mock<RazorEditorParser>(CreateHost(), TestLinePragmaFileName) { CallBase = true };
|
||||
}
|
||||
|
||||
private static RazorEditorParser CreateClientParser()
|
||||
{
|
||||
return new RazorEditorParser(CreateHost(), TestLinePragmaFileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Test.Framework
|
||||
{
|
||||
public static class BlockExtensions
|
||||
{
|
||||
public static void LinkNodes(this Block self)
|
||||
{
|
||||
Span first = null;
|
||||
Span previous = null;
|
||||
foreach (Span span in self.Flatten())
|
||||
{
|
||||
if (first == null)
|
||||
{
|
||||
first = span;
|
||||
}
|
||||
span.Previous = previous;
|
||||
|
||||
if (previous != null)
|
||||
{
|
||||
previous.Next = span;
|
||||
}
|
||||
previous = span;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,235 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNet.Razor.Generator;
|
||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Test.Framework
|
||||
{
|
||||
// The product code doesn't need this, but having subclasses for the block types makes tests much cleaner :)
|
||||
|
||||
public class StatementBlock : Block
|
||||
{
|
||||
private const BlockType ThisBlockType = BlockType.Statement;
|
||||
|
||||
public StatementBlock(IBlockCodeGenerator codeGenerator, IEnumerable<SyntaxTreeNode> children)
|
||||
: base(ThisBlockType, children, codeGenerator)
|
||||
{
|
||||
}
|
||||
|
||||
public StatementBlock(IBlockCodeGenerator codeGenerator, params SyntaxTreeNode[] children)
|
||||
: this(codeGenerator, (IEnumerable<SyntaxTreeNode>)children)
|
||||
{
|
||||
}
|
||||
|
||||
public StatementBlock(params SyntaxTreeNode[] children)
|
||||
: this(BlockCodeGenerator.Null, children)
|
||||
{
|
||||
}
|
||||
|
||||
public StatementBlock(IEnumerable<SyntaxTreeNode> children)
|
||||
: this(BlockCodeGenerator.Null, children)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class DirectiveBlock : Block
|
||||
{
|
||||
private const BlockType ThisBlockType = BlockType.Directive;
|
||||
|
||||
public DirectiveBlock(IBlockCodeGenerator codeGenerator, IEnumerable<SyntaxTreeNode> children)
|
||||
: base(ThisBlockType, children, codeGenerator)
|
||||
{
|
||||
}
|
||||
|
||||
public DirectiveBlock(IBlockCodeGenerator codeGenerator, params SyntaxTreeNode[] children)
|
||||
: this(codeGenerator, (IEnumerable<SyntaxTreeNode>)children)
|
||||
{
|
||||
}
|
||||
|
||||
public DirectiveBlock(params SyntaxTreeNode[] children)
|
||||
: this(BlockCodeGenerator.Null, children)
|
||||
{
|
||||
}
|
||||
|
||||
public DirectiveBlock(IEnumerable<SyntaxTreeNode> children)
|
||||
: this(BlockCodeGenerator.Null, children)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class FunctionsBlock : Block
|
||||
{
|
||||
private const BlockType ThisBlockType = BlockType.Functions;
|
||||
|
||||
public FunctionsBlock(IBlockCodeGenerator codeGenerator, IEnumerable<SyntaxTreeNode> children)
|
||||
: base(ThisBlockType, children, codeGenerator)
|
||||
{
|
||||
}
|
||||
|
||||
public FunctionsBlock(IBlockCodeGenerator codeGenerator, params SyntaxTreeNode[] children)
|
||||
: this(codeGenerator, (IEnumerable<SyntaxTreeNode>)children)
|
||||
{
|
||||
}
|
||||
|
||||
public FunctionsBlock(params SyntaxTreeNode[] children)
|
||||
: this(BlockCodeGenerator.Null, children)
|
||||
{
|
||||
}
|
||||
|
||||
public FunctionsBlock(IEnumerable<SyntaxTreeNode> children)
|
||||
: this(BlockCodeGenerator.Null, children)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class ExpressionBlock : Block
|
||||
{
|
||||
private const BlockType ThisBlockType = BlockType.Expression;
|
||||
|
||||
public ExpressionBlock(IBlockCodeGenerator codeGenerator, IEnumerable<SyntaxTreeNode> children)
|
||||
: base(ThisBlockType, children, codeGenerator)
|
||||
{
|
||||
}
|
||||
|
||||
public ExpressionBlock(IBlockCodeGenerator codeGenerator, params SyntaxTreeNode[] children)
|
||||
: this(codeGenerator, (IEnumerable<SyntaxTreeNode>)children)
|
||||
{
|
||||
}
|
||||
|
||||
public ExpressionBlock(params SyntaxTreeNode[] children)
|
||||
: this(new ExpressionCodeGenerator(), children)
|
||||
{
|
||||
}
|
||||
|
||||
public ExpressionBlock(IEnumerable<SyntaxTreeNode> children)
|
||||
: this(new ExpressionCodeGenerator(), children)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class HelperBlock : Block
|
||||
{
|
||||
private const BlockType ThisBlockType = BlockType.Helper;
|
||||
|
||||
public HelperBlock(IBlockCodeGenerator codeGenerator, IEnumerable<SyntaxTreeNode> children)
|
||||
: base(ThisBlockType, children, codeGenerator)
|
||||
{
|
||||
}
|
||||
|
||||
public HelperBlock(IBlockCodeGenerator codeGenerator, params SyntaxTreeNode[] children)
|
||||
: this(codeGenerator, (IEnumerable<SyntaxTreeNode>)children)
|
||||
{
|
||||
}
|
||||
|
||||
public HelperBlock(params SyntaxTreeNode[] children)
|
||||
: this(BlockCodeGenerator.Null, children)
|
||||
{
|
||||
}
|
||||
|
||||
public HelperBlock(IEnumerable<SyntaxTreeNode> children)
|
||||
: this(BlockCodeGenerator.Null, children)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class MarkupBlock : Block
|
||||
{
|
||||
private const BlockType ThisBlockType = BlockType.Markup;
|
||||
|
||||
public MarkupBlock(IBlockCodeGenerator codeGenerator, IEnumerable<SyntaxTreeNode> children)
|
||||
: base(ThisBlockType, children, codeGenerator)
|
||||
{
|
||||
}
|
||||
|
||||
public MarkupBlock(IBlockCodeGenerator codeGenerator, params SyntaxTreeNode[] children)
|
||||
: this(codeGenerator, (IEnumerable<SyntaxTreeNode>)children)
|
||||
{
|
||||
}
|
||||
|
||||
public MarkupBlock(params SyntaxTreeNode[] children)
|
||||
: this(BlockCodeGenerator.Null, children)
|
||||
{
|
||||
}
|
||||
|
||||
public MarkupBlock(IEnumerable<SyntaxTreeNode> children)
|
||||
: this(BlockCodeGenerator.Null, children)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class SectionBlock : Block
|
||||
{
|
||||
private const BlockType ThisBlockType = BlockType.Section;
|
||||
|
||||
public SectionBlock(IBlockCodeGenerator codeGenerator, IEnumerable<SyntaxTreeNode> children)
|
||||
: base(ThisBlockType, children, codeGenerator)
|
||||
{
|
||||
}
|
||||
|
||||
public SectionBlock(IBlockCodeGenerator codeGenerator, params SyntaxTreeNode[] children)
|
||||
: this(codeGenerator, (IEnumerable<SyntaxTreeNode>)children)
|
||||
{
|
||||
}
|
||||
|
||||
public SectionBlock(params SyntaxTreeNode[] children)
|
||||
: this(BlockCodeGenerator.Null, children)
|
||||
{
|
||||
}
|
||||
|
||||
public SectionBlock(IEnumerable<SyntaxTreeNode> children)
|
||||
: this(BlockCodeGenerator.Null, children)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class TemplateBlock : Block
|
||||
{
|
||||
private const BlockType ThisBlockType = BlockType.Template;
|
||||
|
||||
public TemplateBlock(IBlockCodeGenerator codeGenerator, IEnumerable<SyntaxTreeNode> children)
|
||||
: base(ThisBlockType, children, codeGenerator)
|
||||
{
|
||||
}
|
||||
|
||||
public TemplateBlock(IBlockCodeGenerator codeGenerator, params SyntaxTreeNode[] children)
|
||||
: this(codeGenerator, (IEnumerable<SyntaxTreeNode>)children)
|
||||
{
|
||||
}
|
||||
|
||||
public TemplateBlock(params SyntaxTreeNode[] children)
|
||||
: this(new TemplateBlockCodeGenerator(), children)
|
||||
{
|
||||
}
|
||||
|
||||
public TemplateBlock(IEnumerable<SyntaxTreeNode> children)
|
||||
: this(new TemplateBlockCodeGenerator(), children)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class CommentBlock : Block
|
||||
{
|
||||
private const BlockType ThisBlockType = BlockType.Comment;
|
||||
|
||||
public CommentBlock(IBlockCodeGenerator codeGenerator, IEnumerable<SyntaxTreeNode> children)
|
||||
: base(ThisBlockType, children, codeGenerator)
|
||||
{
|
||||
}
|
||||
|
||||
public CommentBlock(IBlockCodeGenerator codeGenerator, params SyntaxTreeNode[] children)
|
||||
: this(codeGenerator, (IEnumerable<SyntaxTreeNode>)children)
|
||||
{
|
||||
}
|
||||
|
||||
public CommentBlock(params SyntaxTreeNode[] children)
|
||||
: this(new RazorCommentCodeGenerator(), children)
|
||||
{
|
||||
}
|
||||
|
||||
public CommentBlock(IEnumerable<SyntaxTreeNode> children)
|
||||
: this(new RazorCommentCodeGenerator(), children)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNet.Razor.Parser;
|
||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Test.Framework
|
||||
{
|
||||
public abstract class CodeParserTestBase : ParserTestBase
|
||||
{
|
||||
protected abstract ISet<string> KeywordSet { get; }
|
||||
|
||||
protected override ParserBase SelectActiveParser(ParserBase codeParser, ParserBase markupParser)
|
||||
{
|
||||
return codeParser;
|
||||
}
|
||||
|
||||
protected void ImplicitExpressionTest(string input, params RazorError[] errors)
|
||||
{
|
||||
ImplicitExpressionTest(input, AcceptedCharacters.NonWhiteSpace, errors);
|
||||
}
|
||||
|
||||
protected void ImplicitExpressionTest(string input, AcceptedCharacters acceptedCharacters, params RazorError[] errors)
|
||||
{
|
||||
ImplicitExpressionTest(input, input, acceptedCharacters, errors);
|
||||
}
|
||||
|
||||
protected void ImplicitExpressionTest(string input, string expected, params RazorError[] errors)
|
||||
{
|
||||
ImplicitExpressionTest(input, expected, AcceptedCharacters.NonWhiteSpace, errors);
|
||||
}
|
||||
|
||||
protected override void SingleSpanBlockTest(string document, BlockType blockType, SpanKind spanType, AcceptedCharacters acceptedCharacters = AcceptedCharacters.Any)
|
||||
{
|
||||
SingleSpanBlockTest(document, blockType, spanType, acceptedCharacters, expectedError: null);
|
||||
}
|
||||
|
||||
protected override void SingleSpanBlockTest(string document, string spanContent, BlockType blockType, SpanKind spanType, AcceptedCharacters acceptedCharacters = AcceptedCharacters.Any)
|
||||
{
|
||||
SingleSpanBlockTest(document, spanContent, blockType, spanType, acceptedCharacters, expectedErrors: null);
|
||||
}
|
||||
|
||||
protected override void SingleSpanBlockTest(string document, BlockType blockType, SpanKind spanType, params RazorError[] expectedError)
|
||||
{
|
||||
SingleSpanBlockTest(document, document, blockType, spanType, expectedError);
|
||||
}
|
||||
|
||||
protected override void SingleSpanBlockTest(string document, string spanContent, BlockType blockType, SpanKind spanType, params RazorError[] expectedErrors)
|
||||
{
|
||||
SingleSpanBlockTest(document, spanContent, blockType, spanType, AcceptedCharacters.Any, expectedErrors ?? new RazorError[0]);
|
||||
}
|
||||
|
||||
protected override void SingleSpanBlockTest(string document, BlockType blockType, SpanKind spanType, AcceptedCharacters acceptedCharacters, params RazorError[] expectedError)
|
||||
{
|
||||
SingleSpanBlockTest(document, document, blockType, spanType, acceptedCharacters, expectedError);
|
||||
}
|
||||
|
||||
protected override void SingleSpanBlockTest(string document, string spanContent, BlockType blockType, SpanKind spanType, AcceptedCharacters acceptedCharacters, params RazorError[] expectedErrors)
|
||||
{
|
||||
Block b = CreateSimpleBlockAndSpan(spanContent, blockType, spanType, acceptedCharacters);
|
||||
ParseBlockTest(document, b, expectedErrors ?? new RazorError[0]);
|
||||
}
|
||||
|
||||
protected void ImplicitExpressionTest(string input, string expected, AcceptedCharacters acceptedCharacters, params RazorError[] errors)
|
||||
{
|
||||
var factory = CreateSpanFactory();
|
||||
ParseBlockTest(SyntaxConstants.TransitionString + input,
|
||||
new ExpressionBlock(
|
||||
factory.CodeTransition(),
|
||||
factory.Code(expected)
|
||||
.AsImplicitExpression(KeywordSet)
|
||||
.Accepts(acceptedCharacters)),
|
||||
errors);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNet.Razor.Parser;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Test.Framework
|
||||
{
|
||||
public abstract class CsHtmlCodeParserTestBase : CodeParserTestBase
|
||||
{
|
||||
protected override ISet<string> KeywordSet
|
||||
{
|
||||
get { return CSharpCodeParser.DefaultKeywords; }
|
||||
}
|
||||
|
||||
protected override SpanFactory CreateSpanFactory()
|
||||
{
|
||||
return SpanFactory.CreateCsHtml();
|
||||
}
|
||||
|
||||
public override ParserBase CreateMarkupParser()
|
||||
{
|
||||
return new HtmlMarkupParser();
|
||||
}
|
||||
|
||||
public override ParserBase CreateCodeParser()
|
||||
{
|
||||
return new CSharpCodeParser();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNet.Razor.Parser;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Test.Framework
|
||||
{
|
||||
public abstract class CsHtmlMarkupParserTestBase : MarkupParserTestBase
|
||||
{
|
||||
protected override ISet<string> KeywordSet
|
||||
{
|
||||
get { return CSharpCodeParser.DefaultKeywords; }
|
||||
}
|
||||
|
||||
protected override SpanFactory CreateSpanFactory()
|
||||
{
|
||||
return SpanFactory.CreateCsHtml();
|
||||
}
|
||||
|
||||
public override ParserBase CreateMarkupParser()
|
||||
{
|
||||
return new HtmlMarkupParser();
|
||||
}
|
||||
|
||||
public override ParserBase CreateCodeParser()
|
||||
{
|
||||
return new CSharpCodeParser();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
using Microsoft.AspNet.Razor.Utils;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Test.Framework
|
||||
{
|
||||
public class ErrorCollector
|
||||
{
|
||||
private StringBuilder _message = new StringBuilder();
|
||||
private int _indent = 0;
|
||||
|
||||
public bool Success { get; private set; }
|
||||
|
||||
public string Message
|
||||
{
|
||||
get { return _message.ToString(); }
|
||||
}
|
||||
|
||||
public ErrorCollector()
|
||||
{
|
||||
Success = true;
|
||||
}
|
||||
|
||||
public void AddError(string msg, params object[] args)
|
||||
{
|
||||
Append("F", msg, args);
|
||||
Success = false;
|
||||
}
|
||||
|
||||
public void AddMessage(string msg, params object[] args)
|
||||
{
|
||||
Append("P", msg, args);
|
||||
}
|
||||
|
||||
public IDisposable Indent()
|
||||
{
|
||||
_indent++;
|
||||
return new DisposableAction(Unindent);
|
||||
}
|
||||
|
||||
public void Unindent()
|
||||
{
|
||||
_indent--;
|
||||
}
|
||||
|
||||
private void Append(string prefix, string msg, object[] args)
|
||||
{
|
||||
_message.Append(prefix);
|
||||
_message.Append(":");
|
||||
_message.Append(new String('\t', _indent));
|
||||
_message.AppendFormat(msg, args);
|
||||
_message.AppendLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNet.Razor.Parser;
|
||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Test.Framework
|
||||
{
|
||||
public abstract class MarkupParserTestBase : CodeParserTestBase
|
||||
{
|
||||
protected override ParserBase SelectActiveParser(ParserBase codeParser, ParserBase markupParser)
|
||||
{
|
||||
return markupParser;
|
||||
}
|
||||
|
||||
protected virtual void SingleSpanDocumentTest(string document, BlockType blockType, SpanKind spanType)
|
||||
{
|
||||
Block b = CreateSimpleBlockAndSpan(document, blockType, spanType);
|
||||
ParseDocumentTest(document, b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,426 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
//#define PARSER_TRACE
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Microsoft.AspNet.Razor.Generator;
|
||||
using Microsoft.AspNet.Razor.Parser;
|
||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||
using Microsoft.AspNet.Razor.Text;
|
||||
using Microsoft.TestCommon;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Test.Framework
|
||||
{
|
||||
public abstract class ParserTestBase
|
||||
{
|
||||
protected static Block IgnoreOutput = new IgnoreOutputBlock();
|
||||
|
||||
public SpanFactory Factory { get; private set; }
|
||||
|
||||
protected ParserTestBase()
|
||||
{
|
||||
Factory = CreateSpanFactory();
|
||||
}
|
||||
|
||||
public abstract ParserBase CreateMarkupParser();
|
||||
public abstract ParserBase CreateCodeParser();
|
||||
|
||||
protected abstract ParserBase SelectActiveParser(ParserBase codeParser, ParserBase markupParser);
|
||||
|
||||
public virtual ParserContext CreateParserContext(ITextDocument input, ParserBase codeParser, ParserBase markupParser)
|
||||
{
|
||||
return new ParserContext(input, codeParser, markupParser, SelectActiveParser(codeParser, markupParser));
|
||||
}
|
||||
|
||||
protected abstract SpanFactory CreateSpanFactory();
|
||||
|
||||
protected virtual void ParseBlockTest(string document)
|
||||
{
|
||||
ParseBlockTest(document, null, false, new RazorError[0]);
|
||||
}
|
||||
|
||||
protected virtual void ParseBlockTest(string document, bool designTimeParser)
|
||||
{
|
||||
ParseBlockTest(document, null, designTimeParser, new RazorError[0]);
|
||||
}
|
||||
|
||||
protected virtual void ParseBlockTest(string document, params RazorError[] expectedErrors)
|
||||
{
|
||||
ParseBlockTest(document, false, expectedErrors);
|
||||
}
|
||||
|
||||
protected virtual void ParseBlockTest(string document, bool designTimeParser, params RazorError[] expectedErrors)
|
||||
{
|
||||
ParseBlockTest(document, null, designTimeParser, expectedErrors);
|
||||
}
|
||||
|
||||
protected virtual void ParseBlockTest(string document, Block expectedRoot)
|
||||
{
|
||||
ParseBlockTest(document, expectedRoot, false, null);
|
||||
}
|
||||
|
||||
protected virtual void ParseBlockTest(string document, Block expectedRoot, bool designTimeParser)
|
||||
{
|
||||
ParseBlockTest(document, expectedRoot, designTimeParser, null);
|
||||
}
|
||||
|
||||
protected virtual void ParseBlockTest(string document, Block expectedRoot, params RazorError[] expectedErrors)
|
||||
{
|
||||
ParseBlockTest(document, expectedRoot, false, expectedErrors);
|
||||
}
|
||||
|
||||
protected virtual void ParseBlockTest(string document, Block expectedRoot, bool designTimeParser, params RazorError[] expectedErrors)
|
||||
{
|
||||
RunParseTest(document, parser => parser.ParseBlock, expectedRoot, (expectedErrors ?? new RazorError[0]).ToList(), designTimeParser);
|
||||
}
|
||||
|
||||
protected virtual void SingleSpanBlockTest(string document, BlockType blockType, SpanKind spanType, AcceptedCharacters acceptedCharacters = AcceptedCharacters.Any)
|
||||
{
|
||||
SingleSpanBlockTest(document, blockType, spanType, acceptedCharacters, expectedError: null);
|
||||
}
|
||||
|
||||
protected virtual void SingleSpanBlockTest(string document, string spanContent, BlockType blockType, SpanKind spanType, AcceptedCharacters acceptedCharacters = AcceptedCharacters.Any)
|
||||
{
|
||||
SingleSpanBlockTest(document, spanContent, blockType, spanType, acceptedCharacters, expectedErrors: null);
|
||||
}
|
||||
|
||||
protected virtual void SingleSpanBlockTest(string document, BlockType blockType, SpanKind spanType, params RazorError[] expectedError)
|
||||
{
|
||||
SingleSpanBlockTest(document, document, blockType, spanType, expectedError);
|
||||
}
|
||||
|
||||
protected virtual void SingleSpanBlockTest(string document, string spanContent, BlockType blockType, SpanKind spanType, params RazorError[] expectedErrors)
|
||||
{
|
||||
SingleSpanBlockTest(document, spanContent, blockType, spanType, AcceptedCharacters.Any, expectedErrors ?? new RazorError[0]);
|
||||
}
|
||||
|
||||
protected virtual void SingleSpanBlockTest(string document, BlockType blockType, SpanKind spanType, AcceptedCharacters acceptedCharacters, params RazorError[] expectedError)
|
||||
{
|
||||
SingleSpanBlockTest(document, document, blockType, spanType, acceptedCharacters, expectedError);
|
||||
}
|
||||
|
||||
protected virtual void SingleSpanBlockTest(string document, string spanContent, BlockType blockType, SpanKind spanType, AcceptedCharacters acceptedCharacters, params RazorError[] expectedErrors)
|
||||
{
|
||||
BlockBuilder builder = new BlockBuilder();
|
||||
builder.Type = blockType;
|
||||
ParseBlockTest(
|
||||
document,
|
||||
ConfigureAndAddSpanToBlock(
|
||||
builder,
|
||||
Factory.Span(spanType, spanContent, spanType == SpanKind.Markup)
|
||||
.Accepts(acceptedCharacters)),
|
||||
expectedErrors ?? new RazorError[0]);
|
||||
}
|
||||
|
||||
protected virtual void ParseDocumentTest(string document) {
|
||||
ParseDocumentTest(document, null, false);
|
||||
}
|
||||
|
||||
protected virtual void ParseDocumentTest(string document, Block expectedRoot) {
|
||||
ParseDocumentTest(document, expectedRoot, false, null);
|
||||
}
|
||||
|
||||
protected virtual void ParseDocumentTest(string document, Block expectedRoot, params RazorError[] expectedErrors) {
|
||||
ParseDocumentTest(document, expectedRoot, false, expectedErrors);
|
||||
}
|
||||
|
||||
protected virtual void ParseDocumentTest(string document, bool designTimeParser) {
|
||||
ParseDocumentTest(document, null, designTimeParser);
|
||||
}
|
||||
|
||||
protected virtual void ParseDocumentTest(string document, Block expectedRoot, bool designTimeParser) {
|
||||
ParseDocumentTest(document, expectedRoot, designTimeParser, null);
|
||||
}
|
||||
|
||||
protected virtual void ParseDocumentTest(string document, Block expectedRoot, bool designTimeParser, params RazorError[] expectedErrors) {
|
||||
RunParseTest(document, parser => parser.ParseDocument, expectedRoot, expectedErrors, designTimeParser, parserSelector: c => c.MarkupParser);
|
||||
}
|
||||
|
||||
protected virtual ParserResults ParseDocument(string document) {
|
||||
return ParseDocument(document, designTimeParser: false);
|
||||
}
|
||||
|
||||
protected virtual ParserResults ParseDocument(string document, bool designTimeParser) {
|
||||
return RunParse(document, parser => parser.ParseDocument, designTimeParser, parserSelector: c => c.MarkupParser);
|
||||
}
|
||||
|
||||
protected virtual ParserResults ParseBlock(string document) {
|
||||
return ParseBlock(document, designTimeParser: false);
|
||||
}
|
||||
|
||||
protected virtual ParserResults ParseBlock(string document, bool designTimeParser) {
|
||||
return RunParse(document, parser => parser.ParseBlock, designTimeParser);
|
||||
}
|
||||
|
||||
protected virtual ParserResults RunParse(string document, Func<ParserBase, Action> parserActionSelector, bool designTimeParser, Func<ParserContext, ParserBase> parserSelector = null)
|
||||
{
|
||||
parserSelector = parserSelector ?? (c => c.ActiveParser);
|
||||
|
||||
// Create the source
|
||||
ParserResults results = null;
|
||||
using (SeekableTextReader reader = new SeekableTextReader(document))
|
||||
{
|
||||
try
|
||||
{
|
||||
ParserBase codeParser = CreateCodeParser();
|
||||
ParserBase markupParser = CreateMarkupParser();
|
||||
ParserContext context = CreateParserContext(reader, codeParser, markupParser);
|
||||
context.DesignTimeMode = designTimeParser;
|
||||
|
||||
codeParser.Context = context;
|
||||
markupParser.Context = context;
|
||||
|
||||
// Run the parser
|
||||
parserActionSelector(parserSelector(context))();
|
||||
results = context.CompleteParse();
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (results != null && results.Document != null)
|
||||
{
|
||||
WriteTraceLine(String.Empty);
|
||||
WriteTraceLine("Actual Parse Tree:");
|
||||
WriteNode(0, results.Document);
|
||||
}
|
||||
}
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
protected virtual void RunParseTest(string document, Func<ParserBase, Action> parserActionSelector, Block expectedRoot, IList<RazorError> expectedErrors, bool designTimeParser, Func<ParserContext, ParserBase> parserSelector = null)
|
||||
{
|
||||
// Create the source
|
||||
ParserResults results = RunParse(document, parserActionSelector, designTimeParser, parserSelector);
|
||||
|
||||
// Evaluate the results
|
||||
if (!ReferenceEquals(expectedRoot, IgnoreOutput))
|
||||
{
|
||||
EvaluateResults(results, expectedRoot, expectedErrors);
|
||||
}
|
||||
}
|
||||
|
||||
[Conditional("PARSER_TRACE")]
|
||||
private void WriteNode(int indent, SyntaxTreeNode node)
|
||||
{
|
||||
string content = node.ToString().Replace("\r", "\\r")
|
||||
.Replace("\n", "\\n")
|
||||
.Replace("{", "{{")
|
||||
.Replace("}", "}}");
|
||||
if (indent > 0)
|
||||
{
|
||||
content = new String('.', indent * 2) + content;
|
||||
}
|
||||
WriteTraceLine(content);
|
||||
Block block = node as Block;
|
||||
if (block != null)
|
||||
{
|
||||
foreach (SyntaxTreeNode child in block.Children)
|
||||
{
|
||||
WriteNode(indent + 1, child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void EvaluateResults(ParserResults results, Block expectedRoot)
|
||||
{
|
||||
EvaluateResults(results, expectedRoot, null);
|
||||
}
|
||||
|
||||
public static void EvaluateResults(ParserResults results, Block expectedRoot, IList<RazorError> expectedErrors)
|
||||
{
|
||||
EvaluateParseTree(results.Document, expectedRoot);
|
||||
EvaluateRazorErrors(results.ParserErrors, expectedErrors);
|
||||
}
|
||||
|
||||
public static void EvaluateParseTree(Block actualRoot, Block expectedRoot)
|
||||
{
|
||||
// Evaluate the result
|
||||
ErrorCollector collector = new ErrorCollector();
|
||||
|
||||
// Link all the nodes
|
||||
expectedRoot.LinkNodes();
|
||||
|
||||
if (expectedRoot == null)
|
||||
{
|
||||
Assert.Null(actualRoot);
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert.NotNull(actualRoot);
|
||||
EvaluateSyntaxTreeNode(collector, actualRoot, expectedRoot);
|
||||
if (collector.Success)
|
||||
{
|
||||
WriteTraceLine("Parse Tree Validation Succeeded:\r\n{0}", collector.Message);
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert.True(false, String.Format("\r\n{0}", collector.Message));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void EvaluateSyntaxTreeNode(ErrorCollector collector, SyntaxTreeNode actual, SyntaxTreeNode expected)
|
||||
{
|
||||
if (actual == null)
|
||||
{
|
||||
AddNullActualError(collector, actual, expected);
|
||||
}
|
||||
|
||||
if (actual.IsBlock != expected.IsBlock)
|
||||
{
|
||||
AddMismatchError(collector, actual, expected);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (expected.IsBlock)
|
||||
{
|
||||
EvaluateBlock(collector, (Block)actual, (Block)expected);
|
||||
}
|
||||
else
|
||||
{
|
||||
EvaluateSpan(collector, (Span)actual, (Span)expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void EvaluateSpan(ErrorCollector collector, Span actual, Span expected)
|
||||
{
|
||||
if (!Equals(expected, actual))
|
||||
{
|
||||
AddMismatchError(collector, actual, expected);
|
||||
}
|
||||
else
|
||||
{
|
||||
AddPassedMessage(collector, expected);
|
||||
}
|
||||
}
|
||||
|
||||
private static void EvaluateBlock(ErrorCollector collector, Block actual, Block expected)
|
||||
{
|
||||
if (actual.Type != expected.Type || !expected.CodeGenerator.Equals(actual.CodeGenerator))
|
||||
{
|
||||
AddMismatchError(collector, actual, expected);
|
||||
}
|
||||
else
|
||||
{
|
||||
AddPassedMessage(collector, expected);
|
||||
using (collector.Indent())
|
||||
{
|
||||
IEnumerator<SyntaxTreeNode> expectedNodes = expected.Children.GetEnumerator();
|
||||
IEnumerator<SyntaxTreeNode> actualNodes = actual.Children.GetEnumerator();
|
||||
while (expectedNodes.MoveNext())
|
||||
{
|
||||
if (!actualNodes.MoveNext())
|
||||
{
|
||||
collector.AddError("{0} - FAILED :: No more elements at this node", expectedNodes.Current);
|
||||
}
|
||||
else
|
||||
{
|
||||
EvaluateSyntaxTreeNode(collector, actualNodes.Current, expectedNodes.Current);
|
||||
}
|
||||
}
|
||||
while (actualNodes.MoveNext())
|
||||
{
|
||||
collector.AddError("End of Node - FAILED :: Found Node: {0}", actualNodes.Current);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void AddPassedMessage(ErrorCollector collector, SyntaxTreeNode expected)
|
||||
{
|
||||
collector.AddMessage("{0} - PASSED", expected);
|
||||
}
|
||||
|
||||
private static void AddMismatchError(ErrorCollector collector, SyntaxTreeNode actual, SyntaxTreeNode expected)
|
||||
{
|
||||
collector.AddError("{0} - FAILED :: Actual: {1}", expected, actual);
|
||||
}
|
||||
|
||||
private static void AddNullActualError(ErrorCollector collector, SyntaxTreeNode actual, SyntaxTreeNode expected)
|
||||
{
|
||||
collector.AddError("{0} - FAILED :: Actual: << Null >>", expected);
|
||||
}
|
||||
|
||||
public static void EvaluateRazorErrors(IList<RazorError> actualErrors, IList<RazorError> expectedErrors)
|
||||
{
|
||||
// Evaluate the errors
|
||||
if (expectedErrors == null || expectedErrors.Count == 0)
|
||||
{
|
||||
Assert.True(actualErrors.Count == 0,
|
||||
String.Format("Expected that no errors would be raised, but the following errors were:\r\n{0}", FormatErrors(actualErrors)));
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert.True(expectedErrors.Count == actualErrors.Count,
|
||||
String.Format("Expected that {0} errors would be raised, but {1} errors were.\r\nExpected Errors: \r\n{2}\r\nActual Errors: \r\n{3}",
|
||||
expectedErrors.Count,
|
||||
actualErrors.Count,
|
||||
FormatErrors(expectedErrors),
|
||||
FormatErrors(actualErrors)));
|
||||
Assert.Equal(expectedErrors.ToArray(), actualErrors.ToArray());
|
||||
}
|
||||
WriteTraceLine("Expected Errors were raised:\r\n{0}", FormatErrors(expectedErrors));
|
||||
}
|
||||
|
||||
public static string FormatErrors(IList<RazorError> errors)
|
||||
{
|
||||
if (errors == null)
|
||||
{
|
||||
return "\t<< No Errors >>";
|
||||
}
|
||||
|
||||
StringBuilder builder = new StringBuilder();
|
||||
foreach (RazorError err in errors)
|
||||
{
|
||||
builder.AppendFormat("\t{0}", err);
|
||||
builder.AppendLine();
|
||||
}
|
||||
return builder.ToString();
|
||||
}
|
||||
|
||||
[Conditional("PARSER_TRACE")]
|
||||
private static void WriteTraceLine(string format, params object[] args)
|
||||
{
|
||||
Trace.WriteLine(String.Format(format, args));
|
||||
}
|
||||
|
||||
protected virtual Block CreateSimpleBlockAndSpan(string spanContent, BlockType blockType, SpanKind spanType, AcceptedCharacters acceptedCharacters = AcceptedCharacters.Any)
|
||||
{
|
||||
SpanConstructor span = Factory.Span(spanType, spanContent, spanType == SpanKind.Markup).Accepts(acceptedCharacters);
|
||||
BlockBuilder b = new BlockBuilder()
|
||||
{
|
||||
Type = blockType
|
||||
};
|
||||
return ConfigureAndAddSpanToBlock(b, span);
|
||||
}
|
||||
|
||||
protected virtual Block ConfigureAndAddSpanToBlock(BlockBuilder block, SpanConstructor span)
|
||||
{
|
||||
switch (block.Type)
|
||||
{
|
||||
case BlockType.Markup:
|
||||
span.With(new MarkupCodeGenerator());
|
||||
break;
|
||||
case BlockType.Statement:
|
||||
span.With(new StatementCodeGenerator());
|
||||
break;
|
||||
case BlockType.Expression:
|
||||
block.CodeGenerator = new ExpressionCodeGenerator();
|
||||
span.With(new ExpressionCodeGenerator());
|
||||
break;
|
||||
}
|
||||
block.Children.Add(span);
|
||||
return block.Build();
|
||||
}
|
||||
|
||||
private class IgnoreOutputBlock : Block
|
||||
{
|
||||
public IgnoreOutputBlock() : base(BlockType.Template, Enumerable.Empty<SyntaxTreeNode>(), null) { }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||
using Microsoft.AspNet.Razor.Text;
|
||||
using Microsoft.AspNet.Razor.Tokenizer.Symbols;
|
||||
using Microsoft.Internal.Web.Utils;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Test.Framework
|
||||
{
|
||||
internal class RawTextSymbol : ISymbol
|
||||
{
|
||||
public SourceLocation Start { get; private set; }
|
||||
public string Content { get; private set; }
|
||||
|
||||
public RawTextSymbol(SourceLocation start, string content)
|
||||
{
|
||||
if (content == null)
|
||||
{
|
||||
throw new ArgumentNullException("content");
|
||||
}
|
||||
|
||||
Start = start;
|
||||
Content = content;
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
RawTextSymbol other = obj as RawTextSymbol;
|
||||
return Equals(Start, other.Start) && Equals(Content, other.Content);
|
||||
}
|
||||
|
||||
internal bool EquivalentTo(ISymbol sym)
|
||||
{
|
||||
return Equals(Start, sym.Start) && Equals(Content, sym.Content);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return HashCodeCombiner.Start()
|
||||
.Add(Start)
|
||||
.Add(Content)
|
||||
.CombinedHash;
|
||||
}
|
||||
|
||||
public void OffsetStart(SourceLocation documentStart)
|
||||
{
|
||||
Start = documentStart + Start;
|
||||
}
|
||||
|
||||
public void ChangeStart(SourceLocation newStart)
|
||||
{
|
||||
Start = newStart;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return String.Format(CultureInfo.InvariantCulture, "{0} RAW - [{1}]", Start, Content);
|
||||
}
|
||||
|
||||
internal void CalculateStart(Span prev)
|
||||
{
|
||||
if (prev == null)
|
||||
{
|
||||
Start = SourceLocation.Zero;
|
||||
}
|
||||
else
|
||||
{
|
||||
Start = new SourceLocationTracker(prev.Start).UpdateLocation(prev.Content).CurrentLocation;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,408 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNet.Razor.Editor;
|
||||
using Microsoft.AspNet.Razor.Generator;
|
||||
using Microsoft.AspNet.Razor.Parser;
|
||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||
using Microsoft.AspNet.Razor.Text;
|
||||
using Microsoft.AspNet.Razor.Tokenizer;
|
||||
using Microsoft.AspNet.Razor.Tokenizer.Symbols;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Test.Framework
|
||||
{
|
||||
public static class SpanFactoryExtensions
|
||||
{
|
||||
public static UnclassifiedCodeSpanConstructor EmptyCSharp(this SpanFactory self)
|
||||
{
|
||||
return new UnclassifiedCodeSpanConstructor(
|
||||
self.Span(SpanKind.Code, new CSharpSymbol(self.LocationTracker.CurrentLocation, String.Empty, CSharpSymbolType.Unknown)));
|
||||
}
|
||||
|
||||
public static UnclassifiedCodeSpanConstructor EmptyVB(this SpanFactory self)
|
||||
{
|
||||
return new UnclassifiedCodeSpanConstructor(
|
||||
self.Span(SpanKind.Code, new VBSymbol(self.LocationTracker.CurrentLocation, String.Empty, VBSymbolType.Unknown)));
|
||||
}
|
||||
|
||||
public static SpanConstructor EmptyHtml(this SpanFactory self)
|
||||
{
|
||||
return self.Span(SpanKind.Markup, new HtmlSymbol(self.LocationTracker.CurrentLocation, String.Empty, HtmlSymbolType.Unknown))
|
||||
.With(new MarkupCodeGenerator());
|
||||
}
|
||||
|
||||
public static UnclassifiedCodeSpanConstructor Code(this SpanFactory self, string content)
|
||||
{
|
||||
return new UnclassifiedCodeSpanConstructor(
|
||||
self.Span(SpanKind.Code, content, markup: false));
|
||||
}
|
||||
|
||||
public static SpanConstructor CodeTransition(this SpanFactory self)
|
||||
{
|
||||
return self.Span(SpanKind.Transition, SyntaxConstants.TransitionString, markup: false).Accepts(AcceptedCharacters.None);
|
||||
}
|
||||
|
||||
public static SpanConstructor CodeTransition(this SpanFactory self, string content)
|
||||
{
|
||||
return self.Span(SpanKind.Transition, content, markup: false).Accepts(AcceptedCharacters.None);
|
||||
}
|
||||
|
||||
public static SpanConstructor CodeTransition(this SpanFactory self, CSharpSymbolType type)
|
||||
{
|
||||
return self.Span(SpanKind.Transition, SyntaxConstants.TransitionString, type).Accepts(AcceptedCharacters.None);
|
||||
}
|
||||
|
||||
public static SpanConstructor CodeTransition(this SpanFactory self, string content, CSharpSymbolType type)
|
||||
{
|
||||
return self.Span(SpanKind.Transition, content, type).Accepts(AcceptedCharacters.None);
|
||||
}
|
||||
|
||||
public static SpanConstructor CodeTransition(this SpanFactory self, VBSymbolType type)
|
||||
{
|
||||
return self.Span(SpanKind.Transition, SyntaxConstants.TransitionString, type).Accepts(AcceptedCharacters.None);
|
||||
}
|
||||
|
||||
public static SpanConstructor CodeTransition(this SpanFactory self, string content, VBSymbolType type)
|
||||
{
|
||||
return self.Span(SpanKind.Transition, content, type).Accepts(AcceptedCharacters.None);
|
||||
}
|
||||
|
||||
public static SpanConstructor MarkupTransition(this SpanFactory self)
|
||||
{
|
||||
return self.Span(SpanKind.Transition, SyntaxConstants.TransitionString, markup: true).Accepts(AcceptedCharacters.None);
|
||||
}
|
||||
|
||||
public static SpanConstructor MarkupTransition(this SpanFactory self, string content)
|
||||
{
|
||||
return self.Span(SpanKind.Transition, content, markup: true).Accepts(AcceptedCharacters.None);
|
||||
}
|
||||
|
||||
public static SpanConstructor MarkupTransition(this SpanFactory self, HtmlSymbolType type)
|
||||
{
|
||||
return self.Span(SpanKind.Transition, SyntaxConstants.TransitionString, type).Accepts(AcceptedCharacters.None);
|
||||
}
|
||||
|
||||
public static SpanConstructor MarkupTransition(this SpanFactory self, string content, HtmlSymbolType type)
|
||||
{
|
||||
return self.Span(SpanKind.Transition, content, type).Accepts(AcceptedCharacters.None);
|
||||
}
|
||||
|
||||
public static SpanConstructor MetaCode(this SpanFactory self, string content)
|
||||
{
|
||||
return self.Span(SpanKind.MetaCode, content, markup: false);
|
||||
}
|
||||
|
||||
public static SpanConstructor MetaCode(this SpanFactory self, string content, CSharpSymbolType type)
|
||||
{
|
||||
return self.Span(SpanKind.MetaCode, content, type);
|
||||
}
|
||||
|
||||
public static SpanConstructor MetaCode(this SpanFactory self, string content, VBSymbolType type)
|
||||
{
|
||||
return self.Span(SpanKind.MetaCode, content, type);
|
||||
}
|
||||
|
||||
public static SpanConstructor MetaMarkup(this SpanFactory self, string content)
|
||||
{
|
||||
return self.Span(SpanKind.MetaCode, content, markup: true);
|
||||
}
|
||||
|
||||
public static SpanConstructor MetaMarkup(this SpanFactory self, string content, HtmlSymbolType type)
|
||||
{
|
||||
return self.Span(SpanKind.MetaCode, content, type);
|
||||
}
|
||||
|
||||
public static SpanConstructor Comment(this SpanFactory self, string content, CSharpSymbolType type)
|
||||
{
|
||||
return self.Span(SpanKind.Comment, content, type);
|
||||
}
|
||||
|
||||
public static SpanConstructor Comment(this SpanFactory self, string content, VBSymbolType type)
|
||||
{
|
||||
return self.Span(SpanKind.Comment, content, type);
|
||||
}
|
||||
|
||||
public static SpanConstructor Comment(this SpanFactory self, string content, HtmlSymbolType type)
|
||||
{
|
||||
return self.Span(SpanKind.Comment, content, type);
|
||||
}
|
||||
|
||||
public static SpanConstructor Markup(this SpanFactory self, string content)
|
||||
{
|
||||
return self.Span(SpanKind.Markup, content, markup: true).With(new MarkupCodeGenerator());
|
||||
}
|
||||
|
||||
public static SpanConstructor Markup(this SpanFactory self, params string[] content)
|
||||
{
|
||||
return self.Span(SpanKind.Markup, content, markup: true).With(new MarkupCodeGenerator());
|
||||
}
|
||||
|
||||
public static SourceLocation GetLocationAndAdvance(this SourceLocationTracker self, string content)
|
||||
{
|
||||
SourceLocation ret = self.CurrentLocation;
|
||||
self.UpdateLocation(content);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
public class SpanFactory
|
||||
{
|
||||
public Func<ITextDocument, ITokenizer> MarkupTokenizerFactory { get; set; }
|
||||
public Func<ITextDocument, ITokenizer> CodeTokenizerFactory { get; set; }
|
||||
public SourceLocationTracker LocationTracker { get; private set; }
|
||||
|
||||
public static SpanFactory CreateCsHtml()
|
||||
{
|
||||
return new SpanFactory()
|
||||
{
|
||||
MarkupTokenizerFactory = doc => new HtmlTokenizer(doc),
|
||||
CodeTokenizerFactory = doc => new CSharpTokenizer(doc)
|
||||
};
|
||||
}
|
||||
|
||||
public static SpanFactory CreateVbHtml()
|
||||
{
|
||||
return new SpanFactory()
|
||||
{
|
||||
MarkupTokenizerFactory = doc => new HtmlTokenizer(doc),
|
||||
CodeTokenizerFactory = doc => new VBTokenizer(doc)
|
||||
};
|
||||
}
|
||||
|
||||
public SpanFactory()
|
||||
{
|
||||
LocationTracker = new SourceLocationTracker();
|
||||
}
|
||||
|
||||
public SpanConstructor Span(SpanKind kind, string content, CSharpSymbolType type)
|
||||
{
|
||||
return CreateSymbolSpan(kind, content, st => new CSharpSymbol(st, content, type));
|
||||
}
|
||||
|
||||
public SpanConstructor Span(SpanKind kind, string content, VBSymbolType type)
|
||||
{
|
||||
return CreateSymbolSpan(kind, content, st => new VBSymbol(st, content, type));
|
||||
}
|
||||
|
||||
public SpanConstructor Span(SpanKind kind, string content, HtmlSymbolType type)
|
||||
{
|
||||
return CreateSymbolSpan(kind, content, st => new HtmlSymbol(st, content, type));
|
||||
}
|
||||
|
||||
public SpanConstructor Span(SpanKind kind, string content, bool markup)
|
||||
{
|
||||
return new SpanConstructor(kind, Tokenize(new[] { content }, markup));
|
||||
}
|
||||
|
||||
public SpanConstructor Span(SpanKind kind, string[] content, bool markup)
|
||||
{
|
||||
return new SpanConstructor(kind, Tokenize(content, markup));
|
||||
}
|
||||
|
||||
public SpanConstructor Span(SpanKind kind, params ISymbol[] symbols)
|
||||
{
|
||||
return new SpanConstructor(kind, symbols);
|
||||
}
|
||||
|
||||
private SpanConstructor CreateSymbolSpan(SpanKind kind, string content, Func<SourceLocation, ISymbol> ctor)
|
||||
{
|
||||
SourceLocation start = LocationTracker.CurrentLocation;
|
||||
LocationTracker.UpdateLocation(content);
|
||||
return new SpanConstructor(kind, new[] { ctor(start) });
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
LocationTracker.CurrentLocation = SourceLocation.Zero;
|
||||
}
|
||||
|
||||
private IEnumerable<ISymbol> Tokenize(IEnumerable<string> contentFragments, bool markup)
|
||||
{
|
||||
return contentFragments.SelectMany(fragment => Tokenize(fragment, markup));
|
||||
}
|
||||
|
||||
private IEnumerable<ISymbol> Tokenize(string content, bool markup)
|
||||
{
|
||||
ITokenizer tok = MakeTokenizer(markup, new SeekableTextReader(content));
|
||||
ISymbol sym;
|
||||
ISymbol last = null;
|
||||
while ((sym = tok.NextSymbol()) != null)
|
||||
{
|
||||
OffsetStart(sym, LocationTracker.CurrentLocation);
|
||||
last = sym;
|
||||
yield return sym;
|
||||
}
|
||||
LocationTracker.UpdateLocation(content);
|
||||
}
|
||||
|
||||
private ITokenizer MakeTokenizer(bool markup, SeekableTextReader seekableTextReader)
|
||||
{
|
||||
if (markup)
|
||||
{
|
||||
return MarkupTokenizerFactory(seekableTextReader);
|
||||
}
|
||||
else
|
||||
{
|
||||
return CodeTokenizerFactory(seekableTextReader);
|
||||
}
|
||||
}
|
||||
|
||||
private void OffsetStart(ISymbol sym, SourceLocation sourceLocation)
|
||||
{
|
||||
sym.OffsetStart(sourceLocation);
|
||||
}
|
||||
}
|
||||
|
||||
public static class SpanConstructorExtensions
|
||||
{
|
||||
public static SpanConstructor Accepts(this SpanConstructor self, AcceptedCharacters accepted)
|
||||
{
|
||||
return self.With(eh => eh.AcceptedCharacters = accepted);
|
||||
}
|
||||
|
||||
public static SpanConstructor AutoCompleteWith(this SpanConstructor self, string autoCompleteString)
|
||||
{
|
||||
return AutoCompleteWith(self, autoCompleteString, atEndOfSpan: false);
|
||||
}
|
||||
|
||||
public static SpanConstructor AutoCompleteWith(this SpanConstructor self, string autoCompleteString, bool atEndOfSpan)
|
||||
{
|
||||
return self.With(new AutoCompleteEditHandler(SpanConstructor.TestTokenizer) { AutoCompleteString = autoCompleteString, AutoCompleteAtEndOfSpan = atEndOfSpan });
|
||||
}
|
||||
|
||||
public static SpanConstructor WithEditorHints(this SpanConstructor self, EditorHints hints)
|
||||
{
|
||||
return self.With(eh => eh.EditorHints = hints);
|
||||
}
|
||||
}
|
||||
|
||||
public class UnclassifiedCodeSpanConstructor
|
||||
{
|
||||
SpanConstructor _self;
|
||||
|
||||
public UnclassifiedCodeSpanConstructor(SpanConstructor self)
|
||||
{
|
||||
_self = self;
|
||||
}
|
||||
|
||||
public SpanConstructor AsMetaCode()
|
||||
{
|
||||
_self.Builder.Kind = SpanKind.MetaCode;
|
||||
return _self;
|
||||
}
|
||||
|
||||
public SpanConstructor AsStatement()
|
||||
{
|
||||
return _self.With(new StatementCodeGenerator());
|
||||
}
|
||||
|
||||
public SpanConstructor AsExpression()
|
||||
{
|
||||
return _self.With(new ExpressionCodeGenerator());
|
||||
}
|
||||
|
||||
public SpanConstructor AsImplicitExpression(ISet<string> keywords)
|
||||
{
|
||||
return AsImplicitExpression(keywords, acceptTrailingDot: false);
|
||||
}
|
||||
|
||||
public SpanConstructor AsImplicitExpression(ISet<string> keywords, bool acceptTrailingDot)
|
||||
{
|
||||
return _self.With(new ImplicitExpressionEditHandler(SpanConstructor.TestTokenizer, keywords, acceptTrailingDot))
|
||||
.With(new ExpressionCodeGenerator());
|
||||
}
|
||||
|
||||
public SpanConstructor AsFunctionsBody()
|
||||
{
|
||||
return _self.With(new TypeMemberCodeGenerator());
|
||||
}
|
||||
|
||||
public SpanConstructor AsNamespaceImport(string ns, int namespaceKeywordLength)
|
||||
{
|
||||
return _self.With(new AddImportCodeGenerator(ns, namespaceKeywordLength));
|
||||
}
|
||||
|
||||
public SpanConstructor Hidden()
|
||||
{
|
||||
return _self.With(SpanCodeGenerator.Null);
|
||||
}
|
||||
|
||||
public SpanConstructor AsBaseType(string baseType)
|
||||
{
|
||||
return _self.With(new SetBaseTypeCodeGenerator(baseType));
|
||||
}
|
||||
|
||||
public SpanConstructor AsRazorDirectiveAttribute(string key, string value)
|
||||
{
|
||||
return _self.With(new RazorDirectiveAttributeCodeGenerator(key, value));
|
||||
}
|
||||
|
||||
public SpanConstructor As(ISpanCodeGenerator codeGenerator)
|
||||
{
|
||||
return _self.With(codeGenerator);
|
||||
}
|
||||
}
|
||||
|
||||
public class SpanConstructor
|
||||
{
|
||||
public SpanBuilder Builder { get; private set; }
|
||||
|
||||
internal static IEnumerable<ISymbol> TestTokenizer(string str)
|
||||
{
|
||||
yield return new RawTextSymbol(SourceLocation.Zero, str);
|
||||
}
|
||||
|
||||
public SpanConstructor(SpanKind kind, IEnumerable<ISymbol> symbols)
|
||||
{
|
||||
Builder = new SpanBuilder();
|
||||
Builder.Kind = kind;
|
||||
Builder.EditHandler = SpanEditHandler.CreateDefault(TestTokenizer);
|
||||
foreach (ISymbol sym in symbols)
|
||||
{
|
||||
Builder.Accept(sym);
|
||||
}
|
||||
}
|
||||
|
||||
private Span Build()
|
||||
{
|
||||
return Builder.Build();
|
||||
}
|
||||
|
||||
public SpanConstructor With(ISpanCodeGenerator generator)
|
||||
{
|
||||
Builder.CodeGenerator = generator;
|
||||
return this;
|
||||
}
|
||||
|
||||
public SpanConstructor With(SpanEditHandler handler)
|
||||
{
|
||||
Builder.EditHandler = handler;
|
||||
return this;
|
||||
}
|
||||
|
||||
public SpanConstructor With(Action<ISpanCodeGenerator> generatorConfigurer)
|
||||
{
|
||||
generatorConfigurer(Builder.CodeGenerator);
|
||||
return this;
|
||||
}
|
||||
|
||||
public SpanConstructor With(Action<SpanEditHandler> handlerConfigurer)
|
||||
{
|
||||
handlerConfigurer(Builder.EditHandler);
|
||||
return this;
|
||||
}
|
||||
|
||||
public static implicit operator Span(SpanConstructor self)
|
||||
{
|
||||
return self.Build();
|
||||
}
|
||||
|
||||
public SpanConstructor Hidden()
|
||||
{
|
||||
Builder.CodeGenerator = SpanCodeGenerator.Null;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNet.Razor.Parser;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Test.Framework
|
||||
{
|
||||
public abstract class VBHtmlCodeParserTestBase : CodeParserTestBase
|
||||
{
|
||||
protected override ISet<string> KeywordSet
|
||||
{
|
||||
get { return VBCodeParser.DefaultKeywords; }
|
||||
}
|
||||
|
||||
protected override SpanFactory CreateSpanFactory()
|
||||
{
|
||||
return SpanFactory.CreateVbHtml();
|
||||
}
|
||||
|
||||
public override ParserBase CreateMarkupParser()
|
||||
{
|
||||
return new HtmlMarkupParser();
|
||||
}
|
||||
|
||||
public override ParserBase CreateCodeParser()
|
||||
{
|
||||
return new VBCodeParser();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNet.Razor.Parser;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Test.Framework
|
||||
{
|
||||
public abstract class VBHtmlMarkupParserTestBase : MarkupParserTestBase
|
||||
{
|
||||
protected override ISet<string> KeywordSet
|
||||
{
|
||||
get { return VBCodeParser.DefaultKeywords; }
|
||||
}
|
||||
|
||||
protected override SpanFactory CreateSpanFactory()
|
||||
{
|
||||
return SpanFactory.CreateVbHtml();
|
||||
}
|
||||
|
||||
public override ParserBase CreateMarkupParser()
|
||||
{
|
||||
return new HtmlMarkupParser();
|
||||
}
|
||||
|
||||
public override ParserBase CreateCodeParser()
|
||||
{
|
||||
return new VBCodeParser();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,417 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNet.Razor.Generator;
|
||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||
using Microsoft.TestCommon;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Test.Generator
|
||||
{
|
||||
public class CSharpRazorCodeGeneratorTest : RazorCodeGeneratorTest<CSharpRazorCodeLanguage>
|
||||
{
|
||||
protected override string FileExtension
|
||||
{
|
||||
get { return "cshtml"; }
|
||||
}
|
||||
|
||||
protected override string LanguageName
|
||||
{
|
||||
get { return "CS"; }
|
||||
}
|
||||
|
||||
protected override string BaselineExtension
|
||||
{
|
||||
get { return "cs"; }
|
||||
}
|
||||
|
||||
private const string TestPhysicalPath = @"C:\Bar.cshtml";
|
||||
private const string TestVirtualPath = "~/Foo/Bar.cshtml";
|
||||
|
||||
[Fact]
|
||||
public void ConstructorRequiresNonNullClassName()
|
||||
{
|
||||
Assert.ThrowsArgumentNullOrEmptyString(() => new CSharpRazorCodeGenerator(null, TestRootNamespaceName, TestPhysicalPath, CreateHost()), "className");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ConstructorRequiresNonEmptyClassName()
|
||||
{
|
||||
Assert.ThrowsArgumentNullOrEmptyString(() => new CSharpRazorCodeGenerator(String.Empty, TestRootNamespaceName, TestPhysicalPath, CreateHost()), "className");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ConstructorRequiresNonNullRootNamespaceName()
|
||||
{
|
||||
Assert.ThrowsArgumentNull(() => new CSharpRazorCodeGenerator("Foo", null, TestPhysicalPath, CreateHost()), "rootNamespaceName");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ConstructorAllowsEmptyRootNamespaceName()
|
||||
{
|
||||
new CSharpRazorCodeGenerator("Foo", String.Empty, TestPhysicalPath, CreateHost());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ConstructorRequiresNonNullHost()
|
||||
{
|
||||
Assert.ThrowsArgumentNull(() => new CSharpRazorCodeGenerator("Foo", TestRootNamespaceName, TestPhysicalPath, null), "host");
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("NestedCodeBlocks")]
|
||||
[InlineData("CodeBlock")]
|
||||
[InlineData("ExplicitExpression")]
|
||||
[InlineData("MarkupInCodeBlock")]
|
||||
[InlineData("Blocks")]
|
||||
[InlineData("ImplicitExpression")]
|
||||
[InlineData("Imports")]
|
||||
[InlineData("ExpressionsInCode")]
|
||||
[InlineData("FunctionsBlock")]
|
||||
[InlineData("FunctionsBlock_Tabs")]
|
||||
[InlineData("Templates")]
|
||||
[InlineData("Sections")]
|
||||
[InlineData("RazorComments")]
|
||||
[InlineData("Helpers")]
|
||||
[InlineData("HelpersMissingCloseParen")]
|
||||
[InlineData("HelpersMissingOpenBrace")]
|
||||
[InlineData("HelpersMissingOpenParen")]
|
||||
[InlineData("NestedHelpers")]
|
||||
[InlineData("InlineBlocks")]
|
||||
[InlineData("NestedHelpers")]
|
||||
[InlineData("LayoutDirective")]
|
||||
[InlineData("ConditionalAttributes")]
|
||||
[InlineData("ResolveUrl")]
|
||||
public void CSharpCodeGeneratorCorrectlyGeneratesRunTimeCode(string testType)
|
||||
{
|
||||
RunTest(testType);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CSharpCodeGeneratorCorrectlyGeneratesMappingsForSimpleUnspacedIf()
|
||||
{
|
||||
RunTest("SimpleUnspacedIf",
|
||||
"SimpleUnspacedIf.DesignTime.Tabs",
|
||||
designTimeMode: true,
|
||||
tabTest: TabTest.Tabs,
|
||||
expectedDesignTimePragmas: new List<GeneratedCodeMapping>()
|
||||
{
|
||||
/* 01 */ new GeneratedCodeMapping(1, 2, 1, 15),
|
||||
/* 02 */ new GeneratedCodeMapping(3, 13, 7, 3),
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CSharpCodeGeneratorCorrectlyGeneratesMappingsForRazorCommentsAtDesignTime()
|
||||
{
|
||||
RunTest("RazorComments", "RazorComments.DesignTime", designTimeMode: true, tabTest: TabTest.NoTabs, expectedDesignTimePragmas: new List<GeneratedCodeMapping>()
|
||||
{
|
||||
/* 01 */ new GeneratedCodeMapping(4, 3, 3, 6),
|
||||
/* 02 */ new GeneratedCodeMapping(5, 40, 39, 22),
|
||||
/* 03 */ new GeneratedCodeMapping(6, 50, 49, 58),
|
||||
/* 04 */ new GeneratedCodeMapping(12, 3, 3, 24),
|
||||
/* 05 */ new GeneratedCodeMapping(13, 46, 46, 3),
|
||||
/* 06 */ new GeneratedCodeMapping(15, 3, 7, 1),
|
||||
/* 07 */ new GeneratedCodeMapping(15, 8, 8, 1)
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CSharpCodeGeneratorCorrectlyGenerateMappingForOpenedCurlyIf()
|
||||
{
|
||||
OpenedIf(withTabs: true);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CSharpCodeGeneratorCorrectlyGenerateMappingForOpenedCurlyIfSpaces()
|
||||
{
|
||||
OpenedIf(withTabs: false);
|
||||
}
|
||||
|
||||
private void OpenedIf(bool withTabs)
|
||||
{
|
||||
int tabOffsetForMapping = 0;
|
||||
|
||||
// where the test is running with tabs, the offset into the CS buffer changes for the whitespace mapping
|
||||
// with spaces we get 7xspace -> offset of 8 (column = offset+1)
|
||||
// with tabs we get tab + 3 spaces -> offset of 4 chars + 1 = 5
|
||||
if (withTabs)
|
||||
{
|
||||
tabOffsetForMapping = 3;
|
||||
}
|
||||
|
||||
RunTest("OpenedIf",
|
||||
"OpenedIf.DesignTime" + (withTabs ? ".Tabs" : ""),
|
||||
designTimeMode: true,
|
||||
tabTest: withTabs ? TabTest.Tabs : TabTest.NoTabs,
|
||||
spans: new TestSpan[]
|
||||
{
|
||||
new TestSpan(SpanKind.Markup, 0, 16),
|
||||
new TestSpan(SpanKind.Transition, 16, 17),
|
||||
new TestSpan(SpanKind.Code, 17, 31),
|
||||
new TestSpan(SpanKind.Markup, 31, 38),
|
||||
new TestSpan(SpanKind.Code, 38, 40),
|
||||
new TestSpan(SpanKind.Markup, 40, 47),
|
||||
new TestSpan(SpanKind.Code, 47, 47),
|
||||
},
|
||||
expectedDesignTimePragmas: new List<GeneratedCodeMapping>()
|
||||
{
|
||||
/* 01 */ new GeneratedCodeMapping(3, 2, 1, 14),
|
||||
/* 02 */ new GeneratedCodeMapping(4, 8, 8 - tabOffsetForMapping, 2),
|
||||
/* 03 */ new GeneratedCodeMapping(5, 8, 8 - tabOffsetForMapping, 0),
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CSharpCodeGeneratorCorrectlyGeneratesImportStatementsAtDesignTime()
|
||||
{
|
||||
RunTest("Imports", "Imports.DesignTime", designTimeMode: true, tabTest: TabTest.NoTabs, expectedDesignTimePragmas: new List<GeneratedCodeMapping>()
|
||||
{
|
||||
/* 01 */ new GeneratedCodeMapping(1, 2, 1, 15),
|
||||
/* 02 */ new GeneratedCodeMapping(2, 2, 1, 32),
|
||||
/* 03 */ new GeneratedCodeMapping(3, 2, 1, 12),
|
||||
/* 04 */ new GeneratedCodeMapping(5, 30, 30, 21),
|
||||
/* 05 */ new GeneratedCodeMapping(6, 36, 36, 20),
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CSharpCodeGeneratorCorrectlyGeneratesFunctionsBlocksAtDesignTime()
|
||||
{
|
||||
RunTest("FunctionsBlock",
|
||||
"FunctionsBlock.DesignTime",
|
||||
designTimeMode: true,
|
||||
tabTest: TabTest.NoTabs,
|
||||
expectedDesignTimePragmas: new List<GeneratedCodeMapping>()
|
||||
{
|
||||
/* 01 */ new GeneratedCodeMapping(1, 13, 13, 4),
|
||||
/* 02 */ new GeneratedCodeMapping(5, 13, 13, 104),
|
||||
/* 03 */ new GeneratedCodeMapping(12, 26, 26, 11)
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CSharpCodeGeneratorCorrectlyGeneratesFunctionsBlocksAtDesignTimeTabs()
|
||||
{
|
||||
RunTest("FunctionsBlock",
|
||||
"FunctionsBlock.DesignTime" + ".Tabs",
|
||||
designTimeMode: true,
|
||||
tabTest: TabTest.Tabs,
|
||||
expectedDesignTimePragmas: new List<GeneratedCodeMapping>()
|
||||
{
|
||||
/* 01 */ new GeneratedCodeMapping(1, 13, 4, 4),
|
||||
/* 02 */ new GeneratedCodeMapping(5, 13, 4, 104),
|
||||
/* 03 */ new GeneratedCodeMapping(12, 26, 14, 11)
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CSharpCodeGeneratorCorrectlyGeneratesMinimalFunctionsBlocksAtDesignTimeTabs()
|
||||
{
|
||||
RunTest("FunctionsBlockMinimal",
|
||||
"FunctionsBlockMinimal.DesignTime" + ".Tabs",
|
||||
designTimeMode: true,
|
||||
tabTest: TabTest.Tabs,
|
||||
expectedDesignTimePragmas: new List<GeneratedCodeMapping>()
|
||||
{
|
||||
/* 01 */ new GeneratedCodeMapping(3, 13, 7, 55),
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CSharpCodeGeneratorCorrectlyGeneratesHiddenSpansWithinCode()
|
||||
{
|
||||
RunTest("HiddenSpansInCode", designTimeMode: true, tabTest: TabTest.NoTabs, expectedDesignTimePragmas: new List<GeneratedCodeMapping>
|
||||
{
|
||||
/* 01 */ new GeneratedCodeMapping(1, 3, 3, 6),
|
||||
/* 02 */ new GeneratedCodeMapping(2, 6, 6, 5)
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CSharpCodeGeneratorGeneratesCodeWithParserErrorsInDesignTimeMode()
|
||||
{
|
||||
RunTest("ParserError", designTimeMode: true, expectedDesignTimePragmas: new List<GeneratedCodeMapping>()
|
||||
{
|
||||
/* 01 */ new GeneratedCodeMapping(1, 3, 3, 31)
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CSharpCodeGeneratorCorrectlyGeneratesInheritsAtRuntime()
|
||||
{
|
||||
RunTest("Inherits", baselineName: "Inherits.Runtime");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CSharpCodeGeneratorCorrectlyGeneratesInheritsAtDesigntime()
|
||||
{
|
||||
RunTest("Inherits", baselineName: "Inherits.Designtime", designTimeMode: true, tabTest: TabTest.NoTabs, expectedDesignTimePragmas: new List<GeneratedCodeMapping>()
|
||||
{
|
||||
/* 01 */ new GeneratedCodeMapping(1, 2, 7, 5),
|
||||
/* 02 */ new GeneratedCodeMapping(3, 11, 11, 25),
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CSharpCodeGeneratorCorrectlyGeneratesDesignTimePragmasForUnfinishedExpressionsInCode()
|
||||
{
|
||||
RunTest("UnfinishedExpressionInCode", tabTest: TabTest.NoTabs, designTimeMode: true, expectedDesignTimePragmas: new List<GeneratedCodeMapping>()
|
||||
{
|
||||
/* 01 */ new GeneratedCodeMapping(1, 3, 3, 2),
|
||||
/* 02 */ new GeneratedCodeMapping(2, 2, 7, 9),
|
||||
/* 03 */ new GeneratedCodeMapping(2, 11, 11, 2)
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CSharpCodeGeneratorCorrectlyGeneratesDesignTimePragmasForUnfinishedExpressionsInCodeTabs()
|
||||
{
|
||||
RunTest("UnfinishedExpressionInCode",
|
||||
"UnfinishedExpressionInCode.Tabs",
|
||||
tabTest: TabTest.Tabs,
|
||||
designTimeMode: true, expectedDesignTimePragmas: new List<GeneratedCodeMapping>()
|
||||
{
|
||||
/* 01 */ new GeneratedCodeMapping(1, 3, 3, 2),
|
||||
/* 02 */ new GeneratedCodeMapping(2, 2, 7, 9),
|
||||
/* 03 */ new GeneratedCodeMapping(2, 11, 5, 2)
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CSharpCodeGeneratorCorrectlyGeneratesDesignTimePragmasMarkupAndExpressions()
|
||||
{
|
||||
RunTest("DesignTime",
|
||||
designTimeMode: true,
|
||||
tabTest: TabTest.NoTabs,
|
||||
expectedDesignTimePragmas: new List<GeneratedCodeMapping>()
|
||||
{
|
||||
/* 01 */ new GeneratedCodeMapping(2, 14, 13, 36),
|
||||
/* 02 */ new GeneratedCodeMapping(3, 23, 23, 1),
|
||||
/* 03 */ new GeneratedCodeMapping(3, 28, 28, 15),
|
||||
/* 04 */ new GeneratedCodeMapping(8, 3, 7, 12),
|
||||
/* 05 */ new GeneratedCodeMapping(9, 2, 7, 4),
|
||||
/* 06 */ new GeneratedCodeMapping(9, 15, 15, 3),
|
||||
/* 07 */ new GeneratedCodeMapping(9, 26, 26, 1),
|
||||
/* 08 */ new GeneratedCodeMapping(14, 6, 7, 3),
|
||||
/* 09 */ new GeneratedCodeMapping(17, 9, 24, 7),
|
||||
/* 10 */ new GeneratedCodeMapping(17, 16, 16, 26),
|
||||
/* 11 */ new GeneratedCodeMapping(19, 19, 19, 9),
|
||||
/* 12 */ new GeneratedCodeMapping(21, 1, 1, 1)
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
[Fact]
|
||||
public void CSharpCodeGeneratorCorrectlyGeneratesDesignTimePragmasForImplicitExpressionStartedAtEOF()
|
||||
{
|
||||
RunTest("ImplicitExpressionAtEOF", designTimeMode: true, expectedDesignTimePragmas: new List<GeneratedCodeMapping>()
|
||||
{
|
||||
/* 01 */ new GeneratedCodeMapping(3, 2, 7, 0)
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CSharpCodeGeneratorCorrectlyGeneratesDesignTimePragmasForExplicitExpressionStartedAtEOF()
|
||||
{
|
||||
RunTest("ExplicitExpressionAtEOF", designTimeMode: true, expectedDesignTimePragmas: new List<GeneratedCodeMapping>()
|
||||
{
|
||||
/* 01 */ new GeneratedCodeMapping(3, 3, 7, 0)
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CSharpCodeGeneratorCorrectlyGeneratesDesignTimePragmasForCodeBlockStartedAtEOF()
|
||||
{
|
||||
RunTest("CodeBlockAtEOF", designTimeMode: true, expectedDesignTimePragmas: new List<GeneratedCodeMapping>()
|
||||
{
|
||||
/* 01 */ new GeneratedCodeMapping(1, 3, 3, 0)
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CSharpCodeGeneratorCorrectlyGeneratesDesignTimePragmasForEmptyImplicitExpression()
|
||||
{
|
||||
RunTest("EmptyImplicitExpression", designTimeMode: true, expectedDesignTimePragmas: new List<GeneratedCodeMapping>()
|
||||
{
|
||||
/* 01 */ new GeneratedCodeMapping(3, 2, 7, 0)
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CSharpCodeGeneratorCorrectlyGeneratesDesignTimePragmasForEmptyImplicitExpressionInCode()
|
||||
{
|
||||
RunTest("EmptyImplicitExpressionInCode", tabTest: TabTest.NoTabs, designTimeMode: true, expectedDesignTimePragmas: new List<GeneratedCodeMapping>()
|
||||
{
|
||||
/* 01 */ new GeneratedCodeMapping(1, 3, 3, 6),
|
||||
/* 02 */ new GeneratedCodeMapping(2, 6, 7, 0),
|
||||
/* 03 */ new GeneratedCodeMapping(2, 6, 6, 2)
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CSharpCodeGeneratorCorrectlyGeneratesDesignTimePragmasForEmptyImplicitExpressionInCodeTabs()
|
||||
{
|
||||
RunTest("EmptyImplicitExpressionInCode",
|
||||
"EmptyImplicitExpressionInCode.Tabs",
|
||||
tabTest: TabTest.Tabs,
|
||||
designTimeMode: true, expectedDesignTimePragmas: new List<GeneratedCodeMapping>()
|
||||
{
|
||||
/* 01 */ new GeneratedCodeMapping(1, 3, 3, 6),
|
||||
/* 02 */ new GeneratedCodeMapping(2, 6, 7, 0),
|
||||
/* 03 */ new GeneratedCodeMapping(2, 6, 3, 2)
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CSharpCodeGeneratorCorrectlyGeneratesDesignTimePragmasForEmptyExplicitExpression()
|
||||
{
|
||||
RunTest("EmptyExplicitExpression", designTimeMode: true, expectedDesignTimePragmas: new List<GeneratedCodeMapping>()
|
||||
{
|
||||
/* 01 */ new GeneratedCodeMapping(3, 3, 7, 0)
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CSharpCodeGeneratorCorrectlyGeneratesDesignTimePragmasForEmptyCodeBlock()
|
||||
{
|
||||
RunTest("EmptyCodeBlock", designTimeMode: true, expectedDesignTimePragmas: new List<GeneratedCodeMapping>()
|
||||
{
|
||||
/* 01 */ new GeneratedCodeMapping(3, 3, 3, 0)
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CSharpCodeGeneratorDoesNotRenderLinePragmasIfGenerateLinePragmasIsSetToFalse()
|
||||
{
|
||||
RunTest("NoLinePragmas", generatePragmas: false);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CSharpCodeGeneratorRendersHelpersBlockCorrectlyWhenInstanceHelperRequested()
|
||||
{
|
||||
RunTest("Helpers", baselineName: "Helpers.Instance", hostConfig: h => h.StaticHelpers = false);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CSharpCodeGeneratorCorrectlyInstrumentsRazorCodeWhenInstrumentationRequested()
|
||||
{
|
||||
RunTest("Instrumented", hostConfig: host =>
|
||||
{
|
||||
host.EnableInstrumentation = true;
|
||||
host.InstrumentedSourceFilePath = String.Format("~/{0}.cshtml", host.DefaultClassName);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CSharpCodeGeneratorGeneratesUrlsCorrectlyWithCommentsAndQuotes()
|
||||
{
|
||||
RunTest("HtmlCommentWithQuote_Single",
|
||||
tabTest: TabTest.NoTabs);
|
||||
|
||||
RunTest("HtmlCommentWithQuote_Double",
|
||||
tabTest: TabTest.NoTabs);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNet.Razor.Generator;
|
||||
using Microsoft.TestCommon;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Test.Generator
|
||||
{
|
||||
public class GeneratedCodeMappingTest
|
||||
{
|
||||
[Fact]
|
||||
public void GeneratedCodeMappingsAreEqualIfDataIsEqual()
|
||||
{
|
||||
GeneratedCodeMapping left = new GeneratedCodeMapping(12, 34, 56, 78);
|
||||
GeneratedCodeMapping right = new GeneratedCodeMapping(12, 34, 56, 78);
|
||||
Assert.True(left == right);
|
||||
Assert.True(left.Equals(right));
|
||||
Assert.True(right.Equals(left));
|
||||
Assert.True(Equals(left, right));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GeneratedCodeMappingsAreNotEqualIfCodeLengthIsNotEqual()
|
||||
{
|
||||
GeneratedCodeMapping left = new GeneratedCodeMapping(12, 34, 56, 87);
|
||||
GeneratedCodeMapping right = new GeneratedCodeMapping(12, 34, 56, 78);
|
||||
Assert.False(left == right);
|
||||
Assert.False(left.Equals(right));
|
||||
Assert.False(right.Equals(left));
|
||||
Assert.False(Equals(left, right));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GeneratedCodeMappingsAreNotEqualIfStartGeneratedColumnIsNotEqual()
|
||||
{
|
||||
GeneratedCodeMapping left = new GeneratedCodeMapping(12, 34, 56, 87);
|
||||
GeneratedCodeMapping right = new GeneratedCodeMapping(12, 34, 65, 87);
|
||||
Assert.False(left == right);
|
||||
Assert.False(left.Equals(right));
|
||||
Assert.False(right.Equals(left));
|
||||
Assert.False(Equals(left, right));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GeneratedCodeMappingsAreNotEqualIfStartColumnIsNotEqual()
|
||||
{
|
||||
GeneratedCodeMapping left = new GeneratedCodeMapping(12, 34, 56, 87);
|
||||
GeneratedCodeMapping right = new GeneratedCodeMapping(12, 43, 56, 87);
|
||||
Assert.False(left == right);
|
||||
Assert.False(left.Equals(right));
|
||||
Assert.False(right.Equals(left));
|
||||
Assert.False(Equals(left, right));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GeneratedCodeMappingsAreNotEqualIfStartLineIsNotEqual()
|
||||
{
|
||||
GeneratedCodeMapping left = new GeneratedCodeMapping(12, 34, 56, 87);
|
||||
GeneratedCodeMapping right = new GeneratedCodeMapping(21, 34, 56, 87);
|
||||
Assert.False(left == right);
|
||||
Assert.False(left.Equals(right));
|
||||
Assert.False(right.Equals(left));
|
||||
Assert.False(Equals(left, right));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,236 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNet.Razor.Generator;
|
||||
using Microsoft.AspNet.Razor.Parser;
|
||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||
using Microsoft.TestCommon;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Test.Generator
|
||||
{
|
||||
public class PaddingTest
|
||||
{
|
||||
[Fact]
|
||||
public void CalculatePaddingForEmptySpanReturnsZero()
|
||||
{
|
||||
RazorEngineHost host = CreateHost(designTime: true);
|
||||
|
||||
Span span = new Span(new SpanBuilder());
|
||||
|
||||
int padding = CodeGeneratorPaddingHelper.CalculatePadding(host, span, 0);
|
||||
|
||||
Assert.Equal(0, padding);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(true, false, 4)]
|
||||
[InlineData(true, false, 2)]
|
||||
[InlineData(false, true, 4)]
|
||||
[InlineData(false, true, 2)]
|
||||
[InlineData(false, false, 4)]
|
||||
[InlineData(false, false, 2)]
|
||||
[InlineData(true, true, 4)]
|
||||
[InlineData(true, true, 2)]
|
||||
[InlineData(true, true, 1)]
|
||||
[InlineData(true, true, 0)]
|
||||
public void CalculatePaddingForEmptySpanWith4Spaces(bool designTime, bool isIndentingWithTabs, int tabSize)
|
||||
{
|
||||
RazorEngineHost host = CreateHost(designTime: designTime, isIndentingWithTabs: isIndentingWithTabs, tabSize: tabSize);
|
||||
|
||||
Span span = GenerateSpan(@" @{", SpanKind.Code, 3, "");
|
||||
|
||||
int padding = CodeGeneratorPaddingHelper.CalculatePadding(host, span, 0);
|
||||
|
||||
Assert.Equal(6, padding);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(true, false, 4)]
|
||||
[InlineData(true, false, 2)]
|
||||
[InlineData(false, true, 4)]
|
||||
[InlineData(false, true, 2)]
|
||||
[InlineData(false, false, 4)]
|
||||
[InlineData(false, false, 2)]
|
||||
[InlineData(true, true, 4)]
|
||||
[InlineData(true, true, 2)]
|
||||
[InlineData(true, true, 1)]
|
||||
[InlineData(true, true, 0)]
|
||||
public void CalculatePaddingForIfSpanWith4Spaces(bool designTime, bool isIndentingWithTabs, int tabSize)
|
||||
{
|
||||
RazorEngineHost host = CreateHost(designTime: designTime, isIndentingWithTabs: isIndentingWithTabs, tabSize: tabSize);
|
||||
|
||||
Span span = GenerateSpan(@" @if (true)", SpanKind.Code, 2, "if (true)");
|
||||
|
||||
int padding = CodeGeneratorPaddingHelper.CalculatePadding(host, span, 1);
|
||||
|
||||
Assert.Equal(4, padding);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(true, false, 4, 0, 4)]
|
||||
[InlineData(true, false, 2, 0, 4)]
|
||||
[InlineData(true, true, 4, 1, 0)]
|
||||
[InlineData(true, true, 2, 2, 0)]
|
||||
[InlineData(true, true, 1, 4, 0)]
|
||||
[InlineData(true, true, 0, 4, 0)]
|
||||
[InlineData(true, true, 3, 1, 1)]
|
||||
|
||||
// in non design time mode padding falls back to spaces to keep runtime code identical to v2 code.
|
||||
[InlineData(false, true, 4, 0, 5)]
|
||||
[InlineData(false, true, 2, 0, 5)]
|
||||
|
||||
[InlineData(false, false, 4, 0, 5)]
|
||||
[InlineData(false, false, 2, 0, 5)]
|
||||
public void VerifyPaddingForIfSpanWith4Spaces(bool designTime, bool isIndentingWithTabs, int tabSize, int numTabs, int numSpaces)
|
||||
{
|
||||
RazorEngineHost host = CreateHost(designTime: designTime, isIndentingWithTabs: isIndentingWithTabs, tabSize: tabSize);
|
||||
|
||||
// no new lines involved
|
||||
Span span = GenerateSpan(" @if (true)", SpanKind.Code, 2, "if (true)");
|
||||
|
||||
int generatedStart = 1;
|
||||
string code = " if (true)";
|
||||
int paddingCharCount;
|
||||
|
||||
string padded = CodeGeneratorPaddingHelper.PadStatement(host, code, span, ref generatedStart, out paddingCharCount);
|
||||
|
||||
VerifyPadded(numTabs, numSpaces, code, padded, paddingCharCount);
|
||||
|
||||
// with new lines involved
|
||||
Span newLineSpan = GenerateSpan("\t<div>\r\n @if (true)", SpanKind.Code, 3, "if (true)");
|
||||
|
||||
string newLinePadded = CodeGeneratorPaddingHelper.PadStatement(host, code, span, ref generatedStart, out paddingCharCount);
|
||||
|
||||
VerifyPadded(numTabs, numSpaces, code, newLinePadded, paddingCharCount);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(true, false, 4, 0, 8)]
|
||||
[InlineData(true, false, 2, 0, 4)]
|
||||
[InlineData(true, true, 4, 2, 0)]
|
||||
[InlineData(true, true, 2, 2, 0)]
|
||||
[InlineData(true, true, 1, 2, 0)]
|
||||
[InlineData(true, true, 0, 2, 0)]
|
||||
[InlineData(true, true, 3, 2, 0)]
|
||||
|
||||
// in non design time mode padding falls back to spaces to keep runtime code identical to v2 code.
|
||||
[InlineData(false, true, 4, 0, 9)]
|
||||
[InlineData(false, true, 2, 0, 5)]
|
||||
|
||||
[InlineData(false, false, 4, 0, 9)]
|
||||
[InlineData(false, false, 2, 0, 5)]
|
||||
public void VerifyPaddingForIfSpanWithTwoTabs(bool designTime, bool isIndentingWithTabs, int tabSize, int numTabs, int numSpaces)
|
||||
{
|
||||
RazorEngineHost host = CreateHost(designTime: designTime, isIndentingWithTabs: isIndentingWithTabs, tabSize: tabSize);
|
||||
|
||||
// no new lines involved
|
||||
Span span = GenerateSpan("\t\t@if (true)", SpanKind.Code, 2, "if (true)");
|
||||
|
||||
int generatedStart = 1;
|
||||
string code = " if (true)";
|
||||
int paddingCharCount;
|
||||
|
||||
string padded = CodeGeneratorPaddingHelper.PadStatement(host, code, span, ref generatedStart, out paddingCharCount);
|
||||
|
||||
VerifyPadded(numTabs, numSpaces, code, padded, paddingCharCount);
|
||||
|
||||
// with new lines involved
|
||||
Span newLineSpan = GenerateSpan("\t<div>\r\n\t\t@if (true)", SpanKind.Code, 3, "if (true)");
|
||||
|
||||
string newLinePadded = CodeGeneratorPaddingHelper.PadStatement(host, code, span, ref generatedStart, out paddingCharCount);
|
||||
|
||||
VerifyPadded(numTabs, numSpaces, code, newLinePadded, paddingCharCount);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(true, false, 4, 0, 8)]
|
||||
[InlineData(true, false, 2, 0, 4)]
|
||||
[InlineData(true, true, 4, 2, 0)]
|
||||
[InlineData(true, true, 2, 2, 0)]
|
||||
[InlineData(true, true, 1, 2, 0)]
|
||||
[InlineData(true, true, 0, 2, 0)]
|
||||
|
||||
// in non design time mode padding falls back to spaces to keep runtime code identical to v2 code.
|
||||
[InlineData(false, true, 4, 0, 9)]
|
||||
[InlineData(false, true, 2, 0, 5)]
|
||||
|
||||
[InlineData(false, false, 4, 0, 9)]
|
||||
[InlineData(false, false, 2, 0, 5)]
|
||||
public void CalculatePaddingForOpenedIf(bool designTime, bool isIndentingWithTabs, int tabSize, int numTabs, int numSpaces)
|
||||
{
|
||||
RazorEngineHost host = CreateHost(designTime: designTime, isIndentingWithTabs: isIndentingWithTabs, tabSize: tabSize);
|
||||
|
||||
string text = "\r\n<html>\r\n<body>\r\n\t\t@if (true) { \r\n</body>\r\n</html>";
|
||||
|
||||
Span span = GenerateSpan(text, SpanKind.Code, 3, "if (true) { \r\n");
|
||||
|
||||
int generatedStart = 1;
|
||||
string code = " if (true) { \r\n";
|
||||
int paddingCharCount;
|
||||
string padded = CodeGeneratorPaddingHelper.PadStatement(host, code, span, ref generatedStart, out paddingCharCount);
|
||||
|
||||
VerifyPadded(numTabs, numSpaces, code, padded, paddingCharCount);
|
||||
}
|
||||
|
||||
private static void VerifyPadded(int numTabs, int numSpaces, string code, string padded, int paddingCharCount)
|
||||
{
|
||||
Assert.Equal(numTabs + numSpaces + code.Length, padded.Length);
|
||||
|
||||
if (numTabs > 0 || numSpaces > 0)
|
||||
{
|
||||
Assert.True(padded.Length > numTabs + numSpaces, "padded string too short");
|
||||
}
|
||||
|
||||
for (int i = 0; i < numTabs; i++)
|
||||
{
|
||||
Assert.Equal('\t', padded[i]);
|
||||
}
|
||||
|
||||
for (int i = numTabs; i < numTabs + numSpaces; i++)
|
||||
{
|
||||
Assert.Equal(' ', padded[i]);
|
||||
}
|
||||
|
||||
Assert.Equal(numSpaces + numTabs, paddingCharCount);
|
||||
}
|
||||
|
||||
private static RazorEngineHost CreateHost(bool designTime, bool isIndentingWithTabs = false, int tabSize = 4)
|
||||
{
|
||||
return new RazorEngineHost(new CSharpRazorCodeLanguage())
|
||||
{
|
||||
DesignTimeMode = designTime,
|
||||
IsIndentingWithTabs = isIndentingWithTabs,
|
||||
TabSize = tabSize,
|
||||
};
|
||||
}
|
||||
|
||||
private static Span GenerateSpan(string text, SpanKind spanKind, int spanIndex, string spanText)
|
||||
{
|
||||
Span[] spans = GenerateSpans(text, spanKind, spanIndex, spanText);
|
||||
|
||||
return spans[spanIndex];
|
||||
}
|
||||
|
||||
private static Span[] GenerateSpans(string text, SpanKind spanKind, int spanIndex, string spanText)
|
||||
{
|
||||
Assert.True(spanIndex > 0);
|
||||
|
||||
RazorParser parser = new RazorParser(new CSharpCodeParser(), new HtmlMarkupParser());
|
||||
|
||||
Span[] spans;
|
||||
|
||||
using (var reader = new StringReader(text))
|
||||
{
|
||||
ParserResults results = parser.Parse(reader);
|
||||
spans = results.Document.Flatten().ToArray();
|
||||
}
|
||||
|
||||
Assert.True(spans.Length > spanIndex);
|
||||
Assert.Equal(spanKind, spans[spanIndex].Kind);
|
||||
Assert.Equal(spanText, spans[spanIndex].Content);
|
||||
|
||||
return spans;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,245 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
//#define GENERATE_BASELINES
|
||||
|
||||
using System.CodeDom;
|
||||
using System.CodeDom.Compiler;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Microsoft.AspNet.Razor.Generator;
|
||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||
using Microsoft.AspNet.Razor.Test.Utils;
|
||||
using System.Web.WebPages.TestUtils;
|
||||
using Microsoft.TestCommon;
|
||||
using System;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Test.Generator
|
||||
{
|
||||
public abstract class RazorCodeGeneratorTest<TLanguage>
|
||||
where TLanguage : RazorCodeLanguage, new()
|
||||
{
|
||||
protected static readonly string TestRootNamespaceName = "TestOutput";
|
||||
|
||||
protected abstract string FileExtension { get; }
|
||||
protected abstract string LanguageName { get; }
|
||||
protected abstract string BaselineExtension { get; }
|
||||
|
||||
protected RazorEngineHost CreateHost()
|
||||
{
|
||||
return new RazorEngineHost(new TLanguage());
|
||||
}
|
||||
|
||||
protected void RunTest(string name,
|
||||
string baselineName = null,
|
||||
bool generatePragmas = true,
|
||||
bool designTimeMode = false,
|
||||
IList<GeneratedCodeMapping> expectedDesignTimePragmas = null,
|
||||
TestSpan[] spans = null,
|
||||
TabTest tabTest = TabTest.Both,
|
||||
Action<RazorEngineHost> hostConfig = null)
|
||||
{
|
||||
bool testRun = false;
|
||||
|
||||
if ((tabTest & TabTest.Tabs) == TabTest.Tabs)
|
||||
{
|
||||
// CodeDOM will inject its strings into the generated file header, so we force English.
|
||||
using (new CultureReplacer())
|
||||
{
|
||||
RunTestInternal(
|
||||
name: name,
|
||||
baselineName: baselineName,
|
||||
generatePragmas: generatePragmas,
|
||||
designTimeMode: designTimeMode,
|
||||
expectedDesignTimePragmas: expectedDesignTimePragmas,
|
||||
spans: spans,
|
||||
withTabs: true,
|
||||
hostConfig: hostConfig);
|
||||
}
|
||||
|
||||
testRun = true;
|
||||
}
|
||||
|
||||
if ((tabTest & TabTest.NoTabs) == TabTest.NoTabs)
|
||||
{
|
||||
// CodeDOM will inject its strings into the generated file header, so we force English.
|
||||
using (new CultureReplacer())
|
||||
{
|
||||
RunTestInternal(
|
||||
name: name,
|
||||
baselineName: baselineName,
|
||||
generatePragmas: generatePragmas,
|
||||
designTimeMode: designTimeMode,
|
||||
expectedDesignTimePragmas: expectedDesignTimePragmas,
|
||||
spans: spans,
|
||||
withTabs: false,
|
||||
hostConfig: hostConfig);
|
||||
}
|
||||
|
||||
testRun = true;
|
||||
}
|
||||
|
||||
Assert.True(testRun, "No test was run because TabTest is not set correctly");
|
||||
}
|
||||
|
||||
private void RunTestInternal(string name,
|
||||
string baselineName,
|
||||
bool generatePragmas,
|
||||
bool designTimeMode,
|
||||
IList<GeneratedCodeMapping> expectedDesignTimePragmas,
|
||||
TestSpan[] spans,
|
||||
bool withTabs,
|
||||
Action<RazorEngineHost> hostConfig)
|
||||
{
|
||||
// Load the test files
|
||||
if (baselineName == null)
|
||||
{
|
||||
baselineName = name;
|
||||
}
|
||||
|
||||
string source = TestFile.Create(String.Format("CodeGenerator.{1}.Source.{0}.{2}", name, LanguageName, FileExtension)).ReadAllText();
|
||||
string expectedOutput = TestFile.Create(String.Format("CodeGenerator.{1}.Output.{0}.{2}", baselineName, LanguageName, BaselineExtension)).ReadAllText();
|
||||
|
||||
// Set up the host and engine
|
||||
RazorEngineHost host = CreateHost();
|
||||
host.NamespaceImports.Add("System");
|
||||
host.DesignTimeMode = designTimeMode;
|
||||
host.StaticHelpers = true;
|
||||
host.DefaultClassName = name;
|
||||
|
||||
// Add support for templates, etc.
|
||||
host.GeneratedClassContext = new GeneratedClassContext(GeneratedClassContext.DefaultExecuteMethodName,
|
||||
GeneratedClassContext.DefaultWriteMethodName,
|
||||
GeneratedClassContext.DefaultWriteLiteralMethodName,
|
||||
"WriteTo",
|
||||
"WriteLiteralTo",
|
||||
"Template",
|
||||
"DefineSection",
|
||||
"BeginContext",
|
||||
"EndContext")
|
||||
{
|
||||
LayoutPropertyName = "Layout",
|
||||
ResolveUrlMethodName = "Href"
|
||||
};
|
||||
if (hostConfig != null)
|
||||
{
|
||||
hostConfig(host);
|
||||
}
|
||||
|
||||
host.IsIndentingWithTabs = withTabs;
|
||||
|
||||
RazorTemplateEngine engine = new RazorTemplateEngine(host);
|
||||
|
||||
// Generate code for the file
|
||||
GeneratorResults results = null;
|
||||
using (StringTextBuffer buffer = new StringTextBuffer(source))
|
||||
{
|
||||
results = engine.GenerateCode(buffer, className: name, rootNamespace: TestRootNamespaceName, sourceFileName: generatePragmas ? String.Format("{0}.{1}", name, FileExtension) : null);
|
||||
}
|
||||
|
||||
// Generate code
|
||||
CodeCompileUnit ccu = results.GeneratedCode;
|
||||
CodeDomProvider codeProvider = (CodeDomProvider)Activator.CreateInstance(host.CodeLanguage.CodeDomProviderType);
|
||||
|
||||
CodeGeneratorOptions options = new CodeGeneratorOptions();
|
||||
|
||||
// Both run-time and design-time use these settings. See:
|
||||
// * $/Dev10/pu/SP_WebTools/venus/html/Razor/Impl/RazorCodeGenerator.cs:204
|
||||
// * $/Dev10/Releases/RTMRel/ndp/fx/src/xsp/System/Web/Compilation/BuildManagerHost.cs:373
|
||||
options.BlankLinesBetweenMembers = false;
|
||||
options.IndentString = String.Empty;
|
||||
|
||||
StringBuilder output = new StringBuilder();
|
||||
using (StringWriter writer = new StringWriter(output))
|
||||
{
|
||||
codeProvider.GenerateCodeFromCompileUnit(ccu, writer, options);
|
||||
}
|
||||
|
||||
WriteBaseline(String.Format(@"test\Microsoft.AspNet.Razor.Test\TestFiles\CodeGenerator\{0}\Output\{1}.{2}", LanguageName, baselineName, BaselineExtension), MiscUtils.StripRuntimeVersion(output.ToString()));
|
||||
|
||||
#if !GENERATE_BASELINES
|
||||
string textOutput = MiscUtils.StripRuntimeVersion(output.ToString());
|
||||
|
||||
//// Verify code against baseline
|
||||
Assert.Equal(expectedOutput, textOutput);
|
||||
#endif
|
||||
|
||||
IEnumerable<Span> generatedSpans = results.Document.Flatten();
|
||||
|
||||
foreach (var span in generatedSpans)
|
||||
{
|
||||
VerifyNoBrokenEndOfLines(span.Content);
|
||||
}
|
||||
|
||||
// Verify design-time pragmas
|
||||
if (designTimeMode)
|
||||
{
|
||||
if (spans != null)
|
||||
{
|
||||
Assert.Equal(spans, generatedSpans.Select(span => new TestSpan(span)).ToArray());
|
||||
}
|
||||
|
||||
if (expectedDesignTimePragmas != null)
|
||||
{
|
||||
Assert.True(results.DesignTimeLineMappings != null && results.DesignTimeLineMappings.Count > 0);
|
||||
|
||||
Assert.Equal(expectedDesignTimePragmas.Count, results.DesignTimeLineMappings.Count);
|
||||
|
||||
Assert.Equal(
|
||||
expectedDesignTimePragmas.ToArray(),
|
||||
results.DesignTimeLineMappings
|
||||
.OrderBy(p => p.Key)
|
||||
.Select(p => p.Value)
|
||||
.ToArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Conditional("GENERATE_BASELINES")]
|
||||
private void WriteBaseline(string baselineFile, string output)
|
||||
{
|
||||
string root = RecursiveFind("Runtime.sln", Path.GetFullPath("."));
|
||||
string baselinePath = Path.Combine(root, baselineFile);
|
||||
|
||||
// Update baseline
|
||||
// IMPORTANT! Replace this path with the local path on your machine to the baseline files!
|
||||
if (File.Exists(baselinePath))
|
||||
{
|
||||
File.Delete(baselinePath);
|
||||
}
|
||||
File.WriteAllText(baselinePath, output.ToString());
|
||||
}
|
||||
|
||||
private string RecursiveFind(string path, string start)
|
||||
{
|
||||
string test = Path.Combine(start, path);
|
||||
if (File.Exists(test))
|
||||
{
|
||||
return start;
|
||||
}
|
||||
else
|
||||
{
|
||||
return RecursiveFind(path, new DirectoryInfo(start).Parent.FullName);
|
||||
}
|
||||
}
|
||||
|
||||
private void VerifyNoBrokenEndOfLines(string text)
|
||||
{
|
||||
for (int i = 0; i < text.Length; i++)
|
||||
{
|
||||
if (text[i] == '\r')
|
||||
{
|
||||
Assert.True(text.Length > i + 1);
|
||||
Assert.Equal('\n', text[i + 1]);
|
||||
}
|
||||
else if (text[i] == '\n')
|
||||
{
|
||||
Assert.True(i > 0);
|
||||
Assert.Equal('\r', text[i - 1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
namespace Microsoft.AspNet.Razor.Test.Generator
|
||||
{
|
||||
[Flags]
|
||||
public enum TabTest
|
||||
{
|
||||
NoTabs = 1,
|
||||
Tabs = 2,
|
||||
Both = 3
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Test.Generator
|
||||
{
|
||||
public class TestSpan
|
||||
{
|
||||
/// <summary>
|
||||
/// Test span to simplify the generation of the actual Span in test initializer.
|
||||
/// </summary>
|
||||
/// <param name="kind">Span kind</param>
|
||||
/// <param name="start">Zero indexed start char index in the buffer.</param>
|
||||
/// <param name="end">End Column, if the text length is zero Start == End.</param>
|
||||
public TestSpan(SpanKind kind, int start, int end)
|
||||
{
|
||||
Kind = kind;
|
||||
Start = start;
|
||||
End = end;
|
||||
}
|
||||
|
||||
public TestSpan(Span span)
|
||||
: this(span.Kind,
|
||||
span.Start.AbsoluteIndex,
|
||||
span.Start.AbsoluteIndex + span.Length)
|
||||
{
|
||||
}
|
||||
|
||||
public SpanKind Kind { get; private set; }
|
||||
public int Start { get; private set; }
|
||||
public int End { get; private set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return String.Format("{0}: {1}-{2}", Kind, Start, End);
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
TestSpan other = obj as TestSpan;
|
||||
|
||||
if (other != null)
|
||||
{
|
||||
return (Kind == other.Kind) &&
|
||||
(Start == other.Start) &&
|
||||
(End == other.End);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return base.GetHashCode();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,281 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNet.Razor.Generator;
|
||||
using Microsoft.TestCommon;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Test.Generator
|
||||
{
|
||||
public class VBRazorCodeGeneratorTest : RazorCodeGeneratorTest<VBRazorCodeLanguage>
|
||||
{
|
||||
private const string TestPhysicalPath = @"C:\Bar.vbhtml";
|
||||
private const string TestVirtualPath = "~/Foo/Bar.vbhtml";
|
||||
|
||||
protected override string FileExtension
|
||||
{
|
||||
get { return "vbhtml"; }
|
||||
}
|
||||
|
||||
protected override string LanguageName
|
||||
{
|
||||
get { return "VB"; }
|
||||
}
|
||||
|
||||
protected override string BaselineExtension
|
||||
{
|
||||
get { return "vb"; }
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ConstructorRequiresNonNullClassName()
|
||||
{
|
||||
Assert.ThrowsArgumentNullOrEmptyString(() => new VBRazorCodeGenerator(null, TestRootNamespaceName, TestPhysicalPath, CreateHost()), "className");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ConstructorRequiresNonEmptyClassName()
|
||||
{
|
||||
Assert.ThrowsArgumentNullOrEmptyString(() => new VBRazorCodeGenerator(String.Empty, TestRootNamespaceName, TestPhysicalPath, CreateHost()), "className");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ConstructorRequiresNonNullRootNamespaceName()
|
||||
{
|
||||
Assert.ThrowsArgumentNull(() => new VBRazorCodeGenerator("Foo", null, TestPhysicalPath, CreateHost()), "rootNamespaceName");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ConstructorAllowsEmptyRootNamespaceName()
|
||||
{
|
||||
new VBRazorCodeGenerator("Foo", String.Empty, TestPhysicalPath, CreateHost());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ConstructorRequiresNonNullHost()
|
||||
{
|
||||
Assert.ThrowsArgumentNull(() => new VBRazorCodeGenerator("Foo", TestRootNamespaceName, TestPhysicalPath, null), "host");
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("NestedCodeBlocks")]
|
||||
[InlineData("NestedCodeBlocks")]
|
||||
[InlineData("CodeBlock")]
|
||||
[InlineData("ExplicitExpression")]
|
||||
[InlineData("MarkupInCodeBlock")]
|
||||
[InlineData("Blocks")]
|
||||
[InlineData("ImplicitExpression")]
|
||||
[InlineData("Imports")]
|
||||
[InlineData("ExpressionsInCode")]
|
||||
[InlineData("FunctionsBlock")]
|
||||
[InlineData("Options")]
|
||||
[InlineData("Templates")]
|
||||
[InlineData("RazorComments")]
|
||||
[InlineData("Sections")]
|
||||
[InlineData("EmptySection")] // this scenario causes a crash in Razor V2.0
|
||||
[InlineData("Helpers")]
|
||||
[InlineData("HelpersMissingCloseParen")]
|
||||
[InlineData("HelpersMissingOpenParen")]
|
||||
[InlineData("NestedHelpers")]
|
||||
[InlineData("LayoutDirective")]
|
||||
[InlineData("ConditionalAttributes")]
|
||||
[InlineData("ResolveUrl")]
|
||||
public void VBCodeGeneratorCorrectlyGeneratesRunTimeCode(string testName)
|
||||
{
|
||||
RunTest(testName);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VBCodeGeneratorCorrectlyGeneratesMappingsForRazorCommentsAtDesignTime()
|
||||
{
|
||||
// (4, 6) -> (?, 6) [6]
|
||||
// ( 5, 40) -> (?, 39) [2]
|
||||
// ( 8, 6) -> (?, 6) [33]
|
||||
// ( 9, 46) -> (?, 46) [3]
|
||||
// ( 12, 3) -> (?, 7) [3]
|
||||
// ( 12, 8) -> (?, 8) [1]
|
||||
RunTest("RazorComments", "RazorComments.DesignTime", designTimeMode: true, tabTest: TabTest.NoTabs, expectedDesignTimePragmas: new List<GeneratedCodeMapping>()
|
||||
{
|
||||
/* 01 */ new GeneratedCodeMapping(4, 6, 6, 6),
|
||||
/* 02 */ new GeneratedCodeMapping(5, 40, 39, 2),
|
||||
/* 03 */ new GeneratedCodeMapping(8, 6, 6, 33),
|
||||
/* 04 */ new GeneratedCodeMapping(9, 46, 46, 3),
|
||||
/* 05 */ new GeneratedCodeMapping(12, 3, 7, 1),
|
||||
/* 06 */ new GeneratedCodeMapping(12, 8, 8, 1)
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VBCodeGeneratorCorrectlyGeneratesHelperMissingNameAtDesignTime()
|
||||
{
|
||||
RunTest("HelpersMissingName", designTimeMode: true);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VBCodeGeneratorCorrectlyGeneratesImportStatementsAtDesignTimeButCannotWrapPragmasAroundImportStatement()
|
||||
{
|
||||
RunTest("Imports", "Imports.DesignTime", designTimeMode: true, tabTest: TabTest.NoTabs, expectedDesignTimePragmas: new List<GeneratedCodeMapping>()
|
||||
{
|
||||
/* 01 */ new GeneratedCodeMapping(1, 2, 1, 19),
|
||||
/* 02 */ new GeneratedCodeMapping(2, 2, 1, 36),
|
||||
/* 03 */ new GeneratedCodeMapping(3, 2, 1, 16),
|
||||
/* 04 */ new GeneratedCodeMapping(5, 30, 30, 22),
|
||||
/* 05 */ new GeneratedCodeMapping(6, 36, 36, 21),
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VBCodeGeneratorCorrectlyGeneratesFunctionsBlocksAtDesignTime()
|
||||
{
|
||||
RunTest("FunctionsBlock", "FunctionsBlock.DesignTime", designTimeMode: true, tabTest: TabTest.NoTabs, expectedDesignTimePragmas: new List<GeneratedCodeMapping>()
|
||||
{
|
||||
/* 01 */ new GeneratedCodeMapping(1, 11, 11, 4),
|
||||
/* 02 */ new GeneratedCodeMapping(5, 11, 11, 129),
|
||||
/* 03 */ new GeneratedCodeMapping(12, 26, 26, 11)
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VBCodeGeneratorCorrectlyGeneratesFunctionsBlocksAtDesignTimeTabs()
|
||||
{
|
||||
RunTest("FunctionsBlock", "FunctionsBlock.DesignTime.Tabs", designTimeMode: true, tabTest: TabTest.Tabs, expectedDesignTimePragmas: new List<GeneratedCodeMapping>()
|
||||
{
|
||||
/* 01 */ new GeneratedCodeMapping(1, 11, 5, 4),
|
||||
/* 02 */ new GeneratedCodeMapping(5, 11, 5, 129),
|
||||
/* 03 */ new GeneratedCodeMapping(12, 26, 14, 11)
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VBCodeGeneratorGeneratesCodeWithParserErrorsInDesignTimeMode()
|
||||
{
|
||||
RunTest("ParserError", designTimeMode: true, tabTest: TabTest.NoTabs, expectedDesignTimePragmas: new List<GeneratedCodeMapping>()
|
||||
{
|
||||
/* 01 */ new GeneratedCodeMapping(1, 6, 6, 16)
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VBCodeGeneratorCorrectlyGeneratesInheritsAtRuntime()
|
||||
{
|
||||
RunTest("Inherits", baselineName: "Inherits.Runtime");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VBCodeGeneratorCorrectlyGeneratesInheritsAtDesigntime()
|
||||
{
|
||||
RunTest("Inherits", baselineName: "Inherits.Designtime", designTimeMode: true, expectedDesignTimePragmas: new List<GeneratedCodeMapping>()
|
||||
{
|
||||
/* 01 */ new GeneratedCodeMapping(1, 11, 25, 27)
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VBCodeGeneratorCorrectlyGeneratesDesignTimePragmasForUnfinishedExpressionsInCode()
|
||||
{
|
||||
RunTest("UnfinishedExpressionInCode", designTimeMode: true, tabTest: TabTest.NoTabs, expectedDesignTimePragmas: new List<GeneratedCodeMapping>()
|
||||
{
|
||||
/* 01 */ new GeneratedCodeMapping(1, 6, 6, 2),
|
||||
/* 02 */ new GeneratedCodeMapping(2, 2, 7, 9),
|
||||
/* 03 */ new GeneratedCodeMapping(2, 11, 11, 2)
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VBCodeGeneratorCorrectlyGeneratesDesignTimePragmasMarkupAndExpressions()
|
||||
{
|
||||
RunTest("DesignTime", designTimeMode: true, tabTest: TabTest.NoTabs, expectedDesignTimePragmas: new List<GeneratedCodeMapping>()
|
||||
{
|
||||
/* 01 */ new GeneratedCodeMapping(2, 14, 13, 17),
|
||||
/* 02 */ new GeneratedCodeMapping(3, 20, 20, 1),
|
||||
/* 03 */ new GeneratedCodeMapping(3, 25, 25, 20),
|
||||
/* 04 */ new GeneratedCodeMapping(8, 3, 7, 12),
|
||||
/* 05 */ new GeneratedCodeMapping(9, 2, 7, 4),
|
||||
/* 06 */ new GeneratedCodeMapping(9, 16, 16, 3),
|
||||
/* 07 */ new GeneratedCodeMapping(9, 27, 27, 1),
|
||||
/* 08 */ new GeneratedCodeMapping(14, 6, 7, 3),
|
||||
/* 09 */ new GeneratedCodeMapping(17, 9, 24, 5),
|
||||
/* 10 */ new GeneratedCodeMapping(17, 14, 14, 28),
|
||||
/* 11 */ new GeneratedCodeMapping(19, 20, 20, 14)
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VBCodeGeneratorCorrectlyGeneratesDesignTimePragmasForImplicitExpressionStartedAtEOF()
|
||||
{
|
||||
RunTest("ImplicitExpressionAtEOF", designTimeMode: true, expectedDesignTimePragmas: new List<GeneratedCodeMapping>()
|
||||
{
|
||||
/* 01 */ new GeneratedCodeMapping(3, 2, 7, 0)
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VBCodeGeneratorCorrectlyGeneratesDesignTimePragmasForExplicitExpressionStartedAtEOF()
|
||||
{
|
||||
RunTest("ExplicitExpressionAtEOF", designTimeMode: true, expectedDesignTimePragmas: new List<GeneratedCodeMapping>()
|
||||
{
|
||||
/* 01 */ new GeneratedCodeMapping(3, 3, 7, 0)
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VBCodeGeneratorCorrectlyGeneratesDesignTimePragmasForCodeBlockStartedAtEOF()
|
||||
{
|
||||
RunTest("CodeBlockAtEOF", designTimeMode: true, tabTest: TabTest.NoTabs, expectedDesignTimePragmas: new List<GeneratedCodeMapping>()
|
||||
{
|
||||
/* 01 */ new GeneratedCodeMapping(3, 6, 6, 0)
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VBCodeGeneratorCorrectlyGeneratesDesignTimePragmasForEmptyImplicitExpression()
|
||||
{
|
||||
RunTest("EmptyImplicitExpression", designTimeMode: true, expectedDesignTimePragmas: new List<GeneratedCodeMapping>()
|
||||
{
|
||||
/* 01 */ new GeneratedCodeMapping(3, 2, 7, 0)
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VBCodeGeneratorCorrectlyGeneratesDesignTimePragmasForEmptyImplicitExpressionInCode()
|
||||
{
|
||||
RunTest("EmptyImplicitExpressionInCode", designTimeMode: true, tabTest: TabTest.NoTabs, expectedDesignTimePragmas: new List<GeneratedCodeMapping>()
|
||||
{
|
||||
/* 01 */ new GeneratedCodeMapping(1, 6, 6, 6),
|
||||
/* 02 */ new GeneratedCodeMapping(2, 6, 7, 0),
|
||||
/* 03 */ new GeneratedCodeMapping(2, 6, 6, 2)
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VBCodeGeneratorCorrectlyGeneratesDesignTimePragmasForEmptyExplicitExpression()
|
||||
{
|
||||
RunTest("EmptyExplicitExpression", designTimeMode: true, expectedDesignTimePragmas: new List<GeneratedCodeMapping>()
|
||||
{
|
||||
/* 01 */ new GeneratedCodeMapping(3, 3, 7, 0)
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VBCodeGeneratorDoesNotRenderLinePragmasIfGenerateLinePragmasIsSetToFalse()
|
||||
{
|
||||
RunTest("NoLinePragmas", generatePragmas: false);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VBCodeGeneratorRendersHelpersBlockCorrectlyWhenInstanceHelperRequested()
|
||||
{
|
||||
RunTest("Helpers", baselineName: "Helpers.Instance", hostConfig: h => h.StaticHelpers = false);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VBCodeGeneratorCorrectlyInstrumentsRazorCodeWhenInstrumentationRequested()
|
||||
{
|
||||
RunTest("Instrumented", hostConfig: host =>
|
||||
{
|
||||
host.EnableInstrumentation = true;
|
||||
host.InstrumentedSourceFilePath = String.Format("~/{0}.vbhtml", host.DefaultClassName);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,468 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<ProjectGuid>{0BB62A1D-E6B5-49FA-9E3C-6AF679A66DFE}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Microsoft.AspNet.Razor.Test</RootNamespace>
|
||||
<AssemblyName>Microsoft.AspNet.Razor.Test</AssemblyName>
|
||||
<OutputPath>..\..\bin\$(Configuration)\Test\</OutputPath>
|
||||
<NoWarn>0618</NoWarn>
|
||||
<TargetFrameworkVersion>v4.5.1</TargetFrameworkVersion>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)' == 'Debug'">
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="Moq, Version=4.0.10827.0, Culture=neutral, PublicKeyToken=69f491c39445e920, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\packages\Moq.4.0.10827\lib\NET40\Moq.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core">
|
||||
<RequiredTargetFramework>3.5</RequiredTargetFramework>
|
||||
</Reference>
|
||||
<Reference Include="xunit, Version=1.9.1.1600, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\packages\xunit.1.9.1\lib\net20\xunit.dll</HintPath>
|
||||
<Aliases>unused</Aliases>
|
||||
</Reference>
|
||||
<Reference Include="xunit.extensions, Version=1.9.1.1600, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\packages\xunit.extensions.1.9.1\lib\net20\xunit.extensions.dll</HintPath>
|
||||
<Aliases>unused</Aliases>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="CodeCompileUnitExtensions.cs" />
|
||||
<Compile Include="Framework\BlockExtensions.cs" />
|
||||
<Compile Include="Framework\BlockTypes.cs" />
|
||||
<Compile Include="Framework\CodeParserTestBase.cs" />
|
||||
<Compile Include="Framework\CsHtmlCodeParserTestBase.cs" />
|
||||
<Compile Include="Framework\CsHtmlMarkupParserTestBase.cs" />
|
||||
<Compile Include="Framework\ErrorCollector.cs" />
|
||||
<Compile Include="Framework\MarkupParserTestBase.cs" />
|
||||
<Compile Include="Framework\ParserTestBase.cs" />
|
||||
<Compile Include="Framework\RawTextSymbol.cs" />
|
||||
<Compile Include="Framework\TestSpanBuilder.cs" />
|
||||
<Compile Include="Framework\VBHtmlCodeParserTestBase.cs" />
|
||||
<Compile Include="Framework\VBHtmlMarkupParserTestBase.cs" />
|
||||
<Compile Include="Generator\GeneratedCodeMappingTest.cs" />
|
||||
<Compile Include="Generator\PaddingTest.cs" />
|
||||
<Compile Include="Generator\TabTest.cs" />
|
||||
<Compile Include="Generator\TestSpan.cs" />
|
||||
<Compile Include="Parser\CSharp\CSharpAutoCompleteTest.cs" />
|
||||
<Compile Include="Parser\CSharp\CSharpDirectivesTest.cs" />
|
||||
<Compile Include="Parser\CSharp\CSharpLayoutDirectiveTest.cs" />
|
||||
<Compile Include="Parser\CSharp\CSharpNestedStatementsTest.cs" />
|
||||
<Compile Include="Parser\CSharp\CSharpRazorCommentsTest.cs" />
|
||||
<Compile Include="Parser\CSharp\CSharpStatementTest.cs" />
|
||||
<Compile Include="Parser\CSharp\CSharpTemplateTest.cs" />
|
||||
<Compile Include="Parser\CSharp\CSharpToMarkupSwitchTest.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Parser\CSharp\CSharpVerbatimBlockTest.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Parser\CSharp\CSharpWhitespaceHandlingTest.cs" />
|
||||
<Compile Include="Parser\CSharp\CsHtmlDocumentTest.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Parser\Html\HtmlAttributeTest.cs" />
|
||||
<Compile Include="Parser\Html\HtmlUrlAttributeTest.cs" />
|
||||
<Compile Include="Parser\ParserVisitorExtensionsTest.cs" />
|
||||
<Compile Include="Parser\VB\VBRazorCommentsTest.cs" />
|
||||
<Compile Include="Parser\VB\VBLayoutDirectiveTest.cs" />
|
||||
<Compile Include="Parser\VB\VBAutoCompleteTest.cs" />
|
||||
<Compile Include="Parser\Html\HtmlTagsTest.cs" />
|
||||
<Compile Include="Parser\VB\VBContinueStatementTest.cs" />
|
||||
<Compile Include="Parser\VB\VBDirectiveTest.cs" />
|
||||
<Compile Include="Parser\VB\VBExitStatementTest.cs" />
|
||||
<Compile Include="Parser\VB\VBExplicitExpressionTest.cs" />
|
||||
<Compile Include="Parser\VB\VBImplicitExpressionTest.cs" />
|
||||
<Compile Include="Parser\VB\VBReservedWordsTest.cs" />
|
||||
<Compile Include="Parser\CSharp\CSharpReservedWordsTest.cs" />
|
||||
<Compile Include="Parser\PartialParsing\VBPartialParsingTest.cs" />
|
||||
<Compile Include="Parser\PartialParsing\CSharpPartialParsingTest.cs" />
|
||||
<Compile Include="Parser\VB\VBHelperTest.cs" />
|
||||
<Compile Include="Parser\CSharp\CSharpHelperTest.cs" />
|
||||
<Compile Include="Generator\RazorCodeGeneratorTest.cs" />
|
||||
<Compile Include="Parser\PartialParsing\PartialParsingTestBase.cs" />
|
||||
<Compile Include="Parser\VB\VBNestedStatementsTest.cs" />
|
||||
<Compile Include="Parser\VB\VBStatementTest.cs" />
|
||||
<Compile Include="Parser\WhitespaceRewriterTest.cs" />
|
||||
<Compile Include="RazorCodeLanguageTest.cs" />
|
||||
<Compile Include="Parser\VB\VBHtmlDocumentTest.cs" />
|
||||
<Compile Include="Parser\VB\VBErrorTest.cs" />
|
||||
<Compile Include="Parser\VB\VBSectionTest.cs" />
|
||||
<Compile Include="Parser\VB\VBTemplateTest.cs" />
|
||||
<Compile Include="Parser\VB\VBExpressionsInCodeTest.cs" />
|
||||
<Compile Include="Parser\VB\VBSpecialKeywordsTest.cs" />
|
||||
<Compile Include="Parser\VB\VBBlockTest.cs" />
|
||||
<Compile Include="Parser\VB\VBToMarkupSwitchTest.cs" />
|
||||
<Compile Include="Editor\RazorEditorParserTest.cs" />
|
||||
<Compile Include="RazorDirectiveAttributeTest.cs" />
|
||||
<Compile Include="RazorEngineHostTest.cs" />
|
||||
<Compile Include="RazorTemplateEngineTest.cs" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Output\Blocks.cs" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Output\CodeBlock.cs" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Output\CodeBlockAtEOF.cs" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Output\Comments.cs" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Output\ConditionalAttributes.cs" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Output\DesignTime.cs" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Output\EmptyCodeBlock.cs" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Output\EmptyExplicitExpression.cs" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Output\EmptyImplicitExpression.cs" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Output\EmptyImplicitExpressionInCode.cs" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Output\ExplicitExpression.cs" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Output\ExplicitExpressionAtEOF.cs" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Output\ExpressionsInCode.cs" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Output\FunctionsBlock.cs" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Output\FunctionsBlock.DesignTime.cs" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Output\Helpers.cs" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Output\Helpers.Instance.cs" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Output\HelpersMissingCloseParen.cs" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Output\HelpersMissingName.cs" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Output\HelpersMissingOpenBrace.cs" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Output\HelpersMissingOpenParen.cs" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Output\HiddenSpansInCode.cs" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Output\ImplicitExpression.cs" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Output\ImplicitExpressionAtEOF.cs" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Output\Imports.cs" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Output\Imports.DesignTime.cs" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Output\Inherits.Designtime.cs" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Output\Inherits.Runtime.cs" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Output\InlineBlocks.cs" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Output\Instrumented.cs" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Output\LayoutDirective.cs" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Output\MarkupInCodeBlock.cs" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Output\NestedCodeBlocks.cs" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Output\NestedHelpers.cs" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Output\NoLinePragmas.cs" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Output\ParserError.cs" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Output\RazorComments.cs" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Output\ResolveUrl.cs" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Output\Sections.cs" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Output\Templates.cs" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Output\UnfinishedExpressionInCode.cs" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Output\RazorComments.DesignTime.cs" />
|
||||
<Compile Include="StringTextBuffer.cs" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Output\OpenedIf.DesignTime.cs" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Output\OpenedIf.DesignTime.Tabs.cs" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Output\UnfinishedExpressionInCode.Tabs.cs" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Output\EmptyImplicitExpressionInCode.Tabs.cs" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Output\DesignTime.Tabs.cs" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Output\FunctionsBlock.DesignTime.Tabs.cs" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Output\FunctionsBlock_Tabs.cs" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Output\FunctionsBlockMinimal.DesignTime.Tabs.cs" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Output\SimpleUnspacedIf.DesignTime.Tabs.cs" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Output\HtmlCommentWithQuote_Single.cs" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Output\HtmlCommentWithQuote_Double.cs" />
|
||||
<Compile Include="Text\LineTrackingStringBufferTest.cs" />
|
||||
<Compile Include="Tokenizer\VBTokenizerLiteralTest.cs" />
|
||||
<Compile Include="Tokenizer\VBTokenizerIdentifierTest.cs" />
|
||||
<Compile Include="Tokenizer\VBTokenizerCommentTest.cs" />
|
||||
<Compile Include="Tokenizer\VBTokenizerOperatorsTest.cs" />
|
||||
<Compile Include="Tokenizer\VBTokenizerTestBase.cs" />
|
||||
<Compile Include="Tokenizer\VBTokenizerTest.cs" />
|
||||
<Compile Include="Tokenizer\CSharpTokenizerCommentTest.cs" />
|
||||
<Compile Include="Tokenizer\CSharpTokenizerLiteralTest.cs" />
|
||||
<Compile Include="Tokenizer\CSharpTokenizerIdentifierTest.cs" />
|
||||
<Compile Include="Tokenizer\CSharpTokenizerOperatorsTest.cs" />
|
||||
<Compile Include="Tokenizer\CSharpTokenizerTestBase.cs" />
|
||||
<Compile Include="Tokenizer\CSharpTokenizerTest.cs" />
|
||||
<Compile Include="Tokenizer\TokenizerLookaheadTest.cs" />
|
||||
<Compile Include="Tokenizer\HtmlTokenizerTest.cs" />
|
||||
<Compile Include="Tokenizer\HtmlTokenizerTestBase.cs" />
|
||||
<Compile Include="Tokenizer\TokenizerTestBase.cs" />
|
||||
<Compile Include="Utils\MiscUtils.cs" />
|
||||
<Compile Include="Generator\VBRazorCodeGeneratorTest.cs" />
|
||||
<Compile Include="Generator\CSharpRazorCodeGeneratorTest.cs" />
|
||||
<Compile Include="CSharpRazorCodeLanguageTest.cs" />
|
||||
<Compile Include="Parser\CallbackParserListenerTest.cs" />
|
||||
<Compile Include="Parser\CSharp\CSharpExplicitExpressionTest.cs" />
|
||||
<Compile Include="Parser\CSharp\CSharpSectionTest.cs" />
|
||||
<Compile Include="Parser\BlockTest.cs" />
|
||||
<Compile Include="Parser\VB\VBExpressionTest.cs" />
|
||||
<Compile Include="Text\BufferingTextReaderTest.cs" />
|
||||
<Compile Include="Parser\CSharp\CSharpErrorTest.cs" />
|
||||
<Compile Include="Parser\CSharp\CSharpImplicitExpressionTest.cs" />
|
||||
<Compile Include="Parser\CSharp\CSharpSpecialBlockTest.cs" />
|
||||
<Compile Include="Parser\Html\HtmlBlockTest.cs" />
|
||||
<Compile Include="Parser\CSharp\CSharpBlockTest.cs" />
|
||||
<Compile Include="Text\LookaheadTextReaderTestBase.cs" />
|
||||
<Compile Include="Text\SourceLocationTrackerTest.cs" />
|
||||
<Compile Include="Text\TextBufferReaderTest.cs" />
|
||||
<Compile Include="Utils\DisposableActionTest.cs" />
|
||||
<Compile Include="Parser\Html\HtmlDocumentTest.cs" />
|
||||
<Compile Include="Parser\ParserContextTest.cs" />
|
||||
<Compile Include="Parser\Html\HtmlErrorTest.cs" />
|
||||
<Compile Include="Parser\Html\HtmlParserTestUtils.cs" />
|
||||
<Compile Include="Parser\Html\HtmlToCodeSwitchTest.cs" />
|
||||
<Compile Include="Parser\RazorParserTest.cs" />
|
||||
<Compile Include="Text\SourceLocationTest.cs" />
|
||||
<Compile Include="Utils\SpanAssert.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="VBRazorCodeLanguageTest.cs" />
|
||||
<Compile Include="Text\TextChangeTest.cs" />
|
||||
<Compile Include="Text\TextReaderExtensionsTest.cs" />
|
||||
<Compile Include="Utils\EnumerableUtils.cs" />
|
||||
<Compile Include="Utils\MiscAssert.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\Microsoft.AspNet.Razor\Microsoft.AspNet.Razor.csproj">
|
||||
<Project>{e75d8296-3ba6-4e67-afeb-90ff77460b15}</Project>
|
||||
<Name>Microsoft.AspNet.Razor</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Microsoft.TestCommon\Microsoft.TestCommon.csproj">
|
||||
<Project>{FCCC4CB7-BAF7-4A57-9F89-E5766FE536C0}</Project>
|
||||
<Name>Microsoft.TestCommon</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="TestFiles\nested-1000.html" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Service Include="{508349B6-6B84-4DF5-91F0-309BEEBAD82D}" />
|
||||
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\VB\Source\CodeBlock.vbhtml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\VB\Source\ExplicitExpression.vbhtml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\VB\Source\MarkupInCodeBlock.vbhtml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\VB\Source\Blocks.vbhtml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\VB\Source\ImplicitExpression.vbhtml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\VB\Source\NoLinePragmas.vbhtml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\VB\Source\Imports.vbhtml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\VB\Source\ExpressionsInCode.vbhtml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\VB\Source\FunctionsBlock.vbhtml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\VB\Source\Options.vbhtml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\VB\Source\Templates.vbhtml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\VB\Source\Sections.vbhtml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\VB\Source\DesignTime.vbhtml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Source\Templates.cshtml" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Source\Blocks.cshtml" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Source\CodeBlock.cshtml" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Source\NoLinePragmas.cshtml" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Source\ExplicitExpression.cshtml" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Source\ImplicitExpression.cshtml" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Source\Imports.cshtml" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Source\MarkupInCodeBlock.cshtml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Source\DesignTime.cshtml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Source\ExpressionsInCode.cshtml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Source\FunctionsBlock.cshtml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Source\Sections.cshtml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Source\Inherits.cshtml" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\VB\Source\Inherits.vbhtml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Source\NestedHelpers.cshtml" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\VB\Source\NestedHelpers.vbhtml" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Source\Instrumented.cshtml" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\VB\Source\Instrumented.vbhtml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Source\RazorComments.cshtml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\VB\Source\RazorComments.vbhtml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Source\ParserError.cshtml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\VB\Source\ParserError.vbhtml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Source\ImplicitExpressionAtEOF.cshtml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Source\CodeBlockAtEOF.cshtml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Source\ExplicitExpressionAtEOF.cshtml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Source\EmptyCodeBlock.cshtml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Source\EmptyExplicitExpression.cshtml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Source\EmptyImplicitExpression.cshtml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\VB\Source\CodeBlockAtEOF.vbhtml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\VB\Source\EmptyExplicitExpression.vbhtml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\VB\Source\EmptyImplicitExpression.vbhtml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\VB\Source\ExplicitExpressionAtEOF.vbhtml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\VB\Source\ImplicitExpressionAtEOF.vbhtml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Source\UnfinishedExpressionInCode.cshtml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\VB\Source\UnfinishedExpressionInCode.vbhtml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="TestFiles\DesignTime\Simple.cshtml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="TestFiles\DesignTime\Simple.txt" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Source\Helpers.cshtml" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Source\HelpersMissingCloseParen.cshtml" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Source\HelpersMissingName.cshtml" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Source\HelpersMissingOpenBrace.cshtml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Source\HelpersMissingOpenParen.cshtml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\VB\Source\HelpersMissingOpenParen.vbhtml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\VB\Source\Helpers.vbhtml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\VB\Source\HelpersMissingCloseParen.vbhtml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\VB\Source\HelpersMissingName.vbhtml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Source\NestedCodeBlocks.cshtml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\VB\Source\NestedCodeBlocks.vbhtml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Source\InlineBlocks.cshtml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Source\EmptyImplicitExpressionInCode.cshtml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\VB\Source\EmptyImplicitExpressionInCode.vbhtml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Source\HiddenSpansInCode.cshtml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Source\ResolveUrl.cshtml" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\VB\Source\ResolveUrl.vbhtml" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Source\LayoutDirective.cshtml" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\VB\Source\LayoutDirective.vbhtml" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Source\ConditionalAttributes.cshtml" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\VB\Source\ConditionalAttributes.vbhtml" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\VB\Source\EmptySection.vbhtml" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Source\OpenedIf.cshtml" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Source\FunctionsBlock_Tabs.cshtml" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Source\FunctionsBlockMinimal.cshtml" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Source\SimpleUnspacedIf.cshtml" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Source\HtmlCommentWithQuote_Double.cshtml" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\CS\Source\HtmlCommentWithQuote_Single.cshtml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\VB\Output\Blocks.vb" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\VB\Output\CodeBlock.vb" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\VB\Output\CodeBlockAtEOF.vb" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\VB\Output\Comments.vb" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\VB\Output\ConditionalAttributes.vb" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\VB\Output\DesignTime.vb" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\VB\Output\EmptyExplicitExpression.vb" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\VB\Output\EmptyImplicitExpression.vb" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\VB\Output\EmptyImplicitExpressionInCode.vb" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\VB\Output\ExplicitExpression.vb" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\VB\Output\ExplicitExpressionAtEOF.vb" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\VB\Output\ExpressionsInCode.vb" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\VB\Output\FunctionsBlock.DesignTime.vb" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\VB\Output\FunctionsBlock.vb" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\VB\Output\Helpers.Instance.vb" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\VB\Output\Helpers.vb" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\VB\Output\HelpersMissingCloseParen.vb" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\VB\Output\HelpersMissingName.vb" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\VB\Output\HelpersMissingOpenParen.vb" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\VB\Output\ImplicitExpression.vb" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\VB\Output\ImplicitExpressionAtEOF.vb" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\VB\Output\Imports.DesignTime.vb" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\VB\Output\Imports.vb" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\VB\Output\Inherits.Designtime.vb" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\VB\Output\Inherits.Runtime.vb" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\VB\Output\Instrumented.vb" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\VB\Output\LayoutDirective.vb" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\VB\Output\MarkupInCodeBlock.vb" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\VB\Output\NestedCodeBlocks.vb" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\VB\Output\NestedHelpers.vb" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\VB\Output\NoLinePragmas.vb" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\VB\Output\Options.vb" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\VB\Output\ParserError.vb" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\VB\Output\RazorComments.vb" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\VB\Output\ResolveUrl.vb" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\VB\Output\Sections.vb" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\VB\Output\Templates.vb" />
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\VB\Output\UnfinishedExpressionInCode.vb" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\VB\Output\RazorComments.DesignTime.vb" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="Properties\" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\VB\Output\EmptySection.vb" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="TestFiles\CodeGenerator\VB\Output\FunctionsBlock.DesignTime.Tabs.vb" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,124 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using System.Linq;
|
||||
using Microsoft.AspNet.Razor.Generator;
|
||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||
using Microsoft.AspNet.Razor.Test.Framework;
|
||||
using Microsoft.AspNet.Razor.Text;
|
||||
using System.Web.WebPages.TestUtils;
|
||||
using Microsoft.TestCommon;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Test.Parser
|
||||
{
|
||||
public class BlockTest
|
||||
{
|
||||
[Fact]
|
||||
public void ConstructorWithBlockBuilderSetsParent()
|
||||
{
|
||||
// Arrange
|
||||
BlockBuilder builder = new BlockBuilder() { Type = BlockType.Comment };
|
||||
Span span = new SpanBuilder() { Kind = SpanKind.Code }.Build();
|
||||
builder.Children.Add(span);
|
||||
|
||||
// Act
|
||||
Block block = builder.Build();
|
||||
|
||||
// Assert
|
||||
Assert.Same(block, span.Parent);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ConstructorCopiesBasicValuesFromBlockBuilder()
|
||||
{
|
||||
// Arrange
|
||||
BlockBuilder builder = new BlockBuilder()
|
||||
{
|
||||
Name = "Foo",
|
||||
Type = BlockType.Helper
|
||||
};
|
||||
|
||||
// Act
|
||||
Block actual = builder.Build();
|
||||
|
||||
// Assert
|
||||
Assert.Equal("Foo", actual.Name);
|
||||
Assert.Equal(BlockType.Helper, actual.Type);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ConstructorTransfersInstanceOfCodeGeneratorFromBlockBuilder()
|
||||
{
|
||||
// Arrange
|
||||
IBlockCodeGenerator expected = new ExpressionCodeGenerator();
|
||||
BlockBuilder builder = new BlockBuilder()
|
||||
{
|
||||
Type = BlockType.Helper,
|
||||
CodeGenerator = expected
|
||||
};
|
||||
|
||||
// Act
|
||||
Block actual = builder.Build();
|
||||
|
||||
// Assert
|
||||
Assert.Same(expected, actual.CodeGenerator);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ConstructorTransfersChildrenFromBlockBuilder()
|
||||
{
|
||||
// Arrange
|
||||
Span expected = new SpanBuilder() { Kind = SpanKind.Code }.Build();
|
||||
BlockBuilder builder = new BlockBuilder()
|
||||
{
|
||||
Type = BlockType.Functions
|
||||
};
|
||||
builder.Children.Add(expected);
|
||||
|
||||
// Act
|
||||
Block block = builder.Build();
|
||||
|
||||
// Assert
|
||||
Assert.Same(expected, block.Children.Single());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void LocateOwnerReturnsNullIfNoSpanReturnsTrueForOwnsSpan()
|
||||
{
|
||||
// Arrange
|
||||
var factory = SpanFactory.CreateCsHtml();
|
||||
Block block = new MarkupBlock(
|
||||
factory.Markup("Foo "),
|
||||
new StatementBlock(
|
||||
factory.CodeTransition(),
|
||||
factory.Code("bar").AsStatement()),
|
||||
factory.Markup(" Baz"));
|
||||
TextChange change = new TextChange(128, 1, new StringTextBuffer("Foo @bar Baz"), 1, new StringTextBuffer("Foo @bor Baz"));
|
||||
|
||||
// Act
|
||||
Span actual = block.LocateOwner(change);
|
||||
|
||||
// Assert
|
||||
Assert.Null(actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void LocateOwnerReturnsNullIfChangeCrossesMultipleSpans()
|
||||
{
|
||||
// Arrange
|
||||
var factory = SpanFactory.CreateCsHtml();
|
||||
Block block = new MarkupBlock(
|
||||
factory.Markup("Foo "),
|
||||
new StatementBlock(
|
||||
factory.CodeTransition(),
|
||||
factory.Code("bar").AsStatement()),
|
||||
factory.Markup(" Baz"));
|
||||
TextChange change = new TextChange(4, 10, new StringTextBuffer("Foo @bar Baz"), 10, new StringTextBuffer("Foo @bor Baz"));
|
||||
|
||||
// Act
|
||||
Span actual = block.LocateOwner(change);
|
||||
|
||||
// Assert
|
||||
Assert.Null(actual);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,175 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.AspNet.Razor.Generator;
|
||||
using Microsoft.AspNet.Razor.Parser;
|
||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||
using Microsoft.AspNet.Razor.Resources;
|
||||
using Microsoft.AspNet.Razor.Test.Framework;
|
||||
using Microsoft.AspNet.Razor.Text;
|
||||
using Microsoft.AspNet.Razor.Tokenizer.Symbols;
|
||||
using Microsoft.TestCommon;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Test.Parser.CSharp
|
||||
{
|
||||
public class CSharpAutoCompleteTest : CsHtmlCodeParserTestBase
|
||||
{
|
||||
[Fact]
|
||||
public void FunctionsDirectiveAutoCompleteAtEOF()
|
||||
{
|
||||
ParseBlockTest("@functions{",
|
||||
new FunctionsBlock(
|
||||
Factory.CodeTransition("@")
|
||||
.Accepts(AcceptedCharacters.None),
|
||||
Factory.MetaCode("functions{")
|
||||
.Accepts(AcceptedCharacters.None),
|
||||
Factory.EmptyCSharp()
|
||||
.AsFunctionsBody()
|
||||
.With(new AutoCompleteEditHandler(CSharpLanguageCharacteristics.Instance.TokenizeString)
|
||||
{
|
||||
AutoCompleteString = "}"
|
||||
})),
|
||||
new RazorError(String.Format(RazorResources.ParseError_Expected_EndOfBlock_Before_EOF, "functions", "}", "{"),
|
||||
1, 0, 1));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void HelperDirectiveAutoCompleteAtEOF()
|
||||
{
|
||||
ParseBlockTest("@helper Strong(string value) {",
|
||||
new HelperBlock(new HelperCodeGenerator(new LocationTagged<string>("Strong(string value) {", 8, 0, 8), headerComplete: true),
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("helper ")
|
||||
.Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("Strong(string value) {")
|
||||
.Hidden()
|
||||
.Accepts(AcceptedCharacters.None),
|
||||
new StatementBlock(
|
||||
Factory.EmptyCSharp()
|
||||
.AsStatement()
|
||||
.With(new AutoCompleteEditHandler(CSharpLanguageCharacteristics.Instance.TokenizeString) { AutoCompleteString = "}" })
|
||||
)
|
||||
),
|
||||
new RazorError(String.Format(RazorResources.ParseError_Expected_EndOfBlock_Before_EOF, "helper", "}", "{"),
|
||||
1, 0, 1));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SectionDirectiveAutoCompleteAtEOF()
|
||||
{
|
||||
ParseBlockTest("@section Header {",
|
||||
new SectionBlock(new SectionCodeGenerator("Header"),
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("section Header {")
|
||||
.AutoCompleteWith("}", atEndOfSpan: true)
|
||||
.Accepts(AcceptedCharacters.Any),
|
||||
new MarkupBlock()),
|
||||
new RazorError(
|
||||
String.Format(RazorResources.ParseError_Expected_X, "}"),
|
||||
17, 0, 17));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VerbatimBlockAutoCompleteAtEOF()
|
||||
{
|
||||
ParseBlockTest("@{",
|
||||
new StatementBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("{").Accepts(AcceptedCharacters.None),
|
||||
Factory.EmptyCSharp()
|
||||
.AsStatement()
|
||||
.With(new AutoCompleteEditHandler(CSharpLanguageCharacteristics.Instance.TokenizeString) { AutoCompleteString = "}" })
|
||||
),
|
||||
new RazorError(String.Format(RazorResources.ParseError_Expected_EndOfBlock_Before_EOF, RazorResources.BlockName_Code, "}", "{"),
|
||||
1, 0, 1));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FunctionsDirectiveAutoCompleteAtStartOfFile()
|
||||
{
|
||||
ParseBlockTest("@functions{" + Environment.NewLine
|
||||
+ "foo",
|
||||
new FunctionsBlock(
|
||||
Factory.CodeTransition("@")
|
||||
.Accepts(AcceptedCharacters.None),
|
||||
Factory.MetaCode("functions{")
|
||||
.Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("\r\nfoo")
|
||||
.AsFunctionsBody()
|
||||
.With(new AutoCompleteEditHandler(CSharpLanguageCharacteristics.Instance.TokenizeString)
|
||||
{
|
||||
AutoCompleteString = "}"
|
||||
})),
|
||||
new RazorError(String.Format(RazorResources.ParseError_Expected_EndOfBlock_Before_EOF, "functions", "}", "{"),
|
||||
1, 0, 1));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void HelperDirectiveAutoCompleteAtStartOfFile()
|
||||
{
|
||||
ParseBlockTest("@helper Strong(string value) {" + Environment.NewLine
|
||||
+ "<p></p>",
|
||||
new HelperBlock(new HelperCodeGenerator(new LocationTagged<string>("Strong(string value) {", 8, 0, 8), headerComplete: true),
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("helper ")
|
||||
.Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("Strong(string value) {")
|
||||
.Hidden()
|
||||
.Accepts(AcceptedCharacters.None),
|
||||
new StatementBlock(
|
||||
Factory.Code("\r\n")
|
||||
.AsStatement()
|
||||
.With(new AutoCompleteEditHandler(CSharpLanguageCharacteristics.Instance.TokenizeString) { AutoCompleteString = "}" }),
|
||||
new MarkupBlock(
|
||||
Factory.Markup(@"<p></p>")
|
||||
.With(new MarkupCodeGenerator())
|
||||
.Accepts(AcceptedCharacters.None)
|
||||
),
|
||||
Factory.Span(SpanKind.Code, new CSharpSymbol(Factory.LocationTracker.CurrentLocation, String.Empty, CSharpSymbolType.Unknown))
|
||||
.With(new StatementCodeGenerator())
|
||||
)
|
||||
),
|
||||
new RazorError(String.Format(RazorResources.ParseError_Expected_EndOfBlock_Before_EOF, "helper", "}", "{"),
|
||||
1, 0, 1));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SectionDirectiveAutoCompleteAtStartOfFile()
|
||||
{
|
||||
ParseBlockTest("@section Header {" + Environment.NewLine
|
||||
+ "<p>Foo</p>",
|
||||
new SectionBlock(new SectionCodeGenerator("Header"),
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("section Header {")
|
||||
.AutoCompleteWith("}", atEndOfSpan: true)
|
||||
.Accepts(AcceptedCharacters.Any),
|
||||
new MarkupBlock(
|
||||
Factory.Markup("\r\n<p>Foo</p>"))),
|
||||
new RazorError(String.Format(RazorResources.ParseError_Expected_X, "}"),
|
||||
29, 1, 10));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VerbatimBlockAutoCompleteAtStartOfFile()
|
||||
{
|
||||
ParseBlockTest("@{" + Environment.NewLine
|
||||
+ "<p></p>",
|
||||
new StatementBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("{").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("\r\n")
|
||||
.AsStatement()
|
||||
.With(new AutoCompleteEditHandler(CSharpLanguageCharacteristics.Instance.TokenizeString) { AutoCompleteString = "}" }),
|
||||
new MarkupBlock(
|
||||
Factory.Markup(@"<p></p>")
|
||||
.With(new MarkupCodeGenerator())
|
||||
.Accepts(AcceptedCharacters.None)
|
||||
),
|
||||
Factory.Span(SpanKind.Code, new CSharpSymbol(Factory.LocationTracker.CurrentLocation, String.Empty, CSharpSymbolType.Unknown))
|
||||
.With(new StatementCodeGenerator())
|
||||
),
|
||||
new RazorError(String.Format(RazorResources.ParseError_Expected_EndOfBlock_Before_EOF, RazorResources.BlockName_Code, "}", "{"),
|
||||
1, 0, 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,733 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.AspNet.Razor.Generator;
|
||||
using Microsoft.AspNet.Razor.Parser;
|
||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||
using Microsoft.AspNet.Razor.Resources;
|
||||
using Microsoft.AspNet.Razor.Test.Framework;
|
||||
using Microsoft.AspNet.Razor.Text;
|
||||
using Microsoft.AspNet.Razor.Tokenizer.Symbols;
|
||||
using Microsoft.TestCommon;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Test.Parser.CSharp
|
||||
{
|
||||
public class CSharpBlockTest : CsHtmlCodeParserTestBase
|
||||
{
|
||||
[Fact]
|
||||
public void ParseBlockMethodThrowsArgNullExceptionOnNullContext()
|
||||
{
|
||||
// Arrange
|
||||
CSharpCodeParser parser = new CSharpCodeParser();
|
||||
|
||||
// Act and Assert
|
||||
Assert.Throws<InvalidOperationException>(() => parser.ParseBlock(), RazorResources.Parser_Context_Not_Set);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BalancingBracketsIgnoresStringLiteralCharactersAndBracketsInsideSingleLineComments()
|
||||
{
|
||||
SingleSpanBlockTest(@"if(foo) {
|
||||
// bar } "" baz '
|
||||
zoop();
|
||||
}", BlockType.Statement, SpanKind.Code);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NestedCodeBlockWithAtCausesError()
|
||||
{
|
||||
ParseBlockTest("if (true) { @if(false) { } }",
|
||||
new StatementBlock(
|
||||
Factory.Code("if (true) { ").AsStatement(),
|
||||
new StatementBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("if(false) { }").AsStatement()
|
||||
),
|
||||
Factory.Code(" }").AsStatement()),
|
||||
new RazorError(
|
||||
String.Format(RazorResources.ParseError_Unexpected_Keyword_After_At,
|
||||
"if"),
|
||||
new SourceLocation(13, 0, 13)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BalancingBracketsIgnoresStringLiteralCharactersAndBracketsInsideBlockComments()
|
||||
{
|
||||
SingleSpanBlockTest(
|
||||
@"if(foo) {
|
||||
/* bar } "" */ ' baz } '
|
||||
zoop();
|
||||
}", BlockType.Statement, SpanKind.Code);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockSkipsParenthesisedExpressionAndThenBalancesBracesIfFirstIdentifierIsForKeyword()
|
||||
{
|
||||
SingleSpanBlockTest("for(int i = 0; i < 10; new Foo { Bar = \"baz\" }) { Debug.WriteLine(@\"foo } bar\"); }", BlockType.Statement, SpanKind.Code, acceptedCharacters: AcceptedCharacters.None);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockSkipsParenthesisedExpressionAndThenBalancesBracesIfFirstIdentifierIsForeachKeyword()
|
||||
{
|
||||
SingleSpanBlockTest("foreach(int i = 0; i < 10; new Foo { Bar = \"baz\" }) { Debug.WriteLine(@\"foo } bar\"); }", BlockType.Statement, SpanKind.Code, acceptedCharacters: AcceptedCharacters.None);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockSkipsParenthesisedExpressionAndThenBalancesBracesIfFirstIdentifierIsWhileKeyword()
|
||||
{
|
||||
SingleSpanBlockTest("while(int i = 0; i < 10; new Foo { Bar = \"baz\" }) { Debug.WriteLine(@\"foo } bar\"); }", BlockType.Statement, SpanKind.Code, acceptedCharacters: AcceptedCharacters.None);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockSkipsParenthesisedExpressionAndThenBalancesBracesIfFirstIdentifierIsUsingKeywordFollowedByParen()
|
||||
{
|
||||
SingleSpanBlockTest("using(int i = 0; i < 10; new Foo { Bar = \"baz\" }) { Debug.WriteLine(@\"foo } bar\"); }", BlockType.Statement, SpanKind.Code, acceptedCharacters: AcceptedCharacters.None);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockSupportsUsingsNestedWithinOtherBlocks()
|
||||
{
|
||||
SingleSpanBlockTest("if(foo) { using(int i = 0; i < 10; new Foo { Bar = \"baz\" }) { Debug.WriteLine(@\"foo } bar\"); } }", BlockType.Statement, SpanKind.Code);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockSkipsParenthesisedExpressionAndThenBalancesBracesIfFirstIdentifierIsIfKeywordWithNoElseBranches()
|
||||
{
|
||||
SingleSpanBlockTest("if(int i = 0; i < 10; new Foo { Bar = \"baz\" }) { Debug.WriteLine(@\"foo } bar\"); }", BlockType.Statement, SpanKind.Code);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockAllowsEmptyBlockStatement()
|
||||
{
|
||||
SingleSpanBlockTest("if(false) { }", BlockType.Statement, SpanKind.Code);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockTerminatesParenBalancingAtEOF()
|
||||
{
|
||||
ImplicitExpressionTest("Html.En(code()", "Html.En(code()",
|
||||
AcceptedCharacters.Any,
|
||||
new RazorError(
|
||||
String.Format(RazorResources.ParseError_Expected_CloseBracket_Before_EOF,
|
||||
"(", ")"),
|
||||
new SourceLocation(8, 0, 8)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockSupportsBlockCommentBetweenIfAndElseClause()
|
||||
{
|
||||
SingleSpanBlockTest("if(foo) { bar(); } /* Foo */ /* Bar */ else { baz(); }", BlockType.Statement, SpanKind.Code, acceptedCharacters: AcceptedCharacters.None);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockSupportsRazorCommentBetweenIfAndElseClause()
|
||||
{
|
||||
RunRazorCommentBetweenClausesTest("if(foo) { bar(); } ", " else { baz(); }", acceptedCharacters: AcceptedCharacters.None);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockSupportsBlockCommentBetweenElseIfAndElseClause()
|
||||
{
|
||||
SingleSpanBlockTest("if(foo) { bar(); } else if(bar) { baz(); } /* Foo */ /* Bar */ else { biz(); }", BlockType.Statement, SpanKind.Code, acceptedCharacters: AcceptedCharacters.None);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockSupportsRazorCommentBetweenElseIfAndElseClause()
|
||||
{
|
||||
RunRazorCommentBetweenClausesTest("if(foo) { bar(); } else if(bar) { baz(); } ", " else { baz(); }", acceptedCharacters: AcceptedCharacters.None);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockSupportsBlockCommentBetweenIfAndElseIfClause()
|
||||
{
|
||||
SingleSpanBlockTest("if(foo) { bar(); } /* Foo */ /* Bar */ else if(bar) { baz(); }", BlockType.Statement, SpanKind.Code);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockSupportsRazorCommentBetweenIfAndElseIfClause()
|
||||
{
|
||||
RunRazorCommentBetweenClausesTest("if(foo) { bar(); } ", " else if(bar) { baz(); }");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockSupportsLineCommentBetweenIfAndElseClause()
|
||||
{
|
||||
SingleSpanBlockTest(@"if(foo) { bar(); }
|
||||
// Foo
|
||||
// Bar
|
||||
else { baz(); }", BlockType.Statement, SpanKind.Code, acceptedCharacters: AcceptedCharacters.None);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockSupportsLineCommentBetweenElseIfAndElseClause()
|
||||
{
|
||||
SingleSpanBlockTest(@"if(foo) { bar(); } else if(bar) { baz(); }
|
||||
// Foo
|
||||
// Bar
|
||||
else { biz(); }", BlockType.Statement, SpanKind.Code, acceptedCharacters: AcceptedCharacters.None);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockSupportsLineCommentBetweenIfAndElseIfClause()
|
||||
{
|
||||
SingleSpanBlockTest(@"if(foo) { bar(); }
|
||||
// Foo
|
||||
// Bar
|
||||
else if(bar) { baz(); }", BlockType.Statement, SpanKind.Code);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockParsesElseIfBranchesOfIfStatement()
|
||||
{
|
||||
const string ifStatement = @"if(int i = 0; i < 10; new Foo { Bar = ""baz"" }) {
|
||||
Debug.WriteLine(@""foo } bar"");
|
||||
}";
|
||||
const string elseIfBranch = @" else if(int i = 0; i < 10; new Foo { Bar = ""baz"" }) {
|
||||
Debug.WriteLine(@""bar } baz"");
|
||||
}";
|
||||
const string document = ifStatement + elseIfBranch;
|
||||
|
||||
SingleSpanBlockTest(document, BlockType.Statement, SpanKind.Code);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockParsesMultipleElseIfBranchesOfIfStatement()
|
||||
{
|
||||
const string ifStatement = @"if(int i = 0; i < 10; new Foo { Bar = ""baz"" }) {
|
||||
Debug.WriteLine(@""foo } bar"");
|
||||
}";
|
||||
const string elseIfBranch = @" else if(int i = 0; i < 10; new Foo { Bar = ""baz"" }) {
|
||||
Debug.WriteLine(@""bar } baz"");
|
||||
}";
|
||||
const string document = ifStatement + elseIfBranch + elseIfBranch + elseIfBranch + elseIfBranch;
|
||||
SingleSpanBlockTest(document, BlockType.Statement, SpanKind.Code);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockParsesMultipleElseIfBranchesOfIfStatementFollowedByOneElseBranch()
|
||||
{
|
||||
const string ifStatement = @"if(int i = 0; i < 10; new Foo { Bar = ""baz"" }) {
|
||||
Debug.WriteLine(@""foo } bar"");
|
||||
}";
|
||||
const string elseIfBranch = @" else if(int i = 0; i < 10; new Foo { Bar = ""baz"" }) {
|
||||
Debug.WriteLine(@""bar } baz"");
|
||||
}";
|
||||
const string elseBranch = @" else { Debug.WriteLine(@""bar } baz""); }";
|
||||
const string document = ifStatement + elseIfBranch + elseIfBranch + elseBranch;
|
||||
|
||||
SingleSpanBlockTest(document, BlockType.Statement, SpanKind.Code, acceptedCharacters: AcceptedCharacters.None);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockStopsParsingCodeAfterElseBranch()
|
||||
{
|
||||
const string ifStatement = @"if(int i = 0; i < 10; new Foo { Bar = ""baz"" }) {
|
||||
Debug.WriteLine(@""foo } bar"");
|
||||
}";
|
||||
const string elseIfBranch = @" else if(int i = 0; i < 10; new Foo { Bar = ""baz"" }) {
|
||||
Debug.WriteLine(@""bar } baz"");
|
||||
}";
|
||||
const string elseBranch = @" else { Debug.WriteLine(@""bar } baz""); }";
|
||||
const string document = ifStatement + elseIfBranch + elseBranch + elseIfBranch;
|
||||
const string expected = ifStatement + elseIfBranch + elseBranch;
|
||||
|
||||
ParseBlockTest(document, new StatementBlock(Factory.Code(expected).AsStatement().Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockStopsParsingIfIfStatementNotFollowedByElse()
|
||||
{
|
||||
const string document = @"if(int i = 0; i < 10; new Foo { Bar = ""baz"" }) {
|
||||
Debug.WriteLine(@""foo } bar"");
|
||||
}";
|
||||
|
||||
SingleSpanBlockTest(document, BlockType.Statement, SpanKind.Code);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockAcceptsElseIfWithNoCondition()
|
||||
{
|
||||
// We don't want to be a full C# parser - If the else if is missing it's condition, the C# compiler can handle that, we have all the info we need to keep parsing
|
||||
const string ifBranch = @"if(int i = 0; i < 10; new Foo { Bar = ""baz"" }) {
|
||||
Debug.WriteLine(@""foo } bar"");
|
||||
}";
|
||||
const string elseIfBranch = @" else if { foo(); }";
|
||||
const string document = ifBranch + elseIfBranch;
|
||||
|
||||
SingleSpanBlockTest(document, BlockType.Statement, SpanKind.Code);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockCorrectlyParsesDoWhileBlock()
|
||||
{
|
||||
SingleSpanBlockTest("do { var foo = bar; } while(foo != bar);", BlockType.Statement, SpanKind.Code, acceptedCharacters: AcceptedCharacters.None);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockCorrectlyParsesDoWhileBlockMissingSemicolon()
|
||||
{
|
||||
SingleSpanBlockTest("do { var foo = bar; } while(foo != bar)", BlockType.Statement, SpanKind.Code);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockCorrectlyParsesDoWhileBlockMissingWhileCondition()
|
||||
{
|
||||
SingleSpanBlockTest("do { var foo = bar; } while", BlockType.Statement, SpanKind.Code);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockCorrectlyParsesDoWhileBlockMissingWhileConditionWithSemicolon()
|
||||
{
|
||||
SingleSpanBlockTest("do { var foo = bar; } while;", BlockType.Statement, SpanKind.Code, acceptedCharacters: AcceptedCharacters.None);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockCorrectlyParsesDoWhileBlockMissingWhileClauseEntirely()
|
||||
{
|
||||
SingleSpanBlockTest("do { var foo = bar; } narf;", "do { var foo = bar; }", BlockType.Statement, SpanKind.Code);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockSupportsBlockCommentBetweenDoAndWhileClause()
|
||||
{
|
||||
SingleSpanBlockTest("do { var foo = bar; } /* Foo */ /* Bar */ while(true);", BlockType.Statement, SpanKind.Code, acceptedCharacters: AcceptedCharacters.None);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockSupportsLineCommentBetweenDoAndWhileClause()
|
||||
{
|
||||
SingleSpanBlockTest(@"do { var foo = bar; }
|
||||
// Foo
|
||||
// Bar
|
||||
while(true);", BlockType.Statement, SpanKind.Code, acceptedCharacters: AcceptedCharacters.None);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockSupportsRazorCommentBetweenDoAndWhileClause()
|
||||
{
|
||||
RunRazorCommentBetweenClausesTest("do { var foo = bar; } ", " while(true);", acceptedCharacters: AcceptedCharacters.None);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockCorrectlyParsesMarkupInDoWhileBlock()
|
||||
{
|
||||
ParseBlockTest("@do { var foo = bar; <p>Foo</p> foo++; } while (foo<bar>);",
|
||||
new StatementBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("do { var foo = bar;").AsStatement(),
|
||||
new MarkupBlock(
|
||||
Factory.Markup(" <p>Foo</p> ").Accepts(AcceptedCharacters.None)
|
||||
),
|
||||
Factory.Code("foo++; } while (foo<bar>);").AsStatement().Accepts(AcceptedCharacters.None)
|
||||
));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockSkipsParenthesisedExpressionAndThenBalancesBracesIfFirstIdentifierIsSwitchKeyword()
|
||||
{
|
||||
SingleSpanBlockTest(@"switch(foo) {
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
{
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
return;
|
||||
default:
|
||||
return;
|
||||
}", BlockType.Statement, SpanKind.Code, acceptedCharacters: AcceptedCharacters.None);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockSkipsParenthesisedExpressionAndThenBalancesBracesIfFirstIdentifierIsLockKeyword()
|
||||
{
|
||||
SingleSpanBlockTest("lock(foo) { Debug.WriteLine(@\"foo } bar\"); }", BlockType.Statement, SpanKind.Code, acceptedCharacters: AcceptedCharacters.None);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockHasErrorsIfNamespaceImportMissingSemicolon()
|
||||
{
|
||||
NamespaceImportTest("using Foo.Bar.Baz", " Foo.Bar.Baz", acceptedCharacters: AcceptedCharacters.NonWhiteSpace | AcceptedCharacters.WhiteSpace, location: new SourceLocation(17, 0, 17));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockHasErrorsIfNamespaceAliasMissingSemicolon()
|
||||
{
|
||||
NamespaceImportTest("using Foo.Bar.Baz = FooBarBaz", " Foo.Bar.Baz = FooBarBaz", acceptedCharacters: AcceptedCharacters.NonWhiteSpace | AcceptedCharacters.WhiteSpace, location: new SourceLocation(29, 0, 29));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockParsesNamespaceImportWithSemicolonForUsingKeywordIfIsInValidFormat()
|
||||
{
|
||||
NamespaceImportTest("using Foo.Bar.Baz;", " Foo.Bar.Baz", AcceptedCharacters.NonWhiteSpace | AcceptedCharacters.WhiteSpace);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockDoesntCaptureWhitespaceAfterUsing()
|
||||
{
|
||||
ParseBlockTest("using Foo ",
|
||||
new DirectiveBlock(
|
||||
Factory.Code("using Foo")
|
||||
.AsNamespaceImport(" Foo", CSharpCodeParser.UsingKeywordLength)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace | AcceptedCharacters.WhiteSpace)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockParsesNamespaceAliasWithSemicolonForUsingKeywordIfIsInValidFormat()
|
||||
{
|
||||
NamespaceImportTest("using FooBarBaz = FooBarBaz;", " FooBarBaz = FooBarBaz", AcceptedCharacters.NonWhiteSpace | AcceptedCharacters.WhiteSpace);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockTerminatesUsingKeywordAtEOFAndOutputsFileCodeBlock()
|
||||
{
|
||||
SingleSpanBlockTest("using ", BlockType.Statement, SpanKind.Code);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockTerminatesSingleLineCommentAtEndOfFile()
|
||||
{
|
||||
const string document = "foreach(var f in Foo) { // foo bar baz";
|
||||
SingleSpanBlockTest(document, document, BlockType.Statement, SpanKind.Code,
|
||||
new RazorError(String.Format(RazorResources.ParseError_Expected_EndOfBlock_Before_EOF, "foreach", '}', '{'), SourceLocation.Zero));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockTerminatesBlockCommentAtEndOfFile()
|
||||
{
|
||||
const string document = "foreach(var f in Foo) { /* foo bar baz";
|
||||
SingleSpanBlockTest(document, document, BlockType.Statement, SpanKind.Code,
|
||||
new RazorError(String.Format(RazorResources.ParseError_BlockComment_Not_Terminated), 24, 0, 24),
|
||||
new RazorError(String.Format(RazorResources.ParseError_Expected_EndOfBlock_Before_EOF, "foreach", '}', '{'), SourceLocation.Zero));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockTerminatesSingleSlashAtEndOfFile()
|
||||
{
|
||||
const string document = "foreach(var f in Foo) { / foo bar baz";
|
||||
SingleSpanBlockTest(document, document, BlockType.Statement, SpanKind.Code,
|
||||
new RazorError(String.Format(RazorResources.ParseError_Expected_EndOfBlock_Before_EOF, "foreach", '}', '{'), SourceLocation.Zero));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockSupportsBlockCommentBetweenTryAndFinallyClause()
|
||||
{
|
||||
SingleSpanBlockTest("try { bar(); } /* Foo */ /* Bar */ finally { baz(); }", BlockType.Statement, SpanKind.Code, acceptedCharacters: AcceptedCharacters.None);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockSupportsRazorCommentBetweenTryAndFinallyClause()
|
||||
{
|
||||
RunRazorCommentBetweenClausesTest("try { bar(); } ", " finally { biz(); }", acceptedCharacters: AcceptedCharacters.None);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockSupportsBlockCommentBetweenCatchAndFinallyClause()
|
||||
{
|
||||
SingleSpanBlockTest("try { bar(); } catch(bar) { baz(); } /* Foo */ /* Bar */ finally { biz(); }", BlockType.Statement, SpanKind.Code, acceptedCharacters: AcceptedCharacters.None);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockSupportsRazorCommentBetweenCatchAndFinallyClause()
|
||||
{
|
||||
RunRazorCommentBetweenClausesTest("try { bar(); } catch(bar) { baz(); } ", " finally { biz(); }", acceptedCharacters: AcceptedCharacters.None);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockSupportsBlockCommentBetweenTryAndCatchClause()
|
||||
{
|
||||
SingleSpanBlockTest("try { bar(); } /* Foo */ /* Bar */ catch(bar) { baz(); }", BlockType.Statement, SpanKind.Code);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockSupportsRazorCommentBetweenTryAndCatchClause()
|
||||
{
|
||||
RunRazorCommentBetweenClausesTest("try { bar(); }", " catch(bar) { baz(); }");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockSupportsLineCommentBetweenTryAndFinallyClause()
|
||||
{
|
||||
SingleSpanBlockTest(@"try { bar(); }
|
||||
// Foo
|
||||
// Bar
|
||||
finally { baz(); }", BlockType.Statement, SpanKind.Code, acceptedCharacters: AcceptedCharacters.None);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockSupportsLineCommentBetweenCatchAndFinallyClause()
|
||||
{
|
||||
SingleSpanBlockTest(@"try { bar(); } catch(bar) { baz(); }
|
||||
// Foo
|
||||
// Bar
|
||||
finally { biz(); }", BlockType.Statement, SpanKind.Code, acceptedCharacters: AcceptedCharacters.None);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockSupportsLineCommentBetweenTryAndCatchClause()
|
||||
{
|
||||
SingleSpanBlockTest(@"try { bar(); }
|
||||
// Foo
|
||||
// Bar
|
||||
catch(bar) { baz(); }", BlockType.Statement, SpanKind.Code);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockSupportsTryStatementWithNoAdditionalClauses()
|
||||
{
|
||||
SingleSpanBlockTest("try { var foo = new { } }", BlockType.Statement, SpanKind.Code);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockSupportsMarkupWithinTryClause()
|
||||
{
|
||||
RunSimpleWrappedMarkupTest("try {", " <p>Foo</p> ", "}");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockSupportsTryStatementWithOneCatchClause()
|
||||
{
|
||||
SingleSpanBlockTest("try { var foo = new { } } catch(Foo Bar Baz) { var foo = new { } }", BlockType.Statement, SpanKind.Code);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockSupportsMarkupWithinCatchClause()
|
||||
{
|
||||
RunSimpleWrappedMarkupTest("try { var foo = new { } } catch(Foo Bar Baz) {", " <p>Foo</p> ", "}");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockSupportsTryStatementWithMultipleCatchClause()
|
||||
{
|
||||
SingleSpanBlockTest("try { var foo = new { } } catch(Foo Bar Baz) { var foo = new { } } catch(Foo Bar Baz) { var foo = new { } } catch(Foo Bar Baz) { var foo = new { } }", BlockType.Statement, SpanKind.Code);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockSupportsExceptionLessCatchClauses()
|
||||
{
|
||||
SingleSpanBlockTest("try { var foo = new { } } catch { var foo = new { } }", BlockType.Statement, SpanKind.Code);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockSupportsMarkupWithinAdditionalCatchClauses()
|
||||
{
|
||||
RunSimpleWrappedMarkupTest("try { var foo = new { } } catch(Foo Bar Baz) { var foo = new { } } catch(Foo Bar Baz) { var foo = new { } } catch(Foo Bar Baz) {", " <p>Foo</p> ", "}");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockSupportsTryStatementWithFinallyClause()
|
||||
{
|
||||
SingleSpanBlockTest("try { var foo = new { } } finally { var foo = new { } }", BlockType.Statement, SpanKind.Code, acceptedCharacters: AcceptedCharacters.None);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockSupportsMarkupWithinFinallyClause()
|
||||
{
|
||||
RunSimpleWrappedMarkupTest("try { var foo = new { } } finally {", " <p>Foo</p> ", "}", acceptedCharacters: AcceptedCharacters.None);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockStopsParsingCatchClausesAfterFinallyBlock()
|
||||
{
|
||||
string expectedContent = "try { var foo = new { } } finally { var foo = new { } }";
|
||||
SingleSpanBlockTest(expectedContent + " catch(Foo Bar Baz) { }", expectedContent, BlockType.Statement, SpanKind.Code, acceptedCharacters: AcceptedCharacters.None);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockDoesNotAllowMultipleFinallyBlocks()
|
||||
{
|
||||
string expectedContent = "try { var foo = new { } } finally { var foo = new { } }";
|
||||
SingleSpanBlockTest(expectedContent + " finally { }", expectedContent, BlockType.Statement, SpanKind.Code, acceptedCharacters: AcceptedCharacters.None);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockAcceptsTrailingDotIntoImplicitExpressionWhenEmbeddedInCode()
|
||||
{
|
||||
// Arrange
|
||||
ParseBlockTest(@"if(foo) { @foo. }",
|
||||
new StatementBlock(
|
||||
Factory.Code("if(foo) { ").AsStatement(),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("foo.")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords, acceptTrailingDot: true)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)
|
||||
),
|
||||
Factory.Code(" }").AsStatement()
|
||||
));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockParsesExpressionOnSwitchCharacterFollowedByOpenParen()
|
||||
{
|
||||
// Arrange
|
||||
ParseBlockTest(@"if(foo) { @(foo + bar) }",
|
||||
new StatementBlock(
|
||||
Factory.Code("if(foo) { ").AsStatement(),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("(").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("foo + bar").AsExpression(),
|
||||
Factory.MetaCode(")").Accepts(AcceptedCharacters.None)
|
||||
),
|
||||
Factory.Code(" }").AsStatement()
|
||||
));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockParsesExpressionOnSwitchCharacterFollowedByIdentifierStart()
|
||||
{
|
||||
// Arrange
|
||||
ParseBlockTest(@"if(foo) { @foo[4].bar() }",
|
||||
new StatementBlock(
|
||||
Factory.Code("if(foo) { ").AsStatement(),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("foo[4].bar()")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords, acceptTrailingDot: true)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)
|
||||
),
|
||||
Factory.Code(" }").AsStatement()
|
||||
));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockTreatsDoubleAtSignAsEscapeSequenceIfAtStatementStart()
|
||||
{
|
||||
// Arrange
|
||||
ParseBlockTest(@"if(foo) { @@class.Foo() }",
|
||||
new StatementBlock(
|
||||
Factory.Code("if(foo) { ").AsStatement(),
|
||||
Factory.Code("@").Hidden(),
|
||||
Factory.Code("@class.Foo() }").AsStatement()
|
||||
));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockTreatsAtSignsAfterFirstPairAsPartOfCSharpStatement()
|
||||
{
|
||||
// Arrange
|
||||
ParseBlockTest(@"if(foo) { @@@@class.Foo() }",
|
||||
new StatementBlock(
|
||||
Factory.Code("if(foo) { ").AsStatement(),
|
||||
Factory.Code("@").Hidden(),
|
||||
Factory.Code("@@@class.Foo() }").AsStatement()
|
||||
));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockDoesNotParseMarkupStatementOrExpressionOnSwitchCharacterNotFollowedByOpenAngleOrColon()
|
||||
{
|
||||
// Arrange
|
||||
ParseBlockTest("if(foo) { @\"Foo\".ToString(); }",
|
||||
new StatementBlock(
|
||||
Factory.Code("if(foo) { @\"Foo\".ToString(); }").AsStatement()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParsersCanNestRecursively()
|
||||
{
|
||||
// Arrange
|
||||
ParseBlockTest("foreach(var c in db.Categories) {" + Environment.NewLine
|
||||
+ " <div>" + Environment.NewLine
|
||||
+ " <h1>@c.Name</h1>" + Environment.NewLine
|
||||
+ " <ul>" + Environment.NewLine
|
||||
+ " @foreach(var p in c.Products) {" + Environment.NewLine
|
||||
+ " <li><a href=\"@Html.ActionUrl(\"Products\", \"Detail\", new { id = p.Id })\">@p.Name</a></li>" + Environment.NewLine
|
||||
+ " }" + Environment.NewLine
|
||||
+ " </ul>" + Environment.NewLine
|
||||
+ " </div>" + Environment.NewLine
|
||||
+ " }",
|
||||
new StatementBlock(
|
||||
Factory.Code("foreach(var c in db.Categories) {\r\n").AsStatement(),
|
||||
new MarkupBlock(
|
||||
Factory.Markup(" <div>\r\n <h1>"),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("c.Name")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
Factory.Markup("</h1>\r\n <ul>\r\n"),
|
||||
new StatementBlock(
|
||||
Factory.Code(@" ").AsStatement(),
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("foreach(var p in c.Products) {\r\n").AsStatement(),
|
||||
new MarkupBlock(
|
||||
Factory.Markup(" <li><a"),
|
||||
new MarkupBlock(new AttributeBlockCodeGenerator("href", new LocationTagged<string>(" href=\"", 193, 5, 30), new LocationTagged<string>("\"", 256, 5, 93)),
|
||||
Factory.Markup(" href=\"").With(SpanCodeGenerator.Null),
|
||||
new MarkupBlock(new DynamicAttributeBlockCodeGenerator(new LocationTagged<string>(String.Empty, 200, 5, 37), 200, 5, 37),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("Html.ActionUrl(\"Products\", \"Detail\", new { id = p.Id })")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace))),
|
||||
Factory.Markup("\"").With(SpanCodeGenerator.Null)),
|
||||
Factory.Markup(">"),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("p.Name")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
Factory.Markup("</a></li>\r\n").Accepts(AcceptedCharacters.None)),
|
||||
Factory.Code(" }\r\n").AsStatement().Accepts(AcceptedCharacters.None)),
|
||||
Factory.Markup(" </ul>\r\n </div>\r\n")
|
||||
.Accepts(AcceptedCharacters.None)),
|
||||
Factory.Code(" }").AsStatement().Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
|
||||
private void RunRazorCommentBetweenClausesTest(string preComment, string postComment, AcceptedCharacters acceptedCharacters = AcceptedCharacters.Any)
|
||||
{
|
||||
ParseBlockTest(preComment + "@* Foo *@ @* Bar *@" + postComment,
|
||||
new StatementBlock(
|
||||
Factory.Code(preComment).AsStatement(),
|
||||
new CommentBlock(
|
||||
Factory.CodeTransition(CSharpSymbolType.RazorCommentTransition),
|
||||
Factory.MetaCode("*", CSharpSymbolType.RazorCommentStar).Accepts(AcceptedCharacters.None),
|
||||
Factory.Comment(" Foo ", CSharpSymbolType.RazorComment),
|
||||
Factory.MetaCode("*", CSharpSymbolType.RazorCommentStar).Accepts(AcceptedCharacters.None),
|
||||
Factory.CodeTransition(CSharpSymbolType.RazorCommentTransition)
|
||||
),
|
||||
Factory.Code(" ").AsStatement(),
|
||||
new CommentBlock(
|
||||
Factory.CodeTransition(CSharpSymbolType.RazorCommentTransition),
|
||||
Factory.MetaCode("*", CSharpSymbolType.RazorCommentStar).Accepts(AcceptedCharacters.None),
|
||||
Factory.Comment(" Bar ", CSharpSymbolType.RazorComment),
|
||||
Factory.MetaCode("*", CSharpSymbolType.RazorCommentStar).Accepts(AcceptedCharacters.None),
|
||||
Factory.CodeTransition(CSharpSymbolType.RazorCommentTransition)
|
||||
),
|
||||
Factory.Code(postComment).AsStatement().Accepts(acceptedCharacters)));
|
||||
}
|
||||
|
||||
private void RunSimpleWrappedMarkupTest(string prefix, string markup, string suffix, AcceptedCharacters acceptedCharacters = AcceptedCharacters.Any)
|
||||
{
|
||||
ParseBlockTest(prefix + markup + suffix,
|
||||
new StatementBlock(
|
||||
Factory.Code(prefix).AsStatement(),
|
||||
new MarkupBlock(
|
||||
Factory.Markup(markup).Accepts(AcceptedCharacters.None)
|
||||
),
|
||||
Factory.Code(suffix).AsStatement().Accepts(acceptedCharacters)
|
||||
));
|
||||
}
|
||||
|
||||
private void NamespaceImportTest(string content, string expectedNS, AcceptedCharacters acceptedCharacters = AcceptedCharacters.None, string errorMessage = null, SourceLocation? location = null)
|
||||
{
|
||||
var errors = new RazorError[0];
|
||||
if (!String.IsNullOrEmpty(errorMessage) && location.HasValue)
|
||||
{
|
||||
errors = new RazorError[]
|
||||
{
|
||||
new RazorError(errorMessage, location.Value)
|
||||
};
|
||||
}
|
||||
ParseBlockTest(content,
|
||||
new DirectiveBlock(
|
||||
Factory.Code(content)
|
||||
.AsNamespaceImport(expectedNS, CSharpCodeParser.UsingKeywordLength)
|
||||
.Accepts(acceptedCharacters)),
|
||||
errors);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,163 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNet.Razor.Generator;
|
||||
using Microsoft.AspNet.Razor.Parser;
|
||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||
using Microsoft.AspNet.Razor.Test.Framework;
|
||||
using Microsoft.AspNet.Razor.Text;
|
||||
using Microsoft.TestCommon;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Test.Parser.CSharp
|
||||
{
|
||||
public class CSharpDirectivesTest : CsHtmlCodeParserTestBase
|
||||
{
|
||||
[Fact]
|
||||
public void InheritsDirective()
|
||||
{
|
||||
ParseBlockTest("@inherits System.Web.WebPages.WebPage",
|
||||
new DirectiveBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode(SyntaxConstants.CSharp.InheritsKeyword + " ")
|
||||
.Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("System.Web.WebPages.WebPage")
|
||||
.AsBaseType("System.Web.WebPages.WebPage")));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InheritsDirectiveSupportsArrays()
|
||||
{
|
||||
ParseBlockTest("@inherits string[[]][]",
|
||||
new DirectiveBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode(SyntaxConstants.CSharp.InheritsKeyword + " ")
|
||||
.Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("string[[]][]")
|
||||
.AsBaseType("string[[]][]")));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InheritsDirectiveSupportsNestedGenerics()
|
||||
{
|
||||
ParseBlockTest("@inherits System.Web.Mvc.WebViewPage<IEnumerable<MvcApplication2.Models.RegisterModel>>",
|
||||
new DirectiveBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode(SyntaxConstants.CSharp.InheritsKeyword + " ")
|
||||
.Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("System.Web.Mvc.WebViewPage<IEnumerable<MvcApplication2.Models.RegisterModel>>")
|
||||
.AsBaseType("System.Web.Mvc.WebViewPage<IEnumerable<MvcApplication2.Models.RegisterModel>>")));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InheritsDirectiveSupportsTypeKeywords()
|
||||
{
|
||||
ParseBlockTest("@inherits string",
|
||||
new DirectiveBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode(SyntaxConstants.CSharp.InheritsKeyword + " ")
|
||||
.Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("string")
|
||||
.AsBaseType("string")));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InheritsDirectiveSupportsVSTemplateTokens()
|
||||
{
|
||||
ParseBlockTest("@inherits $rootnamespace$.MyBase",
|
||||
new DirectiveBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode(SyntaxConstants.CSharp.InheritsKeyword + " ")
|
||||
.Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("$rootnamespace$.MyBase")
|
||||
.AsBaseType("$rootnamespace$.MyBase")));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SessionStateDirectiveWorks()
|
||||
{
|
||||
ParseBlockTest("@sessionstate InProc",
|
||||
new DirectiveBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode(SyntaxConstants.CSharp.SessionStateKeyword + " ")
|
||||
.Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("InProc")
|
||||
.AsRazorDirectiveAttribute("sessionstate", "InProc")
|
||||
));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SessionStateDirectiveParsesInvalidSessionValue()
|
||||
{
|
||||
ParseBlockTest("@sessionstate Blah",
|
||||
new DirectiveBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode(SyntaxConstants.CSharp.SessionStateKeyword + " ")
|
||||
.Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("Blah")
|
||||
.AsRazorDirectiveAttribute("sessionstate", "Blah")
|
||||
));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FunctionsDirective()
|
||||
{
|
||||
ParseBlockTest("@functions { foo(); bar(); }",
|
||||
new FunctionsBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode(SyntaxConstants.CSharp.FunctionsKeyword + " {")
|
||||
.Accepts(AcceptedCharacters.None),
|
||||
Factory.Code(" foo(); bar(); ")
|
||||
.AsFunctionsBody(),
|
||||
Factory.MetaCode("}")
|
||||
.Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EmptyFunctionsDirective()
|
||||
{
|
||||
ParseBlockTest("@functions { }",
|
||||
new FunctionsBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode(SyntaxConstants.CSharp.FunctionsKeyword + " {")
|
||||
.Accepts(AcceptedCharacters.None),
|
||||
Factory.Code(" ")
|
||||
.AsFunctionsBody(),
|
||||
Factory.MetaCode("}")
|
||||
.Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SectionDirective()
|
||||
{
|
||||
ParseBlockTest("@section Header { <p>F{o}o</p> }",
|
||||
new SectionBlock(new SectionCodeGenerator("Header"),
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("section Header {")
|
||||
.AutoCompleteWith(null, atEndOfSpan: true)
|
||||
.Accepts(AcceptedCharacters.Any),
|
||||
new MarkupBlock(
|
||||
Factory.Markup(" <p>F", "{", "o", "}", "o", "</p> ")),
|
||||
Factory.MetaCode("}")
|
||||
.Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void HelperDirective()
|
||||
{
|
||||
ParseBlockTest("@helper Strong(string value) { foo(); }",
|
||||
new HelperBlock(new HelperCodeGenerator(new LocationTagged<string>("Strong(string value) {", new SourceLocation(8, 0, 8)), headerComplete: true),
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("helper ")
|
||||
.Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("Strong(string value) {")
|
||||
.Hidden()
|
||||
.Accepts(AcceptedCharacters.None),
|
||||
new StatementBlock(
|
||||
Factory.Code(" foo(); ")
|
||||
.AsStatement()
|
||||
.With(new StatementCodeGenerator())),
|
||||
Factory.Code("}")
|
||||
.Hidden()
|
||||
.Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,624 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.AspNet.Razor.Parser;
|
||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||
using Microsoft.AspNet.Razor.Resources;
|
||||
using Microsoft.AspNet.Razor.Test.Framework;
|
||||
using Microsoft.AspNet.Razor.Text;
|
||||
using Microsoft.TestCommon;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Test.Parser.CSharp
|
||||
{
|
||||
public class CSharpErrorTest : CsHtmlCodeParserTestBase
|
||||
{
|
||||
[Fact]
|
||||
public void ParseBlockHandlesQuotesAfterTransition()
|
||||
{
|
||||
ParseBlockTest("@\"",
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.EmptyCSharp()
|
||||
.AsImplicitExpression(KeywordSet)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)
|
||||
),
|
||||
new RazorError(
|
||||
String.Format(RazorResources.ParseError_Unexpected_Character_At_Start_Of_CodeBlock_CS, '"'),
|
||||
1, 0, 1));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockCapturesWhitespaceToEndOfLineInInvalidUsingStatementAndTreatsAsFileCode()
|
||||
{
|
||||
ParseBlockTest("using " + Environment.NewLine
|
||||
+ Environment.NewLine,
|
||||
new StatementBlock(
|
||||
Factory.Code("using \r\n").AsStatement()
|
||||
));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockMethodOutputsOpenCurlyAsCodeSpanIfEofFoundAfterOpenCurlyBrace()
|
||||
{
|
||||
ParseBlockTest("{",
|
||||
new StatementBlock(
|
||||
Factory.MetaCode("{").Accepts(AcceptedCharacters.None),
|
||||
Factory.EmptyCSharp()
|
||||
.AsStatement()
|
||||
.With(new AutoCompleteEditHandler(CSharpLanguageCharacteristics.Instance.TokenizeString) { AutoCompleteString = "}" })
|
||||
),
|
||||
new RazorError(
|
||||
String.Format(RazorResources.ParseError_Expected_EndOfBlock_Before_EOF,
|
||||
RazorResources.BlockName_Code,
|
||||
"}", "{"),
|
||||
SourceLocation.Zero));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockMethodOutputsZeroLengthCodeSpanIfStatementBlockEmpty()
|
||||
{
|
||||
ParseBlockTest("{}",
|
||||
new StatementBlock(
|
||||
Factory.MetaCode("{").Accepts(AcceptedCharacters.None),
|
||||
Factory.EmptyCSharp().AsStatement(),
|
||||
Factory.MetaCode("}").Accepts(AcceptedCharacters.None)
|
||||
));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockMethodProducesErrorIfNewlineFollowsTransition()
|
||||
{
|
||||
ParseBlockTest("@" + Environment.NewLine,
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.EmptyCSharp()
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
new RazorError(RazorResources.ParseError_Unexpected_WhiteSpace_At_Start_Of_CodeBlock_CS, new SourceLocation(1, 0, 1)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockMethodProducesErrorIfWhitespaceBetweenTransitionAndBlockStartInEmbeddedExpression()
|
||||
{
|
||||
ParseBlockTest("{" + Environment.NewLine
|
||||
+ " @ {}" + Environment.NewLine
|
||||
+ "}",
|
||||
new StatementBlock(
|
||||
Factory.MetaCode("{").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("\r\n ").AsStatement(),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.EmptyCSharp()
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords, acceptTrailingDot: true)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
Factory.Code(" {}\r\n").AsStatement(),
|
||||
Factory.MetaCode("}").Accepts(AcceptedCharacters.None)
|
||||
),
|
||||
new RazorError(RazorResources.ParseError_Unexpected_WhiteSpace_At_Start_Of_CodeBlock_CS, 8, 1, 5));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockMethodProducesErrorIfEOFAfterTransitionInEmbeddedExpression()
|
||||
{
|
||||
ParseBlockTest("{" + Environment.NewLine
|
||||
+ " @",
|
||||
new StatementBlock(
|
||||
Factory.MetaCode("{").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("\r\n ").AsStatement(),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.EmptyCSharp()
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords, acceptTrailingDot: true)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
Factory.EmptyCSharp().AsStatement()
|
||||
),
|
||||
new RazorError(RazorResources.ParseError_Unexpected_EndOfFile_At_Start_Of_CodeBlock, 8, 1, 5),
|
||||
new RazorError(
|
||||
String.Format(RazorResources.ParseError_Expected_EndOfBlock_Before_EOF, RazorResources.BlockName_Code, "}", "{"),
|
||||
SourceLocation.Zero));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockMethodParsesNothingIfFirstCharacterIsNotIdentifierStartOrParenOrBrace()
|
||||
{
|
||||
ParseBlockTest("@!!!",
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.EmptyCSharp()
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
new RazorError(
|
||||
String.Format(RazorResources.ParseError_Unexpected_Character_At_Start_Of_CodeBlock_CS, "!"),
|
||||
1, 0, 1));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockShouldReportErrorAndTerminateAtEOFIfIfParenInExplicitExpressionUnclosed()
|
||||
{
|
||||
ParseBlockTest("(foo bar" + Environment.NewLine
|
||||
+ "baz",
|
||||
new ExpressionBlock(
|
||||
Factory.MetaCode("(").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("foo bar\r\nbaz").AsExpression()
|
||||
),
|
||||
new RazorError(
|
||||
String.Format(RazorResources.ParseError_Expected_EndOfBlock_Before_EOF,
|
||||
RazorResources.BlockName_ExplicitExpression, ')', '('),
|
||||
new SourceLocation(0, 0, 0)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockShouldReportErrorAndTerminateAtMarkupIfIfParenInExplicitExpressionUnclosed()
|
||||
{
|
||||
ParseBlockTest("(foo bar" + Environment.NewLine
|
||||
+ "<html>" + Environment.NewLine
|
||||
+ "baz" + Environment.NewLine
|
||||
+ "</html",
|
||||
new ExpressionBlock(
|
||||
Factory.MetaCode("(").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("foo bar\r\n").AsExpression()
|
||||
),
|
||||
new RazorError(
|
||||
String.Format(RazorResources.ParseError_Expected_EndOfBlock_Before_EOF,
|
||||
RazorResources.BlockName_ExplicitExpression, ')', '('),
|
||||
new SourceLocation(0, 0, 0)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockCorrectlyHandlesInCorrectTransitionsIfImplicitExpressionParensUnclosed()
|
||||
{
|
||||
ParseBlockTest("Href(" + Environment.NewLine
|
||||
+ "<h1>@Html.Foo(Bar);</h1>" + Environment.NewLine,
|
||||
new ExpressionBlock(
|
||||
Factory.Code("Href(\r\n")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||
),
|
||||
new RazorError(
|
||||
String.Format(RazorResources.ParseError_Expected_CloseBracket_Before_EOF,
|
||||
"(", ")"),
|
||||
new SourceLocation(4, 0, 4)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
// Test for fix to Dev10 884975 - Incorrect Error Messaging
|
||||
public void ParseBlockShouldReportErrorAndTerminateAtEOFIfParenInImplicitExpressionUnclosed()
|
||||
{
|
||||
ParseBlockTest("Foo(Bar(Baz)" + Environment.NewLine
|
||||
+ "Biz" + Environment.NewLine
|
||||
+ "Boz",
|
||||
new ExpressionBlock(
|
||||
Factory.Code("Foo(Bar(Baz)\r\nBiz\r\nBoz")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||
),
|
||||
new RazorError(String.Format(RazorResources.ParseError_Expected_CloseBracket_Before_EOF,
|
||||
"(", ")"),
|
||||
new SourceLocation(3, 0, 3)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
// Test for fix to Dev10 884975 - Incorrect Error Messaging
|
||||
public void ParseBlockShouldReportErrorAndTerminateAtMarkupIfParenInImplicitExpressionUnclosed()
|
||||
{
|
||||
ParseBlockTest("Foo(Bar(Baz)" + Environment.NewLine
|
||||
+ "Biz" + Environment.NewLine
|
||||
+ "<html>" + Environment.NewLine
|
||||
+ "Boz" + Environment.NewLine
|
||||
+ "</html>",
|
||||
new ExpressionBlock(
|
||||
Factory.Code("Foo(Bar(Baz)\r\nBiz\r\n")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||
),
|
||||
new RazorError(String.Format(RazorResources.ParseError_Expected_CloseBracket_Before_EOF,
|
||||
"(", ")"),
|
||||
new SourceLocation(3, 0, 3)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
// Test for fix to Dev10 884975 - Incorrect Error Messaging
|
||||
public void ParseBlockShouldReportErrorAndTerminateAtEOFIfBracketInImplicitExpressionUnclosed()
|
||||
{
|
||||
ParseBlockTest("Foo[Bar[Baz]" + Environment.NewLine
|
||||
+ "Biz" + Environment.NewLine
|
||||
+ "Boz",
|
||||
new ExpressionBlock(
|
||||
Factory.Code("Foo[Bar[Baz]\r\nBiz\r\nBoz")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||
),
|
||||
new RazorError(
|
||||
String.Format(RazorResources.ParseError_Expected_CloseBracket_Before_EOF,
|
||||
"[", "]"),
|
||||
new SourceLocation(3, 0, 3)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
// Test for fix to Dev10 884975 - Incorrect Error Messaging
|
||||
public void ParseBlockShouldReportErrorAndTerminateAtMarkupIfBracketInImplicitExpressionUnclosed()
|
||||
{
|
||||
ParseBlockTest("Foo[Bar[Baz]" + Environment.NewLine
|
||||
+ "Biz" + Environment.NewLine
|
||||
+ "<b>" + Environment.NewLine
|
||||
+ "Boz" + Environment.NewLine
|
||||
+ "</b>",
|
||||
new ExpressionBlock(
|
||||
Factory.Code("Foo[Bar[Baz]\r\nBiz\r\n")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||
),
|
||||
new RazorError(
|
||||
String.Format(RazorResources.ParseError_Expected_CloseBracket_Before_EOF,
|
||||
"[", "]"),
|
||||
new SourceLocation(3, 0, 3)));
|
||||
}
|
||||
|
||||
// Simple EOF handling errors:
|
||||
[Fact]
|
||||
public void ParseBlockReportsErrorIfExplicitCodeBlockUnterminatedAtEOF()
|
||||
{
|
||||
ParseBlockTest("{ var foo = bar; if(foo != null) { bar(); } ",
|
||||
new StatementBlock(
|
||||
Factory.MetaCode("{").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code(" var foo = bar; if(foo != null) { bar(); } ").AsStatement()
|
||||
),
|
||||
new RazorError(
|
||||
String.Format(RazorResources.ParseError_Expected_EndOfBlock_Before_EOF,
|
||||
RazorResources.BlockName_Code, '}', '{'),
|
||||
SourceLocation.Zero));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockReportsErrorIfClassBlockUnterminatedAtEOF()
|
||||
{
|
||||
ParseBlockTest("functions { var foo = bar; if(foo != null) { bar(); } ",
|
||||
new FunctionsBlock(
|
||||
Factory.MetaCode("functions {").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code(" var foo = bar; if(foo != null) { bar(); } ").AsFunctionsBody()
|
||||
),
|
||||
new RazorError(
|
||||
String.Format(RazorResources.ParseError_Expected_EndOfBlock_Before_EOF,
|
||||
"functions", '}', '{'),
|
||||
SourceLocation.Zero));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockReportsErrorIfIfBlockUnterminatedAtEOF()
|
||||
{
|
||||
RunUnterminatedSimpleKeywordBlock("if");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockReportsErrorIfElseBlockUnterminatedAtEOF()
|
||||
{
|
||||
ParseBlockTest("if(foo) { baz(); } else { var foo = bar; if(foo != null) { bar(); } ",
|
||||
new StatementBlock(
|
||||
Factory.Code("if(foo) { baz(); } else { var foo = bar; if(foo != null) { bar(); } ").AsStatement()
|
||||
),
|
||||
new RazorError(
|
||||
String.Format(RazorResources.ParseError_Expected_EndOfBlock_Before_EOF,
|
||||
"else", '}', '{'),
|
||||
new SourceLocation(19, 0, 19)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockReportsErrorIfElseIfBlockUnterminatedAtEOF()
|
||||
{
|
||||
ParseBlockTest("if(foo) { baz(); } else if { var foo = bar; if(foo != null) { bar(); } ",
|
||||
new StatementBlock(
|
||||
Factory.Code("if(foo) { baz(); } else if { var foo = bar; if(foo != null) { bar(); } ").AsStatement()
|
||||
),
|
||||
new RazorError(
|
||||
String.Format(RazorResources.ParseError_Expected_EndOfBlock_Before_EOF,
|
||||
"else if", '}', '{'),
|
||||
new SourceLocation(19, 0, 19)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockReportsErrorIfDoBlockUnterminatedAtEOF()
|
||||
{
|
||||
ParseBlockTest("do { var foo = bar; if(foo != null) { bar(); } ",
|
||||
new StatementBlock(
|
||||
Factory.Code("do { var foo = bar; if(foo != null) { bar(); } ").AsStatement()
|
||||
),
|
||||
new RazorError(
|
||||
String.Format(RazorResources.ParseError_Expected_EndOfBlock_Before_EOF,
|
||||
"do", '}', '{'),
|
||||
SourceLocation.Zero));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockReportsErrorIfTryBlockUnterminatedAtEOF()
|
||||
{
|
||||
ParseBlockTest("try { var foo = bar; if(foo != null) { bar(); } ",
|
||||
new StatementBlock(
|
||||
Factory.Code("try { var foo = bar; if(foo != null) { bar(); } ").AsStatement()
|
||||
),
|
||||
new RazorError(
|
||||
String.Format(RazorResources.ParseError_Expected_EndOfBlock_Before_EOF,
|
||||
"try", '}', '{'),
|
||||
SourceLocation.Zero));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockReportsErrorIfCatchBlockUnterminatedAtEOF()
|
||||
{
|
||||
ParseBlockTest("try { baz(); } catch(Foo) { var foo = bar; if(foo != null) { bar(); } ",
|
||||
new StatementBlock(
|
||||
Factory.Code("try { baz(); } catch(Foo) { var foo = bar; if(foo != null) { bar(); } ").AsStatement()
|
||||
),
|
||||
new RazorError(
|
||||
String.Format(RazorResources.ParseError_Expected_EndOfBlock_Before_EOF,
|
||||
"catch", '}', '{'),
|
||||
new SourceLocation(15, 0, 15)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockReportsErrorIfFinallyBlockUnterminatedAtEOF()
|
||||
{
|
||||
ParseBlockTest("try { baz(); } finally { var foo = bar; if(foo != null) { bar(); } ",
|
||||
new StatementBlock(
|
||||
Factory.Code("try { baz(); } finally { var foo = bar; if(foo != null) { bar(); } ").AsStatement()
|
||||
),
|
||||
new RazorError(
|
||||
String.Format(RazorResources.ParseError_Expected_EndOfBlock_Before_EOF,
|
||||
"finally", '}', '{'),
|
||||
new SourceLocation(15, 0, 15)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockReportsErrorIfForBlockUnterminatedAtEOF()
|
||||
{
|
||||
RunUnterminatedSimpleKeywordBlock("for");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockReportsErrorIfForeachBlockUnterminatedAtEOF()
|
||||
{
|
||||
RunUnterminatedSimpleKeywordBlock("foreach");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockReportsErrorIfWhileBlockUnterminatedAtEOF()
|
||||
{
|
||||
RunUnterminatedSimpleKeywordBlock("while");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockReportsErrorIfSwitchBlockUnterminatedAtEOF()
|
||||
{
|
||||
RunUnterminatedSimpleKeywordBlock("switch");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockReportsErrorIfLockBlockUnterminatedAtEOF()
|
||||
{
|
||||
RunUnterminatedSimpleKeywordBlock("lock");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockReportsErrorIfUsingBlockUnterminatedAtEOF()
|
||||
{
|
||||
RunUnterminatedSimpleKeywordBlock("using");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockRequiresControlFlowStatementsToHaveBraces()
|
||||
{
|
||||
string expectedMessage = String.Format(RazorResources.ParseError_SingleLine_ControlFlowStatements_Not_Allowed, "{", "<");
|
||||
ParseBlockTest("if(foo) <p>Bar</p> else if(bar) <p>Baz</p> else <p>Boz</p>",
|
||||
new StatementBlock(
|
||||
Factory.Code("if(foo) ").AsStatement(),
|
||||
new MarkupBlock(
|
||||
Factory.Markup("<p>Bar</p> ").Accepts(AcceptedCharacters.None)
|
||||
),
|
||||
Factory.Code("else if(bar) ").AsStatement(),
|
||||
new MarkupBlock(
|
||||
Factory.Markup("<p>Baz</p> ").Accepts(AcceptedCharacters.None)
|
||||
),
|
||||
Factory.Code("else ").AsStatement(),
|
||||
new MarkupBlock(
|
||||
Factory.Markup("<p>Boz</p>").Accepts(AcceptedCharacters.None)
|
||||
),
|
||||
Factory.EmptyCSharp().AsStatement()
|
||||
),
|
||||
new RazorError(expectedMessage, 8, 0, 8),
|
||||
new RazorError(expectedMessage, 32, 0, 32),
|
||||
new RazorError(expectedMessage, 48, 0, 48));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockIncludesUnexpectedCharacterInSingleStatementControlFlowStatementError()
|
||||
{
|
||||
ParseBlockTest("if(foo)) { var bar = foo; }",
|
||||
new StatementBlock(
|
||||
Factory.Code("if(foo)) { var bar = foo; }").AsStatement()
|
||||
),
|
||||
new RazorError(
|
||||
String.Format(RazorResources.ParseError_SingleLine_ControlFlowStatements_Not_Allowed,
|
||||
"{", ")"),
|
||||
new SourceLocation(7, 0, 7)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockOutputsErrorIfAtSignFollowedByLessThanSignAtStatementStart()
|
||||
{
|
||||
ParseBlockTest("if(foo) { @<p>Bar</p> }",
|
||||
new StatementBlock(
|
||||
Factory.Code("if(foo) {").AsStatement(),
|
||||
new MarkupBlock(
|
||||
Factory.Markup(" "),
|
||||
Factory.MarkupTransition(),
|
||||
Factory.Markup("<p>Bar</p> ").Accepts(AcceptedCharacters.None)
|
||||
),
|
||||
Factory.Code("}").AsStatement()
|
||||
),
|
||||
new RazorError(
|
||||
RazorResources.ParseError_AtInCode_Must_Be_Followed_By_Colon_Paren_Or_Identifier_Start,
|
||||
10, 0, 10));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockTerminatesIfBlockAtEOLWhenRecoveringFromMissingCloseParen()
|
||||
{
|
||||
ParseBlockTest("if(foo bar" + Environment.NewLine
|
||||
+ "baz",
|
||||
new StatementBlock(
|
||||
Factory.Code("if(foo bar\r\n").AsStatement()
|
||||
),
|
||||
new RazorError(
|
||||
String.Format(RazorResources.ParseError_Expected_CloseBracket_Before_EOF,
|
||||
"(", ")"),
|
||||
new SourceLocation(2, 0, 2)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockTerminatesForeachBlockAtEOLWhenRecoveringFromMissingCloseParen()
|
||||
{
|
||||
ParseBlockTest("foreach(foo bar" + Environment.NewLine
|
||||
+ "baz",
|
||||
new StatementBlock(
|
||||
Factory.Code("foreach(foo bar\r\n").AsStatement()
|
||||
),
|
||||
new RazorError(
|
||||
String.Format(RazorResources.ParseError_Expected_CloseBracket_Before_EOF,
|
||||
"(", ")"),
|
||||
new SourceLocation(7, 0, 7)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockTerminatesWhileClauseInDoStatementAtEOLWhenRecoveringFromMissingCloseParen()
|
||||
{
|
||||
ParseBlockTest("do { } while(foo bar" + Environment.NewLine
|
||||
+ "baz",
|
||||
new StatementBlock(
|
||||
Factory.Code("do { } while(foo bar\r\n").AsStatement()
|
||||
),
|
||||
new RazorError(
|
||||
String.Format(RazorResources.ParseError_Expected_CloseBracket_Before_EOF,
|
||||
"(", ")"),
|
||||
new SourceLocation(12, 0, 12)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockTerminatesUsingBlockAtEOLWhenRecoveringFromMissingCloseParen()
|
||||
{
|
||||
ParseBlockTest("using(foo bar" + Environment.NewLine
|
||||
+ "baz",
|
||||
new StatementBlock(
|
||||
Factory.Code("using(foo bar\r\n").AsStatement()
|
||||
),
|
||||
new RazorError(
|
||||
String.Format(RazorResources.ParseError_Expected_CloseBracket_Before_EOF,
|
||||
"(", ")"),
|
||||
new SourceLocation(5, 0, 5)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockResumesIfStatementAfterOpenParen()
|
||||
{
|
||||
ParseBlockTest("if(" + Environment.NewLine
|
||||
+ "else { <p>Foo</p> }",
|
||||
new StatementBlock(
|
||||
Factory.Code("if(\r\nelse {").AsStatement(),
|
||||
new MarkupBlock(
|
||||
Factory.Markup(" <p>Foo</p> ").Accepts(AcceptedCharacters.None)
|
||||
),
|
||||
Factory.Code("}").AsStatement().Accepts(AcceptedCharacters.None)
|
||||
),
|
||||
new RazorError(
|
||||
String.Format(RazorResources.ParseError_Expected_CloseBracket_Before_EOF,
|
||||
"(", ")"),
|
||||
new SourceLocation(2, 0, 2)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockTerminatesNormalCSharpStringsAtEOLIfEndQuoteMissing()
|
||||
{
|
||||
SingleSpanBlockTest("if(foo) {" + Environment.NewLine
|
||||
+ " var p = \"foo bar baz" + Environment.NewLine
|
||||
+ ";" + Environment.NewLine
|
||||
+ "}",
|
||||
BlockType.Statement, SpanKind.Code,
|
||||
new RazorError(RazorResources.ParseError_Unterminated_String_Literal, 23, 1, 12));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockTerminatesNormalStringAtEndOfFile()
|
||||
{
|
||||
SingleSpanBlockTest("if(foo) { var foo = \"blah blah blah blah blah", BlockType.Statement, SpanKind.Code,
|
||||
new RazorError(RazorResources.ParseError_Unterminated_String_Literal, 20, 0, 20),
|
||||
new RazorError(String.Format(RazorResources.ParseError_Expected_EndOfBlock_Before_EOF, "if", '}', '{'), SourceLocation.Zero));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockTerminatesVerbatimStringAtEndOfFile()
|
||||
{
|
||||
SingleSpanBlockTest("if(foo) { var foo = @\"blah " + Environment.NewLine
|
||||
+ "blah; " + Environment.NewLine
|
||||
+ "<p>Foo</p>" + Environment.NewLine
|
||||
+ "blah " + Environment.NewLine
|
||||
+ "blah",
|
||||
BlockType.Statement, SpanKind.Code,
|
||||
new RazorError(RazorResources.ParseError_Unterminated_String_Literal, 20, 0, 20),
|
||||
new RazorError(String.Format(RazorResources.ParseError_Expected_EndOfBlock_Before_EOF, "if", '}', '{'), SourceLocation.Zero));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockCorrectlyParsesMarkupIncorrectyAssumedToBeWithinAStatement()
|
||||
{
|
||||
ParseBlockTest("if(foo) {" + Environment.NewLine
|
||||
+ " var foo = \"foo bar baz" + Environment.NewLine
|
||||
+ " <p>Foo is @foo</p>" + Environment.NewLine
|
||||
+ "}",
|
||||
new StatementBlock(
|
||||
Factory.Code("if(foo) {\r\n var foo = \"foo bar baz\r\n ").AsStatement(),
|
||||
new MarkupBlock(
|
||||
Factory.Markup("<p>Foo is "),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("foo")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
Factory.Markup("</p>\r\n").Accepts(AcceptedCharacters.None)),
|
||||
Factory.Code("}").AsStatement()
|
||||
),
|
||||
new RazorError(
|
||||
RazorResources.ParseError_Unterminated_String_Literal,
|
||||
25, 1, 14));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockCorrectlyParsesAtSignInDelimitedBlock()
|
||||
{
|
||||
ParseBlockTest("(Request[\"description\"] ?? @photo.Description)",
|
||||
new ExpressionBlock(
|
||||
Factory.MetaCode("(").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("Request[\"description\"] ?? @photo.Description").AsExpression(),
|
||||
Factory.MetaCode(")").Accepts(AcceptedCharacters.None)
|
||||
));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockCorrectlyRecoversFromMissingCloseParenInExpressionWithinCode()
|
||||
{
|
||||
ParseBlockTest(@"{String.Format(<html></html>}",
|
||||
new StatementBlock(
|
||||
Factory.MetaCode("{").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("String.Format(")
|
||||
.AsStatement(),
|
||||
new MarkupBlock(
|
||||
Factory.Markup("<html></html>").Accepts(AcceptedCharacters.None)),
|
||||
Factory.EmptyCSharp().AsStatement(),
|
||||
Factory.MetaCode("}").Accepts(AcceptedCharacters.None)),
|
||||
expectedErrors: new[] {
|
||||
new RazorError(
|
||||
String.Format(RazorResources.ParseError_Expected_CloseBracket_Before_EOF, "(", ")"),
|
||||
14, 0, 14)
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private void RunUnterminatedSimpleKeywordBlock(string keyword)
|
||||
{
|
||||
SingleSpanBlockTest(keyword + " (foo) { var foo = bar; if(foo != null) { bar(); } ", BlockType.Statement, SpanKind.Code,
|
||||
new RazorError(String.Format(RazorResources.ParseError_Expected_EndOfBlock_Before_EOF, keyword, '}', '{'), SourceLocation.Zero));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,142 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||
using Microsoft.AspNet.Razor.Resources;
|
||||
using Microsoft.AspNet.Razor.Test.Framework;
|
||||
using Microsoft.AspNet.Razor.Text;
|
||||
using Microsoft.TestCommon;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Test.Parser.CSharp
|
||||
{
|
||||
public class CSharpExplicitExpressionTest : CsHtmlCodeParserTestBase
|
||||
{
|
||||
[Fact]
|
||||
public void ParseBlockShouldOutputZeroLengthCodeSpanIfExplicitExpressionIsEmpty()
|
||||
{
|
||||
ParseBlockTest("@()",
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("(").Accepts(AcceptedCharacters.None),
|
||||
Factory.EmptyCSharp().AsExpression(),
|
||||
Factory.MetaCode(")").Accepts(AcceptedCharacters.None)
|
||||
));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockShouldOutputZeroLengthCodeSpanIfEOFOccursAfterStartOfExplicitExpression()
|
||||
{
|
||||
ParseBlockTest("@(",
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("(").Accepts(AcceptedCharacters.None),
|
||||
Factory.EmptyCSharp().AsExpression()
|
||||
),
|
||||
new RazorError(
|
||||
String.Format(RazorResources.ParseError_Expected_EndOfBlock_Before_EOF,
|
||||
RazorResources.BlockName_ExplicitExpression,
|
||||
")", "("),
|
||||
new SourceLocation(1, 0, 1)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockShouldAcceptEscapedQuoteInNonVerbatimStrings()
|
||||
{
|
||||
ParseBlockTest("@(\"\\\"\")",
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("(").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("\"\\\"\"").AsExpression(),
|
||||
Factory.MetaCode(")").Accepts(AcceptedCharacters.None)
|
||||
));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockShouldAcceptEscapedQuoteInVerbatimStrings()
|
||||
{
|
||||
ParseBlockTest("@(@\"\"\"\")",
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("(").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("@\"\"\"\"").AsExpression(),
|
||||
Factory.MetaCode(")").Accepts(AcceptedCharacters.None)
|
||||
));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockShouldAcceptMultipleRepeatedEscapedQuoteInVerbatimStrings()
|
||||
{
|
||||
ParseBlockTest("@(@\"\"\"\"\"\")",
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("(").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("@\"\"\"\"\"\"").AsExpression(),
|
||||
Factory.MetaCode(")").Accepts(AcceptedCharacters.None)
|
||||
));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockShouldAcceptMultiLineVerbatimStrings()
|
||||
{
|
||||
ParseBlockTest(@"@(@""" + Environment.NewLine
|
||||
+ @"Foo" + Environment.NewLine
|
||||
+ @"Bar" + Environment.NewLine
|
||||
+ @"Baz" + Environment.NewLine
|
||||
+ @""")",
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("(").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("@\"\r\nFoo\r\nBar\r\nBaz\r\n\"").AsExpression(),
|
||||
Factory.MetaCode(")").Accepts(AcceptedCharacters.None)
|
||||
));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockShouldAcceptMultipleEscapedQuotesInNonVerbatimStrings()
|
||||
{
|
||||
ParseBlockTest("@(\"\\\"hello, world\\\"\")",
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("(").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("\"\\\"hello, world\\\"\"").AsExpression(),
|
||||
Factory.MetaCode(")").Accepts(AcceptedCharacters.None)
|
||||
));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockShouldAcceptMultipleEscapedQuotesInVerbatimStrings()
|
||||
{
|
||||
ParseBlockTest("@(@\"\"\"hello, world\"\"\")",
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("(").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("@\"\"\"hello, world\"\"\"").AsExpression(),
|
||||
Factory.MetaCode(")").Accepts(AcceptedCharacters.None)
|
||||
));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockShouldAcceptConsecutiveEscapedQuotesInNonVerbatimStrings()
|
||||
{
|
||||
ParseBlockTest("@(\"\\\"\\\"\")",
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("(").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("\"\\\"\\\"\"").AsExpression(),
|
||||
Factory.MetaCode(")").Accepts(AcceptedCharacters.None)
|
||||
));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockShouldAcceptConsecutiveEscapedQuotesInVerbatimStrings()
|
||||
{
|
||||
ParseBlockTest("@(@\"\"\"\"\"\")",
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("(").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("@\"\"\"\"\"\"").AsExpression(),
|
||||
Factory.MetaCode(")").Accepts(AcceptedCharacters.None)
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,347 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.AspNet.Razor.Generator;
|
||||
using Microsoft.AspNet.Razor.Parser;
|
||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||
using Microsoft.AspNet.Razor.Resources;
|
||||
using Microsoft.AspNet.Razor.Test.Framework;
|
||||
using Microsoft.AspNet.Razor.Text;
|
||||
using Microsoft.TestCommon;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Test.Parser.CSharp
|
||||
{
|
||||
public class CSharpHelperTest : CsHtmlMarkupParserTestBase
|
||||
{
|
||||
[Fact]
|
||||
public void ParseHelperCorrectlyParsesHelperWithNoSpaceInBody()
|
||||
{
|
||||
ParseDocumentTest("@helper Foo(){@Bar()}",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new HelperBlock(new HelperCodeGenerator(new LocationTagged<string>("Foo(){", 8, 0, 8), headerComplete: true),
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("helper ").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("Foo(){").Hidden().Accepts(AcceptedCharacters.None),
|
||||
new StatementBlock(
|
||||
Factory.EmptyCSharp().AsStatement(),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("Bar()")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords, acceptTrailingDot: true)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
Factory.EmptyCSharp().AsStatement()),
|
||||
Factory.Code("}").Hidden().Accepts(AcceptedCharacters.None)),
|
||||
Factory.EmptyHtml()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseHelperCorrectlyParsesIncompleteHelperPreceedingCodeBlock()
|
||||
{
|
||||
ParseDocumentTest("@helper" + Environment.NewLine
|
||||
+ "@{}",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new HelperBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("helper")),
|
||||
Factory.Markup("\r\n"),
|
||||
new StatementBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("{").Accepts(AcceptedCharacters.None),
|
||||
Factory.EmptyCSharp().AsStatement(),
|
||||
Factory.MetaCode("}").Accepts(AcceptedCharacters.None)),
|
||||
Factory.EmptyHtml()),
|
||||
new RazorError(
|
||||
String.Format(
|
||||
RazorResources.ParseError_Unexpected_Character_At_Helper_Name_Start,
|
||||
RazorResources.ErrorComponent_Newline),
|
||||
7, 0, 7));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseHelperRequiresSpaceBeforeSignature()
|
||||
{
|
||||
ParseDocumentTest("@helper{",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new HelperBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("helper")),
|
||||
Factory.Markup("{")),
|
||||
new RazorError(
|
||||
String.Format(
|
||||
RazorResources.ParseError_Unexpected_Character_At_Helper_Name_Start,
|
||||
String.Format(RazorResources.ErrorComponent_Character, "{")),
|
||||
7, 0, 7));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseHelperOutputsErrorButContinuesIfLParenFoundAfterHelperKeyword()
|
||||
{
|
||||
ParseDocumentTest("@helper () {",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new HelperBlock(new HelperCodeGenerator(new LocationTagged<string>("() {", 8, 0, 8), headerComplete: true),
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("helper ").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("() {").Hidden().Accepts(AcceptedCharacters.None),
|
||||
new StatementBlock(
|
||||
Factory.EmptyCSharp()
|
||||
.AsStatement()
|
||||
.AutoCompleteWith("}")))),
|
||||
new RazorError(
|
||||
String.Format(
|
||||
RazorResources.ParseError_Unexpected_Character_At_Helper_Name_Start,
|
||||
String.Format(RazorResources.ErrorComponent_Character, "(")),
|
||||
8, 0, 8),
|
||||
new RazorError(
|
||||
String.Format(
|
||||
RazorResources.ParseError_Expected_EndOfBlock_Before_EOF,
|
||||
"helper", "}", "{"),
|
||||
1, 0, 1));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseHelperStatementOutputsMarkerHelperHeaderSpanOnceKeywordComplete()
|
||||
{
|
||||
ParseDocumentTest("@helper ",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new HelperBlock(new HelperCodeGenerator(new LocationTagged<string>(String.Empty, 8, 0, 8), headerComplete: false),
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("helper ").Accepts(AcceptedCharacters.None),
|
||||
Factory.EmptyCSharp().Hidden())),
|
||||
new RazorError(
|
||||
String.Format(
|
||||
RazorResources.ParseError_Unexpected_Character_At_Helper_Name_Start,
|
||||
RazorResources.ErrorComponent_EndOfFile),
|
||||
8, 0, 8));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseHelperStatementMarksHelperSpanAsCanGrowIfMissingTrailingSpace()
|
||||
{
|
||||
ParseDocumentTest("@helper",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new HelperBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("helper").Accepts(AcceptedCharacters.Any))),
|
||||
new RazorError(
|
||||
String.Format(
|
||||
RazorResources.ParseError_Unexpected_Character_At_Helper_Name_Start,
|
||||
RazorResources.ErrorComponent_EndOfFile),
|
||||
7, 0, 7));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseHelperStatementCapturesWhitespaceToEndOfLineIfHelperStatementMissingName()
|
||||
{
|
||||
ParseDocumentTest("@helper " + Environment.NewLine
|
||||
+ " ",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new HelperBlock(new HelperCodeGenerator(new LocationTagged<string>(" ", 8, 0, 8), headerComplete: false),
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("helper ").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code(" \r\n").Hidden()),
|
||||
Factory.Markup(@" ")),
|
||||
new RazorError(
|
||||
String.Format(
|
||||
RazorResources.ParseError_Unexpected_Character_At_Helper_Name_Start,
|
||||
RazorResources.ErrorComponent_Newline),
|
||||
30, 0, 30));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseHelperStatementCapturesWhitespaceToEndOfLineIfHelperStatementMissingOpenParen()
|
||||
{
|
||||
ParseDocumentTest("@helper Foo " + Environment.NewLine
|
||||
+ " ",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new HelperBlock(new HelperCodeGenerator(new LocationTagged<string>("Foo ", 8, 0, 8), headerComplete: false),
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("helper ").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("Foo \r\n").Hidden()),
|
||||
Factory.Markup(" ")),
|
||||
new RazorError(
|
||||
String.Format(RazorResources.ParseError_MissingCharAfterHelperName, "("),
|
||||
15, 0, 15));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseHelperStatementCapturesAllContentToEndOfFileIfHelperStatementMissingCloseParenInParameterList()
|
||||
{
|
||||
ParseDocumentTest("@helper Foo(Foo Bar" + Environment.NewLine
|
||||
+ "Biz" + Environment.NewLine
|
||||
+ "Boz",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new HelperBlock(new HelperCodeGenerator(new LocationTagged<string>("Foo(Foo Bar\r\nBiz\r\nBoz", 8, 0, 8), headerComplete: false),
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("helper ").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("Foo(Foo Bar\r\nBiz\r\nBoz").Hidden())),
|
||||
new RazorError(
|
||||
RazorResources.ParseError_UnterminatedHelperParameterList,
|
||||
11, 0, 11));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseHelperStatementCapturesWhitespaceToEndOfLineIfHelperStatementMissingOpenBraceAfterParameterList()
|
||||
{
|
||||
ParseDocumentTest("@helper Foo(string foo) " + Environment.NewLine,
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new HelperBlock(new HelperCodeGenerator(new LocationTagged<string>("Foo(string foo) ", 8, 0, 8), headerComplete: false),
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("helper ").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("Foo(string foo) \r\n").Hidden())),
|
||||
new RazorError(
|
||||
String.Format(RazorResources.ParseError_MissingCharAfterHelperParameters, "{"),
|
||||
29, 1, 0));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseHelperStatementContinuesParsingHelperUntilEOF()
|
||||
{
|
||||
ParseDocumentTest("@helper Foo(string foo) { " + Environment.NewLine
|
||||
+ " <p>Foo</p>",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new HelperBlock(new HelperCodeGenerator(new LocationTagged<string>("Foo(string foo) {", 8, 0, 8), headerComplete: true),
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("helper ").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code(@"Foo(string foo) {").Hidden().Accepts(AcceptedCharacters.None),
|
||||
new StatementBlock(
|
||||
Factory.Code(" \r\n")
|
||||
.AsStatement()
|
||||
.AutoCompleteWith("}"),
|
||||
new MarkupBlock(
|
||||
Factory.Markup(" <p>Foo</p>").Accepts(AcceptedCharacters.None)),
|
||||
Factory.EmptyCSharp().AsStatement()))),
|
||||
new RazorError(
|
||||
String.Format(
|
||||
RazorResources.ParseError_Expected_EndOfBlock_Before_EOF,
|
||||
"helper", "}", "{"),
|
||||
1, 0, 1));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseHelperStatementCorrectlyParsesHelperWithEmbeddedCode()
|
||||
{
|
||||
ParseDocumentTest("@helper Foo(string foo) { " + Environment.NewLine
|
||||
+ " <p>@foo</p>" + Environment.NewLine
|
||||
+ "}",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new HelperBlock(new HelperCodeGenerator(new LocationTagged<string>("Foo(string foo) {", 8, 0, 8), headerComplete: true),
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("helper ").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code(@"Foo(string foo) {").Hidden().Accepts(AcceptedCharacters.None),
|
||||
new StatementBlock(
|
||||
Factory.Code(" \r\n").AsStatement(),
|
||||
new MarkupBlock(
|
||||
Factory.Markup(" <p>"),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("foo")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
Factory.Markup("</p>\r\n").Accepts(AcceptedCharacters.None)),
|
||||
Factory.EmptyCSharp().AsStatement()),
|
||||
Factory.Code("}").Hidden().Accepts(AcceptedCharacters.None)),
|
||||
Factory.EmptyHtml()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseHelperStatementCorrectlyParsesHelperWithNewlinesBetweenCloseParenAndOpenBrace()
|
||||
{
|
||||
ParseDocumentTest("@helper Foo(string foo)" + Environment.NewLine
|
||||
+ Environment.NewLine
|
||||
+ Environment.NewLine
|
||||
+ Environment.NewLine
|
||||
+ "{ " + Environment.NewLine
|
||||
+ " <p>@foo</p>" + Environment.NewLine
|
||||
+ "}",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new HelperBlock(new HelperCodeGenerator(new LocationTagged<string>("Foo(string foo)\r\n\r\n\r\n\r\n{", 8, 0, 8), headerComplete: true),
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("helper ").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("Foo(string foo)\r\n\r\n\r\n\r\n{").Hidden().Accepts(AcceptedCharacters.None),
|
||||
new StatementBlock(
|
||||
Factory.Code(" \r\n").AsStatement(),
|
||||
new MarkupBlock(
|
||||
Factory.Markup(@" <p>"),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("foo")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
Factory.Markup("</p>\r\n").Accepts(AcceptedCharacters.None)),
|
||||
Factory.EmptyCSharp().AsStatement()),
|
||||
Factory.Code("}").Hidden().Accepts(AcceptedCharacters.None)),
|
||||
Factory.EmptyHtml()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseHelperStatementGivesWhitespaceAfterOpenBraceToMarkupInDesignMode()
|
||||
{
|
||||
ParseDocumentTest("@helper Foo(string foo) { " + Environment.NewLine
|
||||
+ " ",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new HelperBlock(new HelperCodeGenerator(new LocationTagged<string>("Foo(string foo) {", 8, 0, 8), headerComplete: true),
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("helper ").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code(@"Foo(string foo) {").Hidden().Accepts(AcceptedCharacters.None),
|
||||
new StatementBlock(
|
||||
Factory.Code(" \r\n ")
|
||||
.AsStatement()
|
||||
.AutoCompleteWith("}")))),
|
||||
designTimeParser: true,
|
||||
expectedErrors: new[]
|
||||
{
|
||||
new RazorError(
|
||||
String.Format(
|
||||
RazorResources.ParseError_Expected_EndOfBlock_Before_EOF,
|
||||
"helper", "}", "{"),
|
||||
new SourceLocation(1, 0, 1))
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseHelperAcceptsNestedHelpersButOutputsError()
|
||||
{
|
||||
ParseDocumentTest(@"@helper Foo(string foo) {" + Environment.NewLine
|
||||
+ " @helper Bar(string baz) {" + Environment.NewLine
|
||||
+ " }" + Environment.NewLine
|
||||
+ "}",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new HelperBlock(new HelperCodeGenerator(new LocationTagged<string>("Foo(string foo) {", 8, 0, 8), headerComplete: true),
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("helper ").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code(@"Foo(string foo) {").Hidden().Accepts(AcceptedCharacters.None),
|
||||
new StatementBlock(
|
||||
Factory.Code("\r\n ").AsStatement(),
|
||||
new HelperBlock(new HelperCodeGenerator(new LocationTagged<string>("Bar(string baz) {", 39, 1, 12), headerComplete: true),
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("helper ").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code(@"Bar(string baz) {").Hidden().Accepts(AcceptedCharacters.None),
|
||||
new StatementBlock(
|
||||
Factory.Code("\r\n ").AsStatement()),
|
||||
Factory.Code("}").Hidden().Accepts(AcceptedCharacters.None)),
|
||||
Factory.Code("\r\n").AsStatement()),
|
||||
Factory.Code("}").Hidden().Accepts(AcceptedCharacters.None)),
|
||||
Factory.EmptyHtml()),
|
||||
designTimeParser: true,
|
||||
expectedErrors: new[]
|
||||
{
|
||||
new RazorError(RazorResources.ParseError_Helpers_Cannot_Be_Nested, 38, 1, 11)
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,204 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.AspNet.Razor.Parser;
|
||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||
using Microsoft.AspNet.Razor.Resources;
|
||||
using Microsoft.AspNet.Razor.Test.Framework;
|
||||
using Microsoft.AspNet.Razor.Text;
|
||||
using Microsoft.TestCommon;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Test.Parser.CSharp
|
||||
{
|
||||
public class CSharpImplicitExpressionTest : CsHtmlCodeParserTestBase
|
||||
{
|
||||
private const string TestExtraKeyword = "model";
|
||||
|
||||
public override ParserBase CreateCodeParser()
|
||||
{
|
||||
return new CSharpCodeParser();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NestedImplicitExpression()
|
||||
{
|
||||
ParseBlockTest("if (true) { @foo }",
|
||||
new StatementBlock(
|
||||
Factory.Code("if (true) { ").AsStatement(),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("foo")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords, acceptTrailingDot: true)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
Factory.Code(" }").AsStatement()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockAcceptsNonEnglishCharactersThatAreValidIdentifiers()
|
||||
{
|
||||
ImplicitExpressionTest("हळूँजद॔.", "हळूँजद॔");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockOutputsZeroLengthCodeSpanIfInvalidCharacterFollowsTransition()
|
||||
{
|
||||
ParseBlockTest("@/",
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.EmptyCSharp()
|
||||
.AsImplicitExpression(KeywordSet)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
new RazorError(
|
||||
String.Format(RazorResources.ParseError_Unexpected_Character_At_Start_Of_CodeBlock_CS, "/"),
|
||||
new SourceLocation(1, 0, 1)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockOutputsZeroLengthCodeSpanIfEOFOccursAfterTransition()
|
||||
{
|
||||
ParseBlockTest("@",
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.EmptyCSharp()
|
||||
.AsImplicitExpression(KeywordSet)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
new RazorError(
|
||||
RazorResources.ParseError_Unexpected_EndOfFile_At_Start_Of_CodeBlock,
|
||||
new SourceLocation(1, 0, 1)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockSupportsSlashesWithinComplexImplicitExpressions()
|
||||
{
|
||||
ImplicitExpressionTest("DataGridColumn.Template(\"Years of Service\", e => (int)Math.Round((DateTime.Now - dt).TotalDays / 365))");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockMethodParsesSingleIdentifierAsImplicitExpression()
|
||||
{
|
||||
ImplicitExpressionTest("foo");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockMethodDoesNotAcceptSemicolonIfExpressionTerminatedByWhitespace()
|
||||
{
|
||||
ImplicitExpressionTest("foo ;", "foo");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockMethodIgnoresSemicolonAtEndOfSimpleImplicitExpression()
|
||||
{
|
||||
RunTrailingSemicolonTest("foo");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockMethodParsesDottedIdentifiersAsImplicitExpression()
|
||||
{
|
||||
ImplicitExpressionTest("foo.bar.baz");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockMethodIgnoresSemicolonAtEndOfDottedIdentifiers()
|
||||
{
|
||||
RunTrailingSemicolonTest("foo.bar.baz");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockMethodDoesNotIncludeDotAtEOFInImplicitExpression()
|
||||
{
|
||||
ImplicitExpressionTest("foo.bar.", "foo.bar");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockMethodDoesNotIncludeDotFollowedByInvalidIdentifierCharacterInImplicitExpression()
|
||||
{
|
||||
ImplicitExpressionTest("foo.bar.0", "foo.bar");
|
||||
ImplicitExpressionTest("foo.bar.</p>", "foo.bar");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockMethodDoesNotIncludeSemicolonAfterDot()
|
||||
{
|
||||
ImplicitExpressionTest("foo.bar.;", "foo.bar");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockMethodTerminatesAfterIdentifierUnlessFollowedByDotOrParenInImplicitExpression()
|
||||
{
|
||||
ImplicitExpressionTest("foo.bar</p>", "foo.bar");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockProperlyParsesParenthesesAndBalancesThemInImplicitExpression()
|
||||
{
|
||||
ImplicitExpressionTest(@"foo().bar(""bi\""z"", 4)(""chained method; call"").baz(@""bo""""z"", '\'', () => { return 4; }, (4+5+new { foo = bar[4] }))");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockProperlyParsesBracketsAndBalancesThemInImplicitExpression()
|
||||
{
|
||||
ImplicitExpressionTest(@"foo.bar[4 * (8 + 7)][""fo\""o""].baz");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockTerminatesImplicitExpressionAtHtmlEndTag()
|
||||
{
|
||||
ImplicitExpressionTest("foo().bar.baz</p>zoop", "foo().bar.baz");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockTerminatesImplicitExpressionAtHtmlStartTag()
|
||||
{
|
||||
ImplicitExpressionTest("foo().bar.baz<p>zoop", "foo().bar.baz");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockTerminatesImplicitExpressionBeforeDotIfDotNotFollowedByIdentifierStartCharacter()
|
||||
{
|
||||
ImplicitExpressionTest("foo().bar.baz.42", "foo().bar.baz");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockStopsBalancingParenthesesAtEOF()
|
||||
{
|
||||
ImplicitExpressionTest("foo(()", "foo(()",
|
||||
acceptedCharacters: AcceptedCharacters.Any,
|
||||
errors: new RazorError(String.Format(RazorResources.ParseError_Expected_CloseBracket_Before_EOF, "(", ")"), new SourceLocation(4, 0, 4)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockTerminatesImplicitExpressionIfCloseParenFollowedByAnyWhiteSpace()
|
||||
{
|
||||
ImplicitExpressionTest("foo.bar() (baz)", "foo.bar()");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockTerminatesImplicitExpressionIfIdentifierFollowedByAnyWhiteSpace()
|
||||
{
|
||||
ImplicitExpressionTest("foo .bar() (baz)", "foo");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockTerminatesImplicitExpressionAtLastValidPointIfDotFollowedByWhitespace()
|
||||
{
|
||||
ImplicitExpressionTest("foo. bar() (baz)", "foo");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockOutputExpressionIfModuleTokenNotFollowedByBrace()
|
||||
{
|
||||
ImplicitExpressionTest("module.foo()");
|
||||
}
|
||||
|
||||
private void RunTrailingSemicolonTest(string expr)
|
||||
{
|
||||
ParseBlockTest(SyntaxConstants.TransitionString + expr + ";",
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code(expr)
|
||||
.AsImplicitExpression(KeywordSet)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,109 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.AspNet.Razor.Editor;
|
||||
using Microsoft.AspNet.Razor.Generator;
|
||||
using Microsoft.AspNet.Razor.Parser;
|
||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||
using Microsoft.AspNet.Razor.Test.Framework;
|
||||
using Microsoft.TestCommon;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Test.Parser.CSharp
|
||||
{
|
||||
public class CSharpLayoutDirectiveTest : CsHtmlCodeParserTestBase
|
||||
{
|
||||
[Theory]
|
||||
[InlineData("Layout")]
|
||||
[InlineData("LAYOUT")]
|
||||
[InlineData("layOut")]
|
||||
[InlineData("LayOut")]
|
||||
private void LayoutKeywordIsCaseSensitive(string word)
|
||||
{
|
||||
ParseBlockTest(word,
|
||||
new ExpressionBlock(
|
||||
Factory.Code(word)
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)
|
||||
));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void LayoutDirectiveAcceptsAllTextToEndOfLine()
|
||||
{
|
||||
ParseBlockTest("@layout Foo Bar Baz",
|
||||
new DirectiveBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("layout ").Accepts(AcceptedCharacters.None),
|
||||
Factory.MetaCode("Foo Bar Baz")
|
||||
.With(new SetLayoutCodeGenerator("Foo Bar Baz"))
|
||||
.WithEditorHints(EditorHints.VirtualPath | EditorHints.LayoutPage)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void LayoutDirectiveAcceptsAnyIfNoWhitespaceFollowingLayoutKeyword()
|
||||
{
|
||||
ParseBlockTest("@layout",
|
||||
new DirectiveBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("layout")
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void LayoutDirectiveOutputsMarkerSpanIfAnyWhitespaceAfterLayoutKeyword()
|
||||
{
|
||||
ParseBlockTest("@layout ",
|
||||
new DirectiveBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("layout ").Accepts(AcceptedCharacters.None),
|
||||
Factory.EmptyCSharp()
|
||||
.AsMetaCode()
|
||||
.With(new SetLayoutCodeGenerator(String.Empty))
|
||||
.WithEditorHints(EditorHints.VirtualPath | EditorHints.LayoutPage)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void LayoutDirectiveAcceptsTrailingNewlineButDoesNotIncludeItInLayoutPath()
|
||||
{
|
||||
ParseBlockTest("@layout Foo" + Environment.NewLine,
|
||||
new DirectiveBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("layout ").Accepts(AcceptedCharacters.None),
|
||||
Factory.MetaCode("Foo\r\n")
|
||||
.With(new SetLayoutCodeGenerator("Foo"))
|
||||
.Accepts(AcceptedCharacters.None)
|
||||
.WithEditorHints(EditorHints.VirtualPath | EditorHints.LayoutPage)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void LayoutDirectiveCorrectlyRestoresContextAfterCompleting()
|
||||
{
|
||||
ParseDocumentTest("@layout Foo" + Environment.NewLine
|
||||
+ "@foo",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new DirectiveBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("layout ").Accepts(AcceptedCharacters.None),
|
||||
Factory.MetaCode("Foo\r\n")
|
||||
.With(new SetLayoutCodeGenerator("Foo"))
|
||||
.Accepts(AcceptedCharacters.None)
|
||||
.WithEditorHints(EditorHints.VirtualPath | EditorHints.LayoutPage)
|
||||
),
|
||||
Factory.EmptyHtml(),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("foo")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords, acceptTrailingDot: false)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
Factory.EmptyHtml()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,102 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNet.Razor.Generator;
|
||||
using Microsoft.AspNet.Razor.Parser;
|
||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||
using Microsoft.AspNet.Razor.Test.Framework;
|
||||
using Microsoft.TestCommon;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Test.Parser.CSharp
|
||||
{
|
||||
public class CSharpNestedStatementsTest : CsHtmlCodeParserTestBase
|
||||
{
|
||||
[Fact]
|
||||
public void NestedSimpleStatement()
|
||||
{
|
||||
ParseBlockTest("@while(true) { foo(); }",
|
||||
new StatementBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("while(true) { foo(); }")
|
||||
.AsStatement()
|
||||
.Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NestedKeywordStatement()
|
||||
{
|
||||
ParseBlockTest("@while(true) { for(int i = 0; i < 10; i++) { foo(); } }",
|
||||
new StatementBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("while(true) { for(int i = 0; i < 10; i++) { foo(); } }")
|
||||
.AsStatement()
|
||||
.Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NestedCodeBlock()
|
||||
{
|
||||
ParseBlockTest("@while(true) { { { { foo(); } } } }",
|
||||
new StatementBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("while(true) { { { { foo(); } } } }")
|
||||
.AsStatement()
|
||||
.Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NestedImplicitExpression()
|
||||
{
|
||||
ParseBlockTest("@while(true) { @foo }",
|
||||
new StatementBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("while(true) { ")
|
||||
.AsStatement(),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("foo")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords, acceptTrailingDot: true)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
Factory.Code(" }")
|
||||
.AsStatement()
|
||||
.Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NestedExplicitExpression()
|
||||
{
|
||||
ParseBlockTest("@while(true) { @(foo) }",
|
||||
new StatementBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("while(true) { ")
|
||||
.AsStatement(),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("(")
|
||||
.Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("foo")
|
||||
.AsExpression(),
|
||||
Factory.MetaCode(")")
|
||||
.Accepts(AcceptedCharacters.None)),
|
||||
Factory.Code(" }")
|
||||
.AsStatement()
|
||||
.Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NestedMarkupBlock()
|
||||
{
|
||||
ParseBlockTest("@while(true) { <p>Hello</p> }",
|
||||
new StatementBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("while(true) {")
|
||||
.AsStatement(),
|
||||
new MarkupBlock(
|
||||
Factory.Markup(" <p>Hello</p> ")
|
||||
.With(new MarkupCodeGenerator())
|
||||
.Accepts(AcceptedCharacters.None)),
|
||||
Factory.Code("}")
|
||||
.AsStatement()
|
||||
.Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,174 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.AspNet.Razor.Parser;
|
||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||
using Microsoft.AspNet.Razor.Resources;
|
||||
using Microsoft.AspNet.Razor.Test.Framework;
|
||||
using Microsoft.AspNet.Razor.Tokenizer.Symbols;
|
||||
using Microsoft.TestCommon;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Test.Parser.CSharp
|
||||
{
|
||||
public class CSharpRazorCommentsTest : CsHtmlMarkupParserTestBase
|
||||
{
|
||||
[Fact]
|
||||
public void UnterminatedRazorComment()
|
||||
{
|
||||
ParseDocumentTest("@*",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new CommentBlock(
|
||||
Factory.MarkupTransition(HtmlSymbolType.RazorCommentTransition)
|
||||
.Accepts(AcceptedCharacters.None),
|
||||
Factory.MetaMarkup("*", HtmlSymbolType.RazorCommentStar)
|
||||
.Accepts(AcceptedCharacters.None),
|
||||
Factory.Span(SpanKind.Comment, new HtmlSymbol(
|
||||
Factory.LocationTracker.CurrentLocation,
|
||||
String.Empty,
|
||||
HtmlSymbolType.Unknown))
|
||||
.Accepts(AcceptedCharacters.Any))),
|
||||
new RazorError(RazorResources.ParseError_RazorComment_Not_Terminated, 0, 0, 0));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EmptyRazorComment()
|
||||
{
|
||||
ParseDocumentTest("@**@",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new CommentBlock(
|
||||
Factory.MarkupTransition(HtmlSymbolType.RazorCommentTransition)
|
||||
.Accepts(AcceptedCharacters.None),
|
||||
Factory.MetaMarkup("*", HtmlSymbolType.RazorCommentStar)
|
||||
.Accepts(AcceptedCharacters.None),
|
||||
Factory.Span(SpanKind.Comment, new HtmlSymbol(
|
||||
Factory.LocationTracker.CurrentLocation,
|
||||
String.Empty,
|
||||
HtmlSymbolType.Unknown))
|
||||
.Accepts(AcceptedCharacters.Any),
|
||||
Factory.MetaMarkup("*", HtmlSymbolType.RazorCommentStar)
|
||||
.Accepts(AcceptedCharacters.None),
|
||||
Factory.MarkupTransition(HtmlSymbolType.RazorCommentTransition)
|
||||
.Accepts(AcceptedCharacters.None)),
|
||||
Factory.EmptyHtml()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RazorCommentInImplicitExpressionMethodCall()
|
||||
{
|
||||
ParseDocumentTest("@foo(" + Environment.NewLine
|
||||
+ "@**@" + Environment.NewLine,
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("foo(\r\n")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords),
|
||||
new CommentBlock(
|
||||
Factory.CodeTransition(CSharpSymbolType.RazorCommentTransition)
|
||||
.Accepts(AcceptedCharacters.None),
|
||||
Factory.MetaCode("*", CSharpSymbolType.RazorCommentStar)
|
||||
.Accepts(AcceptedCharacters.None),
|
||||
Factory.Span(SpanKind.Comment, new CSharpSymbol(
|
||||
Factory.LocationTracker.CurrentLocation,
|
||||
String.Empty,
|
||||
CSharpSymbolType.Unknown))
|
||||
.Accepts(AcceptedCharacters.Any),
|
||||
Factory.MetaCode("*", CSharpSymbolType.RazorCommentStar)
|
||||
.Accepts(AcceptedCharacters.None),
|
||||
Factory.CodeTransition(CSharpSymbolType.RazorCommentTransition)
|
||||
.Accepts(AcceptedCharacters.None)),
|
||||
Factory.Code("\r\n")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords))),
|
||||
new RazorError(
|
||||
String.Format(RazorResources.ParseError_Expected_CloseBracket_Before_EOF, "(", ")"),
|
||||
4, 0, 4));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void UnterminatedRazorCommentInImplicitExpressionMethodCall()
|
||||
{
|
||||
ParseDocumentTest("@foo(@*",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("foo(")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords),
|
||||
new CommentBlock(
|
||||
Factory.CodeTransition(CSharpSymbolType.RazorCommentTransition)
|
||||
.Accepts(AcceptedCharacters.None),
|
||||
Factory.MetaCode("*", CSharpSymbolType.RazorCommentStar)
|
||||
.Accepts(AcceptedCharacters.None),
|
||||
Factory.Span(SpanKind.Comment, new CSharpSymbol(
|
||||
Factory.LocationTracker.CurrentLocation,
|
||||
String.Empty,
|
||||
CSharpSymbolType.Unknown))
|
||||
.Accepts(AcceptedCharacters.Any)))),
|
||||
new RazorError(RazorResources.ParseError_RazorComment_Not_Terminated, 5, 0, 5),
|
||||
new RazorError(String.Format(RazorResources.ParseError_Expected_CloseBracket_Before_EOF, "(", ")"), 4, 0, 4));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RazorCommentInVerbatimBlock()
|
||||
{
|
||||
ParseDocumentTest("@{" + Environment.NewLine
|
||||
+ " <text" + Environment.NewLine
|
||||
+ " @**@" + Environment.NewLine
|
||||
+ "}",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new StatementBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("{").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("\r\n").AsStatement(),
|
||||
new MarkupBlock(
|
||||
Factory.Markup(" "),
|
||||
Factory.MarkupTransition("<text").Accepts(AcceptedCharacters.Any),
|
||||
Factory.Markup("\r\n "),
|
||||
new CommentBlock(
|
||||
Factory.MarkupTransition(HtmlSymbolType.RazorCommentTransition)
|
||||
.Accepts(AcceptedCharacters.None),
|
||||
Factory.MetaMarkup("*", HtmlSymbolType.RazorCommentStar)
|
||||
.Accepts(AcceptedCharacters.None),
|
||||
Factory.Span(SpanKind.Comment, new HtmlSymbol(
|
||||
Factory.LocationTracker.CurrentLocation,
|
||||
String.Empty,
|
||||
HtmlSymbolType.Unknown))
|
||||
.Accepts(AcceptedCharacters.Any),
|
||||
Factory.MetaMarkup("*", HtmlSymbolType.RazorCommentStar)
|
||||
.Accepts(AcceptedCharacters.None),
|
||||
Factory.MarkupTransition(HtmlSymbolType.RazorCommentTransition)
|
||||
.Accepts(AcceptedCharacters.None)),
|
||||
Factory.Markup("\r\n}")))),
|
||||
new RazorError(RazorResources.ParseError_TextTagCannotContainAttributes, 8, 1, 4),
|
||||
new RazorError(String.Format(RazorResources.ParseError_MissingEndTag, "text"), 8, 1, 4),
|
||||
new RazorError(String.Format(RazorResources.ParseError_Expected_EndOfBlock_Before_EOF, RazorResources.BlockName_Code, "}", "{"), 1, 0, 1));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void UnterminatedRazorCommentInVerbatimBlock()
|
||||
{
|
||||
ParseDocumentTest("@{@*",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new StatementBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("{").Accepts(AcceptedCharacters.None),
|
||||
Factory.EmptyCSharp()
|
||||
.AsStatement(),
|
||||
new CommentBlock(
|
||||
Factory.CodeTransition(CSharpSymbolType.RazorCommentTransition)
|
||||
.Accepts(AcceptedCharacters.None),
|
||||
Factory.MetaCode("*", CSharpSymbolType.RazorCommentStar)
|
||||
.Accepts(AcceptedCharacters.None),
|
||||
Factory.Span(SpanKind.Comment, new CSharpSymbol(Factory.LocationTracker.CurrentLocation,
|
||||
String.Empty,
|
||||
CSharpSymbolType.Unknown))
|
||||
.Accepts(AcceptedCharacters.Any)))),
|
||||
new RazorError(RazorResources.ParseError_RazorComment_Not_Terminated, 2, 0, 2),
|
||||
new RazorError(String.Format(RazorResources.ParseError_Expected_EndOfBlock_Before_EOF, RazorResources.BlockName_Code, "}", "{"), 1, 0, 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.AspNet.Razor.Parser;
|
||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||
using Microsoft.AspNet.Razor.Resources;
|
||||
using Microsoft.AspNet.Razor.Test.Framework;
|
||||
using Microsoft.AspNet.Razor.Text;
|
||||
using Microsoft.TestCommon;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Test.Parser.CSharp
|
||||
{
|
||||
public class CSharpReservedWordsTest : CsHtmlCodeParserTestBase
|
||||
{
|
||||
[Theory]
|
||||
[InlineData("namespace")]
|
||||
[InlineData("class")]
|
||||
public void ReservedWords(string word)
|
||||
{
|
||||
ParseBlockTest(word,
|
||||
new DirectiveBlock(
|
||||
Factory.MetaCode(word).Accepts(AcceptedCharacters.None)
|
||||
),
|
||||
new RazorError(String.Format(RazorResources.ParseError_ReservedWord, word), SourceLocation.Zero));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("Namespace")]
|
||||
[InlineData("Class")]
|
||||
[InlineData("NAMESPACE")]
|
||||
[InlineData("CLASS")]
|
||||
[InlineData("nameSpace")]
|
||||
[InlineData("NameSpace")]
|
||||
private void ReservedWordsAreCaseSensitive(string word)
|
||||
{
|
||||
ParseBlockTest(word,
|
||||
new ExpressionBlock(
|
||||
Factory.Code(word)
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,405 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.AspNet.Razor.Generator;
|
||||
using Microsoft.AspNet.Razor.Parser;
|
||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||
using Microsoft.AspNet.Razor.Resources;
|
||||
using Microsoft.AspNet.Razor.Test.Framework;
|
||||
using Microsoft.TestCommon;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Test.Parser.CSharp
|
||||
{
|
||||
public class CSharpSectionTest : CsHtmlMarkupParserTestBase
|
||||
{
|
||||
[Fact]
|
||||
public void ParseSectionBlockCapturesNewlineImmediatelyFollowing()
|
||||
{
|
||||
ParseDocumentTest("@section" + Environment.NewLine,
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new SectionBlock(new SectionCodeGenerator(String.Empty),
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("section\r\n"))),
|
||||
new RazorError(
|
||||
String.Format(
|
||||
RazorResources.ParseError_Unexpected_Character_At_Section_Name_Start,
|
||||
RazorResources.ErrorComponent_EndOfFile),
|
||||
10, 1, 0));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseSectionBlockCapturesWhitespaceToEndOfLineInSectionStatementMissingOpenBrace()
|
||||
{
|
||||
ParseDocumentTest("@section Foo " + Environment.NewLine
|
||||
+ " ",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new SectionBlock(new SectionCodeGenerator("Foo"),
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("section Foo \r\n")),
|
||||
Factory.Markup(" ")),
|
||||
new RazorError(RazorResources.ParseError_MissingOpenBraceAfterSection, 12, 0, 12));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseSectionBlockCapturesWhitespaceToEndOfLineInSectionStatementMissingName()
|
||||
{
|
||||
ParseDocumentTest("@section " + Environment.NewLine
|
||||
+ " ",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new SectionBlock(new SectionCodeGenerator(String.Empty),
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("section \r\n")),
|
||||
Factory.Markup(" ")),
|
||||
new RazorError(
|
||||
String.Format(
|
||||
RazorResources.ParseError_Unexpected_Character_At_Section_Name_Start,
|
||||
RazorResources.ErrorComponent_EndOfFile),
|
||||
23, 1, 4));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseSectionBlockIgnoresSectionUnlessAllLowerCase()
|
||||
{
|
||||
ParseDocumentTest("@Section foo",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("Section")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
Factory.Markup(" foo")));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseSectionBlockReportsErrorAndTerminatesSectionBlockIfKeywordNotFollowedByIdentifierStartCharacter()
|
||||
{
|
||||
ParseDocumentTest("@section 9 { <p>Foo</p> }",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new SectionBlock(new SectionCodeGenerator(String.Empty),
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("section ")),
|
||||
Factory.Markup("9 { <p>Foo</p> }")),
|
||||
new RazorError(
|
||||
String.Format(
|
||||
RazorResources.ParseError_Unexpected_Character_At_Section_Name_Start,
|
||||
String.Format(RazorResources.ErrorComponent_Character, "9")),
|
||||
9, 0, 9));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseSectionBlockReportsErrorAndTerminatesSectionBlockIfNameNotFollowedByOpenBrace()
|
||||
{
|
||||
ParseDocumentTest("@section foo-bar { <p>Foo</p> }",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new SectionBlock(new SectionCodeGenerator("foo"),
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("section foo")),
|
||||
Factory.Markup("-bar { <p>Foo</p> }")),
|
||||
new RazorError(RazorResources.ParseError_MissingOpenBraceAfterSection, 12, 0, 12));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParserOutputsErrorOnNestedSections()
|
||||
{
|
||||
ParseDocumentTest("@section foo { @section bar { <p>Foo</p> } }",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new SectionBlock(new SectionCodeGenerator("foo"),
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("section foo {")
|
||||
.AutoCompleteWith(null, atEndOfSpan: true),
|
||||
new MarkupBlock(
|
||||
Factory.Markup(" "),
|
||||
new SectionBlock(new SectionCodeGenerator("bar"),
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("section bar {")
|
||||
.AutoCompleteWith(null, atEndOfSpan: true),
|
||||
new MarkupBlock(
|
||||
Factory.Markup(" <p>Foo</p> ")),
|
||||
Factory.MetaCode("}").Accepts(AcceptedCharacters.None)),
|
||||
Factory.Markup(" ")),
|
||||
Factory.MetaCode("}").Accepts(AcceptedCharacters.None)),
|
||||
Factory.EmptyHtml()),
|
||||
new RazorError(
|
||||
String.Format(
|
||||
RazorResources.ParseError_Sections_Cannot_Be_Nested,
|
||||
RazorResources.SectionExample_CS),
|
||||
23, 0, 23));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseSectionBlockHandlesEOFAfterOpenBrace()
|
||||
{
|
||||
ParseDocumentTest("@section foo {",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new SectionBlock(new SectionCodeGenerator("foo"),
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("section foo {")
|
||||
.AutoCompleteWith("}", atEndOfSpan: true),
|
||||
new MarkupBlock())),
|
||||
new RazorError(
|
||||
String.Format(RazorResources.ParseError_Expected_X, "}"),
|
||||
14, 0, 14));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseSectionBlockHandlesUnterminatedSection()
|
||||
{
|
||||
ParseDocumentTest("@section foo { <p>Foo{}</p>",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new SectionBlock(new SectionCodeGenerator("foo"),
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("section foo {")
|
||||
.AutoCompleteWith("}", atEndOfSpan: true),
|
||||
new MarkupBlock(
|
||||
// Need to provide the markup span as fragments, since the parser will split the {} into separate symbols.
|
||||
Factory.Markup(" <p>Foo", "{", "}", "</p>")))),
|
||||
new RazorError(
|
||||
String.Format(RazorResources.ParseError_Expected_X, "}"),
|
||||
27, 0, 27));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseSectionBlockReportsErrorAndAcceptsWhitespaceToEndOfLineIfSectionNotFollowedByOpenBrace()
|
||||
{
|
||||
ParseDocumentTest("@section foo " + Environment.NewLine,
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new SectionBlock(new SectionCodeGenerator("foo"),
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("section foo \r\n"))),
|
||||
new RazorError(RazorResources.ParseError_MissingOpenBraceAfterSection, 12, 0, 12));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseSectionBlockAcceptsOpenBraceMultipleLinesBelowSectionName()
|
||||
{
|
||||
ParseDocumentTest("@section foo " + Environment.NewLine
|
||||
+ Environment.NewLine
|
||||
+ Environment.NewLine
|
||||
+ Environment.NewLine
|
||||
+ Environment.NewLine
|
||||
+ Environment.NewLine
|
||||
+ "{" + Environment.NewLine
|
||||
+ "<p>Foo</p>" + Environment.NewLine
|
||||
+ "}",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new SectionBlock(new SectionCodeGenerator("foo"),
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("section foo \r\n\r\n\r\n\r\n\r\n\r\n{")
|
||||
.AutoCompleteWith(null, atEndOfSpan: true),
|
||||
new MarkupBlock(
|
||||
Factory.Markup("\r\n<p>Foo</p>\r\n")),
|
||||
Factory.MetaCode("}").Accepts(AcceptedCharacters.None)),
|
||||
Factory.EmptyHtml()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseSectionBlockParsesNamedSectionCorrectly()
|
||||
{
|
||||
ParseDocumentTest("@section foo { <p>Foo</p> }",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new SectionBlock(new SectionCodeGenerator("foo"),
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("section foo {")
|
||||
.AutoCompleteWith(null, atEndOfSpan: true),
|
||||
new MarkupBlock(
|
||||
Factory.Markup(" <p>Foo</p> ")),
|
||||
Factory.MetaCode("}").Accepts(AcceptedCharacters.None)),
|
||||
Factory.EmptyHtml()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseSectionBlockDoesNotRequireSpaceBetweenSectionNameAndOpenBrace()
|
||||
{
|
||||
ParseDocumentTest("@section foo{ <p>Foo</p> }",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new SectionBlock(new SectionCodeGenerator("foo"),
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("section foo{")
|
||||
.AutoCompleteWith(null, atEndOfSpan: true),
|
||||
new MarkupBlock(
|
||||
Factory.Markup(" <p>Foo</p> ")),
|
||||
Factory.MetaCode("}").Accepts(AcceptedCharacters.None)),
|
||||
Factory.EmptyHtml()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseSectionBlockBalancesBraces()
|
||||
{
|
||||
ParseDocumentTest("@section foo { <script>(function foo() { return 1; })();</script> }",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new SectionBlock(new SectionCodeGenerator("foo"),
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("section foo {")
|
||||
.AutoCompleteWith(null, atEndOfSpan: true),
|
||||
new MarkupBlock(
|
||||
Factory.Markup(" <script>(function foo() { return 1; })();</script> ")),
|
||||
Factory.MetaCode("}").Accepts(AcceptedCharacters.None)),
|
||||
Factory.EmptyHtml()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseSectionBlockAllowsBracesInCSharpExpression()
|
||||
{
|
||||
ParseDocumentTest("@section foo { I really want to render a close brace, so here I go: @(\"}\") }",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new SectionBlock(new SectionCodeGenerator("foo"),
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("section foo {")
|
||||
.AutoCompleteWith(null, atEndOfSpan: true),
|
||||
new MarkupBlock(
|
||||
Factory.Markup(" I really want to render a close brace, so here I go: "),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("(").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("\"}\"").AsExpression(),
|
||||
Factory.MetaCode(")").Accepts(AcceptedCharacters.None)),
|
||||
Factory.Markup(" ")),
|
||||
Factory.MetaCode("}").Accepts(AcceptedCharacters.None)),
|
||||
Factory.EmptyHtml()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SectionIsCorrectlyTerminatedWhenCloseBraceImmediatelyFollowsCodeBlock()
|
||||
{
|
||||
ParseDocumentTest("@section Foo {" + Environment.NewLine
|
||||
+ "@if(true) {" + Environment.NewLine
|
||||
+ "}" + Environment.NewLine
|
||||
+ "}",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new SectionBlock(new SectionCodeGenerator("Foo"),
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("section Foo {")
|
||||
.AutoCompleteWith(null, atEndOfSpan: true),
|
||||
new MarkupBlock(
|
||||
Factory.Markup("\r\n"),
|
||||
new StatementBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("if(true) {\r\n}\r\n").AsStatement()
|
||||
)),
|
||||
Factory.MetaCode("}").Accepts(AcceptedCharacters.None)),
|
||||
Factory.EmptyHtml()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SectionIsCorrectlyTerminatedWhenCloseBraceImmediatelyFollowsCodeBlockNoWhitespace()
|
||||
{
|
||||
ParseDocumentTest("@section Foo {" + Environment.NewLine
|
||||
+ "@if(true) {" + Environment.NewLine
|
||||
+ "}}",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new SectionBlock(new SectionCodeGenerator("Foo"),
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("section Foo {")
|
||||
.AutoCompleteWith(null, atEndOfSpan: true),
|
||||
new MarkupBlock(
|
||||
Factory.Markup("\r\n"),
|
||||
new StatementBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("if(true) {\r\n}").AsStatement()
|
||||
)),
|
||||
Factory.MetaCode("}").Accepts(AcceptedCharacters.None)),
|
||||
Factory.EmptyHtml()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseSectionBlockCorrectlyTerminatesWhenCloseBraceImmediatelyFollowsMarkup()
|
||||
{
|
||||
ParseDocumentTest("@section foo {something}",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new SectionBlock(new SectionCodeGenerator("foo"),
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("section foo {")
|
||||
.AutoCompleteWith(null, atEndOfSpan: true),
|
||||
new MarkupBlock(
|
||||
Factory.Markup("something")),
|
||||
Factory.MetaCode("}").Accepts(AcceptedCharacters.None)),
|
||||
Factory.EmptyHtml()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseSectionBlockParsesComment()
|
||||
{
|
||||
ParseDocumentTest("@section s {<!-- -->}",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new SectionBlock(new SectionCodeGenerator("s"),
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("section s {")
|
||||
.AutoCompleteWith(null, atEndOfSpan: true),
|
||||
new MarkupBlock(
|
||||
Factory.Markup("<!-- -->")),
|
||||
Factory.MetaCode("}").Accepts(AcceptedCharacters.None)),
|
||||
Factory.EmptyHtml()));
|
||||
}
|
||||
|
||||
// This was a user reported bug (codeplex #710), the section parser wasn't handling
|
||||
// comments.
|
||||
[Fact]
|
||||
public void ParseSectionBlockParsesCommentWithDelimiters()
|
||||
{
|
||||
ParseDocumentTest("@section s {<!-- > \" '-->}",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new SectionBlock(new SectionCodeGenerator("s"),
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("section s {")
|
||||
.AutoCompleteWith(null, atEndOfSpan: true),
|
||||
new MarkupBlock(
|
||||
Factory.Markup("<!-- > \" '-->")),
|
||||
Factory.MetaCode("}").Accepts(AcceptedCharacters.None)),
|
||||
Factory.EmptyHtml()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseSectionBlockCommentRecoversFromUnclosedTag()
|
||||
{
|
||||
ParseDocumentTest(
|
||||
"@section s {" + Environment.NewLine + "<a" + Environment.NewLine + "<!-- > \" '-->}",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new SectionBlock(new SectionCodeGenerator("s"),
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("section s {")
|
||||
.AutoCompleteWith(null, atEndOfSpan: true),
|
||||
new MarkupBlock(
|
||||
Factory.Markup(Environment.NewLine + "<a" + Environment.NewLine + "<!-- > \" '-->")),
|
||||
Factory.MetaCode("}").Accepts(AcceptedCharacters.None)),
|
||||
Factory.EmptyHtml()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseSectionBlockParsesXmlProcessingInstruction()
|
||||
{
|
||||
ParseDocumentTest(
|
||||
"@section s { <? xml bleh ?>}",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new SectionBlock(new SectionCodeGenerator("s"),
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("section s {")
|
||||
.AutoCompleteWith(null, atEndOfSpan: true),
|
||||
new MarkupBlock(
|
||||
Factory.Markup(" <? xml bleh ?>")),
|
||||
Factory.MetaCode("}").Accepts(AcceptedCharacters.None)),
|
||||
Factory.EmptyHtml()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,198 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.AspNet.Razor.Parser;
|
||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||
using Microsoft.AspNet.Razor.Resources;
|
||||
using Microsoft.AspNet.Razor.Test.Framework;
|
||||
using Microsoft.AspNet.Razor.Text;
|
||||
using Microsoft.TestCommon;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Test.Parser.CSharp
|
||||
{
|
||||
public class CSharpSpecialBlockTest : CsHtmlCodeParserTestBase
|
||||
{
|
||||
[Fact]
|
||||
public void ParseInheritsStatementMarksInheritsSpanAsCanGrowIfMissingTrailingSpace()
|
||||
{
|
||||
ParseBlockTest("inherits",
|
||||
new DirectiveBlock(
|
||||
Factory.MetaCode("inherits").Accepts(AcceptedCharacters.Any)
|
||||
),
|
||||
new RazorError(
|
||||
RazorResources.ParseError_InheritsKeyword_Must_Be_Followed_By_TypeName,
|
||||
new SourceLocation(8, 0, 8)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InheritsBlockAcceptsMultipleGenericArguments()
|
||||
{
|
||||
ParseBlockTest("inherits Foo.Bar<Biz<Qux>, string, int>.Baz",
|
||||
new DirectiveBlock(
|
||||
Factory.MetaCode("inherits ").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("Foo.Bar<Biz<Qux>, string, int>.Baz")
|
||||
.AsBaseType("Foo.Bar<Biz<Qux>, string, int>.Baz")
|
||||
));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InheritsBlockOutputsErrorIfInheritsNotFollowedByTypeButAcceptsEntireLineAsCode()
|
||||
{
|
||||
ParseBlockTest("inherits " + Environment.NewLine
|
||||
+ "foo",
|
||||
new DirectiveBlock(
|
||||
Factory.MetaCode("inherits ").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code(" \r\n")
|
||||
.AsBaseType(String.Empty)
|
||||
),
|
||||
new RazorError(RazorResources.ParseError_InheritsKeyword_Must_Be_Followed_By_TypeName, 24, 0, 24));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NamespaceImportInsideCodeBlockCausesError()
|
||||
{
|
||||
ParseBlockTest("{ using Foo.Bar.Baz; var foo = bar; }",
|
||||
new StatementBlock(
|
||||
Factory.MetaCode("{").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code(" using Foo.Bar.Baz; var foo = bar; ").AsStatement(),
|
||||
Factory.MetaCode("}").Accepts(AcceptedCharacters.None)
|
||||
),
|
||||
new RazorError(
|
||||
RazorResources.ParseError_NamespaceImportAndTypeAlias_Cannot_Exist_Within_CodeBlock,
|
||||
new SourceLocation(2, 0, 2)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TypeAliasInsideCodeBlockIsNotHandledSpecially()
|
||||
{
|
||||
ParseBlockTest("{ using Foo = Bar.Baz; var foo = bar; }",
|
||||
new StatementBlock(
|
||||
Factory.MetaCode("{").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code(" using Foo = Bar.Baz; var foo = bar; ").AsStatement(),
|
||||
Factory.MetaCode("}").Accepts(AcceptedCharacters.None)
|
||||
),
|
||||
new RazorError(
|
||||
RazorResources.ParseError_NamespaceImportAndTypeAlias_Cannot_Exist_Within_CodeBlock,
|
||||
new SourceLocation(2, 0, 2)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Plan9FunctionsKeywordInsideCodeBlockIsNotHandledSpecially()
|
||||
{
|
||||
ParseBlockTest("{ functions Foo; }",
|
||||
new StatementBlock(
|
||||
Factory.MetaCode("{").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code(" functions Foo; ").AsStatement(),
|
||||
Factory.MetaCode("}").Accepts(AcceptedCharacters.None)
|
||||
));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NonKeywordStatementInCodeBlockIsHandledCorrectly()
|
||||
{
|
||||
ParseBlockTest("{" + Environment.NewLine
|
||||
+ " List<dynamic> photos = gallery.Photo.ToList();" + Environment.NewLine
|
||||
+ "}",
|
||||
new StatementBlock(
|
||||
Factory.MetaCode("{").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("\r\n List<dynamic> photos = gallery.Photo.ToList();\r\n").AsStatement(),
|
||||
Factory.MetaCode("}").Accepts(AcceptedCharacters.None)
|
||||
));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockBalancesBracesOutsideStringsIfFirstCharacterIsBraceAndReturnsSpanOfTypeCode()
|
||||
{
|
||||
// Arrange
|
||||
const string code = "foo\"b}ar\" if(condition) { String.Format(\"{0}\"); } ";
|
||||
|
||||
// Act/Assert
|
||||
ParseBlockTest("{" + code + "}",
|
||||
new StatementBlock(
|
||||
Factory.MetaCode("{").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code(code).AsStatement(),
|
||||
Factory.MetaCode("}").Accepts(AcceptedCharacters.None)
|
||||
));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockBalancesParensOutsideStringsIfFirstCharacterIsParenAndReturnsSpanOfTypeExpression()
|
||||
{
|
||||
// Arrange
|
||||
const string code = "foo\"b)ar\" if(condition) { String.Format(\"{0}\"); } ";
|
||||
|
||||
// Act/Assert
|
||||
ParseBlockTest("(" + code + ")",
|
||||
new ExpressionBlock(
|
||||
Factory.MetaCode("(").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code(code).AsExpression(),
|
||||
Factory.MetaCode(")").Accepts(AcceptedCharacters.None)
|
||||
));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockBalancesBracesAndOutputsContentAsClassLevelCodeSpanIfFirstIdentifierIsFunctionsKeyword()
|
||||
{
|
||||
const string code = " foo(); \"bar}baz\" ";
|
||||
ParseBlockTest("functions {" + code + "} zoop",
|
||||
new FunctionsBlock(
|
||||
Factory.MetaCode("functions {").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code(code).AsFunctionsBody(),
|
||||
Factory.MetaCode("}").Accepts(AcceptedCharacters.None)
|
||||
));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockDoesNoErrorRecoveryForFunctionsBlock()
|
||||
{
|
||||
ParseBlockTest("functions { { { { { } zoop",
|
||||
new FunctionsBlock(
|
||||
Factory.MetaCode("functions {").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code(" { { { { } zoop").AsFunctionsBody()
|
||||
),
|
||||
new RazorError(
|
||||
String.Format(RazorResources.ParseError_Expected_EndOfBlock_Before_EOF, "functions", "}", "{"),
|
||||
SourceLocation.Zero));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockIgnoresFunctionsUnlessAllLowerCase()
|
||||
{
|
||||
ParseBlockTest("Functions { foo() }",
|
||||
new ExpressionBlock(
|
||||
Factory.Code("Functions")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockIgnoresSingleSlashAtStart()
|
||||
{
|
||||
ParseBlockTest("@/ foo",
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.EmptyCSharp()
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
new RazorError(
|
||||
String.Format(RazorResources.ParseError_Unexpected_Character_At_Start_Of_CodeBlock_CS, "/"),
|
||||
1, 0, 1));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockTerminatesSingleLineCommentAtEndOfLine()
|
||||
{
|
||||
ParseBlockTest("if(!false) {" + Environment.NewLine
|
||||
+ " // Foo" + Environment.NewLine
|
||||
+ "\t<p>A real tag!</p>" + Environment.NewLine
|
||||
+ "}",
|
||||
new StatementBlock(
|
||||
Factory.Code("if(!false) {\r\n // Foo\r\n").AsStatement(),
|
||||
new MarkupBlock(
|
||||
Factory.Markup("\t<p>A real tag!</p>\r\n")
|
||||
.Accepts(AcceptedCharacters.None)),
|
||||
Factory.Code("}").AsStatement()
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,210 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNet.Razor.Generator;
|
||||
using Microsoft.AspNet.Razor.Parser;
|
||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||
using Microsoft.AspNet.Razor.Test.Framework;
|
||||
using Microsoft.TestCommon;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Test.Parser.CSharp
|
||||
{
|
||||
// Basic Tests for C# Statements:
|
||||
// * Basic case for each statement
|
||||
// * Basic case for ALL clauses
|
||||
|
||||
// This class DOES NOT contain
|
||||
// * Error cases
|
||||
// * Tests for various types of nested statements
|
||||
// * Comment tests
|
||||
|
||||
public class CSharpStatementTest : CsHtmlCodeParserTestBase
|
||||
{
|
||||
[Fact]
|
||||
public void ForStatement()
|
||||
{
|
||||
ParseBlockTest("@for(int i = 0; i++; i < length) { foo(); }",
|
||||
new StatementBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("for(int i = 0; i++; i < length) { foo(); }")
|
||||
.AsStatement()
|
||||
.Accepts(AcceptedCharacters.None)
|
||||
));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ForEachStatement()
|
||||
{
|
||||
ParseBlockTest("@foreach(var foo in bar) { foo(); }",
|
||||
new StatementBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("foreach(var foo in bar) { foo(); }")
|
||||
.AsStatement()
|
||||
.Accepts(AcceptedCharacters.None)
|
||||
));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void WhileStatement()
|
||||
{
|
||||
ParseBlockTest("@while(true) { foo(); }",
|
||||
new StatementBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("while(true) { foo(); }")
|
||||
.AsStatement()
|
||||
.Accepts(AcceptedCharacters.None)
|
||||
));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SwitchStatement()
|
||||
{
|
||||
ParseBlockTest("@switch(foo) { foo(); }",
|
||||
new StatementBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("switch(foo) { foo(); }")
|
||||
.AsStatement()
|
||||
.Accepts(AcceptedCharacters.None)
|
||||
));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void LockStatement()
|
||||
{
|
||||
ParseBlockTest("@lock(baz) { foo(); }",
|
||||
new StatementBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("lock(baz) { foo(); }")
|
||||
.AsStatement()
|
||||
.Accepts(AcceptedCharacters.None)
|
||||
));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IfStatement()
|
||||
{
|
||||
ParseBlockTest("@if(true) { foo(); }",
|
||||
new StatementBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("if(true) { foo(); }")
|
||||
.AsStatement()
|
||||
));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ElseIfClause()
|
||||
{
|
||||
ParseBlockTest("@if(true) { foo(); } else if(false) { foo(); } else if(!false) { foo(); }",
|
||||
new StatementBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("if(true) { foo(); } else if(false) { foo(); } else if(!false) { foo(); }")
|
||||
.AsStatement()
|
||||
));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ElseClause()
|
||||
{
|
||||
ParseBlockTest("@if(true) { foo(); } else { foo(); }",
|
||||
new StatementBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("if(true) { foo(); } else { foo(); }")
|
||||
.AsStatement()
|
||||
.Accepts(AcceptedCharacters.None)
|
||||
));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TryStatement()
|
||||
{
|
||||
ParseBlockTest("@try { foo(); }",
|
||||
new StatementBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("try { foo(); }")
|
||||
.AsStatement()
|
||||
));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CatchClause()
|
||||
{
|
||||
ParseBlockTest("@try { foo(); } catch(IOException ioex) { handleIO(); } catch(Exception ex) { handleOther(); }",
|
||||
new StatementBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("try { foo(); } catch(IOException ioex) { handleIO(); } catch(Exception ex) { handleOther(); }")
|
||||
.AsStatement()
|
||||
));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FinallyClause()
|
||||
{
|
||||
ParseBlockTest("@try { foo(); } finally { Dispose(); }",
|
||||
new StatementBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("try { foo(); } finally { Dispose(); }")
|
||||
.AsStatement()
|
||||
.Accepts(AcceptedCharacters.None)
|
||||
));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void UsingStatement()
|
||||
{
|
||||
ParseBlockTest("@using(var foo = new Foo()) { foo.Bar(); }",
|
||||
new StatementBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("using(var foo = new Foo()) { foo.Bar(); }")
|
||||
.AsStatement()
|
||||
.Accepts(AcceptedCharacters.None)
|
||||
));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void UsingTypeAlias()
|
||||
{
|
||||
ParseBlockTest("@using StringDictionary = System.Collections.Generic.Dictionary<string, string>",
|
||||
new DirectiveBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("using StringDictionary = System.Collections.Generic.Dictionary<string, string>")
|
||||
.AsNamespaceImport(" StringDictionary = System.Collections.Generic.Dictionary<string, string>", 5)
|
||||
.Accepts(AcceptedCharacters.AnyExceptNewline)
|
||||
));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void UsingNamespaceImport()
|
||||
{
|
||||
ParseBlockTest("@using System.Text.Encoding.ASCIIEncoding",
|
||||
new DirectiveBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("using System.Text.Encoding.ASCIIEncoding")
|
||||
.AsNamespaceImport(" System.Text.Encoding.ASCIIEncoding", 5)
|
||||
.Accepts(AcceptedCharacters.AnyExceptNewline)
|
||||
));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DoStatement()
|
||||
{
|
||||
ParseBlockTest("@do { foo(); } while(true);",
|
||||
new StatementBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("do { foo(); } while(true);")
|
||||
.AsStatement()
|
||||
.Accepts(AcceptedCharacters.None)
|
||||
));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NonBlockKeywordTreatedAsImplicitExpression()
|
||||
{
|
||||
ParseBlockTest("@is foo",
|
||||
new ExpressionBlock(new ExpressionCodeGenerator(),
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("is")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,261 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.AspNet.Razor.Editor;
|
||||
using Microsoft.AspNet.Razor.Parser;
|
||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||
using Microsoft.AspNet.Razor.Resources;
|
||||
using Microsoft.AspNet.Razor.Test.Framework;
|
||||
using Microsoft.AspNet.Razor.Text;
|
||||
using Microsoft.AspNet.Razor.Tokenizer.Symbols;
|
||||
using Microsoft.TestCommon;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Test.Parser.CSharp
|
||||
{
|
||||
public class CSharpTemplateTest : CsHtmlCodeParserTestBase
|
||||
{
|
||||
private const string TestTemplateCode = " @<p>Foo #@item</p>";
|
||||
|
||||
private TemplateBlock TestTemplate()
|
||||
{
|
||||
return new TemplateBlock(
|
||||
new MarkupBlock(
|
||||
Factory.MarkupTransition(),
|
||||
Factory.Markup("<p>Foo #"),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("item")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)
|
||||
),
|
||||
Factory.Markup("</p>").Accepts(AcceptedCharacters.None)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
private const string TestNestedTemplateCode = " @<p>Foo #@Html.Repeat(10, @<p>@item</p>)</p>";
|
||||
|
||||
private TemplateBlock TestNestedTemplate()
|
||||
{
|
||||
return new TemplateBlock(
|
||||
new MarkupBlock(
|
||||
Factory.MarkupTransition(),
|
||||
Factory.Markup("<p>Foo #"),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("Html.Repeat(10, ")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords),
|
||||
new TemplateBlock(
|
||||
new MarkupBlock(
|
||||
Factory.MarkupTransition(),
|
||||
Factory.Markup("<p>"),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("item")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)
|
||||
),
|
||||
Factory.Markup("</p>").Accepts(AcceptedCharacters.None)
|
||||
)
|
||||
),
|
||||
Factory.Code(")")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)
|
||||
),
|
||||
Factory.Markup("</p>").Accepts(AcceptedCharacters.None)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockHandlesSingleLineTemplate()
|
||||
{
|
||||
ParseBlockTest("{ var foo = @: bar" + Environment.NewLine
|
||||
+ "; }",
|
||||
new StatementBlock(
|
||||
Factory.MetaCode("{").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code(" var foo = ").AsStatement(),
|
||||
new TemplateBlock(
|
||||
new MarkupBlock(
|
||||
Factory.MarkupTransition(),
|
||||
Factory.MetaMarkup(":", HtmlSymbolType.Colon),
|
||||
Factory.Markup(" bar\r\n")
|
||||
.With(new SingleLineMarkupEditHandler(CSharpLanguageCharacteristics.Instance.TokenizeString))
|
||||
.Accepts(AcceptedCharacters.None)
|
||||
)
|
||||
),
|
||||
Factory.Code("; ").AsStatement(),
|
||||
Factory.MetaCode("}").Accepts(AcceptedCharacters.None)
|
||||
));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockHandlesSingleLineImmediatelyFollowingStatementChar()
|
||||
{
|
||||
ParseBlockTest("{i@: bar" + Environment.NewLine
|
||||
+ "}",
|
||||
new StatementBlock(
|
||||
Factory.MetaCode("{").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("i").AsStatement(),
|
||||
new TemplateBlock(
|
||||
new MarkupBlock(
|
||||
Factory.MarkupTransition(),
|
||||
Factory.MetaMarkup(":", HtmlSymbolType.Colon),
|
||||
Factory.Markup(" bar\r\n")
|
||||
.With(new SingleLineMarkupEditHandler(CSharpLanguageCharacteristics.Instance.TokenizeString))
|
||||
.Accepts(AcceptedCharacters.None)
|
||||
)
|
||||
),
|
||||
Factory.EmptyCSharp().AsStatement(),
|
||||
Factory.MetaCode("}").Accepts(AcceptedCharacters.None)
|
||||
));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockHandlesSimpleTemplateInExplicitExpressionParens()
|
||||
{
|
||||
ParseBlockTest("(Html.Repeat(10," + TestTemplateCode + "))",
|
||||
new ExpressionBlock(
|
||||
Factory.MetaCode("(").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("Html.Repeat(10, ").AsExpression(),
|
||||
TestTemplate(),
|
||||
Factory.Code(")").AsExpression(),
|
||||
Factory.MetaCode(")").Accepts(AcceptedCharacters.None)
|
||||
));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockHandlesSimpleTemplateInImplicitExpressionParens()
|
||||
{
|
||||
ParseBlockTest("Html.Repeat(10," + TestTemplateCode + ")",
|
||||
new ExpressionBlock(
|
||||
Factory.Code("Html.Repeat(10, ")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords),
|
||||
TestTemplate(),
|
||||
Factory.Code(")")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)
|
||||
));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockHandlesTwoTemplatesInImplicitExpressionParens()
|
||||
{
|
||||
ParseBlockTest("Html.Repeat(10," + TestTemplateCode + "," + TestTemplateCode + ")",
|
||||
new ExpressionBlock(
|
||||
Factory.Code("Html.Repeat(10, ")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords),
|
||||
TestTemplate(),
|
||||
Factory.Code(", ")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords),
|
||||
TestTemplate(),
|
||||
Factory.Code(")")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords).Accepts(AcceptedCharacters.NonWhiteSpace)
|
||||
));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockProducesErrorButCorrectlyParsesNestedTemplateInImplicitExpressionParens()
|
||||
{
|
||||
ParseBlockTest("Html.Repeat(10," + TestNestedTemplateCode + ")",
|
||||
new ExpressionBlock(
|
||||
Factory.Code("Html.Repeat(10, ")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords),
|
||||
TestNestedTemplate(),
|
||||
Factory.Code(")")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)
|
||||
),
|
||||
GetNestedTemplateError(42));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockHandlesSimpleTemplateInStatementWithinCodeBlock()
|
||||
{
|
||||
ParseBlockTest("foreach(foo in Bar) { Html.ExecuteTemplate(foo," + TestTemplateCode + "); }",
|
||||
new StatementBlock(
|
||||
Factory.Code("foreach(foo in Bar) { Html.ExecuteTemplate(foo, ").AsStatement(),
|
||||
TestTemplate(),
|
||||
Factory.Code("); }")
|
||||
.AsStatement()
|
||||
.Accepts(AcceptedCharacters.None)
|
||||
));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockHandlesTwoTemplatesInStatementWithinCodeBlock()
|
||||
{
|
||||
ParseBlockTest("foreach(foo in Bar) { Html.ExecuteTemplate(foo," + TestTemplateCode + "," + TestTemplateCode + "); }",
|
||||
new StatementBlock(
|
||||
Factory.Code("foreach(foo in Bar) { Html.ExecuteTemplate(foo, ").AsStatement(),
|
||||
TestTemplate(),
|
||||
Factory.Code(", ").AsStatement(),
|
||||
TestTemplate(),
|
||||
Factory.Code("); }")
|
||||
.AsStatement()
|
||||
.Accepts(AcceptedCharacters.None)
|
||||
));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockProducesErrorButCorrectlyParsesNestedTemplateInStatementWithinCodeBlock()
|
||||
{
|
||||
ParseBlockTest("foreach(foo in Bar) { Html.ExecuteTemplate(foo," + TestNestedTemplateCode + "); }",
|
||||
new StatementBlock(
|
||||
Factory.Code("foreach(foo in Bar) { Html.ExecuteTemplate(foo, ").AsStatement(),
|
||||
TestNestedTemplate(),
|
||||
Factory.Code("); }")
|
||||
.AsStatement()
|
||||
.Accepts(AcceptedCharacters.None)
|
||||
),
|
||||
GetNestedTemplateError(74));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockHandlesSimpleTemplateInStatementWithinStatementBlock()
|
||||
{
|
||||
ParseBlockTest("{ var foo = bar; Html.ExecuteTemplate(foo," + TestTemplateCode + "); }",
|
||||
new StatementBlock(
|
||||
Factory.MetaCode("{").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code(" var foo = bar; Html.ExecuteTemplate(foo, ").AsStatement(),
|
||||
TestTemplate(),
|
||||
Factory.Code("); ").AsStatement(),
|
||||
Factory.MetaCode("}").Accepts(AcceptedCharacters.None)
|
||||
));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockHandlessTwoTemplatesInStatementWithinStatementBlock()
|
||||
{
|
||||
ParseBlockTest("{ var foo = bar; Html.ExecuteTemplate(foo," + TestTemplateCode + "," + TestTemplateCode + "); }",
|
||||
new StatementBlock(
|
||||
Factory.MetaCode("{").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code(" var foo = bar; Html.ExecuteTemplate(foo, ").AsStatement(),
|
||||
TestTemplate(),
|
||||
Factory.Code(", ").AsStatement(),
|
||||
TestTemplate(),
|
||||
Factory.Code("); ").AsStatement(),
|
||||
Factory.MetaCode("}").Accepts(AcceptedCharacters.None)
|
||||
));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockProducesErrorButCorrectlyParsesNestedTemplateInStatementWithinStatementBlock()
|
||||
{
|
||||
ParseBlockTest("{ var foo = bar; Html.ExecuteTemplate(foo," + TestNestedTemplateCode + "); }",
|
||||
new StatementBlock(
|
||||
Factory.MetaCode("{").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code(" var foo = bar; Html.ExecuteTemplate(foo, ").AsStatement(),
|
||||
TestNestedTemplate(),
|
||||
Factory.Code("); ").AsStatement(),
|
||||
Factory.MetaCode("}").Accepts(AcceptedCharacters.None)
|
||||
),
|
||||
GetNestedTemplateError(69));
|
||||
}
|
||||
|
||||
private static RazorError GetNestedTemplateError(int characterIndex)
|
||||
{
|
||||
return new RazorError(RazorResources.ParseError_InlineMarkup_Blocks_Cannot_Be_Nested, new SourceLocation(characterIndex, 0, characterIndex));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,494 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.AspNet.Razor.Editor;
|
||||
using Microsoft.AspNet.Razor.Parser;
|
||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||
using Microsoft.AspNet.Razor.Resources;
|
||||
using Microsoft.AspNet.Razor.Test.Framework;
|
||||
using Microsoft.AspNet.Razor.Tokenizer.Symbols;
|
||||
using Microsoft.TestCommon;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Test.Parser.CSharp
|
||||
{
|
||||
public class CSharpToMarkupSwitchTest : CsHtmlCodeParserTestBase
|
||||
{
|
||||
[Fact]
|
||||
public void SingleAngleBracketDoesNotCauseSwitchIfOuterBlockIsTerminated()
|
||||
{
|
||||
ParseBlockTest("{ List< }",
|
||||
new StatementBlock(
|
||||
Factory.MetaCode("{").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code(" List< ").AsStatement(),
|
||||
Factory.MetaCode("}").Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockGivesSpacesToCodeOnAtTagTemplateTransitionInDesignTimeMode()
|
||||
{
|
||||
ParseBlockTest("Foo( @<p>Foo</p> )",
|
||||
new ExpressionBlock(
|
||||
Factory.Code("Foo( ")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.Any),
|
||||
new TemplateBlock(
|
||||
new MarkupBlock(
|
||||
Factory.MarkupTransition(),
|
||||
Factory.Markup("<p>Foo</p>").Accepts(AcceptedCharacters.None)
|
||||
)
|
||||
),
|
||||
Factory.Code(" )")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)
|
||||
), designTimeParser: true);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockGivesSpacesToCodeOnAtColonTemplateTransitionInDesignTimeMode()
|
||||
{
|
||||
ParseBlockTest("Foo( " + Environment.NewLine
|
||||
+ "@:<p>Foo</p> " + Environment.NewLine
|
||||
+ ")",
|
||||
new ExpressionBlock(
|
||||
Factory.Code("Foo( \r\n").AsImplicitExpression(CSharpCodeParser.DefaultKeywords),
|
||||
new TemplateBlock(
|
||||
new MarkupBlock(
|
||||
Factory.MarkupTransition(),
|
||||
Factory.MetaMarkup(":", HtmlSymbolType.Colon),
|
||||
Factory.Markup("<p>Foo</p> \r\n")
|
||||
.With(new SingleLineMarkupEditHandler(CSharpLanguageCharacteristics.Instance.TokenizeString, AcceptedCharacters.None))
|
||||
)
|
||||
),
|
||||
Factory.Code(")")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)
|
||||
), designTimeParser: true);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockGivesSpacesToCodeOnTagTransitionInDesignTimeMode()
|
||||
{
|
||||
ParseBlockTest("{" + Environment.NewLine
|
||||
+ " <p>Foo</p> " + Environment.NewLine
|
||||
+ "}",
|
||||
new StatementBlock(
|
||||
Factory.MetaCode("{").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("\r\n ").AsStatement(),
|
||||
new MarkupBlock(
|
||||
Factory.Markup("<p>Foo</p>").Accepts(AcceptedCharacters.None)
|
||||
),
|
||||
Factory.Code(" \r\n").AsStatement(),
|
||||
Factory.MetaCode("}").Accepts(AcceptedCharacters.None)
|
||||
), designTimeParser: true);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockGivesSpacesToCodeOnInvalidAtTagTransitionInDesignTimeMode()
|
||||
{
|
||||
ParseBlockTest("{" + Environment.NewLine
|
||||
+ " @<p>Foo</p> " + Environment.NewLine
|
||||
+ "}",
|
||||
new StatementBlock(
|
||||
Factory.MetaCode("{").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("\r\n ").AsStatement(),
|
||||
new MarkupBlock(
|
||||
Factory.MarkupTransition(),
|
||||
Factory.Markup("<p>Foo</p>").Accepts(AcceptedCharacters.None)
|
||||
),
|
||||
Factory.Code(" \r\n").AsStatement(),
|
||||
Factory.MetaCode("}").Accepts(AcceptedCharacters.None)
|
||||
), true,
|
||||
new RazorError(RazorResources.ParseError_AtInCode_Must_Be_Followed_By_Colon_Paren_Or_Identifier_Start, 7, 1, 4));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockGivesSpacesToCodeOnAtColonTransitionInDesignTimeMode()
|
||||
{
|
||||
ParseBlockTest("{" + Environment.NewLine
|
||||
+ " @:<p>Foo</p> " + Environment.NewLine
|
||||
+ "}",
|
||||
new StatementBlock(
|
||||
Factory.MetaCode("{").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("\r\n ").AsStatement(),
|
||||
new MarkupBlock(
|
||||
Factory.MarkupTransition(),
|
||||
Factory.MetaMarkup(":", HtmlSymbolType.Colon),
|
||||
Factory.Markup("<p>Foo</p> \r\n")
|
||||
.With(new SingleLineMarkupEditHandler(CSharpLanguageCharacteristics.Instance.TokenizeString, AcceptedCharacters.None))
|
||||
),
|
||||
Factory.EmptyCSharp().AsStatement(),
|
||||
Factory.MetaCode("}").Accepts(AcceptedCharacters.None)
|
||||
), designTimeParser: true);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockShouldSupportSingleLineMarkupContainingStatementBlock()
|
||||
{
|
||||
ParseBlockTest("Repeat(10," + Environment.NewLine
|
||||
+ " @: @{}" + Environment.NewLine
|
||||
+ ")",
|
||||
new ExpressionBlock(
|
||||
Factory.Code("Repeat(10,\r\n ")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords),
|
||||
new TemplateBlock(
|
||||
new MarkupBlock(
|
||||
Factory.MarkupTransition(),
|
||||
Factory.MetaMarkup(":", HtmlSymbolType.Colon),
|
||||
Factory.Markup(" ")
|
||||
.With(new SingleLineMarkupEditHandler(CSharpLanguageCharacteristics.Instance.TokenizeString)),
|
||||
new StatementBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("{").Accepts(AcceptedCharacters.None),
|
||||
Factory.EmptyCSharp().AsStatement(),
|
||||
Factory.MetaCode("}").Accepts(AcceptedCharacters.None)
|
||||
),
|
||||
Factory.Markup("\r\n")
|
||||
.With(new SingleLineMarkupEditHandler(CSharpLanguageCharacteristics.Instance.TokenizeString, AcceptedCharacters.None))
|
||||
)
|
||||
),
|
||||
Factory.Code(")")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)
|
||||
));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockShouldSupportMarkupWithoutPreceedingWhitespace()
|
||||
{
|
||||
ParseBlockTest("foreach(var file in files){" + Environment.NewLine
|
||||
+ Environment.NewLine
|
||||
+ Environment.NewLine
|
||||
+ "@:Baz" + Environment.NewLine
|
||||
+ "<br/>" + Environment.NewLine
|
||||
+ "<a>Foo</a>" + Environment.NewLine
|
||||
+ "@:Bar" + Environment.NewLine
|
||||
+ "}",
|
||||
new StatementBlock(
|
||||
Factory.Code("foreach(var file in files){\r\n\r\n\r\n").AsStatement(),
|
||||
new MarkupBlock(
|
||||
Factory.MarkupTransition(),
|
||||
Factory.MetaMarkup(":", HtmlSymbolType.Colon),
|
||||
Factory.Markup("Baz\r\n")
|
||||
.With(new SingleLineMarkupEditHandler(CSharpLanguageCharacteristics.Instance.TokenizeString, AcceptedCharacters.None))
|
||||
),
|
||||
new MarkupBlock(
|
||||
Factory.Markup("<br/>\r\n")
|
||||
.Accepts(AcceptedCharacters.None)
|
||||
),
|
||||
new MarkupBlock(
|
||||
Factory.Markup("<a>Foo</a>\r\n")
|
||||
.Accepts(AcceptedCharacters.None)
|
||||
),
|
||||
new MarkupBlock(
|
||||
Factory.MarkupTransition(),
|
||||
Factory.MetaMarkup(":", HtmlSymbolType.Colon),
|
||||
Factory.Markup("Bar\r\n")
|
||||
.With(new SingleLineMarkupEditHandler(CSharpLanguageCharacteristics.Instance.TokenizeString, AcceptedCharacters.None))
|
||||
),
|
||||
Factory.Code("}").AsStatement().Accepts(AcceptedCharacters.None)
|
||||
));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockGivesAllWhitespaceOnSameLineExcludingPreceedingNewlineButIncludingTrailingNewLineToMarkup()
|
||||
{
|
||||
ParseBlockTest("if(foo) {" + Environment.NewLine
|
||||
+ " var foo = \"After this statement there are 10 spaces\"; " + Environment.NewLine
|
||||
+ " <p>" + Environment.NewLine
|
||||
+ " Foo" + Environment.NewLine
|
||||
+ " @bar" + Environment.NewLine
|
||||
+ " </p>" + Environment.NewLine
|
||||
+ " @:Hello!" + Environment.NewLine
|
||||
+ " var biz = boz;" + Environment.NewLine
|
||||
+ "}",
|
||||
new StatementBlock(
|
||||
Factory.Code("if(foo) {\r\n var foo = \"After this statement there are 10 spaces\"; \r\n").AsStatement(),
|
||||
new MarkupBlock(
|
||||
Factory.Markup(" <p>\r\n Foo\r\n"),
|
||||
new ExpressionBlock(
|
||||
Factory.Code(" ").AsStatement(),
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("bar").AsImplicitExpression(CSharpCodeParser.DefaultKeywords).Accepts(AcceptedCharacters.NonWhiteSpace)
|
||||
),
|
||||
Factory.Markup("\r\n </p>\r\n").Accepts(AcceptedCharacters.None)
|
||||
),
|
||||
new MarkupBlock(
|
||||
Factory.Markup(" "),
|
||||
Factory.MarkupTransition(),
|
||||
Factory.MetaMarkup(":", HtmlSymbolType.Colon),
|
||||
Factory.Markup("Hello!\r\n").With(new SingleLineMarkupEditHandler(CSharpLanguageCharacteristics.Instance.TokenizeString, AcceptedCharacters.None))
|
||||
),
|
||||
Factory.Code(" var biz = boz;\r\n}").AsStatement()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockAllowsMarkupInIfBodyWithBraces()
|
||||
{
|
||||
ParseBlockTest("if(foo) { <p>Bar</p> } else if(bar) { <p>Baz</p> } else { <p>Boz</p> }",
|
||||
new StatementBlock(
|
||||
Factory.Code("if(foo) {").AsStatement(),
|
||||
new MarkupBlock(
|
||||
Factory.Markup(" <p>Bar</p> ").Accepts(AcceptedCharacters.None)
|
||||
),
|
||||
Factory.Code("} else if(bar) {").AsStatement(),
|
||||
new MarkupBlock(
|
||||
Factory.Markup(" <p>Baz</p> ").Accepts(AcceptedCharacters.None)
|
||||
),
|
||||
Factory.Code("} else {").AsStatement(),
|
||||
new MarkupBlock(
|
||||
Factory.Markup(" <p>Boz</p> ").Accepts(AcceptedCharacters.None)
|
||||
),
|
||||
Factory.Code("}").AsStatement().Accepts(AcceptedCharacters.None)
|
||||
));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockAllowsMarkupInIfBodyWithBracesWithinCodeBlock()
|
||||
{
|
||||
ParseBlockTest("{ if(foo) { <p>Bar</p> } else if(bar) { <p>Baz</p> } else { <p>Boz</p> } }",
|
||||
new StatementBlock(
|
||||
Factory.MetaCode("{").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code(" if(foo) {").AsStatement(),
|
||||
new MarkupBlock(
|
||||
Factory.Markup(" <p>Bar</p> ").Accepts(AcceptedCharacters.None)
|
||||
),
|
||||
Factory.Code("} else if(bar) {").AsStatement(),
|
||||
new MarkupBlock(
|
||||
Factory.Markup(" <p>Baz</p> ").Accepts(AcceptedCharacters.None)
|
||||
),
|
||||
Factory.Code("} else {").AsStatement(),
|
||||
new MarkupBlock(
|
||||
Factory.Markup(" <p>Boz</p> ").Accepts(AcceptedCharacters.None)
|
||||
),
|
||||
Factory.Code("} ").AsStatement(),
|
||||
Factory.MetaCode("}").Accepts(AcceptedCharacters.None)
|
||||
));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockSupportsMarkupInCaseAndDefaultBranchesOfSwitch()
|
||||
{
|
||||
// Arrange
|
||||
ParseBlockTest("switch(foo) {" + Environment.NewLine
|
||||
+ " case 0:" + Environment.NewLine
|
||||
+ " <p>Foo</p>" + Environment.NewLine
|
||||
+ " break;" + Environment.NewLine
|
||||
+ " case 1:" + Environment.NewLine
|
||||
+ " <p>Bar</p>" + Environment.NewLine
|
||||
+ " return;" + Environment.NewLine
|
||||
+ " case 2:" + Environment.NewLine
|
||||
+ " {" + Environment.NewLine
|
||||
+ " <p>Baz</p>" + Environment.NewLine
|
||||
+ " <p>Boz</p>" + Environment.NewLine
|
||||
+ " }" + Environment.NewLine
|
||||
+ " default:" + Environment.NewLine
|
||||
+ " <p>Biz</p>" + Environment.NewLine
|
||||
+ "}",
|
||||
new StatementBlock(
|
||||
Factory.Code("switch(foo) {\r\n case 0:\r\n").AsStatement(),
|
||||
new MarkupBlock(
|
||||
Factory.Markup(" <p>Foo</p>\r\n").Accepts(AcceptedCharacters.None)
|
||||
),
|
||||
Factory.Code(" break;\r\n case 1:\r\n").AsStatement(),
|
||||
new MarkupBlock(
|
||||
Factory.Markup(" <p>Bar</p>\r\n").Accepts(AcceptedCharacters.None)
|
||||
),
|
||||
Factory.Code(" return;\r\n case 2:\r\n {\r\n").AsStatement(),
|
||||
new MarkupBlock(
|
||||
Factory.Markup(" <p>Baz</p>\r\n").Accepts(AcceptedCharacters.None)
|
||||
),
|
||||
new MarkupBlock(
|
||||
Factory.Markup(" <p>Boz</p>\r\n").Accepts(AcceptedCharacters.None)
|
||||
),
|
||||
Factory.Code(" }\r\n default:\r\n").AsStatement(),
|
||||
new MarkupBlock(
|
||||
Factory.Markup(" <p>Biz</p>\r\n").Accepts(AcceptedCharacters.None)
|
||||
),
|
||||
Factory.Code("}").AsStatement().Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockSupportsMarkupInCaseAndDefaultBranchesOfSwitchInCodeBlock()
|
||||
{
|
||||
// Arrange
|
||||
ParseBlockTest("{ switch(foo) {" + Environment.NewLine
|
||||
+ " case 0:" + Environment.NewLine
|
||||
+ " <p>Foo</p>" + Environment.NewLine
|
||||
+ " break;" + Environment.NewLine
|
||||
+ " case 1:" + Environment.NewLine
|
||||
+ " <p>Bar</p>" + Environment.NewLine
|
||||
+ " return;" + Environment.NewLine
|
||||
+ " case 2:" + Environment.NewLine
|
||||
+ " {" + Environment.NewLine
|
||||
+ " <p>Baz</p>" + Environment.NewLine
|
||||
+ " <p>Boz</p>" + Environment.NewLine
|
||||
+ " }" + Environment.NewLine
|
||||
+ " default:" + Environment.NewLine
|
||||
+ " <p>Biz</p>" + Environment.NewLine
|
||||
+ "} }",
|
||||
new StatementBlock(
|
||||
Factory.MetaCode("{").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code(" switch(foo) {\r\n case 0:\r\n").AsStatement(),
|
||||
new MarkupBlock(
|
||||
Factory.Markup(" <p>Foo</p>\r\n").Accepts(AcceptedCharacters.None)
|
||||
),
|
||||
Factory.Code(" break;\r\n case 1:\r\n").AsStatement(),
|
||||
new MarkupBlock(
|
||||
Factory.Markup(" <p>Bar</p>\r\n").Accepts(AcceptedCharacters.None)
|
||||
),
|
||||
Factory.Code(" return;\r\n case 2:\r\n {\r\n").AsStatement(),
|
||||
new MarkupBlock(
|
||||
Factory.Markup(" <p>Baz</p>\r\n").Accepts(AcceptedCharacters.None)
|
||||
),
|
||||
new MarkupBlock(
|
||||
Factory.Markup(" <p>Boz</p>\r\n").Accepts(AcceptedCharacters.None)
|
||||
),
|
||||
Factory.Code(" }\r\n default:\r\n").AsStatement(),
|
||||
new MarkupBlock(
|
||||
Factory.Markup(" <p>Biz</p>\r\n").Accepts(AcceptedCharacters.None)
|
||||
),
|
||||
Factory.Code("} ").AsStatement(),
|
||||
Factory.MetaCode("}").Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockParsesMarkupStatementOnOpenAngleBracket()
|
||||
{
|
||||
ParseBlockTest("for(int i = 0; i < 10; i++) { <p>Foo</p> }",
|
||||
new StatementBlock(
|
||||
Factory.Code("for(int i = 0; i < 10; i++) {").AsStatement(),
|
||||
new MarkupBlock(
|
||||
Factory.Markup(" <p>Foo</p> ").Accepts(AcceptedCharacters.None)
|
||||
),
|
||||
Factory.Code("}").AsStatement().Accepts(AcceptedCharacters.None)
|
||||
));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockParsesMarkupStatementOnOpenAngleBracketInCodeBlock()
|
||||
{
|
||||
ParseBlockTest("{ for(int i = 0; i < 10; i++) { <p>Foo</p> } }",
|
||||
new StatementBlock(
|
||||
Factory.MetaCode("{").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code(" for(int i = 0; i < 10; i++) {").AsStatement(),
|
||||
new MarkupBlock(
|
||||
Factory.Markup(" <p>Foo</p> ").Accepts(AcceptedCharacters.None)
|
||||
),
|
||||
Factory.Code("} ").AsStatement(),
|
||||
Factory.MetaCode("}").Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockParsesMarkupStatementOnSwitchCharacterFollowedByColon()
|
||||
{
|
||||
// Arrange
|
||||
ParseBlockTest("if(foo) { @:Bar" + Environment.NewLine
|
||||
+ "} zoop",
|
||||
new StatementBlock(
|
||||
Factory.Code("if(foo) {").AsStatement(),
|
||||
new MarkupBlock(
|
||||
Factory.Markup(" "),
|
||||
Factory.MarkupTransition(),
|
||||
Factory.MetaMarkup(":", HtmlSymbolType.Colon),
|
||||
Factory.Markup("Bar\r\n").With(new SingleLineMarkupEditHandler(CSharpLanguageCharacteristics.Instance.TokenizeString, AcceptedCharacters.None))
|
||||
),
|
||||
Factory.Code("}").AsStatement()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockParsesMarkupStatementOnSwitchCharacterFollowedByColonInCodeBlock()
|
||||
{
|
||||
// Arrange
|
||||
ParseBlockTest("{ if(foo) { @:Bar" + Environment.NewLine
|
||||
+ "} } zoop",
|
||||
new StatementBlock(
|
||||
Factory.MetaCode("{").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code(" if(foo) {").AsStatement(),
|
||||
new MarkupBlock(
|
||||
Factory.Markup(" "),
|
||||
Factory.MarkupTransition(),
|
||||
Factory.MetaMarkup(":", HtmlSymbolType.Colon),
|
||||
Factory.Markup("Bar\r\n").Accepts(AcceptedCharacters.None)
|
||||
),
|
||||
Factory.Code("} ").AsStatement(),
|
||||
Factory.MetaCode("}").Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockCorrectlyReturnsFromMarkupBlockWithPseudoTag()
|
||||
{
|
||||
ParseBlockTest("if (i > 0) { <text>;</text> }",
|
||||
new StatementBlock(
|
||||
Factory.Code("if (i > 0) {").AsStatement(),
|
||||
new MarkupBlock(
|
||||
Factory.Markup(" "),
|
||||
Factory.MarkupTransition("<text>").Accepts(AcceptedCharacters.None),
|
||||
Factory.Markup(";"),
|
||||
Factory.MarkupTransition("</text>").Accepts(AcceptedCharacters.None),
|
||||
Factory.Markup(" ").Accepts(AcceptedCharacters.None)
|
||||
),
|
||||
Factory.Code("}").AsStatement()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockCorrectlyReturnsFromMarkupBlockWithPseudoTagInCodeBlock()
|
||||
{
|
||||
ParseBlockTest("{ if (i > 0) { <text>;</text> } }",
|
||||
new StatementBlock(
|
||||
Factory.MetaCode("{").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code(" if (i > 0) {").AsStatement(),
|
||||
new MarkupBlock(
|
||||
Factory.Markup(" "),
|
||||
Factory.MarkupTransition("<text>").Accepts(AcceptedCharacters.None),
|
||||
Factory.Markup(";"),
|
||||
Factory.MarkupTransition("</text>").Accepts(AcceptedCharacters.None),
|
||||
Factory.Markup(" ").Accepts(AcceptedCharacters.None)
|
||||
),
|
||||
Factory.Code("} ").AsStatement(),
|
||||
Factory.MetaCode("}").Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockSupportsAllKindsOfImplicitMarkupInCodeBlock()
|
||||
{
|
||||
ParseBlockTest("{" + Environment.NewLine
|
||||
+ " if(true) {" + Environment.NewLine
|
||||
+ " @:Single Line Markup" + Environment.NewLine
|
||||
+ " }" + Environment.NewLine
|
||||
+ " foreach (var p in Enumerable.Range(1, 10)) {" + Environment.NewLine
|
||||
+ " <text>The number is @p</text>" + Environment.NewLine
|
||||
+ " }" + Environment.NewLine
|
||||
+ " if(!false) {" + Environment.NewLine
|
||||
+ " <p>A real tag!</p>" + Environment.NewLine
|
||||
+ " }" + Environment.NewLine
|
||||
+ "}",
|
||||
new StatementBlock(
|
||||
Factory.MetaCode("{").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("\r\n if(true) {\r\n").AsStatement(),
|
||||
new MarkupBlock(
|
||||
Factory.Markup(" "),
|
||||
Factory.MarkupTransition(),
|
||||
Factory.MetaMarkup(":", HtmlSymbolType.Colon),
|
||||
Factory.Markup("Single Line Markup\r\n").With(new SingleLineMarkupEditHandler(CSharpLanguageCharacteristics.Instance.TokenizeString, AcceptedCharacters.None))
|
||||
),
|
||||
Factory.Code(" }\r\n foreach (var p in Enumerable.Range(1, 10)) {\r\n").AsStatement(),
|
||||
new MarkupBlock(
|
||||
Factory.Markup(" "),
|
||||
Factory.MarkupTransition("<text>").Accepts(AcceptedCharacters.None),
|
||||
Factory.Markup("The number is "),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("p").AsImplicitExpression(CSharpCodeParser.DefaultKeywords).Accepts(AcceptedCharacters.NonWhiteSpace)
|
||||
),
|
||||
Factory.MarkupTransition("</text>").Accepts(AcceptedCharacters.None),
|
||||
Factory.Markup("\r\n").Accepts(AcceptedCharacters.None)
|
||||
),
|
||||
Factory.Code(" }\r\n if(!false) {\r\n").AsStatement(),
|
||||
new MarkupBlock(
|
||||
Factory.Markup(" <p>A real tag!</p>\r\n").Accepts(AcceptedCharacters.None)
|
||||
),
|
||||
Factory.Code(" }\r\n").AsStatement(),
|
||||
Factory.MetaCode("}").Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,121 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||
using Microsoft.AspNet.Razor.Resources;
|
||||
using Microsoft.AspNet.Razor.Test.Framework;
|
||||
using Microsoft.AspNet.Razor.Text;
|
||||
using Microsoft.TestCommon;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Test.Parser.CSharp
|
||||
{
|
||||
public class CSharpVerbatimBlockTest : CsHtmlCodeParserTestBase
|
||||
{
|
||||
private const string TestExtraKeyword = "model";
|
||||
|
||||
[Fact]
|
||||
public void VerbatimBlock()
|
||||
{
|
||||
ParseBlockTest("@{ foo(); }",
|
||||
new StatementBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("{")
|
||||
.Accepts(AcceptedCharacters.None),
|
||||
Factory.Code(" foo(); ")
|
||||
.AsStatement(),
|
||||
Factory.MetaCode("}")
|
||||
.Accepts(AcceptedCharacters.None)
|
||||
));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InnerImplicitExpressionWithOnlySingleAtOutputsZeroLengthCodeSpan()
|
||||
{
|
||||
ParseBlockTest("{@}",
|
||||
new StatementBlock(
|
||||
Factory.MetaCode("{").Accepts(AcceptedCharacters.None),
|
||||
Factory.EmptyCSharp().AsStatement(),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.EmptyCSharp().AsImplicitExpression(KeywordSet, acceptTrailingDot: true).Accepts(AcceptedCharacters.NonWhiteSpace)
|
||||
),
|
||||
Factory.EmptyCSharp().AsStatement(),
|
||||
Factory.MetaCode("}").Accepts(AcceptedCharacters.None)),
|
||||
designTimeParser: true,
|
||||
expectedErrors: new[]
|
||||
{
|
||||
new RazorError(String.Format(RazorResources.ParseError_Unexpected_Character_At_Start_Of_CodeBlock_CS, "}"), new SourceLocation(2, 0, 2))
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InnerImplicitExpressionDoesNotAcceptDotAfterAt()
|
||||
{
|
||||
ParseBlockTest("{@.}",
|
||||
new StatementBlock(
|
||||
Factory.MetaCode("{").Accepts(AcceptedCharacters.None),
|
||||
Factory.EmptyCSharp().AsStatement(),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.EmptyCSharp().AsImplicitExpression(KeywordSet, acceptTrailingDot: true).Accepts(AcceptedCharacters.NonWhiteSpace)
|
||||
),
|
||||
Factory.Code(".").AsStatement(),
|
||||
Factory.MetaCode("}").Accepts(AcceptedCharacters.None)),
|
||||
designTimeParser: true,
|
||||
expectedErrors: new[]
|
||||
{
|
||||
new RazorError(String.Format(RazorResources.ParseError_Unexpected_Character_At_Start_Of_CodeBlock_CS, "."), new SourceLocation(2, 0, 2))
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InnerImplicitExpressionWithOnlySingleAtAcceptsSingleSpaceOrNewlineAtDesignTime()
|
||||
{
|
||||
ParseBlockTest("{" + Environment.NewLine
|
||||
+ " @" + Environment.NewLine
|
||||
+ "}",
|
||||
new StatementBlock(
|
||||
Factory.MetaCode("{").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("\r\n ").AsStatement(),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.EmptyCSharp().AsImplicitExpression(KeywordSet, acceptTrailingDot: true).Accepts(AcceptedCharacters.NonWhiteSpace)
|
||||
),
|
||||
Factory.Code("\r\n").AsStatement(),
|
||||
Factory.MetaCode("}").Accepts(AcceptedCharacters.None)),
|
||||
/* designTimeParser */ true,
|
||||
new RazorError(RazorResources.ParseError_Unexpected_WhiteSpace_At_Start_Of_CodeBlock_CS, 8, 1, 5));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InnerImplicitExpressionDoesNotAcceptTrailingNewlineInRunTimeMode()
|
||||
{
|
||||
ParseBlockTest("{@foo." + Environment.NewLine
|
||||
+ "}",
|
||||
new StatementBlock(
|
||||
Factory.MetaCode("{").Accepts(AcceptedCharacters.None),
|
||||
Factory.EmptyCSharp().AsStatement(),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("foo.").AsImplicitExpression(KeywordSet, acceptTrailingDot: true).Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
Factory.Code("\r\n").AsStatement(),
|
||||
Factory.MetaCode("}").Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InnerImplicitExpressionAcceptsTrailingNewlineInDesignTimeMode()
|
||||
{
|
||||
ParseBlockTest("{@foo." + Environment.NewLine
|
||||
+ "}",
|
||||
new StatementBlock(
|
||||
Factory.MetaCode("{").Accepts(AcceptedCharacters.None),
|
||||
Factory.EmptyCSharp().AsStatement(),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("foo.").AsImplicitExpression(KeywordSet, acceptTrailingDot: true).Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
Factory.Code("\r\n").AsStatement(),
|
||||
Factory.MetaCode("}").Accepts(AcceptedCharacters.None)),
|
||||
designTimeParser: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||
using Microsoft.AspNet.Razor.Test.Framework;
|
||||
using Microsoft.AspNet.Razor.Tokenizer.Symbols;
|
||||
using Microsoft.TestCommon;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Test.Parser.CSharp
|
||||
{
|
||||
public class CSharpWhitespaceHandlingTest : CsHtmlMarkupParserTestBase
|
||||
{
|
||||
[Fact]
|
||||
public void StatementBlockDoesNotAcceptTrailingNewlineIfNewlinesAreSignificantToAncestor()
|
||||
{
|
||||
ParseBlockTest("@: @if (true) { }" + Environment.NewLine
|
||||
+ "}",
|
||||
new MarkupBlock(
|
||||
Factory.MarkupTransition()
|
||||
.Accepts(AcceptedCharacters.None),
|
||||
Factory.MetaMarkup(":", HtmlSymbolType.Colon),
|
||||
Factory.Markup(" "),
|
||||
new StatementBlock(
|
||||
Factory.CodeTransition()
|
||||
.Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("if (true) { }")
|
||||
.AsStatement()
|
||||
),
|
||||
Factory.Markup("\r\n")
|
||||
.Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,289 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.AspNet.Razor.Parser;
|
||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||
using Microsoft.AspNet.Razor.Resources;
|
||||
using Microsoft.AspNet.Razor.Test.Framework;
|
||||
using Microsoft.AspNet.Razor.Text;
|
||||
using Microsoft.AspNet.Razor.Tokenizer.Symbols;
|
||||
using Microsoft.TestCommon;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Test.Parser.CSharp
|
||||
{
|
||||
public class CsHtmlDocumentTest : CsHtmlMarkupParserTestBase
|
||||
{
|
||||
[Fact]
|
||||
public void UnterminatedBlockCommentCausesRazorError()
|
||||
{
|
||||
ParseDocumentTest("@* Foo Bar",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new CommentBlock(
|
||||
Factory.MarkupTransition(HtmlSymbolType.RazorCommentTransition),
|
||||
Factory.MetaMarkup("*", HtmlSymbolType.RazorCommentStar).Accepts(AcceptedCharacters.None),
|
||||
Factory.Comment(" Foo Bar", HtmlSymbolType.RazorComment)
|
||||
)
|
||||
),
|
||||
new RazorError(RazorResources.ParseError_RazorComment_Not_Terminated, SourceLocation.Zero));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BlockCommentInMarkupDocumentIsHandledCorrectly()
|
||||
{
|
||||
ParseDocumentTest("<ul>" + Environment.NewLine
|
||||
+ " @* This is a block comment </ul> *@ foo",
|
||||
new MarkupBlock(
|
||||
Factory.Markup("<ul>\r\n "),
|
||||
new CommentBlock(
|
||||
Factory.MarkupTransition(HtmlSymbolType.RazorCommentTransition),
|
||||
Factory.MetaMarkup("*", HtmlSymbolType.RazorCommentStar).Accepts(AcceptedCharacters.None),
|
||||
Factory.Comment(" This is a block comment </ul> ", HtmlSymbolType.RazorComment),
|
||||
Factory.MetaMarkup("*", HtmlSymbolType.RazorCommentStar).Accepts(AcceptedCharacters.None),
|
||||
Factory.MarkupTransition(HtmlSymbolType.RazorCommentTransition)
|
||||
),
|
||||
Factory.Markup(" foo")
|
||||
));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BlockCommentInMarkupBlockIsHandledCorrectly()
|
||||
{
|
||||
ParseBlockTest("<ul>" + Environment.NewLine
|
||||
+ " @* This is a block comment </ul> *@ foo </ul>",
|
||||
new MarkupBlock(
|
||||
Factory.Markup("<ul>\r\n "),
|
||||
new CommentBlock(
|
||||
Factory.MarkupTransition(HtmlSymbolType.RazorCommentTransition),
|
||||
Factory.MetaMarkup("*", HtmlSymbolType.RazorCommentStar).Accepts(AcceptedCharacters.None),
|
||||
Factory.Comment(" This is a block comment </ul> ", HtmlSymbolType.RazorComment),
|
||||
Factory.MetaMarkup("*", HtmlSymbolType.RazorCommentStar).Accepts(AcceptedCharacters.None),
|
||||
Factory.MarkupTransition(HtmlSymbolType.RazorCommentTransition)
|
||||
),
|
||||
Factory.Markup(" foo </ul>").Accepts(AcceptedCharacters.None)
|
||||
));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BlockCommentAtStatementStartInCodeBlockIsHandledCorrectly()
|
||||
{
|
||||
ParseDocumentTest("@if(Request.IsAuthenticated) {" + Environment.NewLine
|
||||
+ " @* User is logged in! } *@" + Environment.NewLine
|
||||
+ " Write(\"Hello friend!\");" + Environment.NewLine
|
||||
+ "}",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new StatementBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("if(Request.IsAuthenticated) {\r\n ").AsStatement(),
|
||||
new CommentBlock(
|
||||
Factory.CodeTransition(CSharpSymbolType.RazorCommentTransition),
|
||||
Factory.MetaCode("*", CSharpSymbolType.RazorCommentStar).Accepts(AcceptedCharacters.None),
|
||||
Factory.Comment(" User is logged in! } ", CSharpSymbolType.RazorComment),
|
||||
Factory.MetaCode("*", CSharpSymbolType.RazorCommentStar).Accepts(AcceptedCharacters.None),
|
||||
Factory.CodeTransition(CSharpSymbolType.RazorCommentTransition)
|
||||
),
|
||||
Factory.Code("\r\n Write(\"Hello friend!\");\r\n}").AsStatement())));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BlockCommentInStatementInCodeBlockIsHandledCorrectly()
|
||||
{
|
||||
ParseDocumentTest("@if(Request.IsAuthenticated) {" + Environment.NewLine
|
||||
+ " var foo = @* User is logged in! ; *@;" + Environment.NewLine
|
||||
+ " Write(\"Hello friend!\");" + Environment.NewLine
|
||||
+ "}",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new StatementBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("if(Request.IsAuthenticated) {\r\n var foo = ").AsStatement(),
|
||||
new CommentBlock(
|
||||
Factory.CodeTransition(CSharpSymbolType.RazorCommentTransition),
|
||||
Factory.MetaCode("*", CSharpSymbolType.RazorCommentStar).Accepts(AcceptedCharacters.None),
|
||||
Factory.Comment(" User is logged in! ; ", CSharpSymbolType.RazorComment),
|
||||
Factory.MetaCode("*", CSharpSymbolType.RazorCommentStar).Accepts(AcceptedCharacters.None),
|
||||
Factory.CodeTransition(CSharpSymbolType.RazorCommentTransition)
|
||||
),
|
||||
Factory.Code(";\r\n Write(\"Hello friend!\");\r\n}").AsStatement())));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BlockCommentInStringIsIgnored()
|
||||
{
|
||||
ParseDocumentTest("@if(Request.IsAuthenticated) {" + Environment.NewLine
|
||||
+ " var foo = \"@* User is logged in! ; *\";" + Environment.NewLine
|
||||
+ " Write(\"Hello friend!\");" + Environment.NewLine
|
||||
+ "}",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new StatementBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("if(Request.IsAuthenticated) {" + Environment.NewLine
|
||||
+ " var foo = \"@* User is logged in! ; *\";" + Environment.NewLine
|
||||
+ " Write(\"Hello friend!\");" + Environment.NewLine
|
||||
+ "}").AsStatement())));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BlockCommentInCSharpBlockCommentIsIgnored()
|
||||
{
|
||||
ParseDocumentTest("@if(Request.IsAuthenticated) {" + Environment.NewLine
|
||||
+ " var foo = /*@* User is logged in! */ *@ */;" + Environment.NewLine
|
||||
+ " Write(\"Hello friend!\");" + Environment.NewLine
|
||||
+ "}",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new StatementBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("if(Request.IsAuthenticated) {" + Environment.NewLine
|
||||
+ " var foo = /*@* User is logged in! */ *@ */;" + Environment.NewLine
|
||||
+ " Write(\"Hello friend!\");" + Environment.NewLine
|
||||
+ "}").AsStatement())));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BlockCommentInCSharpLineCommentIsIgnored()
|
||||
{
|
||||
ParseDocumentTest("@if(Request.IsAuthenticated) {" + Environment.NewLine
|
||||
+ " var foo = //@* User is logged in! */ *@;" + Environment.NewLine
|
||||
+ " Write(\"Hello friend!\");" + Environment.NewLine
|
||||
+ "}",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new StatementBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("if(Request.IsAuthenticated) {" + Environment.NewLine
|
||||
+ " var foo = //@* User is logged in! */ *@;" + Environment.NewLine
|
||||
+ " Write(\"Hello friend!\");" + Environment.NewLine
|
||||
+ "}").AsStatement())));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BlockCommentInImplicitExpressionIsHandledCorrectly()
|
||||
{
|
||||
ParseDocumentTest("@Html.Foo@*bar*@",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("Html.Foo").AsImplicitExpression(CSharpCodeParser.DefaultKeywords).Accepts(AcceptedCharacters.NonWhiteSpace)
|
||||
),
|
||||
Factory.EmptyHtml(),
|
||||
new CommentBlock(
|
||||
Factory.MarkupTransition(HtmlSymbolType.RazorCommentTransition),
|
||||
Factory.MetaMarkup("*", HtmlSymbolType.RazorCommentStar).Accepts(AcceptedCharacters.None),
|
||||
Factory.Comment("bar", HtmlSymbolType.RazorComment),
|
||||
Factory.MetaMarkup("*", HtmlSymbolType.RazorCommentStar).Accepts(AcceptedCharacters.None),
|
||||
Factory.MarkupTransition(HtmlSymbolType.RazorCommentTransition)
|
||||
),
|
||||
Factory.EmptyHtml()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BlockCommentAfterDotOfImplicitExpressionIsHandledCorrectly()
|
||||
{
|
||||
ParseDocumentTest("@Html.@*bar*@",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("Html").AsImplicitExpression(CSharpCodeParser.DefaultKeywords).Accepts(AcceptedCharacters.NonWhiteSpace)
|
||||
),
|
||||
Factory.Markup("."),
|
||||
new CommentBlock(
|
||||
Factory.MarkupTransition(HtmlSymbolType.RazorCommentTransition),
|
||||
Factory.MetaMarkup("*", HtmlSymbolType.RazorCommentStar).Accepts(AcceptedCharacters.None),
|
||||
Factory.Comment("bar", HtmlSymbolType.RazorComment),
|
||||
Factory.MetaMarkup("*", HtmlSymbolType.RazorCommentStar).Accepts(AcceptedCharacters.None),
|
||||
Factory.MarkupTransition(HtmlSymbolType.RazorCommentTransition)
|
||||
),
|
||||
Factory.EmptyHtml()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BlockCommentInParensOfImplicitExpressionIsHandledCorrectly()
|
||||
{
|
||||
ParseDocumentTest("@Html.Foo(@*bar*@ 4)",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("Html.Foo(").AsImplicitExpression(CSharpCodeParser.DefaultKeywords).Accepts(AcceptedCharacters.Any),
|
||||
new CommentBlock(
|
||||
Factory.CodeTransition(CSharpSymbolType.RazorCommentTransition),
|
||||
Factory.MetaCode("*", CSharpSymbolType.RazorCommentStar).Accepts(AcceptedCharacters.None),
|
||||
Factory.Comment("bar", CSharpSymbolType.RazorComment),
|
||||
Factory.MetaCode("*", CSharpSymbolType.RazorCommentStar).Accepts(AcceptedCharacters.None),
|
||||
Factory.CodeTransition(CSharpSymbolType.RazorCommentTransition)
|
||||
),
|
||||
Factory.Code(" 4)").AsImplicitExpression(CSharpCodeParser.DefaultKeywords).Accepts(AcceptedCharacters.NonWhiteSpace)
|
||||
),
|
||||
Factory.EmptyHtml()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BlockCommentInBracketsOfImplicitExpressionIsHandledCorrectly()
|
||||
{
|
||||
ParseDocumentTest("@Html.Foo[@*bar*@ 4]",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("Html.Foo[").AsImplicitExpression(CSharpCodeParser.DefaultKeywords).Accepts(AcceptedCharacters.Any),
|
||||
new CommentBlock(
|
||||
Factory.CodeTransition(CSharpSymbolType.RazorCommentTransition),
|
||||
Factory.MetaCode("*", CSharpSymbolType.RazorCommentStar).Accepts(AcceptedCharacters.None),
|
||||
Factory.Comment("bar", CSharpSymbolType.RazorComment),
|
||||
Factory.MetaCode("*", CSharpSymbolType.RazorCommentStar).Accepts(AcceptedCharacters.None),
|
||||
Factory.CodeTransition(CSharpSymbolType.RazorCommentTransition)
|
||||
),
|
||||
Factory.Code(" 4]").AsImplicitExpression(CSharpCodeParser.DefaultKeywords).Accepts(AcceptedCharacters.NonWhiteSpace)
|
||||
),
|
||||
Factory.EmptyHtml()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BlockCommentInParensOfConditionIsHandledCorrectly()
|
||||
{
|
||||
ParseDocumentTest("@if(@*bar*@) {}",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new StatementBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("if(").AsStatement(),
|
||||
new CommentBlock(
|
||||
Factory.CodeTransition(CSharpSymbolType.RazorCommentTransition),
|
||||
Factory.MetaCode("*", CSharpSymbolType.RazorCommentStar).Accepts(AcceptedCharacters.None),
|
||||
Factory.Comment("bar", CSharpSymbolType.RazorComment),
|
||||
Factory.MetaCode("*", CSharpSymbolType.RazorCommentStar).Accepts(AcceptedCharacters.None),
|
||||
Factory.CodeTransition(CSharpSymbolType.RazorCommentTransition)
|
||||
),
|
||||
Factory.Code(") {}").AsStatement()
|
||||
)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BlockCommentInExplicitExpressionIsHandledCorrectly()
|
||||
{
|
||||
ParseDocumentTest("@(1 + @*bar*@ 1)",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("(").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("1 + ").AsExpression(),
|
||||
new CommentBlock(
|
||||
Factory.CodeTransition(CSharpSymbolType.RazorCommentTransition),
|
||||
Factory.MetaCode("*", CSharpSymbolType.RazorCommentStar).Accepts(AcceptedCharacters.None),
|
||||
Factory.Comment("bar", CSharpSymbolType.RazorComment),
|
||||
Factory.MetaCode("*", CSharpSymbolType.RazorCommentStar).Accepts(AcceptedCharacters.None),
|
||||
Factory.CodeTransition(CSharpSymbolType.RazorCommentTransition)
|
||||
),
|
||||
Factory.Code(" 1").AsExpression(),
|
||||
Factory.MetaCode(")").Accepts(AcceptedCharacters.None)
|
||||
),
|
||||
Factory.EmptyHtml()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,165 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Threading;
|
||||
using Microsoft.AspNet.Razor.Parser;
|
||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||
using Microsoft.AspNet.Razor.Test.Framework;
|
||||
using Microsoft.AspNet.Razor.Text;
|
||||
using Microsoft.TestCommon;
|
||||
using Moq;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Test.Parser
|
||||
{
|
||||
public class CallbackParserListenerTest
|
||||
{
|
||||
[Fact]
|
||||
public void ListenerConstructedWithSpanCallbackCallsCallbackOnEndSpan()
|
||||
{
|
||||
RunOnEndSpanTest(callback => new CallbackVisitor(callback));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ListenerConstructedWithSpanCallbackDoesNotThrowOnStartBlockEndBlockOrError()
|
||||
{
|
||||
// Arrange
|
||||
Action<Span> spanCallback = _ => { };
|
||||
CallbackVisitor listener = new CallbackVisitor(spanCallback);
|
||||
|
||||
// Act/Assert
|
||||
listener.VisitStartBlock(new FunctionsBlock());
|
||||
listener.VisitError(new RazorError("Error", SourceLocation.Zero));
|
||||
listener.VisitEndBlock(new FunctionsBlock());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ListenerConstructedWithSpanAndErrorCallbackCallsCallbackOnEndSpan()
|
||||
{
|
||||
RunOnEndSpanTest(spanCallback => new CallbackVisitor(spanCallback, _ => { }));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ListenerConstructedWithSpanAndErrorCallbackCallsCallbackOnError()
|
||||
{
|
||||
RunOnErrorTest(errorCallback => new CallbackVisitor(_ => { }, errorCallback));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ListenerConstructedWithAllCallbacksCallsCallbackOnEndSpan()
|
||||
{
|
||||
RunOnEndSpanTest(spanCallback => new CallbackVisitor(spanCallback, _ => { }, _ => { }, _ => { }));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ListenerConstructedWithAllCallbacksCallsCallbackOnError()
|
||||
{
|
||||
RunOnErrorTest(errorCallback => new CallbackVisitor(_ => { }, errorCallback, _ => { }, _ => { }));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ListenerConstructedWithAllCallbacksCallsCallbackOnStartBlock()
|
||||
{
|
||||
RunOnStartBlockTest(startBlockCallback => new CallbackVisitor(_ => { }, _ => { }, startBlockCallback, _ => { }));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ListenerConstructedWithAllCallbacksCallsCallbackOnEndBlock()
|
||||
{
|
||||
RunOnEndBlockTest(endBlockCallback => new CallbackVisitor(_ => { }, _ => { }, _ => { }, endBlockCallback));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ListenerCallsOnEndSpanCallbackUsingSynchronizationContextIfSpecified()
|
||||
{
|
||||
RunSyncContextTest(new SpanBuilder().Build(),
|
||||
spanCallback => new CallbackVisitor(spanCallback, _ => { }, _ => { }, _ => { }),
|
||||
(listener, expected) => listener.VisitSpan(expected));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ListenerCallsOnStartBlockCallbackUsingSynchronizationContextIfSpecified()
|
||||
{
|
||||
RunSyncContextTest(BlockType.Template,
|
||||
startBlockCallback => new CallbackVisitor(_ => { }, _ => { }, startBlockCallback, _ => { }),
|
||||
(listener, expected) => listener.VisitStartBlock(new BlockBuilder() { Type = expected }.Build()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ListenerCallsOnEndBlockCallbackUsingSynchronizationContextIfSpecified()
|
||||
{
|
||||
RunSyncContextTest(BlockType.Template,
|
||||
endBlockCallback => new CallbackVisitor(_ => { }, _ => { }, _ => { }, endBlockCallback),
|
||||
(listener, expected) => listener.VisitEndBlock(new BlockBuilder() { Type = expected }.Build()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ListenerCallsOnErrorCallbackUsingSynchronizationContextIfSpecified()
|
||||
{
|
||||
RunSyncContextTest(new RazorError("Bar", 42, 42, 42),
|
||||
errorCallback => new CallbackVisitor(_ => { }, errorCallback, _ => { }, _ => { }),
|
||||
(listener, expected) => listener.VisitError(expected));
|
||||
}
|
||||
|
||||
private static void RunSyncContextTest<T>(T expected, Func<Action<T>, CallbackVisitor> ctor, Action<CallbackVisitor, T> call)
|
||||
{
|
||||
// Arrange
|
||||
Mock<SynchronizationContext> mockContext = new Mock<SynchronizationContext>();
|
||||
mockContext.Setup(c => c.Post(It.IsAny<SendOrPostCallback>(), It.IsAny<object>()))
|
||||
.Callback<SendOrPostCallback, object>((callback, state) => { callback(expected); });
|
||||
|
||||
// Act/Assert
|
||||
RunCallbackTest<T>(default(T), callback =>
|
||||
{
|
||||
CallbackVisitor listener = ctor(callback);
|
||||
listener.SynchronizationContext = mockContext.Object;
|
||||
return listener;
|
||||
}, call, (original, actual) =>
|
||||
{
|
||||
Assert.NotEqual(original, actual);
|
||||
Assert.Equal(expected, actual);
|
||||
});
|
||||
}
|
||||
|
||||
private static void RunOnStartBlockTest(Func<Action<BlockType>, CallbackVisitor> ctor, Action<BlockType, BlockType> verifyResults = null)
|
||||
{
|
||||
RunCallbackTest(BlockType.Markup, ctor, (listener, expected) => listener.VisitStartBlock(new BlockBuilder() { Type = expected }.Build()), verifyResults);
|
||||
}
|
||||
|
||||
private static void RunOnEndBlockTest(Func<Action<BlockType>, CallbackVisitor> ctor, Action<BlockType, BlockType> verifyResults = null)
|
||||
{
|
||||
RunCallbackTest(BlockType.Markup, ctor, (listener, expected) => listener.VisitEndBlock(new BlockBuilder() { Type = expected }.Build()), verifyResults);
|
||||
}
|
||||
|
||||
private static void RunOnErrorTest(Func<Action<RazorError>, CallbackVisitor> ctor, Action<RazorError, RazorError> verifyResults = null)
|
||||
{
|
||||
RunCallbackTest(new RazorError("Foo", SourceLocation.Zero), ctor, (listener, expected) => listener.VisitError(expected), verifyResults);
|
||||
}
|
||||
|
||||
private static void RunOnEndSpanTest(Func<Action<Span>, CallbackVisitor> ctor, Action<Span, Span> verifyResults = null)
|
||||
{
|
||||
RunCallbackTest(new SpanBuilder().Build(), ctor, (listener, expected) => listener.VisitSpan(expected), verifyResults);
|
||||
}
|
||||
|
||||
private static void RunCallbackTest<T>(T expected, Func<Action<T>, CallbackVisitor> ctor, Action<CallbackVisitor, T> call, Action<T, T> verifyResults = null)
|
||||
{
|
||||
// Arrange
|
||||
object actual = null;
|
||||
Action<T> callback = t => actual = t;
|
||||
|
||||
CallbackVisitor listener = ctor(callback);
|
||||
|
||||
// Act
|
||||
call(listener, expected);
|
||||
|
||||
// Assert
|
||||
if (verifyResults == null)
|
||||
{
|
||||
Assert.Equal(expected, actual);
|
||||
}
|
||||
else
|
||||
{
|
||||
verifyResults(expected, (T)actual);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,303 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.AspNet.Razor.Editor;
|
||||
using Microsoft.AspNet.Razor.Generator;
|
||||
using Microsoft.AspNet.Razor.Parser;
|
||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||
using Microsoft.AspNet.Razor.Test.Framework;
|
||||
using Microsoft.AspNet.Razor.Text;
|
||||
using Microsoft.TestCommon;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Test.Parser.Html
|
||||
{
|
||||
public class HtmlAttributeTest : CsHtmlMarkupParserTestBase
|
||||
{
|
||||
[Fact]
|
||||
public void SimpleLiteralAttribute()
|
||||
{
|
||||
ParseBlockTest("<a href='Foo' />",
|
||||
new MarkupBlock(
|
||||
Factory.Markup("<a"),
|
||||
new MarkupBlock(new AttributeBlockCodeGenerator(name: "href", prefix: new LocationTagged<string>(" href='", 2, 0, 2), suffix: new LocationTagged<string>("'", 12, 0, 12)),
|
||||
Factory.Markup(" href='").With(SpanCodeGenerator.Null),
|
||||
Factory.Markup("Foo").With(new LiteralAttributeCodeGenerator(prefix: new LocationTagged<string>(String.Empty, 9, 0, 9), value: new LocationTagged<string>("Foo", 9, 0, 9))),
|
||||
Factory.Markup("'").With(SpanCodeGenerator.Null)),
|
||||
Factory.Markup(" />").Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MultiPartLiteralAttribute()
|
||||
{
|
||||
ParseBlockTest("<a href='Foo Bar Baz' />",
|
||||
new MarkupBlock(
|
||||
Factory.Markup("<a"),
|
||||
new MarkupBlock(new AttributeBlockCodeGenerator(name: "href", prefix: new LocationTagged<string>(" href='", 2, 0, 2), suffix: new LocationTagged<string>("'", 20, 0, 20)),
|
||||
Factory.Markup(" href='").With(SpanCodeGenerator.Null),
|
||||
Factory.Markup("Foo").With(new LiteralAttributeCodeGenerator(prefix: new LocationTagged<string>(String.Empty, 9, 0, 9), value: new LocationTagged<string>("Foo", 9, 0, 9))),
|
||||
Factory.Markup(" Bar").With(new LiteralAttributeCodeGenerator(prefix: new LocationTagged<string>(" ", 12, 0, 12), value: new LocationTagged<string>("Bar", 13, 0, 13))),
|
||||
Factory.Markup(" Baz").With(new LiteralAttributeCodeGenerator(prefix: new LocationTagged<string>(" ", 16, 0, 16), value: new LocationTagged<string>("Baz", 17, 0, 17))),
|
||||
Factory.Markup("'").With(SpanCodeGenerator.Null)),
|
||||
Factory.Markup(" />").Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DoubleQuotedLiteralAttribute()
|
||||
{
|
||||
ParseBlockTest("<a href=\"Foo Bar Baz\" />",
|
||||
new MarkupBlock(
|
||||
Factory.Markup("<a"),
|
||||
new MarkupBlock(new AttributeBlockCodeGenerator(name: "href", prefix: new LocationTagged<string>(" href=\"", 2, 0, 2), suffix: new LocationTagged<string>("\"", 20, 0, 20)),
|
||||
Factory.Markup(" href=\"").With(SpanCodeGenerator.Null),
|
||||
Factory.Markup("Foo").With(new LiteralAttributeCodeGenerator(prefix: new LocationTagged<string>(String.Empty, 9, 0, 9), value: new LocationTagged<string>("Foo", 9, 0, 9))),
|
||||
Factory.Markup(" Bar").With(new LiteralAttributeCodeGenerator(prefix: new LocationTagged<string>(" ", 12, 0, 12), value: new LocationTagged<string>("Bar", 13, 0, 13))),
|
||||
Factory.Markup(" Baz").With(new LiteralAttributeCodeGenerator(prefix: new LocationTagged<string>(" ", 16, 0, 16), value: new LocationTagged<string>("Baz", 17, 0, 17))),
|
||||
Factory.Markup("\"").With(SpanCodeGenerator.Null)),
|
||||
Factory.Markup(" />").Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void UnquotedLiteralAttribute()
|
||||
{
|
||||
ParseBlockTest("<a href=Foo Bar Baz />",
|
||||
new MarkupBlock(
|
||||
Factory.Markup("<a"),
|
||||
new MarkupBlock(new AttributeBlockCodeGenerator(name: "href", prefix: new LocationTagged<string>(" href=", 2, 0, 2), suffix: new LocationTagged<string>(String.Empty, 11, 0, 11)),
|
||||
Factory.Markup(" href=").With(SpanCodeGenerator.Null),
|
||||
Factory.Markup("Foo").With(new LiteralAttributeCodeGenerator(prefix: new LocationTagged<string>(String.Empty, 8, 0, 8), value: new LocationTagged<string>("Foo", 8, 0, 8)))),
|
||||
Factory.Markup(" Bar Baz />").Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SimpleExpressionAttribute()
|
||||
{
|
||||
ParseBlockTest("<a href='@foo' />",
|
||||
new MarkupBlock(
|
||||
Factory.Markup("<a"),
|
||||
new MarkupBlock(new AttributeBlockCodeGenerator(name: "href", prefix: new LocationTagged<string>(" href='", 2, 0, 2), suffix: new LocationTagged<string>("'", 13, 0, 13)),
|
||||
Factory.Markup(" href='").With(SpanCodeGenerator.Null),
|
||||
new MarkupBlock(new DynamicAttributeBlockCodeGenerator(new LocationTagged<string>(String.Empty, 9, 0, 9), 9, 0, 9),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("foo")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace))),
|
||||
Factory.Markup("'").With(SpanCodeGenerator.Null)),
|
||||
Factory.Markup(" />").Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MultiValueExpressionAttribute()
|
||||
{
|
||||
ParseBlockTest("<a href='@foo bar @baz' />",
|
||||
new MarkupBlock(
|
||||
Factory.Markup("<a"),
|
||||
new MarkupBlock(new AttributeBlockCodeGenerator(name: "href", prefix: new LocationTagged<string>(" href='", 2, 0, 2), suffix: new LocationTagged<string>("'", 22, 0, 22)),
|
||||
Factory.Markup(" href='").With(SpanCodeGenerator.Null),
|
||||
new MarkupBlock(new DynamicAttributeBlockCodeGenerator(new LocationTagged<string>(String.Empty, 9, 0, 9), 9, 0, 9),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("foo")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace))),
|
||||
Factory.Markup(" bar").With(new LiteralAttributeCodeGenerator(new LocationTagged<string>(" ", 13, 0, 13), new LocationTagged<string>("bar", 14, 0, 14))),
|
||||
new MarkupBlock(new DynamicAttributeBlockCodeGenerator(new LocationTagged<string>(" ", 17, 0, 17), 18, 0, 18),
|
||||
Factory.Markup(" ").With(SpanCodeGenerator.Null),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("baz")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace))),
|
||||
Factory.Markup("'").With(SpanCodeGenerator.Null)),
|
||||
Factory.Markup(" />").Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VirtualPathAttributesWorkWithConditionalAttributes()
|
||||
{
|
||||
ParseBlockTest("<a href='@foo ~/Foo/Bar' />",
|
||||
new MarkupBlock(
|
||||
Factory.Markup("<a"),
|
||||
new MarkupBlock(new AttributeBlockCodeGenerator(name: "href", prefix: new LocationTagged<string>(" href='", 2, 0, 2), suffix: new LocationTagged<string>("'", 23, 0, 23)),
|
||||
Factory.Markup(" href='").With(SpanCodeGenerator.Null),
|
||||
new MarkupBlock(new DynamicAttributeBlockCodeGenerator(new LocationTagged<string>(String.Empty, 9, 0, 9), 9, 0, 9),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("foo")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace))),
|
||||
Factory.Markup(" ~/Foo/Bar")
|
||||
.WithEditorHints(EditorHints.VirtualPath)
|
||||
.With(new LiteralAttributeCodeGenerator(
|
||||
new LocationTagged<string>(" ", 13, 0, 13),
|
||||
new LocationTagged<SpanCodeGenerator>(new ResolveUrlCodeGenerator(), 14, 0, 14))),
|
||||
Factory.Markup("'").With(SpanCodeGenerator.Null)),
|
||||
Factory.Markup(" />").Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void UnquotedAttributeWithCodeWithSpacesInBlock()
|
||||
{
|
||||
ParseBlockTest("<input value=@foo />",
|
||||
new MarkupBlock(
|
||||
Factory.Markup("<input"),
|
||||
new MarkupBlock(new AttributeBlockCodeGenerator(name: "value", prefix: new LocationTagged<string>(" value=", 6, 0, 6), suffix: new LocationTagged<string>(String.Empty, 17, 0, 17)),
|
||||
Factory.Markup(" value=").With(SpanCodeGenerator.Null),
|
||||
new MarkupBlock(new DynamicAttributeBlockCodeGenerator(new LocationTagged<string>(String.Empty, 13, 0, 13), 13, 0, 13),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("foo")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)))),
|
||||
Factory.Markup(" />").Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void UnquotedAttributeWithCodeWithSpacesInDocument()
|
||||
{
|
||||
ParseDocumentTest("<input value=@foo />",
|
||||
new MarkupBlock(
|
||||
Factory.Markup("<input"),
|
||||
new MarkupBlock(new AttributeBlockCodeGenerator(name: "value", prefix: new LocationTagged<string>(" value=", 6, 0, 6), suffix: new LocationTagged<string>(String.Empty, 17, 0, 17)),
|
||||
Factory.Markup(" value=").With(SpanCodeGenerator.Null),
|
||||
new MarkupBlock(new DynamicAttributeBlockCodeGenerator(new LocationTagged<string>(String.Empty, 13, 0, 13), 13, 0, 13),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("foo")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)))),
|
||||
Factory.Markup(" />")));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ConditionalAttributeCollapserDoesNotRemoveUrlAttributeValues()
|
||||
{
|
||||
// Act
|
||||
ParserResults results = ParseDocument("<a href='~/Foo/Bar' />");
|
||||
Block rewritten = new ConditionalAttributeCollapser(new HtmlMarkupParser().BuildSpan).Rewrite(results.Document);
|
||||
rewritten = new MarkupCollapser(new HtmlMarkupParser().BuildSpan).Rewrite(rewritten);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(0, results.ParserErrors.Count);
|
||||
EvaluateParseTree(rewritten,
|
||||
new MarkupBlock(
|
||||
Factory.Markup("<a"),
|
||||
new MarkupBlock(new AttributeBlockCodeGenerator(name: "href", prefix: new LocationTagged<string>(" href='", 2, 0, 2), suffix: new LocationTagged<string>("'", 18, 0, 18)),
|
||||
Factory.Markup(" href='").With(SpanCodeGenerator.Null),
|
||||
Factory.Markup("~/Foo/Bar")
|
||||
.WithEditorHints(EditorHints.VirtualPath)
|
||||
.With(new LiteralAttributeCodeGenerator(
|
||||
new LocationTagged<string>(String.Empty, 9, 0, 9),
|
||||
new LocationTagged<SpanCodeGenerator>(new ResolveUrlCodeGenerator(), 9, 0, 9))),
|
||||
Factory.Markup("'").With(SpanCodeGenerator.Null)),
|
||||
Factory.Markup(" />")));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ConditionalAttributesDoNotCreateExtraDataForEntirelyLiteralAttribute()
|
||||
{
|
||||
// Arrange
|
||||
const string code =
|
||||
@"<div class=""sidebar"">
|
||||
<h1>Title</h1>
|
||||
<p>
|
||||
As the author, you can <a href=""/Photo/Edit/photoId"">edit</a>
|
||||
or <a href=""/Photo/Remove/photoId"">remove</a> this photo.
|
||||
</p>
|
||||
<dl>
|
||||
<dt class=""description"">Description</dt>
|
||||
<dd class=""description"">
|
||||
The uploader did not provide a description for this photo.
|
||||
</dd>
|
||||
<dt class=""uploaded-by"">Uploaded by</dt>
|
||||
<dd class=""uploaded-by""><a href=""/User/View/user.UserId"">user.DisplayName</a></dd>
|
||||
<dt class=""upload-date"">Upload date</dt>
|
||||
<dd class=""upload-date"">photo.UploadDate</dd>
|
||||
<dt class=""part-of-gallery"">Gallery</dt>
|
||||
<dd><a href=""/View/gallery.Id"" title=""View gallery.Name gallery"">gallery.Name</a></dd>
|
||||
<dt class=""tags"">Tags</dt>
|
||||
<dd class=""tags"">
|
||||
<ul class=""tags"">
|
||||
<li>This photo has no tags.</li>
|
||||
</ul>
|
||||
<a href=""/Photo/EditTags/photoId"">edit tags</a>
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<p>
|
||||
<a class=""download"" href=""/Photo/Full/photoId"" title=""Download: (photo.FileTitle + photo.FileExtension)"">Download full photo</a> ((photo.FileSize / 1024) KB)
|
||||
</p>
|
||||
</div>
|
||||
<div class=""main"">
|
||||
<img class=""large-photo"" alt=""photo.FileTitle"" src=""/Photo/Thumbnail"" />
|
||||
<h2>Nobody has commented on this photo</h2>
|
||||
<ol class=""comments"">
|
||||
<li>
|
||||
<h3 class=""comment-header"">
|
||||
<a href=""/User/View/comment.UserId"" title=""View comment.DisplayName's profile"">comment.DisplayName</a> commented at comment.CommentDate:
|
||||
</h3>
|
||||
<p class=""comment-body"">comment.CommentText</p>
|
||||
</li>
|
||||
</ol>
|
||||
|
||||
<form method=""post"" action="""">
|
||||
<fieldset id=""addComment"">
|
||||
<legend>Post new comment</legend>
|
||||
<ol>
|
||||
<li>
|
||||
<label for=""newComment"">Comment</label>
|
||||
<textarea id=""newComment"" name=""newComment"" title=""Your comment"" rows=""6"" cols=""70""></textarea>
|
||||
</li>
|
||||
</ol>
|
||||
<p class=""form-actions"">
|
||||
<input type=""submit"" title=""Add comment"" value=""Add comment"" />
|
||||
</p>
|
||||
</fieldset>
|
||||
</form>
|
||||
</div>";
|
||||
|
||||
// Act
|
||||
ParserResults results = ParseDocument(code);
|
||||
Block rewritten = new ConditionalAttributeCollapser(new HtmlMarkupParser().BuildSpan).Rewrite(results.Document);
|
||||
rewritten = new MarkupCollapser(new HtmlMarkupParser().BuildSpan).Rewrite(rewritten);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(0, results.ParserErrors.Count);
|
||||
EvaluateParseTree(rewritten, new MarkupBlock(Factory.Markup(code)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ConditionalAttributesAreDisabledForDataAttributesInBlock()
|
||||
{
|
||||
ParseBlockTest("<span data-foo='@foo'></span>",
|
||||
new MarkupBlock(
|
||||
Factory.Markup("<span"),
|
||||
new MarkupBlock(
|
||||
Factory.Markup(" data-foo='"),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("foo")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
Factory.Markup("'")),
|
||||
Factory.Markup("></span>").Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ConditionalAttributesAreDisabledForDataAttributesInDocument()
|
||||
{
|
||||
ParseDocumentTest("<span data-foo='@foo'></span>",
|
||||
new MarkupBlock(
|
||||
Factory.Markup("<span"),
|
||||
new MarkupBlock(
|
||||
Factory.Markup(" data-foo='"),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("foo")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
Factory.Markup("'")),
|
||||
Factory.Markup("></span>")));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,393 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.AspNet.Razor.Editor;
|
||||
using Microsoft.AspNet.Razor.Generator;
|
||||
using Microsoft.AspNet.Razor.Parser;
|
||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||
using Microsoft.AspNet.Razor.Resources;
|
||||
using Microsoft.AspNet.Razor.Test.Framework;
|
||||
using Microsoft.AspNet.Razor.Text;
|
||||
using Microsoft.AspNet.Razor.Tokenizer.Symbols;
|
||||
using Microsoft.TestCommon;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Test.Parser.Html
|
||||
{
|
||||
public class HtmlBlockTest : CsHtmlMarkupParserTestBase
|
||||
{
|
||||
[Fact]
|
||||
public void ParseBlockMethodThrowsArgNullExceptionOnNullContext()
|
||||
{
|
||||
// Arrange
|
||||
HtmlMarkupParser parser = new HtmlMarkupParser();
|
||||
|
||||
// Act and Assert
|
||||
Assert.Throws<InvalidOperationException>(() => parser.ParseBlock(), RazorResources.Parser_Context_Not_Set);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockHandlesOpenAngleAtEof()
|
||||
{
|
||||
ParseDocumentTest("@{" + Environment.NewLine
|
||||
+ "<",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new StatementBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("{").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("\r\n").AsStatement(),
|
||||
new MarkupBlock(
|
||||
Factory.Markup("<")))),
|
||||
new RazorError(
|
||||
String.Format(RazorResources.ParseError_Expected_EndOfBlock_Before_EOF, RazorResources.BlockName_Code, "}", "{"),
|
||||
1, 0, 1));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockHandlesOpenAngleWithProperTagFollowingIt()
|
||||
{
|
||||
ParseDocumentTest("@{" + Environment.NewLine
|
||||
+ "<" + Environment.NewLine
|
||||
+ "</html>",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new StatementBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("{").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("\r\n").AsStatement(),
|
||||
new MarkupBlock(
|
||||
Factory.Markup("<\r\n")
|
||||
),
|
||||
new MarkupBlock(
|
||||
Factory.Markup(@"</html>").Accepts(AcceptedCharacters.None)
|
||||
),
|
||||
Factory.EmptyCSharp().AsStatement()
|
||||
)
|
||||
),
|
||||
designTimeParser: true,
|
||||
expectedErrors: new[]
|
||||
{
|
||||
new RazorError(String.Format(RazorResources.ParseError_UnexpectedEndTag, "html"), 7, 2, 0),
|
||||
new RazorError(String.Format(RazorResources.ParseError_Expected_EndOfBlock_Before_EOF, "code", "}", "{"), 1, 0, 1)
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TagWithoutCloseAngleDoesNotTerminateBlock()
|
||||
{
|
||||
ParseBlockTest("< " + Environment.NewLine
|
||||
+ " ",
|
||||
new MarkupBlock(
|
||||
Factory.Markup("< \r\n ")),
|
||||
designTimeParser: true,
|
||||
expectedErrors: new RazorError(String.Format(RazorResources.ParseError_UnfinishedTag, String.Empty), 0, 0, 0));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockAllowsStartAndEndTagsToDifferInCase()
|
||||
{
|
||||
SingleSpanBlockTest("<li><p>Foo</P></lI>", BlockType.Markup, SpanKind.Markup, acceptedCharacters: AcceptedCharacters.None);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockReadsToEndOfLineIfFirstCharacterAfterTransitionIsColon()
|
||||
{
|
||||
ParseBlockTest("@:<li>Foo Bar Baz" + Environment.NewLine
|
||||
+ "bork",
|
||||
new MarkupBlock(
|
||||
Factory.MarkupTransition(),
|
||||
Factory.MetaMarkup(":", HtmlSymbolType.Colon),
|
||||
Factory.Markup("<li>Foo Bar Baz\r\n")
|
||||
.With(new SingleLineMarkupEditHandler(CSharpLanguageCharacteristics.Instance.TokenizeString, AcceptedCharacters.None))
|
||||
));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockStopsParsingSingleLineBlockAtEOFIfNoEOLReached()
|
||||
{
|
||||
ParseBlockTest("@:foo bar",
|
||||
new MarkupBlock(
|
||||
Factory.MarkupTransition(),
|
||||
Factory.MetaMarkup(":", HtmlSymbolType.Colon),
|
||||
Factory.Markup(@"foo bar")
|
||||
.With(new SingleLineMarkupEditHandler(CSharpLanguageCharacteristics.Instance.TokenizeString))
|
||||
));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockStopsAtMatchingCloseTagToStartTag()
|
||||
{
|
||||
SingleSpanBlockTest("<a><b></b></a><c></c>", "<a><b></b></a>", BlockType.Markup, SpanKind.Markup, acceptedCharacters: AcceptedCharacters.None);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockParsesUntilMatchingEndTagIfFirstNonWhitespaceCharacterIsStartTag()
|
||||
{
|
||||
SingleSpanBlockTest("<baz><boz><biz></biz></boz></baz>", BlockType.Markup, SpanKind.Markup, acceptedCharacters: AcceptedCharacters.None);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockAllowsUnclosedTagsAsLongAsItCanRecoverToAnExpectedEndTag()
|
||||
{
|
||||
SingleSpanBlockTest("<foo><bar><baz></foo>", BlockType.Markup, SpanKind.Markup, acceptedCharacters: AcceptedCharacters.None);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockWithSelfClosingTagJustEmitsTag()
|
||||
{
|
||||
SingleSpanBlockTest("<foo />", BlockType.Markup, SpanKind.Markup, acceptedCharacters: AcceptedCharacters.None);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockCanHandleSelfClosingTagsWithinBlock()
|
||||
{
|
||||
SingleSpanBlockTest("<foo><bar /></foo>", BlockType.Markup, SpanKind.Markup, acceptedCharacters: AcceptedCharacters.None);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockSupportsTagsWithAttributes()
|
||||
{
|
||||
ParseBlockTest("<foo bar=\"baz\"><biz><boz zoop=zork/></biz></foo>",
|
||||
new MarkupBlock(
|
||||
Factory.Markup("<foo"),
|
||||
new MarkupBlock(new AttributeBlockCodeGenerator("bar", new LocationTagged<string>(" bar=\"", 4, 0, 4), new LocationTagged<string>("\"", 13, 0, 13)),
|
||||
Factory.Markup(" bar=\"").With(SpanCodeGenerator.Null),
|
||||
Factory.Markup("baz").With(new LiteralAttributeCodeGenerator(new LocationTagged<string>(String.Empty, 10, 0, 10), new LocationTagged<string>("baz", 10, 0, 10))),
|
||||
Factory.Markup("\"").With(SpanCodeGenerator.Null)),
|
||||
Factory.Markup("><biz><boz"),
|
||||
new MarkupBlock(new AttributeBlockCodeGenerator("zoop", new LocationTagged<string>(" zoop=", 24, 0, 24), new LocationTagged<string>(String.Empty, 34, 0, 34)),
|
||||
Factory.Markup(" zoop=").With(SpanCodeGenerator.Null),
|
||||
Factory.Markup("zork").With(new LiteralAttributeCodeGenerator(new LocationTagged<string>(String.Empty, 30, 0, 30), new LocationTagged<string>("zork", 30, 0, 30)))),
|
||||
Factory.Markup("/></biz></foo>").Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockAllowsCloseAngleBracketInAttributeValueIfDoubleQuoted()
|
||||
{
|
||||
ParseBlockTest("<foo><bar baz=\">\" /></foo>",
|
||||
new MarkupBlock(
|
||||
Factory.Markup("<foo><bar"),
|
||||
new MarkupBlock(new AttributeBlockCodeGenerator("baz", new LocationTagged<string>(" baz=\"", 9, 0, 9), new LocationTagged<string>("\"", 16, 0, 16)),
|
||||
Factory.Markup(" baz=\"").With(SpanCodeGenerator.Null),
|
||||
Factory.Markup(">").With(new LiteralAttributeCodeGenerator(new LocationTagged<string>(String.Empty, 15, 0, 15), new LocationTagged<string>(">", 15, 0, 15))),
|
||||
Factory.Markup("\"").With(SpanCodeGenerator.Null)),
|
||||
Factory.Markup(" /></foo>").Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockAllowsCloseAngleBracketInAttributeValueIfSingleQuoted()
|
||||
{
|
||||
ParseBlockTest("<foo><bar baz=\'>\' /></foo>",
|
||||
new MarkupBlock(
|
||||
Factory.Markup("<foo><bar"),
|
||||
new MarkupBlock(new AttributeBlockCodeGenerator("baz", new LocationTagged<string>(" baz='", 9, 0, 9), new LocationTagged<string>("'", 16, 0, 16)),
|
||||
Factory.Markup(" baz='").With(SpanCodeGenerator.Null),
|
||||
Factory.Markup(">").With(new LiteralAttributeCodeGenerator(new LocationTagged<string>(String.Empty, 15, 0, 15), new LocationTagged<string>(">", 15, 0, 15))),
|
||||
Factory.Markup("'").With(SpanCodeGenerator.Null)),
|
||||
Factory.Markup(" /></foo>").Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockAllowsSlashInAttributeValueIfDoubleQuoted()
|
||||
{
|
||||
ParseBlockTest("<foo><bar baz=\"/\"></bar></foo>",
|
||||
new MarkupBlock(
|
||||
Factory.Markup("<foo><bar"),
|
||||
new MarkupBlock(new AttributeBlockCodeGenerator("baz", new LocationTagged<string>(" baz=\"", 9, 0, 9), new LocationTagged<string>("\"", 16, 0, 16)),
|
||||
Factory.Markup(" baz=\"").With(SpanCodeGenerator.Null),
|
||||
Factory.Markup("/").With(new LiteralAttributeCodeGenerator(new LocationTagged<string>(String.Empty, 15, 0, 15), new LocationTagged<string>("/", 15, 0, 15))),
|
||||
Factory.Markup("\"").With(SpanCodeGenerator.Null)),
|
||||
Factory.Markup("></bar></foo>").Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockAllowsSlashInAttributeValueIfSingleQuoted()
|
||||
{
|
||||
ParseBlockTest("<foo><bar baz=\'/\'></bar></foo>",
|
||||
new MarkupBlock(
|
||||
Factory.Markup("<foo><bar"),
|
||||
new MarkupBlock(new AttributeBlockCodeGenerator("baz", new LocationTagged<string>(" baz='", 9, 0, 9), new LocationTagged<string>("'", 16, 0, 16)),
|
||||
Factory.Markup(" baz='").With(SpanCodeGenerator.Null),
|
||||
Factory.Markup("/").With(new LiteralAttributeCodeGenerator(new LocationTagged<string>(String.Empty, 15, 0, 15), new LocationTagged<string>("/", 15, 0, 15))),
|
||||
Factory.Markup("'").With(SpanCodeGenerator.Null)),
|
||||
Factory.Markup("></bar></foo>").Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockTerminatesAtEOF()
|
||||
{
|
||||
SingleSpanBlockTest("<foo>", "<foo>", BlockType.Markup, SpanKind.Markup,
|
||||
new RazorError(String.Format(RazorResources.ParseError_MissingEndTag, "foo"), new SourceLocation(0, 0, 0)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockSupportsCommentAsBlock()
|
||||
{
|
||||
SingleSpanBlockTest("<!-- foo -->", BlockType.Markup, SpanKind.Markup, acceptedCharacters: AcceptedCharacters.None);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockSupportsCommentWithinBlock()
|
||||
{
|
||||
SingleSpanBlockTest("<foo>bar<!-- zoop -->baz</foo>", BlockType.Markup, SpanKind.Markup, acceptedCharacters: AcceptedCharacters.None);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockProperlyBalancesCommentStartAndEndTags()
|
||||
{
|
||||
SingleSpanBlockTest("<!--<foo></bar>-->", BlockType.Markup, SpanKind.Markup, acceptedCharacters: AcceptedCharacters.None);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockTerminatesAtEOFWhenParsingComment()
|
||||
{
|
||||
SingleSpanBlockTest("<!--<foo>", "<!--<foo>", BlockType.Markup, SpanKind.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockOnlyTerminatesCommentOnFullEndSequence()
|
||||
{
|
||||
SingleSpanBlockTest("<!--<foo>--</bar>-->", BlockType.Markup, SpanKind.Markup, acceptedCharacters: AcceptedCharacters.None);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockTerminatesCommentAtFirstOccurrenceOfEndSequence()
|
||||
{
|
||||
SingleSpanBlockTest("<foo><!--<foo></bar-->--></foo>", BlockType.Markup, SpanKind.Markup, acceptedCharacters: AcceptedCharacters.None);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockTreatsMalformedTagsAsContent()
|
||||
{
|
||||
SingleSpanBlockTest(
|
||||
"<foo></!-- bar --></foo>",
|
||||
"<foo></!-- bar -->",
|
||||
BlockType.Markup,
|
||||
SpanKind.Markup,
|
||||
AcceptedCharacters.None,
|
||||
new RazorError(String.Format(RazorResources.ParseError_MissingEndTag, "foo"), 0, 0, 0));
|
||||
}
|
||||
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockParsesSGMLDeclarationAsEmptyTag()
|
||||
{
|
||||
SingleSpanBlockTest("<foo><!DOCTYPE foo bar baz></foo>", BlockType.Markup, SpanKind.Markup, acceptedCharacters: AcceptedCharacters.None);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockTerminatesSGMLDeclarationAtFirstCloseAngle()
|
||||
{
|
||||
SingleSpanBlockTest("<foo><!DOCTYPE foo bar> baz></foo>", BlockType.Markup, SpanKind.Markup, acceptedCharacters: AcceptedCharacters.None);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockParsesXMLProcessingInstructionAsEmptyTag()
|
||||
{
|
||||
SingleSpanBlockTest("<foo><?xml foo bar baz?></foo>", BlockType.Markup, SpanKind.Markup, acceptedCharacters: AcceptedCharacters.None);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockTerminatesXMLProcessingInstructionAtQuestionMarkCloseAnglePair()
|
||||
{
|
||||
SingleSpanBlockTest("<foo><?xml foo bar?> baz</foo>", BlockType.Markup, SpanKind.Markup, acceptedCharacters: AcceptedCharacters.None);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockDoesNotTerminateXMLProcessingInstructionAtCloseAngleUnlessPreceededByQuestionMark()
|
||||
{
|
||||
SingleSpanBlockTest("<foo><?xml foo bar> baz?></foo>", BlockType.Markup, SpanKind.Markup, acceptedCharacters: AcceptedCharacters.None);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockSupportsScriptTagsWithLessThanSignsInThem()
|
||||
{
|
||||
SingleSpanBlockTest(@"<script>if(foo<bar) { alert(""baz"");)</script>", BlockType.Markup, SpanKind.Markup, acceptedCharacters: AcceptedCharacters.None);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockSupportsScriptTagsWithSpacedLessThanSignsInThem()
|
||||
{
|
||||
SingleSpanBlockTest(@"<script>if(foo < bar) { alert(""baz"");)</script>", BlockType.Markup, SpanKind.Markup, acceptedCharacters: AcceptedCharacters.None);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockAcceptsEmptyTextTag()
|
||||
{
|
||||
ParseBlockTest("<text/>",
|
||||
new MarkupBlock(
|
||||
Factory.MarkupTransition("<text/>")
|
||||
));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockAcceptsTextTagAsOuterTagButDoesNotRender()
|
||||
{
|
||||
ParseBlockTest("<text>Foo Bar <foo> Baz</text> zoop",
|
||||
new MarkupBlock(
|
||||
Factory.MarkupTransition("<text>"),
|
||||
Factory.Markup("Foo Bar <foo> Baz"),
|
||||
Factory.MarkupTransition("</text>"),
|
||||
Factory.Markup(" ").Accepts(AcceptedCharacters.None)
|
||||
));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockRendersLiteralTextTagIfDoubled()
|
||||
{
|
||||
ParseBlockTest("<text><text>Foo Bar <foo> Baz</text></text> zoop",
|
||||
new MarkupBlock(
|
||||
Factory.MarkupTransition("<text>"),
|
||||
Factory.Markup("<text>Foo Bar <foo> Baz</text>"),
|
||||
Factory.MarkupTransition("</text>"),
|
||||
Factory.Markup(" ").Accepts(AcceptedCharacters.None)
|
||||
));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockDoesNotConsiderPsuedoTagWithinMarkupBlock()
|
||||
{
|
||||
ParseBlockTest("<foo><text><bar></bar></foo>",
|
||||
new MarkupBlock(
|
||||
Factory.Markup("<foo><text><bar></bar></foo>").Accepts(AcceptedCharacters.None)
|
||||
));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockStopsParsingMidEmptyTagIfEOFReached()
|
||||
{
|
||||
ParseBlockTest("<br/",
|
||||
new MarkupBlock(
|
||||
Factory.Markup("<br/")
|
||||
),
|
||||
new RazorError(String.Format(RazorResources.ParseError_UnfinishedTag, "br"), SourceLocation.Zero));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockCorrectlyHandlesSingleLineOfMarkupWithEmbeddedStatement()
|
||||
{
|
||||
ParseBlockTest("<div>Foo @if(true) {} Bar</div>",
|
||||
new MarkupBlock(
|
||||
Factory.Markup("<div>Foo "),
|
||||
new StatementBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("if(true) {}").AsStatement()),
|
||||
Factory.Markup(" Bar</div>").Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockIgnoresTagsInContentsOfScriptTag()
|
||||
{
|
||||
ParseBlockTest(@"<script>foo<bar baz='@boz'></script>",
|
||||
new MarkupBlock(
|
||||
Factory.Markup("<script>foo<bar baz='"),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("boz")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords, acceptTrailingDot: false)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
Factory.Markup("'></script>")
|
||||
.Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,239 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNet.Razor.Generator;
|
||||
using Microsoft.AspNet.Razor.Parser;
|
||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||
using Microsoft.AspNet.Razor.Resources;
|
||||
using Microsoft.AspNet.Razor.Test.Framework;
|
||||
using Microsoft.AspNet.Razor.Text;
|
||||
using System.Web.WebPages.TestUtils;
|
||||
using Microsoft.TestCommon;
|
||||
using System;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Test.Parser.Html
|
||||
{
|
||||
public class HtmlDocumentTest : CsHtmlMarkupParserTestBase
|
||||
{
|
||||
private static readonly TestFile Nested1000 = TestFile.Create("nested-1000.html");
|
||||
|
||||
[Fact]
|
||||
public void ParseDocumentMethodThrowsArgNullExceptionOnNullContext()
|
||||
{
|
||||
// Arrange
|
||||
HtmlMarkupParser parser = new HtmlMarkupParser();
|
||||
|
||||
// Act and Assert
|
||||
Assert.Throws<InvalidOperationException>(() => parser.ParseDocument(), RazorResources.Parser_Context_Not_Set);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseSectionMethodThrowsArgNullExceptionOnNullContext()
|
||||
{
|
||||
// Arrange
|
||||
HtmlMarkupParser parser = new HtmlMarkupParser();
|
||||
|
||||
// Act and Assert
|
||||
Assert.Throws<InvalidOperationException>(() => parser.ParseSection(null, true), RazorResources.Parser_Context_Not_Set);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseDocumentOutputsEmptyBlockWithEmptyMarkupSpanIfContentIsEmptyString()
|
||||
{
|
||||
ParseDocumentTest(String.Empty, new MarkupBlock(Factory.EmptyHtml()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseDocumentOutputsWhitespaceOnlyContentAsSingleWhitespaceMarkupSpan()
|
||||
{
|
||||
SingleSpanDocumentTest(" ", BlockType.Markup, SpanKind.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseDocumentAcceptsSwapTokenAtEndOfFileAndOutputsZeroLengthCodeSpan()
|
||||
{
|
||||
ParseDocumentTest("@",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.EmptyCSharp()
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
Factory.EmptyHtml()),
|
||||
new RazorError(RazorResources.ParseError_Unexpected_EndOfFile_At_Start_Of_CodeBlock, 1, 0, 1));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseDocumentCorrectlyHandlesSingleLineOfMarkupWithEmbeddedStatement()
|
||||
{
|
||||
ParseDocumentTest("<div>Foo @if(true) {} Bar</div>",
|
||||
new MarkupBlock(
|
||||
Factory.Markup("<div>Foo "),
|
||||
new StatementBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("if(true) {}").AsStatement()),
|
||||
Factory.Markup(" Bar</div>")));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseDocumentWithinSectionDoesNotCreateDocumentLevelSpan()
|
||||
{
|
||||
ParseDocumentTest("@section Foo {" + Environment.NewLine
|
||||
+ " <html></html>" + Environment.NewLine
|
||||
+ "}",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new SectionBlock(new SectionCodeGenerator("Foo"),
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("section Foo {")
|
||||
.AutoCompleteWith(null, atEndOfSpan: true),
|
||||
new MarkupBlock(
|
||||
Factory.Markup("\r\n <html></html>\r\n")),
|
||||
Factory.MetaCode("}").Accepts(AcceptedCharacters.None)),
|
||||
Factory.EmptyHtml()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseDocumentParsesWholeContentAsOneSpanIfNoSwapCharacterEncountered()
|
||||
{
|
||||
SingleSpanDocumentTest("foo <bar>baz</bar>", BlockType.Markup, SpanKind.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseDocumentHandsParsingOverToCodeParserWhenAtSignEncounteredAndEmitsOutput()
|
||||
{
|
||||
ParseDocumentTest("foo @bar baz",
|
||||
new MarkupBlock(
|
||||
Factory.Markup("foo "),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("bar")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
Factory.Markup(" baz")));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseDocumentEmitsAtSignAsMarkupIfAtEndOfFile()
|
||||
{
|
||||
ParseDocumentTest("foo @",
|
||||
new MarkupBlock(
|
||||
Factory.Markup("foo "),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.EmptyCSharp()
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
Factory.EmptyHtml()),
|
||||
new RazorError(RazorResources.ParseError_Unexpected_EndOfFile_At_Start_Of_CodeBlock, 5, 0, 5));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseDocumentEmitsCodeBlockIfFirstCharacterIsSwapCharacter()
|
||||
{
|
||||
ParseDocumentTest("@bar",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("bar")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
Factory.EmptyHtml()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseDocumentDoesNotSwitchToCodeOnEmailAddressInText()
|
||||
{
|
||||
SingleSpanDocumentTest("<foo>anurse@microsoft.com</foo>", BlockType.Markup, SpanKind.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseDocumentDoesNotSwitchToCodeOnEmailAddressInAttribute()
|
||||
{
|
||||
ParseDocumentTest("<a href=\"mailto:anurse@microsoft.com\">Email me</a>",
|
||||
new MarkupBlock(
|
||||
Factory.Markup("<a"),
|
||||
new MarkupBlock(new AttributeBlockCodeGenerator("href", new LocationTagged<string>(" href=\"", 2, 0, 2), new LocationTagged<string>("\"", 36, 0, 36)),
|
||||
Factory.Markup(" href=\"").With(SpanCodeGenerator.Null),
|
||||
Factory.Markup("mailto:anurse@microsoft.com")
|
||||
.With(new LiteralAttributeCodeGenerator(new LocationTagged<string>(String.Empty, 9, 0, 9), new LocationTagged<string>("mailto:anurse@microsoft.com", 9, 0, 9))),
|
||||
Factory.Markup("\"").With(SpanCodeGenerator.Null)),
|
||||
Factory.Markup(">Email me</a>")));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseDocumentDoesNotReturnErrorOnMismatchedTags()
|
||||
{
|
||||
SingleSpanDocumentTest("Foo <div><p></p></p> Baz", BlockType.Markup, SpanKind.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseDocumentReturnsOneMarkupSegmentIfNoCodeBlocksEncountered()
|
||||
{
|
||||
SingleSpanDocumentTest("Foo <p>Baz<!--Foo-->Bar<!-F> Qux", BlockType.Markup, SpanKind.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseDocumentRendersTextPseudoTagAsMarkup()
|
||||
{
|
||||
SingleSpanDocumentTest("Foo <text>Foo</text>", BlockType.Markup, SpanKind.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseDocumentAcceptsEndTagWithNoMatchingStartTag()
|
||||
{
|
||||
SingleSpanDocumentTest("Foo </div> Bar", BlockType.Markup, SpanKind.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseDocumentNoLongerSupportsDollarOpenBraceCombination()
|
||||
{
|
||||
ParseDocumentTest("<foo>${bar}</foo>",
|
||||
new MarkupBlock(
|
||||
Factory.Markup("<foo>${bar}</foo>")));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseDocumentIgnoresTagsInContentsOfScriptTag()
|
||||
{
|
||||
ParseDocumentTest(@"<script>foo<bar baz='@boz'></script>",
|
||||
new MarkupBlock(
|
||||
Factory.Markup("<script>foo<bar baz='"),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("boz")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords, acceptTrailingDot: false)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
Factory.Markup("'></script>")));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseSectionIgnoresTagsInContentsOfScriptTag()
|
||||
{
|
||||
ParseDocumentTest(@"@section Foo { <script>foo<bar baz='@boz'></script> }",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new SectionBlock(new SectionCodeGenerator("Foo"),
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("section Foo {"),
|
||||
new MarkupBlock(
|
||||
Factory.Markup(" <script>foo<bar baz='"),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("boz")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords, acceptTrailingDot: false)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
Factory.Markup("'></script> ")),
|
||||
Factory.MetaCode("}").Accepts(AcceptedCharacters.None)),
|
||||
Factory.EmptyHtml()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockCanParse1000NestedElements()
|
||||
{
|
||||
string content = Nested1000.ReadAllText();
|
||||
SingleSpanDocumentTest(content, BlockType.Markup, SpanKind.Markup);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.AspNet.Razor.Generator;
|
||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||
using Microsoft.AspNet.Razor.Resources;
|
||||
using Microsoft.AspNet.Razor.Test.Framework;
|
||||
using Microsoft.AspNet.Razor.Text;
|
||||
using Microsoft.TestCommon;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Test.Parser.Html
|
||||
{
|
||||
public class HtmlErrorTest : CsHtmlMarkupParserTestBase
|
||||
{
|
||||
[Fact]
|
||||
public void ParseBlockAllowsInvalidTagNamesAsLongAsParserCanIdentifyEndTag()
|
||||
{
|
||||
SingleSpanBlockTest("<1-foo+bar>foo</1-foo+bar>", BlockType.Markup, SpanKind.Markup, acceptedCharacters: AcceptedCharacters.None);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockThrowsErrorIfStartTextTagContainsTextAfterName()
|
||||
{
|
||||
ParseBlockTest("<text foo bar></text>",
|
||||
new MarkupBlock(
|
||||
Factory.MarkupTransition("<text").Accepts(AcceptedCharacters.Any),
|
||||
Factory.Markup(" foo bar>"),
|
||||
Factory.MarkupTransition("</text>")),
|
||||
new RazorError(RazorResources.ParseError_TextTagCannotContainAttributes, SourceLocation.Zero));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockThrowsErrorIfEndTextTagContainsTextAfterName()
|
||||
{
|
||||
ParseBlockTest("<text></text foo bar>",
|
||||
new MarkupBlock(
|
||||
Factory.MarkupTransition("<text>"),
|
||||
Factory.MarkupTransition("</text").Accepts(AcceptedCharacters.Any),
|
||||
Factory.Markup(" ")),
|
||||
new RazorError(RazorResources.ParseError_TextTagCannotContainAttributes, 6, 0, 6));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockThrowsExceptionIfBlockDoesNotStartWithTag()
|
||||
{
|
||||
ParseBlockTest("foo bar <baz>",
|
||||
new MarkupBlock(),
|
||||
new RazorError(RazorResources.ParseError_MarkupBlock_Must_Start_With_Tag, SourceLocation.Zero));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockStartingWithEndTagProducesRazorErrorThenOutputsMarkupSegmentAndEndsBlock()
|
||||
{
|
||||
ParseBlockTest("</foo> bar baz",
|
||||
new MarkupBlock(
|
||||
Factory.Markup("</foo> ").Accepts(AcceptedCharacters.None)),
|
||||
new RazorError(String.Format(RazorResources.ParseError_UnexpectedEndTag, "foo"), SourceLocation.Zero));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockWithUnclosedTopLevelTagThrowsMissingEndTagParserExceptionOnOutermostUnclosedTag()
|
||||
{
|
||||
ParseBlockTest("<p><foo></bar>",
|
||||
new MarkupBlock(
|
||||
Factory.Markup("<p><foo></bar>").Accepts(AcceptedCharacters.None)),
|
||||
new RazorError(String.Format(RazorResources.ParseError_MissingEndTag, "p"), new SourceLocation(0, 0, 0)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockWithUnclosedTagAtEOFThrowsMissingEndTagException()
|
||||
{
|
||||
ParseBlockTest("<foo>blah blah blah blah blah",
|
||||
new MarkupBlock(
|
||||
Factory.Markup("<foo>blah blah blah blah blah")),
|
||||
new RazorError(String.Format(RazorResources.ParseError_MissingEndTag, "foo"), new SourceLocation(0, 0, 0)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockWithUnfinishedTagAtEOFThrowsIncompleteTagException()
|
||||
{
|
||||
ParseBlockTest("<foo bar=baz",
|
||||
new MarkupBlock(
|
||||
Factory.Markup("<foo"),
|
||||
new MarkupBlock(new AttributeBlockCodeGenerator("bar", new LocationTagged<string>(" bar=", 4, 0, 4), new LocationTagged<string>(String.Empty, 12, 0, 12)),
|
||||
Factory.Markup(" bar=").With(SpanCodeGenerator.Null),
|
||||
Factory.Markup("baz").With(new LiteralAttributeCodeGenerator(new LocationTagged<string>(String.Empty, 9, 0, 9), new LocationTagged<string>("baz", 9, 0, 9))))),
|
||||
new RazorError(String.Format(RazorResources.ParseError_UnfinishedTag, "foo"), new SourceLocation(0, 0, 0)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.AspNet.Razor.Parser;
|
||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||
using Microsoft.AspNet.Razor.Test.Framework;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Test.Parser.Html
|
||||
{
|
||||
internal class HtmlParserTestUtils
|
||||
{
|
||||
public static void RunSingleAtEscapeTest(Action<string, Block> testMethod, AcceptedCharacters lastSpanAcceptedCharacters = AcceptedCharacters.None)
|
||||
{
|
||||
var factory = SpanFactory.CreateCsHtml();
|
||||
testMethod("<foo>@@bar</foo>",
|
||||
new MarkupBlock(
|
||||
factory.Markup("<foo>"),
|
||||
factory.Markup("@").Hidden(),
|
||||
factory.Markup("@bar</foo>").Accepts(lastSpanAcceptedCharacters)));
|
||||
}
|
||||
|
||||
public static void RunMultiAtEscapeTest(Action<string, Block> testMethod, AcceptedCharacters lastSpanAcceptedCharacters = AcceptedCharacters.None)
|
||||
{
|
||||
var factory = SpanFactory.CreateCsHtml();
|
||||
testMethod("<foo>@@@@@bar</foo>",
|
||||
new MarkupBlock(
|
||||
factory.Markup("<foo>"),
|
||||
factory.Markup("@").Hidden(),
|
||||
factory.Markup("@"),
|
||||
factory.Markup("@").Hidden(),
|
||||
factory.Markup("@"),
|
||||
new ExpressionBlock(
|
||||
factory.CodeTransition(),
|
||||
factory.Code("bar")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
factory.Markup("</foo>").Accepts(lastSpanAcceptedCharacters)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,152 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||
using Microsoft.AspNet.Razor.Resources;
|
||||
using Microsoft.AspNet.Razor.Test.Framework;
|
||||
using Microsoft.TestCommon;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Test.Parser.Html
|
||||
{
|
||||
public class HtmlTagsTest : CsHtmlMarkupParserTestBase
|
||||
{
|
||||
public static IEnumerable<string[]> VoidElementNames
|
||||
{
|
||||
get
|
||||
{
|
||||
yield return new[] { "area" };
|
||||
yield return new[] { "base" };
|
||||
yield return new[] { "br" };
|
||||
yield return new[] { "col" };
|
||||
yield return new[] { "command" };
|
||||
yield return new[] { "embed" };
|
||||
yield return new[] { "hr" };
|
||||
yield return new[] { "img" };
|
||||
yield return new[] { "input" };
|
||||
yield return new[] { "keygen" };
|
||||
yield return new[] { "link" };
|
||||
yield return new[] { "meta" };
|
||||
yield return new[] { "param" };
|
||||
yield return new[] { "source" };
|
||||
yield return new[] { "track" };
|
||||
yield return new[] { "wbr" };
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EmptyTagNestsLikeNormalTag()
|
||||
{
|
||||
ParseBlockTest("<p></> Bar",
|
||||
new MarkupBlock(
|
||||
Factory.Markup("<p></> ").Accepts(AcceptedCharacters.None)),
|
||||
new RazorError(String.Format(RazorResources.ParseError_MissingEndTag, "p"), 0, 0, 0));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EmptyTag()
|
||||
{
|
||||
ParseBlockTest("<></> Bar",
|
||||
new MarkupBlock(
|
||||
Factory.Markup("<></> ").Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CommentTag()
|
||||
{
|
||||
ParseBlockTest("<!--Foo--> Bar",
|
||||
new MarkupBlock(
|
||||
Factory.Markup("<!--Foo--> ").Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DocTypeTag()
|
||||
{
|
||||
ParseBlockTest("<!DOCTYPE html> foo",
|
||||
new MarkupBlock(
|
||||
Factory.Markup("<!DOCTYPE html> ").Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessingInstructionTag()
|
||||
{
|
||||
ParseBlockTest("<?xml version=\"1.0\" ?> foo",
|
||||
new MarkupBlock(
|
||||
Factory.Markup("<?xml version=\"1.0\" ?> ").Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ElementTags()
|
||||
{
|
||||
ParseBlockTest("<p>Foo</p> Bar",
|
||||
new MarkupBlock(
|
||||
Factory.Markup("<p>Foo</p> ").Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TextTags()
|
||||
{
|
||||
ParseBlockTest("<text>Foo</text>}",
|
||||
new MarkupBlock(
|
||||
Factory.MarkupTransition("<text>"),
|
||||
Factory.Markup("Foo"),
|
||||
Factory.MarkupTransition("</text>")));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CDataTag()
|
||||
{
|
||||
ParseBlockTest("<![CDATA[Foo]]> Bar",
|
||||
new MarkupBlock(
|
||||
Factory.Markup("<![CDATA[Foo]]> ").Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ScriptTag()
|
||||
{
|
||||
ParseDocumentTest("<script>foo < bar && quantity.toString() !== orderQty.val()</script>",
|
||||
new MarkupBlock(
|
||||
Factory.Markup("<script>foo < bar && quantity.toString() !== orderQty.val()</script>")));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[PropertyData("VoidElementNames")]
|
||||
public void VoidElementFollowedByContent(string tagName)
|
||||
{
|
||||
ParseBlockTest("<" + tagName + ">foo",
|
||||
new MarkupBlock(
|
||||
Factory.Markup("<" + tagName + ">")
|
||||
.Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[PropertyData("VoidElementNames")]
|
||||
public void VoidElementFollowedByOtherTag(string tagName)
|
||||
{
|
||||
ParseBlockTest("<" + tagName + "><other>foo",
|
||||
new MarkupBlock(
|
||||
Factory.Markup("<" + tagName + ">")
|
||||
.Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[PropertyData("VoidElementNames")]
|
||||
public void VoidElementFollowedByCloseTag(string tagName)
|
||||
{
|
||||
ParseBlockTest("<" + tagName + "> </" + tagName + ">foo",
|
||||
new MarkupBlock(
|
||||
Factory.Markup("<" + tagName + "> </" + tagName + ">")
|
||||
.Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[PropertyData("VoidElementNames")]
|
||||
public void IncompleteVoidElementEndTag(string tagName)
|
||||
{
|
||||
ParseBlockTest("<" + tagName + "></" + tagName,
|
||||
new MarkupBlock(
|
||||
Factory.Markup("<" + tagName + "></" + tagName)
|
||||
.Accepts(AcceptedCharacters.Any)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,353 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.AspNet.Razor.Editor;
|
||||
using Microsoft.AspNet.Razor.Generator;
|
||||
using Microsoft.AspNet.Razor.Parser;
|
||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||
using Microsoft.AspNet.Razor.Test.Framework;
|
||||
using Microsoft.AspNet.Razor.Text;
|
||||
using Microsoft.AspNet.Razor.Tokenizer.Symbols;
|
||||
using Microsoft.TestCommon;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Test.Parser.Html
|
||||
{
|
||||
public class HtmlToCodeSwitchTest : CsHtmlMarkupParserTestBase
|
||||
{
|
||||
[Fact]
|
||||
public void ParseBlockSwitchesWhenCharacterBeforeSwapIsNonAlphanumeric()
|
||||
{
|
||||
ParseBlockTest("<p>foo#@i</p>",
|
||||
new MarkupBlock(
|
||||
Factory.Markup("<p>foo#"),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("i").AsImplicitExpression(CSharpCodeParser.DefaultKeywords).Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
Factory.Markup("</p>").Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockSwitchesToCodeWhenSwapCharacterEncounteredMidTag()
|
||||
{
|
||||
ParseBlockTest("<foo @bar />",
|
||||
new MarkupBlock(
|
||||
Factory.Markup("<foo "),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("bar")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
Factory.Markup(" />").Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockSwitchesToCodeWhenSwapCharacterEncounteredInAttributeValue()
|
||||
{
|
||||
ParseBlockTest("<foo bar=\"@baz\" />",
|
||||
new MarkupBlock(
|
||||
Factory.Markup("<foo"),
|
||||
new MarkupBlock(new AttributeBlockCodeGenerator("bar", new LocationTagged<string>(" bar=\"", 4, 0, 4), new LocationTagged<string>("\"", 14, 0, 14)),
|
||||
Factory.Markup(" bar=\"").With(SpanCodeGenerator.Null),
|
||||
new MarkupBlock(new DynamicAttributeBlockCodeGenerator(new LocationTagged<string>(String.Empty, 10, 0, 10), 10, 0, 10),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("baz")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace))),
|
||||
Factory.Markup("\"").With(SpanCodeGenerator.Null)),
|
||||
Factory.Markup(" />").Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockSwitchesToCodeWhenSwapCharacterEncounteredInTagContent()
|
||||
{
|
||||
ParseBlockTest("<foo>@bar<baz>@boz</baz></foo>",
|
||||
new MarkupBlock(
|
||||
Factory.Markup("<foo>"),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("bar")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
Factory.Markup("<baz>"),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("boz")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
Factory.Markup("</baz></foo>").Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockParsesCodeWithinSingleLineMarkup()
|
||||
{
|
||||
ParseBlockTest("@:<li>Foo @Bar Baz" + Environment.NewLine
|
||||
+ "bork",
|
||||
new MarkupBlock(
|
||||
Factory.MarkupTransition(),
|
||||
Factory.MetaMarkup(":", HtmlSymbolType.Colon),
|
||||
Factory.Markup("<li>Foo ").With(new SingleLineMarkupEditHandler(CSharpLanguageCharacteristics.Instance.TokenizeString)),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("Bar")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
Factory.Markup(" Baz\r\n")
|
||||
.With(new SingleLineMarkupEditHandler(CSharpLanguageCharacteristics.Instance.TokenizeString, AcceptedCharacters.None))));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockSupportsCodeWithinComment()
|
||||
{
|
||||
ParseBlockTest("<foo><!-- @foo --></foo>",
|
||||
new MarkupBlock(
|
||||
Factory.Markup("<foo><!-- "),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("foo")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
Factory.Markup(" --></foo>").Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockSupportsCodeWithinSGMLDeclaration()
|
||||
{
|
||||
ParseBlockTest("<foo><!DOCTYPE foo @bar baz></foo>",
|
||||
new MarkupBlock(
|
||||
Factory.Markup("<foo><!DOCTYPE foo "),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("bar")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
Factory.Markup(" baz></foo>").Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockSupportsCodeWithinCDataDeclaration()
|
||||
{
|
||||
ParseBlockTest("<foo><![CDATA[ foo @bar baz]]></foo>",
|
||||
new MarkupBlock(
|
||||
Factory.Markup("<foo><![CDATA[ foo "),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("bar")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
Factory.Markup(" baz]]></foo>").Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockSupportsCodeWithinXMLProcessingInstruction()
|
||||
{
|
||||
ParseBlockTest("<foo><?xml foo @bar baz?></foo>",
|
||||
new MarkupBlock(
|
||||
Factory.Markup("<foo><?xml foo "),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("bar")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
Factory.Markup(" baz?></foo>").Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockDoesNotSwitchToCodeOnEmailAddressInText()
|
||||
{
|
||||
SingleSpanBlockTest("<foo>anurse@microsoft.com</foo>", BlockType.Markup, SpanKind.Markup, acceptedCharacters: AcceptedCharacters.None);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockDoesNotSwitchToCodeOnEmailAddressInAttribute()
|
||||
{
|
||||
ParseBlockTest("<a href=\"mailto:anurse@microsoft.com\">Email me</a>",
|
||||
new MarkupBlock(
|
||||
Factory.Markup("<a"),
|
||||
new MarkupBlock(new AttributeBlockCodeGenerator("href", new LocationTagged<string>(" href=\"", 2, 0, 2), new LocationTagged<string>("\"", 36, 0, 36)),
|
||||
Factory.Markup(" href=\"").With(SpanCodeGenerator.Null),
|
||||
Factory.Markup("mailto:anurse@microsoft.com")
|
||||
.With(new LiteralAttributeCodeGenerator(new LocationTagged<string>(String.Empty, 9, 0, 9), new LocationTagged<string>("mailto:anurse@microsoft.com", 9, 0, 9))),
|
||||
Factory.Markup("\"").With(SpanCodeGenerator.Null)),
|
||||
Factory.Markup(">Email me</a>").Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockGivesWhitespacePreceedingAtToCodeIfThereIsNoMarkupOnThatLine()
|
||||
{
|
||||
ParseBlockTest(" <ul>" + Environment.NewLine
|
||||
+ " @foreach(var p in Products) {" + Environment.NewLine
|
||||
+ " <li>Product: @p.Name</li>" + Environment.NewLine
|
||||
+ " }" + Environment.NewLine
|
||||
+ " </ul>",
|
||||
new MarkupBlock(
|
||||
Factory.Markup(" <ul>\r\n"),
|
||||
new StatementBlock(
|
||||
Factory.Code(" ").AsStatement(),
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("foreach(var p in Products) {\r\n").AsStatement(),
|
||||
new MarkupBlock(
|
||||
Factory.Markup(" <li>Product: "),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("p.Name")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
Factory.Markup("</li>\r\n").Accepts(AcceptedCharacters.None)),
|
||||
Factory.Code(" }\r\n").AsStatement().Accepts(AcceptedCharacters.None)),
|
||||
Factory.Markup(" </ul>").Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseDocumentGivesWhitespacePreceedingAtToCodeIfThereIsNoMarkupOnThatLine()
|
||||
{
|
||||
ParseDocumentTest(" <ul>" + Environment.NewLine
|
||||
+ " @foreach(var p in Products) {" + Environment.NewLine
|
||||
+ " <li>Product: @p.Name</li>" + Environment.NewLine
|
||||
+ " }" + Environment.NewLine
|
||||
+ " </ul>",
|
||||
new MarkupBlock(
|
||||
Factory.Markup(" <ul>\r\n"),
|
||||
new StatementBlock(
|
||||
Factory.Code(" ").AsStatement(),
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("foreach(var p in Products) {\r\n").AsStatement(),
|
||||
new MarkupBlock(
|
||||
Factory.Markup(" <li>Product: "),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("p.Name")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
Factory.Markup("</li>\r\n").Accepts(AcceptedCharacters.None)),
|
||||
Factory.Code(" }\r\n").AsStatement().Accepts(AcceptedCharacters.None)),
|
||||
Factory.Markup(" </ul>")));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SectionContextGivesWhitespacePreceedingAtToCodeIfThereIsNoMarkupOnThatLine()
|
||||
{
|
||||
ParseDocumentTest("@section foo {" + Environment.NewLine
|
||||
+ " <ul>" + Environment.NewLine
|
||||
+ " @foreach(var p in Products) {" + Environment.NewLine
|
||||
+ " <li>Product: @p.Name</li>" + Environment.NewLine
|
||||
+ " }" + Environment.NewLine
|
||||
+ " </ul>" + Environment.NewLine
|
||||
+ "}",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new SectionBlock(new SectionCodeGenerator("foo"),
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("section foo {").AutoCompleteWith(null, atEndOfSpan: true),
|
||||
new MarkupBlock(
|
||||
Factory.Markup("\r\n <ul>\r\n"),
|
||||
new StatementBlock(
|
||||
Factory.Code(" ").AsStatement(),
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("foreach(var p in Products) {\r\n").AsStatement(),
|
||||
new MarkupBlock(
|
||||
Factory.Markup(" <li>Product: "),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("p.Name")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
Factory.Markup("</li>\r\n").Accepts(AcceptedCharacters.None)),
|
||||
Factory.Code(" }\r\n").AsStatement().Accepts(AcceptedCharacters.None)),
|
||||
Factory.Markup(" </ul>\r\n")),
|
||||
Factory.MetaCode("}").Accepts(AcceptedCharacters.None)),
|
||||
Factory.EmptyHtml()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CSharpCodeParserDoesNotAcceptLeadingOrTrailingWhitespaceInDesignMode()
|
||||
{
|
||||
ParseBlockTest(" <ul>" + Environment.NewLine
|
||||
+ " @foreach(var p in Products) {" + Environment.NewLine
|
||||
+ " <li>Product: @p.Name</li>" + Environment.NewLine
|
||||
+ " }" + Environment.NewLine
|
||||
+ " </ul>",
|
||||
new MarkupBlock(
|
||||
Factory.Markup(" <ul>\r\n "),
|
||||
new StatementBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("foreach(var p in Products) {\r\n ").AsStatement(),
|
||||
new MarkupBlock(
|
||||
Factory.Markup("<li>Product: "),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("p.Name").AsImplicitExpression(CSharpCodeParser.DefaultKeywords).Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
Factory.Markup("</li>").Accepts(AcceptedCharacters.None)),
|
||||
Factory.Code("\r\n }").AsStatement().Accepts(AcceptedCharacters.None)),
|
||||
Factory.Markup("\r\n </ul>").Accepts(AcceptedCharacters.None)),
|
||||
designTimeParser: true);
|
||||
}
|
||||
|
||||
// Tests for "@@" escape sequence:
|
||||
[Fact]
|
||||
public void ParseBlockTreatsTwoAtSignsAsEscapeSequence()
|
||||
{
|
||||
HtmlParserTestUtils.RunSingleAtEscapeTest(ParseBlockTest);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockTreatsPairsOfAtSignsAsEscapeSequence()
|
||||
{
|
||||
HtmlParserTestUtils.RunMultiAtEscapeTest(ParseBlockTest);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseDocumentTreatsTwoAtSignsAsEscapeSequence()
|
||||
{
|
||||
HtmlParserTestUtils.RunSingleAtEscapeTest(ParseDocumentTest, lastSpanAcceptedCharacters: AcceptedCharacters.Any);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseDocumentTreatsPairsOfAtSignsAsEscapeSequence()
|
||||
{
|
||||
HtmlParserTestUtils.RunMultiAtEscapeTest(ParseDocumentTest, lastSpanAcceptedCharacters: AcceptedCharacters.Any);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SectionBodyTreatsTwoAtSignsAsEscapeSequence()
|
||||
{
|
||||
ParseDocumentTest("@section Foo { <foo>@@bar</foo> }",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new SectionBlock(new SectionCodeGenerator("Foo"),
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("section Foo {").AutoCompleteWith(null, atEndOfSpan: true),
|
||||
new MarkupBlock(
|
||||
Factory.Markup(" <foo>"),
|
||||
Factory.Markup("@").Hidden(),
|
||||
Factory.Markup("@bar</foo> ")),
|
||||
Factory.MetaCode("}").Accepts(AcceptedCharacters.None)),
|
||||
Factory.EmptyHtml()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SectionBodyTreatsPairsOfAtSignsAsEscapeSequence()
|
||||
{
|
||||
ParseDocumentTest("@section Foo { <foo>@@@@@bar</foo> }",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new SectionBlock(new SectionCodeGenerator("Foo"),
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("section Foo {").AutoCompleteWith(null, atEndOfSpan: true),
|
||||
new MarkupBlock(
|
||||
Factory.Markup(" <foo>"),
|
||||
Factory.Markup("@").Hidden(),
|
||||
Factory.Markup("@"),
|
||||
Factory.Markup("@").Hidden(),
|
||||
Factory.Markup("@"),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("bar")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
Factory.Markup("</foo> ")),
|
||||
Factory.MetaCode("}").Accepts(AcceptedCharacters.None)),
|
||||
Factory.EmptyHtml()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,273 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.AspNet.Razor.Editor;
|
||||
using Microsoft.AspNet.Razor.Generator;
|
||||
using Microsoft.AspNet.Razor.Parser;
|
||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||
using Microsoft.AspNet.Razor.Test.Framework;
|
||||
using Microsoft.AspNet.Razor.Text;
|
||||
using Microsoft.TestCommon;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Test.Parser.Html
|
||||
{
|
||||
public class HtmlUrlAttributeTest : CsHtmlMarkupParserTestBase
|
||||
{
|
||||
[Fact]
|
||||
public void SimpleUrlInAttributeInMarkupBlock()
|
||||
{
|
||||
ParseBlockTest("<a href='~/Foo/Bar/Baz' />",
|
||||
new MarkupBlock(
|
||||
Factory.Markup("<a"),
|
||||
new MarkupBlock(new AttributeBlockCodeGenerator("href", new LocationTagged<string>(" href='", 2, 0, 2), new LocationTagged<string>("'", 22, 0, 22)),
|
||||
Factory.Markup(" href='").With(SpanCodeGenerator.Null),
|
||||
Factory.Markup("~/Foo/Bar/Baz")
|
||||
.WithEditorHints(EditorHints.VirtualPath)
|
||||
.With(new LiteralAttributeCodeGenerator(
|
||||
new LocationTagged<string>(String.Empty, 9, 0, 9),
|
||||
new LocationTagged<SpanCodeGenerator>(new ResolveUrlCodeGenerator(), 9, 0, 9))),
|
||||
Factory.Markup("'").With(SpanCodeGenerator.Null)),
|
||||
Factory.Markup(" />").Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SimpleUrlInAttributeInMarkupDocument()
|
||||
{
|
||||
ParseDocumentTest("<a href='~/Foo/Bar/Baz' />",
|
||||
new MarkupBlock(
|
||||
Factory.Markup("<a"),
|
||||
new MarkupBlock(new AttributeBlockCodeGenerator("href", new LocationTagged<string>(" href='", 2, 0, 2), new LocationTagged<string>("'", 22, 0, 22)),
|
||||
Factory.Markup(" href='").With(SpanCodeGenerator.Null),
|
||||
Factory.Markup("~/Foo/Bar/Baz")
|
||||
.WithEditorHints(EditorHints.VirtualPath)
|
||||
.With(new LiteralAttributeCodeGenerator(
|
||||
new LocationTagged<string>(String.Empty, 9, 0, 9),
|
||||
new LocationTagged<SpanCodeGenerator>(new ResolveUrlCodeGenerator(), 9, 0, 9))),
|
||||
Factory.Markup("'").With(SpanCodeGenerator.Null)),
|
||||
Factory.Markup(" />")));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SimpleUrlInAttributeInMarkupSection()
|
||||
{
|
||||
ParseDocumentTest("@section Foo { <a href='~/Foo/Bar/Baz' /> }",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new SectionBlock(new SectionCodeGenerator("Foo"),
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("section Foo {")
|
||||
.AutoCompleteWith(null, atEndOfSpan: true)
|
||||
.Accepts(AcceptedCharacters.Any),
|
||||
new MarkupBlock(
|
||||
Factory.Markup(" <a"),
|
||||
new MarkupBlock(new AttributeBlockCodeGenerator("href", new LocationTagged<string>(" href='", 17, 0, 17), new LocationTagged<string>("'", 37, 0, 37)),
|
||||
Factory.Markup(" href='").With(SpanCodeGenerator.Null),
|
||||
Factory.Markup("~/Foo/Bar/Baz")
|
||||
.WithEditorHints(EditorHints.VirtualPath)
|
||||
.With(new LiteralAttributeCodeGenerator(
|
||||
new LocationTagged<string>(String.Empty, 24, 0, 24),
|
||||
new LocationTagged<SpanCodeGenerator>(new ResolveUrlCodeGenerator(), 24, 0, 24))),
|
||||
Factory.Markup("'").With(SpanCodeGenerator.Null)),
|
||||
Factory.Markup(" /> ")),
|
||||
Factory.MetaCode("}").Accepts(AcceptedCharacters.None)),
|
||||
Factory.EmptyHtml()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void UrlWithExpressionsInAttributeInMarkupBlock()
|
||||
{
|
||||
ParseBlockTest("<a href='~/Foo/@id/Baz' />",
|
||||
new MarkupBlock(
|
||||
Factory.Markup("<a"),
|
||||
new MarkupBlock(new AttributeBlockCodeGenerator("href", new LocationTagged<string>(" href='", 2, 0, 2), new LocationTagged<string>("'", 22, 0, 22)),
|
||||
Factory.Markup(" href='").With(SpanCodeGenerator.Null),
|
||||
Factory.Markup("~/Foo/")
|
||||
.WithEditorHints(EditorHints.VirtualPath)
|
||||
.With(new LiteralAttributeCodeGenerator(
|
||||
new LocationTagged<string>(String.Empty, 9, 0, 9),
|
||||
new LocationTagged<SpanCodeGenerator>(new ResolveUrlCodeGenerator(), 9, 0, 9))),
|
||||
new MarkupBlock(new DynamicAttributeBlockCodeGenerator(new LocationTagged<string>(String.Empty, 15, 0, 15), 15, 0, 15),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition().Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("id")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace))),
|
||||
Factory.Markup("/Baz")
|
||||
.With(new LiteralAttributeCodeGenerator(new LocationTagged<string>(String.Empty, 18, 0, 18), new LocationTagged<string>("/Baz", 18, 0, 18))),
|
||||
Factory.Markup("'").With(SpanCodeGenerator.Null)),
|
||||
Factory.Markup(" />").Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void UrlWithExpressionsInAttributeInMarkupDocument()
|
||||
{
|
||||
ParseDocumentTest("<a href='~/Foo/@id/Baz' />",
|
||||
new MarkupBlock(
|
||||
Factory.Markup("<a"),
|
||||
new MarkupBlock(new AttributeBlockCodeGenerator("href", new LocationTagged<string>(" href='", 2, 0, 2), new LocationTagged<string>("'", 22, 0, 22)),
|
||||
Factory.Markup(" href='").With(SpanCodeGenerator.Null),
|
||||
Factory.Markup("~/Foo/")
|
||||
.WithEditorHints(EditorHints.VirtualPath)
|
||||
.With(new LiteralAttributeCodeGenerator(
|
||||
new LocationTagged<string>(String.Empty, 9, 0, 9),
|
||||
new LocationTagged<SpanCodeGenerator>(new ResolveUrlCodeGenerator(), 9, 0, 9))),
|
||||
new MarkupBlock(new DynamicAttributeBlockCodeGenerator(new LocationTagged<string>(String.Empty, 15, 0, 15), 15, 0, 15),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition().Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("id")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace))),
|
||||
Factory.Markup("/Baz")
|
||||
.With(new LiteralAttributeCodeGenerator(new LocationTagged<string>(String.Empty, 18, 0, 18), new LocationTagged<string>("/Baz", 18, 0, 18))),
|
||||
Factory.Markup("'").With(SpanCodeGenerator.Null)),
|
||||
Factory.Markup(" />")));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void UrlWithExpressionsInAttributeInMarkupSection()
|
||||
{
|
||||
ParseDocumentTest("@section Foo { <a href='~/Foo/@id/Baz' /> }",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new SectionBlock(new SectionCodeGenerator("Foo"),
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("section Foo {")
|
||||
.AutoCompleteWith(null, atEndOfSpan: true),
|
||||
new MarkupBlock(
|
||||
Factory.Markup(" <a"),
|
||||
new MarkupBlock(new AttributeBlockCodeGenerator("href", new LocationTagged<string>(" href='", 17, 0, 17), new LocationTagged<string>("'", 37, 0, 37)),
|
||||
Factory.Markup(" href='").With(SpanCodeGenerator.Null),
|
||||
Factory.Markup("~/Foo/")
|
||||
.WithEditorHints(EditorHints.VirtualPath)
|
||||
.With(new LiteralAttributeCodeGenerator(
|
||||
new LocationTagged<string>(String.Empty, 24, 0, 24),
|
||||
new LocationTagged<SpanCodeGenerator>(new ResolveUrlCodeGenerator(), 24, 0, 24))),
|
||||
new MarkupBlock(new DynamicAttributeBlockCodeGenerator(new LocationTagged<string>(String.Empty, 30, 0, 30), 30, 0, 30),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition().Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("id")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace))),
|
||||
Factory.Markup("/Baz")
|
||||
.With(new LiteralAttributeCodeGenerator(new LocationTagged<string>(String.Empty, 33, 0, 33), new LocationTagged<string>("/Baz", 33, 0, 33))),
|
||||
Factory.Markup("'").With(SpanCodeGenerator.Null)),
|
||||
Factory.Markup(" /> ")),
|
||||
Factory.MetaCode("}").Accepts(AcceptedCharacters.None)),
|
||||
Factory.EmptyHtml()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void UrlWithComplexCharactersInAttributeInMarkupBlock()
|
||||
{
|
||||
ParseBlockTest("<a href='~/Foo+Bar:Baz(Biz),Boz' />",
|
||||
new MarkupBlock(
|
||||
Factory.Markup("<a"),
|
||||
new MarkupBlock(new AttributeBlockCodeGenerator("href", new LocationTagged<string>(" href='", 2, 0, 2), new LocationTagged<string>("'", 31, 0, 31)),
|
||||
Factory.Markup(" href='").With(SpanCodeGenerator.Null),
|
||||
Factory.Markup("~/Foo+Bar:Baz(Biz),Boz")
|
||||
.WithEditorHints(EditorHints.VirtualPath)
|
||||
.With(new LiteralAttributeCodeGenerator(
|
||||
new LocationTagged<string>(String.Empty, 9, 0, 9),
|
||||
new LocationTagged<SpanCodeGenerator>(new ResolveUrlCodeGenerator(), 9, 0, 9))),
|
||||
Factory.Markup("'").With(SpanCodeGenerator.Null)),
|
||||
Factory.Markup(" />").Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void UrlWithComplexCharactersInAttributeInMarkupDocument()
|
||||
{
|
||||
ParseDocumentTest("<a href='~/Foo+Bar:Baz(Biz),Boz' />",
|
||||
new MarkupBlock(
|
||||
Factory.Markup("<a"),
|
||||
new MarkupBlock(new AttributeBlockCodeGenerator("href", new LocationTagged<string>(" href='", 2, 0, 2), new LocationTagged<string>("'", 31, 0, 31)),
|
||||
Factory.Markup(" href='").With(SpanCodeGenerator.Null),
|
||||
Factory.Markup("~/Foo+Bar:Baz(Biz),Boz")
|
||||
.WithEditorHints(EditorHints.VirtualPath)
|
||||
.With(new LiteralAttributeCodeGenerator(
|
||||
new LocationTagged<string>(String.Empty, 9, 0, 9),
|
||||
new LocationTagged<SpanCodeGenerator>(new ResolveUrlCodeGenerator(), 9, 0, 9))),
|
||||
Factory.Markup("'").With(SpanCodeGenerator.Null)),
|
||||
Factory.Markup(" />")));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void UrlInUnquotedAttributeValueInMarkupBlock()
|
||||
{
|
||||
ParseBlockTest("<a href=~/Foo+Bar:Baz(Biz),Boz/@id/Boz />",
|
||||
new MarkupBlock(
|
||||
Factory.Markup("<a"),
|
||||
new MarkupBlock(new AttributeBlockCodeGenerator("href", new LocationTagged<string>(" href=", 2, 0, 2), new LocationTagged<string>(String.Empty, 38, 0, 38)),
|
||||
Factory.Markup(" href=").With(SpanCodeGenerator.Null),
|
||||
Factory.Markup("~/Foo+Bar:Baz(Biz),Boz/")
|
||||
.WithEditorHints(EditorHints.VirtualPath)
|
||||
.With(new LiteralAttributeCodeGenerator(
|
||||
new LocationTagged<string>(String.Empty, 8, 0, 8),
|
||||
new LocationTagged<SpanCodeGenerator>(new ResolveUrlCodeGenerator(), 8, 0, 8))),
|
||||
new MarkupBlock(new DynamicAttributeBlockCodeGenerator(new LocationTagged<string>(String.Empty, 31, 0, 31), 31, 0, 31),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition()
|
||||
.Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("id")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace))),
|
||||
Factory.Markup("/Boz").With(new LiteralAttributeCodeGenerator(new LocationTagged<string>(String.Empty, 34, 0, 34), new LocationTagged<string>("/Boz", 34, 0, 34)))),
|
||||
Factory.Markup(" />").Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void UrlInUnquotedAttributeValueInMarkupDocument()
|
||||
{
|
||||
ParseDocumentTest("<a href=~/Foo+Bar:Baz(Biz),Boz/@id/Boz />",
|
||||
new MarkupBlock(
|
||||
Factory.Markup("<a"),
|
||||
new MarkupBlock(new AttributeBlockCodeGenerator("href", new LocationTagged<string>(" href=", 2, 0, 2), new LocationTagged<string>(String.Empty, 38, 0, 38)),
|
||||
Factory.Markup(" href=").With(SpanCodeGenerator.Null),
|
||||
Factory.Markup("~/Foo+Bar:Baz(Biz),Boz/")
|
||||
.WithEditorHints(EditorHints.VirtualPath)
|
||||
.With(new LiteralAttributeCodeGenerator(
|
||||
new LocationTagged<string>(String.Empty, 8, 0, 8),
|
||||
new LocationTagged<SpanCodeGenerator>(new ResolveUrlCodeGenerator(), 8, 0, 8))),
|
||||
new MarkupBlock(new DynamicAttributeBlockCodeGenerator(new LocationTagged<string>(String.Empty, 31, 0, 31), 31, 0, 31),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition()
|
||||
.Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("id")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace))),
|
||||
Factory.Markup("/Boz").With(new LiteralAttributeCodeGenerator(new LocationTagged<string>(String.Empty, 34, 0, 34), new LocationTagged<string>("/Boz", 34, 0, 34)))),
|
||||
Factory.Markup(" />")));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void UrlInUnquotedAttributeValueInMarkupSection()
|
||||
{
|
||||
ParseDocumentTest("@section Foo { <a href=~/Foo+Bar:Baz(Biz),Boz/@id/Boz /> }",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new SectionBlock(new SectionCodeGenerator("Foo"),
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("section Foo {")
|
||||
.AutoCompleteWith(null, atEndOfSpan: true),
|
||||
new MarkupBlock(
|
||||
Factory.Markup(" <a"),
|
||||
new MarkupBlock(new AttributeBlockCodeGenerator("href", new LocationTagged<string>(" href=", 17, 0, 17), new LocationTagged<string>(String.Empty, 53, 0, 53)),
|
||||
Factory.Markup(" href=").With(SpanCodeGenerator.Null),
|
||||
Factory.Markup("~/Foo+Bar:Baz(Biz),Boz/")
|
||||
.WithEditorHints(EditorHints.VirtualPath)
|
||||
.With(new LiteralAttributeCodeGenerator(
|
||||
new LocationTagged<string>(String.Empty, 23, 0, 23),
|
||||
new LocationTagged<SpanCodeGenerator>(new ResolveUrlCodeGenerator(), 23, 0, 23))),
|
||||
new MarkupBlock(new DynamicAttributeBlockCodeGenerator(new LocationTagged<string>(String.Empty, 46, 0, 46), 46, 0, 46),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition()
|
||||
.Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("id")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace))),
|
||||
Factory.Markup("/Boz").With(new LiteralAttributeCodeGenerator(new LocationTagged<string>(String.Empty, 49, 0, 49), new LocationTagged<string>("/Boz", 49, 0, 49)))),
|
||||
Factory.Markup(" /> ")),
|
||||
Factory.MetaCode("}").Accepts(AcceptedCharacters.None)),
|
||||
Factory.EmptyHtml()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,242 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using Microsoft.AspNet.Razor.Parser;
|
||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||
using Microsoft.AspNet.Razor.Resources;
|
||||
using Microsoft.AspNet.Razor.Test.Framework;
|
||||
using Microsoft.AspNet.Razor.Text;
|
||||
using Microsoft.AspNet.Razor.Tokenizer.Symbols;
|
||||
using Microsoft.TestCommon;
|
||||
using Moq;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Test.Parser
|
||||
{
|
||||
public class ParserContextTest
|
||||
{
|
||||
[Fact]
|
||||
public void ConstructorRequiresNonNullSource()
|
||||
{
|
||||
var codeParser = new CSharpCodeParser();
|
||||
Assert.ThrowsArgumentNull(() => new ParserContext(null, codeParser, new HtmlMarkupParser(), codeParser), "source");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ConstructorRequiresNonNullCodeParser()
|
||||
{
|
||||
var codeParser = new CSharpCodeParser();
|
||||
Assert.ThrowsArgumentNull(() => new ParserContext(new SeekableTextReader(TextReader.Null), null, new HtmlMarkupParser(), codeParser), "codeParser");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ConstructorRequiresNonNullMarkupParser()
|
||||
{
|
||||
var codeParser = new CSharpCodeParser();
|
||||
Assert.ThrowsArgumentNull(() => new ParserContext(new SeekableTextReader(TextReader.Null), codeParser, null, codeParser), "markupParser");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ConstructorRequiresNonNullActiveParser()
|
||||
{
|
||||
Assert.ThrowsArgumentNull(() => new ParserContext(new SeekableTextReader(TextReader.Null), new CSharpCodeParser(), new HtmlMarkupParser(), null), "activeParser");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ConstructorThrowsIfActiveParserIsNotCodeOrMarkupParser()
|
||||
{
|
||||
Assert.ThrowsArgument(() => new ParserContext(new SeekableTextReader(TextReader.Null), new CSharpCodeParser(), new HtmlMarkupParser(), new CSharpCodeParser()),
|
||||
"activeParser",
|
||||
RazorResources.ActiveParser_Must_Be_Code_Or_Markup_Parser);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ConstructorAcceptsActiveParserIfIsSameAsEitherCodeOrMarkupParser()
|
||||
{
|
||||
var codeParser = new CSharpCodeParser();
|
||||
var markupParser = new HtmlMarkupParser();
|
||||
new ParserContext(new SeekableTextReader(TextReader.Null), codeParser, markupParser, codeParser);
|
||||
new ParserContext(new SeekableTextReader(TextReader.Null), codeParser, markupParser, markupParser);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ConstructorInitializesProperties()
|
||||
{
|
||||
// Arrange
|
||||
SeekableTextReader expectedBuffer = new SeekableTextReader(TextReader.Null);
|
||||
CSharpCodeParser expectedCodeParser = new CSharpCodeParser();
|
||||
HtmlMarkupParser expectedMarkupParser = new HtmlMarkupParser();
|
||||
|
||||
// Act
|
||||
ParserContext context = new ParserContext(expectedBuffer, expectedCodeParser, expectedMarkupParser, expectedCodeParser);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(context.Source);
|
||||
Assert.Same(expectedCodeParser, context.CodeParser);
|
||||
Assert.Same(expectedMarkupParser, context.MarkupParser);
|
||||
Assert.Same(expectedCodeParser, context.ActiveParser);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CurrentCharacterReturnsCurrentCharacterInTextBuffer()
|
||||
{
|
||||
// Arrange
|
||||
ParserContext context = SetupTestContext("bar", b => b.Read());
|
||||
|
||||
// Act
|
||||
char actual = context.CurrentCharacter;
|
||||
|
||||
// Assert
|
||||
Assert.Equal('a', actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CurrentCharacterReturnsNulCharacterIfTextBufferAtEOF()
|
||||
{
|
||||
// Arrange
|
||||
ParserContext context = SetupTestContext("bar", b => b.ReadToEnd());
|
||||
|
||||
// Act
|
||||
char actual = context.CurrentCharacter;
|
||||
|
||||
// Assert
|
||||
Assert.Equal('\0', actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EndOfFileReturnsFalseIfTextBufferNotAtEOF()
|
||||
{
|
||||
// Arrange
|
||||
ParserContext context = SetupTestContext("bar");
|
||||
|
||||
// Act/Assert
|
||||
Assert.False(context.EndOfFile);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EndOfFileReturnsTrueIfTextBufferAtEOF()
|
||||
{
|
||||
// Arrange
|
||||
ParserContext context = SetupTestContext("bar", b => b.ReadToEnd());
|
||||
|
||||
// Act/Assert
|
||||
Assert.True(context.EndOfFile);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void StartBlockCreatesNewBlock()
|
||||
{
|
||||
// Arrange
|
||||
ParserContext context = SetupTestContext("phoo");
|
||||
|
||||
// Act
|
||||
context.StartBlock(BlockType.Expression);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(1, context.BlockStack.Count);
|
||||
Assert.Equal(BlockType.Expression, context.BlockStack.Peek().Type);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EndBlockAddsCurrentBlockToParentBlock()
|
||||
{
|
||||
// Arrange
|
||||
Mock<ParserVisitor> mockListener = new Mock<ParserVisitor>();
|
||||
ParserContext context = SetupTestContext("phoo");
|
||||
|
||||
// Act
|
||||
context.StartBlock(BlockType.Expression);
|
||||
context.StartBlock(BlockType.Statement);
|
||||
context.EndBlock();
|
||||
|
||||
// Assert
|
||||
Assert.Equal(1, context.BlockStack.Count);
|
||||
Assert.Equal(BlockType.Expression, context.BlockStack.Peek().Type);
|
||||
Assert.Equal(1, context.BlockStack.Peek().Children.Count);
|
||||
Assert.Equal(BlockType.Statement, ((Block)context.BlockStack.Peek().Children[0]).Type);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AddSpanAddsSpanToCurrentBlockBuilder()
|
||||
{
|
||||
// Arrange
|
||||
var factory = SpanFactory.CreateCsHtml();
|
||||
Mock<ParserVisitor> mockListener = new Mock<ParserVisitor>();
|
||||
ParserContext context = SetupTestContext("phoo");
|
||||
|
||||
SpanBuilder builder = new SpanBuilder()
|
||||
{
|
||||
Kind = SpanKind.Code
|
||||
};
|
||||
builder.Accept(new CSharpSymbol(1, 0, 1, "foo", CSharpSymbolType.Identifier));
|
||||
Span added = builder.Build();
|
||||
|
||||
using (context.StartBlock(BlockType.Functions))
|
||||
{
|
||||
context.AddSpan(added);
|
||||
}
|
||||
|
||||
BlockBuilder expected = new BlockBuilder()
|
||||
{
|
||||
Type = BlockType.Functions,
|
||||
};
|
||||
expected.Children.Add(added);
|
||||
|
||||
// Assert
|
||||
ParserTestBase.EvaluateResults(context.CompleteParse(), expected.Build());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SwitchActiveParserSetsMarkupParserAsActiveIfCodeParserCurrentlyActive()
|
||||
{
|
||||
// Arrange
|
||||
var codeParser = new CSharpCodeParser();
|
||||
var markupParser = new HtmlMarkupParser();
|
||||
ParserContext context = SetupTestContext("barbazbiz", b => b.Read(), codeParser, markupParser, codeParser);
|
||||
Assert.Same(codeParser, context.ActiveParser);
|
||||
|
||||
// Act
|
||||
context.SwitchActiveParser();
|
||||
|
||||
// Assert
|
||||
Assert.Same(markupParser, context.ActiveParser);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SwitchActiveParserSetsCodeParserAsActiveIfMarkupParserCurrentlyActive()
|
||||
{
|
||||
// Arrange
|
||||
var codeParser = new CSharpCodeParser();
|
||||
var markupParser = new HtmlMarkupParser();
|
||||
ParserContext context = SetupTestContext("barbazbiz", b => b.Read(), codeParser, markupParser, markupParser);
|
||||
Assert.Same(markupParser, context.ActiveParser);
|
||||
|
||||
// Act
|
||||
context.SwitchActiveParser();
|
||||
|
||||
// Assert
|
||||
Assert.Same(codeParser, context.ActiveParser);
|
||||
}
|
||||
|
||||
private ParserContext SetupTestContext(string document)
|
||||
{
|
||||
var codeParser = new CSharpCodeParser();
|
||||
var markupParser = new HtmlMarkupParser();
|
||||
return SetupTestContext(document, b => { }, codeParser, markupParser, codeParser);
|
||||
}
|
||||
|
||||
private ParserContext SetupTestContext(string document, Action<TextReader> positioningAction)
|
||||
{
|
||||
var codeParser = new CSharpCodeParser();
|
||||
var markupParser = new HtmlMarkupParser();
|
||||
return SetupTestContext(document, positioningAction, codeParser, markupParser, codeParser);
|
||||
}
|
||||
|
||||
private ParserContext SetupTestContext(string document, Action<TextReader> positioningAction, ParserBase codeParser, ParserBase markupParser, ParserBase activeParser)
|
||||
{
|
||||
ParserContext context = new ParserContext(new SeekableTextReader(new StringReader(document)), codeParser, markupParser, activeParser);
|
||||
positioningAction(context.Source);
|
||||
return context;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNet.Razor.Parser;
|
||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||
using Microsoft.TestCommon;
|
||||
using Moq;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Test.Parser
|
||||
{
|
||||
public class ParserVisitorExtensionsTest
|
||||
{
|
||||
[Fact]
|
||||
public void VisitThrowsOnNullVisitor()
|
||||
{
|
||||
ParserVisitor target = null;
|
||||
ParserResults results = new ParserResults(new BlockBuilder() { Type = BlockType.Comment }.Build(), new List<RazorError>());
|
||||
|
||||
Assert.ThrowsArgumentNull(() => target.Visit(results), "self");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VisitThrowsOnNullResults()
|
||||
{
|
||||
ParserVisitor target = new Mock<ParserVisitor>().Object;
|
||||
Assert.ThrowsArgumentNull(() => target.Visit(null), "result");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VisitSendsDocumentToVisitor()
|
||||
{
|
||||
// Arrange
|
||||
Mock<ParserVisitor> targetMock = new Mock<ParserVisitor>();
|
||||
Block root = new BlockBuilder() { Type = BlockType.Comment }.Build();
|
||||
ParserResults results = new ParserResults(root, new List<RazorError>());
|
||||
|
||||
// Act
|
||||
targetMock.Object.Visit(results);
|
||||
|
||||
// Assert
|
||||
targetMock.Verify(v => v.VisitBlock(root));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VisitSendsErrorsToVisitor()
|
||||
{
|
||||
// Arrange
|
||||
Mock<ParserVisitor> targetMock = new Mock<ParserVisitor>();
|
||||
Block root = new BlockBuilder() { Type = BlockType.Comment }.Build();
|
||||
List<RazorError> errors = new List<RazorError>() {
|
||||
new RazorError("Foo", 1, 0, 1),
|
||||
new RazorError("Bar", 2, 0, 2)
|
||||
};
|
||||
ParserResults results = new ParserResults(root, errors);
|
||||
|
||||
// Act
|
||||
targetMock.Object.Visit(results);
|
||||
|
||||
// Assert
|
||||
targetMock.Verify(v => v.VisitError(errors[0]));
|
||||
targetMock.Verify(v => v.VisitError(errors[1]));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VisitCallsOnCompleteWhenAllNodesHaveBeenVisited()
|
||||
{
|
||||
// Arrange
|
||||
Mock<ParserVisitor> targetMock = new Mock<ParserVisitor>();
|
||||
Block root = new BlockBuilder() { Type = BlockType.Comment }.Build();
|
||||
List<RazorError> errors = new List<RazorError>() {
|
||||
new RazorError("Foo", 1, 0, 1),
|
||||
new RazorError("Bar", 2, 0, 2)
|
||||
};
|
||||
ParserResults results = new ParserResults(root, errors);
|
||||
|
||||
// Act
|
||||
targetMock.Object.Visit(results);
|
||||
|
||||
// Assert
|
||||
targetMock.Verify(v => v.OnComplete());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,638 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNet.Razor.Parser;
|
||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||
using Microsoft.AspNet.Razor.Test.Framework;
|
||||
using Microsoft.AspNet.Razor.Text;
|
||||
using System.Web.WebPages.TestUtils;
|
||||
using Microsoft.TestCommon;
|
||||
using System;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Test.Parser.PartialParsing
|
||||
{
|
||||
public class CSharpPartialParsingTest : PartialParsingTestBase<CSharpRazorCodeLanguage>
|
||||
{
|
||||
[Fact]
|
||||
public void ImplicitExpressionAcceptsInnerInsertionsInStatementBlock()
|
||||
{
|
||||
// Arrange
|
||||
SpanFactory factory = SpanFactory.CreateCsHtml();
|
||||
StringTextBuffer changed = new StringTextBuffer("@{" + Environment.NewLine
|
||||
+ " @DateTime..Now" + Environment.NewLine
|
||||
+ "}");
|
||||
StringTextBuffer old = new StringTextBuffer("@{" + Environment.NewLine
|
||||
+ " @DateTime.Now" + Environment.NewLine
|
||||
+ "}");
|
||||
|
||||
// Act and Assert
|
||||
RunPartialParseTest(new TextChange(17, 0, old, 1, changed),
|
||||
new MarkupBlock(
|
||||
factory.EmptyHtml(),
|
||||
new StatementBlock(
|
||||
factory.CodeTransition(),
|
||||
factory.MetaCode("{").Accepts(AcceptedCharacters.None),
|
||||
factory.Code("\r\n ").AsStatement(),
|
||||
new ExpressionBlock(
|
||||
factory.CodeTransition(),
|
||||
factory.Code("DateTime..Now")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords, acceptTrailingDot: true)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
factory.Code("\r\n").AsStatement(),
|
||||
factory.MetaCode("}").Accepts(AcceptedCharacters.None)),
|
||||
factory.EmptyHtml()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ImplicitExpressionAcceptsInnerInsertions()
|
||||
{
|
||||
// Arrange
|
||||
SpanFactory factory = SpanFactory.CreateCsHtml();
|
||||
StringTextBuffer changed = new StringTextBuffer("foo @DateTime..Now baz");
|
||||
StringTextBuffer old = new StringTextBuffer("foo @DateTime.Now baz");
|
||||
|
||||
// Act and Assert
|
||||
RunPartialParseTest(new TextChange(13, 0, old, 1, changed),
|
||||
new MarkupBlock(
|
||||
factory.Markup("foo "),
|
||||
new ExpressionBlock(
|
||||
factory.CodeTransition(),
|
||||
factory.Code("DateTime..Now").AsImplicitExpression(CSharpCodeParser.DefaultKeywords).Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
factory.Markup(" baz")), additionalFlags: PartialParseResult.Provisional);
|
||||
}
|
||||
|
||||
|
||||
[Fact]
|
||||
public void ImplicitExpressionAcceptsDotlessCommitInsertionsInStatementBlockAfterIdentifiers()
|
||||
{
|
||||
SpanFactory factory = SpanFactory.CreateCsHtml();
|
||||
StringTextBuffer changed = new StringTextBuffer("@{" + Environment.NewLine
|
||||
+ " @DateTime." + Environment.NewLine
|
||||
+ "}");
|
||||
StringTextBuffer old = new StringTextBuffer("@{" + Environment.NewLine
|
||||
+ " @DateTime" + Environment.NewLine
|
||||
+ "}");
|
||||
|
||||
var textChange = new TextChange(17, 0, old, 1, changed);
|
||||
TestParserManager manager = CreateParserManager();
|
||||
Action<TextChange, PartialParseResult, string> applyAndVerifyPartialChange = (changeToApply, expectedResult, expectedCode) =>
|
||||
{
|
||||
PartialParseResult result = manager.CheckForStructureChangesAndWait(textChange);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expectedResult, result);
|
||||
Assert.Equal(1, manager.ParseCount);
|
||||
ParserTestBase.EvaluateParseTree(manager.Parser.CurrentParseTree, new MarkupBlock(
|
||||
factory.EmptyHtml(),
|
||||
new StatementBlock(
|
||||
factory.CodeTransition(),
|
||||
factory.MetaCode("{").Accepts(AcceptedCharacters.None),
|
||||
factory.Code("\r\n ").AsStatement(),
|
||||
new ExpressionBlock(
|
||||
factory.CodeTransition(),
|
||||
factory.Code(expectedCode)
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords, acceptTrailingDot: true)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
factory.Code("\r\n").AsStatement(),
|
||||
factory.MetaCode("}").Accepts(AcceptedCharacters.None)),
|
||||
factory.EmptyHtml()));
|
||||
};
|
||||
|
||||
manager.InitializeWithDocument(textChange.OldBuffer);
|
||||
|
||||
// This is the process of a dotless commit when doing "." insertions to commit intellisense changes.
|
||||
applyAndVerifyPartialChange(textChange, PartialParseResult.Accepted, "DateTime.");
|
||||
|
||||
old = changed;
|
||||
changed = new StringTextBuffer("@{" + Environment.NewLine
|
||||
+ " @DateTime.." + Environment.NewLine
|
||||
+ "}");
|
||||
textChange = new TextChange(18, 0, old, 1, changed);
|
||||
|
||||
applyAndVerifyPartialChange(textChange, PartialParseResult.Accepted, "DateTime..");
|
||||
|
||||
old = changed;
|
||||
changed = new StringTextBuffer("@{" + Environment.NewLine
|
||||
+ " @DateTime.Now." + Environment.NewLine
|
||||
+ "}");
|
||||
textChange = new TextChange(18, 0, old, 3, changed);
|
||||
|
||||
applyAndVerifyPartialChange(textChange, PartialParseResult.Accepted, "DateTime.Now.");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ImplicitExpressionAcceptsDotlessCommitInsertionsInStatementBlock()
|
||||
{
|
||||
SpanFactory factory = SpanFactory.CreateCsHtml();
|
||||
StringTextBuffer changed = new StringTextBuffer("@{" + Environment.NewLine
|
||||
+ " @DateT." + Environment.NewLine
|
||||
+ "}");
|
||||
StringTextBuffer old = new StringTextBuffer("@{" + Environment.NewLine
|
||||
+ " @DateT" + Environment.NewLine
|
||||
+ "}");
|
||||
|
||||
var textChange = new TextChange(14, 0, old, 1, changed);
|
||||
TestParserManager manager = CreateParserManager();
|
||||
Action<TextChange, PartialParseResult, string> applyAndVerifyPartialChange = (changeToApply, expectedResult, expectedCode) =>
|
||||
{
|
||||
PartialParseResult result = manager.CheckForStructureChangesAndWait(textChange);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expectedResult, result);
|
||||
Assert.Equal(1, manager.ParseCount);
|
||||
ParserTestBase.EvaluateParseTree(manager.Parser.CurrentParseTree, new MarkupBlock(
|
||||
factory.EmptyHtml(),
|
||||
new StatementBlock(
|
||||
factory.CodeTransition(),
|
||||
factory.MetaCode("{").Accepts(AcceptedCharacters.None),
|
||||
factory.Code("\r\n ").AsStatement(),
|
||||
new ExpressionBlock(
|
||||
factory.CodeTransition(),
|
||||
factory.Code(expectedCode)
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords, acceptTrailingDot: true)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
factory.Code("\r\n").AsStatement(),
|
||||
factory.MetaCode("}").Accepts(AcceptedCharacters.None)),
|
||||
factory.EmptyHtml()));
|
||||
};
|
||||
|
||||
manager.InitializeWithDocument(textChange.OldBuffer);
|
||||
|
||||
// This is the process of a dotless commit when doing "." insertions to commit intellisense changes.
|
||||
applyAndVerifyPartialChange(textChange, PartialParseResult.Accepted, "DateT.");
|
||||
|
||||
old = changed;
|
||||
changed = new StringTextBuffer("@{" + Environment.NewLine
|
||||
+ " @DateTime." + Environment.NewLine
|
||||
+ "}");
|
||||
textChange = new TextChange(14, 0, old, 3, changed);
|
||||
|
||||
applyAndVerifyPartialChange(textChange, PartialParseResult.Accepted, "DateTime.");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ImplicitExpressionProvisionallyAcceptsDotlessCommitInsertions()
|
||||
{
|
||||
SpanFactory factory = SpanFactory.CreateCsHtml();
|
||||
var changed = new StringTextBuffer("foo @DateT. baz");
|
||||
var old = new StringTextBuffer("foo @DateT baz");
|
||||
var textChange = new TextChange(10, 0, old, 1, changed);
|
||||
TestParserManager manager = CreateParserManager();
|
||||
Action<TextChange, PartialParseResult, string> applyAndVerifyPartialChange = (changeToApply, expectedResult, expectedCode) =>
|
||||
{
|
||||
PartialParseResult result = manager.CheckForStructureChangesAndWait(textChange);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expectedResult, result);
|
||||
Assert.Equal(1, manager.ParseCount);
|
||||
|
||||
ParserTestBase.EvaluateParseTree(manager.Parser.CurrentParseTree, new MarkupBlock(
|
||||
factory.Markup("foo "),
|
||||
new ExpressionBlock(
|
||||
factory.CodeTransition(),
|
||||
factory.Code(expectedCode).AsImplicitExpression(CSharpCodeParser.DefaultKeywords).Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
factory.Markup(" baz")));
|
||||
};
|
||||
|
||||
manager.InitializeWithDocument(textChange.OldBuffer);
|
||||
|
||||
// This is the process of a dotless commit when doing "." insertions to commit intellisense changes.
|
||||
applyAndVerifyPartialChange(textChange, PartialParseResult.Accepted | PartialParseResult.Provisional, "DateT.");
|
||||
|
||||
old = changed;
|
||||
changed = new StringTextBuffer("foo @DateTime. baz");
|
||||
textChange = new TextChange(10, 0, old, 3, changed);
|
||||
|
||||
applyAndVerifyPartialChange(textChange, PartialParseResult.Accepted | PartialParseResult.Provisional, "DateTime.");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ImplicitExpressionProvisionallyAcceptsDotlessCommitInsertionsAfterIdentifiers()
|
||||
{
|
||||
SpanFactory factory = SpanFactory.CreateCsHtml();
|
||||
var changed = new StringTextBuffer("foo @DateTime. baz");
|
||||
var old = new StringTextBuffer("foo @DateTime baz");
|
||||
var textChange = new TextChange(13, 0, old, 1, changed);
|
||||
TestParserManager manager = CreateParserManager();
|
||||
Action<TextChange, PartialParseResult, string> applyAndVerifyPartialChange = (changeToApply, expectedResult, expectedCode) =>
|
||||
{
|
||||
PartialParseResult result = manager.CheckForStructureChangesAndWait(textChange);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expectedResult, result);
|
||||
Assert.Equal(1, manager.ParseCount);
|
||||
|
||||
ParserTestBase.EvaluateParseTree(manager.Parser.CurrentParseTree, new MarkupBlock(
|
||||
factory.Markup("foo "),
|
||||
new ExpressionBlock(
|
||||
factory.CodeTransition(),
|
||||
factory.Code(expectedCode).AsImplicitExpression(CSharpCodeParser.DefaultKeywords).Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
factory.Markup(" baz")));
|
||||
};
|
||||
|
||||
manager.InitializeWithDocument(textChange.OldBuffer);
|
||||
|
||||
// This is the process of a dotless commit when doing "." insertions to commit intellisense changes.
|
||||
applyAndVerifyPartialChange(textChange, PartialParseResult.Accepted | PartialParseResult.Provisional, "DateTime.");
|
||||
|
||||
old = changed;
|
||||
changed = new StringTextBuffer("foo @DateTime.. baz");
|
||||
textChange = new TextChange(14, 0, old, 1, changed);
|
||||
|
||||
applyAndVerifyPartialChange(textChange, PartialParseResult.Accepted | PartialParseResult.Provisional, "DateTime..");
|
||||
|
||||
old = changed;
|
||||
changed = new StringTextBuffer("foo @DateTime.Now. baz");
|
||||
textChange = new TextChange(14, 0, old, 3, changed);
|
||||
|
||||
applyAndVerifyPartialChange(textChange, PartialParseResult.Accepted | PartialParseResult.Provisional, "DateTime.Now.");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ImplicitExpressionProvisionallyAcceptsDeleteOfIdentifierPartsIfDotRemains()
|
||||
{
|
||||
SpanFactory factory = SpanFactory.CreateCsHtml();
|
||||
StringTextBuffer changed = new StringTextBuffer("foo @User. baz");
|
||||
StringTextBuffer old = new StringTextBuffer("foo @User.Name baz");
|
||||
RunPartialParseTest(new TextChange(10, 4, old, 0, changed),
|
||||
new MarkupBlock(
|
||||
factory.Markup("foo "),
|
||||
new ExpressionBlock(
|
||||
factory.CodeTransition(),
|
||||
factory.Code("User.").AsImplicitExpression(CSharpCodeParser.DefaultKeywords).Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
factory.Markup(" baz")),
|
||||
additionalFlags: PartialParseResult.Provisional);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ImplicitExpressionAcceptsDeleteOfIdentifierPartsIfSomeOfIdentifierRemains()
|
||||
{
|
||||
var factory = SpanFactory.CreateCsHtml();
|
||||
StringTextBuffer changed = new StringTextBuffer("foo @Us baz");
|
||||
StringTextBuffer old = new StringTextBuffer("foo @User baz");
|
||||
RunPartialParseTest(new TextChange(7, 2, old, 0, changed),
|
||||
new MarkupBlock(
|
||||
factory.Markup("foo "),
|
||||
new ExpressionBlock(
|
||||
factory.CodeTransition(),
|
||||
factory.Code("Us").AsImplicitExpression(CSharpCodeParser.DefaultKeywords).Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
factory.Markup(" baz")));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ImplicitExpressionProvisionallyAcceptsMultipleInsertionIfItCausesIdentifierExpansionAndTrailingDot()
|
||||
{
|
||||
var factory = SpanFactory.CreateCsHtml();
|
||||
StringTextBuffer changed = new StringTextBuffer("foo @User. baz");
|
||||
StringTextBuffer old = new StringTextBuffer("foo @U baz");
|
||||
RunPartialParseTest(new TextChange(6, 0, old, 4, changed),
|
||||
new MarkupBlock(
|
||||
factory.Markup("foo "),
|
||||
new ExpressionBlock(
|
||||
factory.CodeTransition(),
|
||||
factory.Code("User.").AsImplicitExpression(CSharpCodeParser.DefaultKeywords).Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
factory.Markup(" baz")),
|
||||
additionalFlags: PartialParseResult.Provisional);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ImplicitExpressionAcceptsMultipleInsertionIfItOnlyCausesIdentifierExpansion()
|
||||
{
|
||||
var factory = SpanFactory.CreateCsHtml();
|
||||
StringTextBuffer changed = new StringTextBuffer("foo @barbiz baz");
|
||||
StringTextBuffer old = new StringTextBuffer("foo @bar baz");
|
||||
RunPartialParseTest(new TextChange(8, 0, old, 3, changed),
|
||||
new MarkupBlock(
|
||||
factory.Markup("foo "),
|
||||
new ExpressionBlock(
|
||||
factory.CodeTransition(),
|
||||
factory.Code("barbiz").AsImplicitExpression(CSharpCodeParser.DefaultKeywords).Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
factory.Markup(" baz")));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ImplicitExpressionAcceptsIdentifierExpansionAtEndOfNonWhitespaceCharacters()
|
||||
{
|
||||
var factory = SpanFactory.CreateCsHtml();
|
||||
StringTextBuffer changed = new StringTextBuffer("@{" + Environment.NewLine
|
||||
+ " @food" + Environment.NewLine
|
||||
+ "}");
|
||||
StringTextBuffer old = new StringTextBuffer("@{" + Environment.NewLine
|
||||
+ " @foo" + Environment.NewLine
|
||||
+ "}");
|
||||
RunPartialParseTest(new TextChange(12, 0, old, 1, changed),
|
||||
new MarkupBlock(
|
||||
factory.EmptyHtml(),
|
||||
new StatementBlock(
|
||||
factory.CodeTransition(),
|
||||
factory.MetaCode("{").Accepts(AcceptedCharacters.None),
|
||||
factory.Code("\r\n ").AsStatement(),
|
||||
new ExpressionBlock(
|
||||
factory.CodeTransition(),
|
||||
factory.Code("food")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords, acceptTrailingDot: true)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
factory.Code("\r\n").AsStatement(),
|
||||
factory.MetaCode("}").Accepts(AcceptedCharacters.None)),
|
||||
factory.EmptyHtml()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ImplicitExpressionAcceptsIdentifierAfterDotAtEndOfNonWhitespaceCharacters()
|
||||
{
|
||||
var factory = SpanFactory.CreateCsHtml();
|
||||
StringTextBuffer changed = new StringTextBuffer("@{" + Environment.NewLine
|
||||
+ " @foo.d" + Environment.NewLine
|
||||
+ "}");
|
||||
StringTextBuffer old = new StringTextBuffer("@{" + Environment.NewLine
|
||||
+ " @foo." + Environment.NewLine
|
||||
+ "}");
|
||||
RunPartialParseTest(new TextChange(13, 0, old, 1, changed),
|
||||
new MarkupBlock(
|
||||
factory.EmptyHtml(),
|
||||
new StatementBlock(
|
||||
factory.CodeTransition(),
|
||||
factory.MetaCode("{").Accepts(AcceptedCharacters.None),
|
||||
factory.Code("\r\n ").AsStatement(),
|
||||
new ExpressionBlock(
|
||||
factory.CodeTransition(),
|
||||
factory.Code("foo.d")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords, acceptTrailingDot: true)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
factory.Code("\r\n").AsStatement(),
|
||||
factory.MetaCode("}").Accepts(AcceptedCharacters.None)),
|
||||
factory.EmptyHtml()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ImplicitExpressionAcceptsDotAtEndOfNonWhitespaceCharacters()
|
||||
{
|
||||
var factory = SpanFactory.CreateCsHtml();
|
||||
StringTextBuffer changed = new StringTextBuffer("@{" + Environment.NewLine
|
||||
+ " @foo." + Environment.NewLine
|
||||
+ "}");
|
||||
StringTextBuffer old = new StringTextBuffer("@{" + Environment.NewLine
|
||||
+ " @foo" + Environment.NewLine
|
||||
+ "}");
|
||||
RunPartialParseTest(new TextChange(12, 0, old, 1, changed),
|
||||
new MarkupBlock(
|
||||
factory.EmptyHtml(),
|
||||
new StatementBlock(
|
||||
factory.CodeTransition(),
|
||||
factory.MetaCode("{").Accepts(AcceptedCharacters.None),
|
||||
factory.Code("\r\n ").AsStatement(),
|
||||
new ExpressionBlock(
|
||||
factory.CodeTransition(),
|
||||
factory.Code(@"foo.")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords, acceptTrailingDot: true)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
factory.Code("\r\n").AsStatement(),
|
||||
factory.MetaCode("}").Accepts(AcceptedCharacters.None)),
|
||||
factory.EmptyHtml()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ImplicitExpressionRejectsChangeWhichWouldHaveBeenAcceptedIfLastChangeWasProvisionallyAcceptedOnDifferentSpan()
|
||||
{
|
||||
var factory = SpanFactory.CreateCsHtml();
|
||||
|
||||
// Arrange
|
||||
TextChange dotTyped = new TextChange(8, 0, new StringTextBuffer("foo @foo @bar"), 1, new StringTextBuffer("foo @foo. @bar"));
|
||||
TextChange charTyped = new TextChange(14, 0, new StringTextBuffer("foo @foo. @bar"), 1, new StringTextBuffer("foo @foo. @barb"));
|
||||
TestParserManager manager = CreateParserManager();
|
||||
manager.InitializeWithDocument(dotTyped.OldBuffer);
|
||||
|
||||
// Apply the dot change
|
||||
Assert.Equal(PartialParseResult.Provisional | PartialParseResult.Accepted, manager.CheckForStructureChangesAndWait(dotTyped));
|
||||
|
||||
// Act (apply the identifier start char change)
|
||||
PartialParseResult result = manager.CheckForStructureChangesAndWait(charTyped);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(PartialParseResult.Rejected, result);
|
||||
Assert.False(manager.Parser.LastResultProvisional, "LastResultProvisional flag should have been cleared but it was not");
|
||||
ParserTestBase.EvaluateParseTree(manager.Parser.CurrentParseTree,
|
||||
new MarkupBlock(
|
||||
factory.Markup("foo "),
|
||||
new ExpressionBlock(
|
||||
factory.CodeTransition(),
|
||||
factory.Code("foo")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
factory.Markup(". "),
|
||||
new ExpressionBlock(
|
||||
factory.CodeTransition(),
|
||||
factory.Code("barb")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
factory.EmptyHtml()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ImplicitExpressionAcceptsIdentifierTypedAfterDotIfLastChangeWasProvisionalAcceptanceOfDot()
|
||||
{
|
||||
var factory = SpanFactory.CreateCsHtml();
|
||||
|
||||
// Arrange
|
||||
TextChange dotTyped = new TextChange(8, 0, new StringTextBuffer("foo @foo bar"), 1, new StringTextBuffer("foo @foo. bar"));
|
||||
TextChange charTyped = new TextChange(9, 0, new StringTextBuffer("foo @foo. bar"), 1, new StringTextBuffer("foo @foo.b bar"));
|
||||
TestParserManager manager = CreateParserManager();
|
||||
manager.InitializeWithDocument(dotTyped.OldBuffer);
|
||||
|
||||
// Apply the dot change
|
||||
Assert.Equal(PartialParseResult.Provisional | PartialParseResult.Accepted, manager.CheckForStructureChangesAndWait(dotTyped));
|
||||
|
||||
// Act (apply the identifier start char change)
|
||||
PartialParseResult result = manager.CheckForStructureChangesAndWait(charTyped);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(PartialParseResult.Accepted, result);
|
||||
Assert.False(manager.Parser.LastResultProvisional, "LastResultProvisional flag should have been cleared but it was not");
|
||||
ParserTestBase.EvaluateParseTree(manager.Parser.CurrentParseTree,
|
||||
new MarkupBlock(
|
||||
factory.Markup("foo "),
|
||||
new ExpressionBlock(
|
||||
factory.CodeTransition(),
|
||||
factory.Code("foo.b")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
factory.Markup(" bar")));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ImplicitExpressionProvisionallyAcceptsDotAfterIdentifierInMarkup()
|
||||
{
|
||||
var factory = SpanFactory.CreateCsHtml();
|
||||
StringTextBuffer changed = new StringTextBuffer("foo @foo. bar");
|
||||
StringTextBuffer old = new StringTextBuffer("foo @foo bar");
|
||||
RunPartialParseTest(new TextChange(8, 0, old, 1, changed),
|
||||
new MarkupBlock(
|
||||
factory.Markup("foo "),
|
||||
new ExpressionBlock(
|
||||
factory.CodeTransition(),
|
||||
factory.Code("foo.")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
factory.Markup(" bar")),
|
||||
additionalFlags: PartialParseResult.Provisional);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ImplicitExpressionAcceptsAdditionalIdentifierCharactersIfEndOfSpanIsIdentifier()
|
||||
{
|
||||
var factory = SpanFactory.CreateCsHtml();
|
||||
StringTextBuffer changed = new StringTextBuffer("foo @foob bar");
|
||||
StringTextBuffer old = new StringTextBuffer("foo @foo bar");
|
||||
RunPartialParseTest(new TextChange(8, 0, old, 1, changed),
|
||||
new MarkupBlock(
|
||||
factory.Markup("foo "),
|
||||
new ExpressionBlock(
|
||||
factory.CodeTransition(),
|
||||
factory.Code("foob")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
factory.Markup(" bar")));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ImplicitExpressionAcceptsAdditionalIdentifierStartCharactersIfEndOfSpanIsDot()
|
||||
{
|
||||
var factory = SpanFactory.CreateCsHtml();
|
||||
StringTextBuffer changed = new StringTextBuffer("@{@foo.b}");
|
||||
StringTextBuffer old = new StringTextBuffer("@{@foo.}");
|
||||
RunPartialParseTest(new TextChange(7, 0, old, 1, changed),
|
||||
new MarkupBlock(
|
||||
factory.EmptyHtml(),
|
||||
new StatementBlock(
|
||||
factory.CodeTransition(),
|
||||
factory.MetaCode("{").Accepts(AcceptedCharacters.None),
|
||||
factory.EmptyCSharp().AsStatement(),
|
||||
new ExpressionBlock(
|
||||
factory.CodeTransition(),
|
||||
factory.Code("foo.b")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords, acceptTrailingDot: true)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
factory.EmptyCSharp().AsStatement(),
|
||||
factory.MetaCode("}").Accepts(AcceptedCharacters.None)),
|
||||
factory.EmptyHtml()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ImplicitExpressionAcceptsDotIfTrailingDotsAreAllowed()
|
||||
{
|
||||
var factory = SpanFactory.CreateCsHtml();
|
||||
StringTextBuffer changed = new StringTextBuffer("@{@foo.}");
|
||||
StringTextBuffer old = new StringTextBuffer("@{@foo}");
|
||||
RunPartialParseTest(new TextChange(6, 0, old, 1, changed),
|
||||
new MarkupBlock(
|
||||
factory.EmptyHtml(),
|
||||
new StatementBlock(
|
||||
factory.CodeTransition(),
|
||||
factory.MetaCode("{").Accepts(AcceptedCharacters.None),
|
||||
factory.EmptyCSharp().AsStatement(),
|
||||
new ExpressionBlock(
|
||||
factory.CodeTransition(),
|
||||
factory.Code("foo.")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords, acceptTrailingDot: true)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
factory.EmptyCSharp().AsStatement(),
|
||||
factory.MetaCode("}").Accepts(AcceptedCharacters.None)),
|
||||
factory.EmptyHtml()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ImplicitExpressionCorrectlyTriggersReparseIfIfKeywordTyped()
|
||||
{
|
||||
RunTypeKeywordTest("if");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ImplicitExpressionCorrectlyTriggersReparseIfDoKeywordTyped()
|
||||
{
|
||||
RunTypeKeywordTest("do");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ImplicitExpressionCorrectlyTriggersReparseIfTryKeywordTyped()
|
||||
{
|
||||
RunTypeKeywordTest("try");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ImplicitExpressionCorrectlyTriggersReparseIfForKeywordTyped()
|
||||
{
|
||||
RunTypeKeywordTest("for");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ImplicitExpressionCorrectlyTriggersReparseIfForEachKeywordTyped()
|
||||
{
|
||||
RunTypeKeywordTest("foreach");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ImplicitExpressionCorrectlyTriggersReparseIfWhileKeywordTyped()
|
||||
{
|
||||
RunTypeKeywordTest("while");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ImplicitExpressionCorrectlyTriggersReparseIfSwitchKeywordTyped()
|
||||
{
|
||||
RunTypeKeywordTest("switch");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ImplicitExpressionCorrectlyTriggersReparseIfLockKeywordTyped()
|
||||
{
|
||||
RunTypeKeywordTest("lock");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ImplicitExpressionCorrectlyTriggersReparseIfUsingKeywordTyped()
|
||||
{
|
||||
RunTypeKeywordTest("using");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ImplicitExpressionCorrectlyTriggersReparseIfSectionKeywordTyped()
|
||||
{
|
||||
RunTypeKeywordTest("section");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ImplicitExpressionCorrectlyTriggersReparseIfInheritsKeywordTyped()
|
||||
{
|
||||
RunTypeKeywordTest("inherits");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ImplicitExpressionCorrectlyTriggersReparseIfHelperKeywordTyped()
|
||||
{
|
||||
RunTypeKeywordTest("helper");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ImplicitExpressionCorrectlyTriggersReparseIfFunctionsKeywordTyped()
|
||||
{
|
||||
RunTypeKeywordTest("functions");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ImplicitExpressionCorrectlyTriggersReparseIfNamespaceKeywordTyped()
|
||||
{
|
||||
RunTypeKeywordTest("namespace");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ImplicitExpressionCorrectlyTriggersReparseIfClassKeywordTyped()
|
||||
{
|
||||
RunTypeKeywordTest("class");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ImplicitExpressionCorrectlyTriggersReparseIfLayoutKeywordTyped()
|
||||
{
|
||||
RunTypeKeywordTest("layout");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,114 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using System.Threading;
|
||||
using Microsoft.AspNet.Razor.Generator;
|
||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||
using Microsoft.AspNet.Razor.Test.Framework;
|
||||
using Microsoft.AspNet.Razor.Test.Utils;
|
||||
using Microsoft.AspNet.Razor.Text;
|
||||
using System.Web.WebPages.TestUtils;
|
||||
using Microsoft.TestCommon;
|
||||
using System;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Test.Parser.PartialParsing
|
||||
{
|
||||
public abstract class PartialParsingTestBase<TLanguage>
|
||||
where TLanguage : RazorCodeLanguage, new()
|
||||
{
|
||||
private const string TestLinePragmaFileName = "C:\\This\\Path\\Is\\Just\\For\\Line\\Pragmas.cshtml";
|
||||
|
||||
protected static void RunFullReparseTest(TextChange change, PartialParseResult additionalFlags = (PartialParseResult)0)
|
||||
{
|
||||
// Arrange
|
||||
TestParserManager manager = CreateParserManager();
|
||||
manager.InitializeWithDocument(change.OldBuffer);
|
||||
|
||||
// Act
|
||||
PartialParseResult result = manager.CheckForStructureChangesAndWait(change);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(PartialParseResult.Rejected | additionalFlags, result);
|
||||
Assert.Equal(2, manager.ParseCount);
|
||||
}
|
||||
|
||||
protected static void RunPartialParseTest(TextChange change, Block newTreeRoot, PartialParseResult additionalFlags = (PartialParseResult)0)
|
||||
{
|
||||
// Arrange
|
||||
TestParserManager manager = CreateParserManager();
|
||||
manager.InitializeWithDocument(change.OldBuffer);
|
||||
|
||||
// Act
|
||||
PartialParseResult result = manager.CheckForStructureChangesAndWait(change);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(PartialParseResult.Accepted | additionalFlags, result);
|
||||
Assert.Equal(1, manager.ParseCount);
|
||||
ParserTestBase.EvaluateParseTree(manager.Parser.CurrentParseTree, newTreeRoot);
|
||||
}
|
||||
|
||||
protected static TestParserManager CreateParserManager()
|
||||
{
|
||||
RazorEngineHost host = CreateHost();
|
||||
RazorEditorParser parser = new RazorEditorParser(host, TestLinePragmaFileName);
|
||||
return new TestParserManager(parser);
|
||||
}
|
||||
|
||||
protected static RazorEngineHost CreateHost()
|
||||
{
|
||||
return new RazorEngineHost(new TLanguage())
|
||||
{
|
||||
GeneratedClassContext = new GeneratedClassContext("Execute", "Write", "WriteLiteral", "WriteTo", "WriteLiteralTo", "Template", "DefineSection"),
|
||||
DesignTimeMode = true
|
||||
};
|
||||
}
|
||||
|
||||
protected static void RunTypeKeywordTest(string keyword)
|
||||
{
|
||||
string before = "@" + keyword.Substring(0, keyword.Length - 1);
|
||||
string after = "@" + keyword;
|
||||
StringTextBuffer changed = new StringTextBuffer(after);
|
||||
StringTextBuffer old = new StringTextBuffer(before);
|
||||
RunFullReparseTest(new TextChange(keyword.Length, 0, old, 1, changed), additionalFlags: PartialParseResult.SpanContextChanged);
|
||||
}
|
||||
|
||||
protected class TestParserManager
|
||||
{
|
||||
public RazorEditorParser Parser;
|
||||
public ManualResetEventSlim ParserComplete;
|
||||
public int ParseCount;
|
||||
|
||||
public TestParserManager(RazorEditorParser parser)
|
||||
{
|
||||
ParserComplete = new ManualResetEventSlim();
|
||||
ParseCount = 0;
|
||||
Parser = parser;
|
||||
parser.DocumentParseComplete += (sender, args) =>
|
||||
{
|
||||
Interlocked.Increment(ref ParseCount);
|
||||
ParserComplete.Set();
|
||||
};
|
||||
}
|
||||
|
||||
public void InitializeWithDocument(ITextBuffer startDocument)
|
||||
{
|
||||
CheckForStructureChangesAndWait(new TextChange(0, 0, new StringTextBuffer(String.Empty), startDocument.Length, startDocument));
|
||||
}
|
||||
|
||||
public PartialParseResult CheckForStructureChangesAndWait(TextChange change)
|
||||
{
|
||||
PartialParseResult result = Parser.CheckForStructureChanges(change);
|
||||
if (result.HasFlag(PartialParseResult.Rejected))
|
||||
{
|
||||
WaitForParse();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public void WaitForParse()
|
||||
{
|
||||
MiscUtils.DoWithTimeoutIfNotDebugging(ParserComplete.Wait); // Wait for the parse to finish
|
||||
ParserComplete.Reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,375 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNet.Razor.Parser;
|
||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||
using Microsoft.AspNet.Razor.Test.Framework;
|
||||
using Microsoft.AspNet.Razor.Text;
|
||||
using System.Web.WebPages.TestUtils;
|
||||
using Microsoft.TestCommon;
|
||||
using System;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Test.Parser.PartialParsing
|
||||
{
|
||||
public class VBPartialParsingTest : PartialParsingTestBase<VBRazorCodeLanguage>
|
||||
{
|
||||
[Fact]
|
||||
public void ImplicitExpressionProvisionallyAcceptsDeleteOfIdentifierPartsIfDotRemains()
|
||||
{
|
||||
var factory = SpanFactory.CreateVbHtml();
|
||||
StringTextBuffer changed = new StringTextBuffer("foo @User. baz");
|
||||
StringTextBuffer old = new StringTextBuffer("foo @User.Name baz");
|
||||
RunPartialParseTest(new TextChange(10, 4, old, 0, changed),
|
||||
new MarkupBlock(
|
||||
factory.Markup("foo "),
|
||||
new ExpressionBlock(
|
||||
factory.CodeTransition(),
|
||||
factory.Code("User.")
|
||||
.AsImplicitExpression(VBCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
factory.Markup(" baz")),
|
||||
additionalFlags: PartialParseResult.Provisional);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ImplicitExpressionAcceptsDeleteOfIdentifierPartsIfSomeOfIdentifierRemains()
|
||||
{
|
||||
var factory = SpanFactory.CreateVbHtml();
|
||||
StringTextBuffer changed = new StringTextBuffer("foo @Us baz");
|
||||
StringTextBuffer old = new StringTextBuffer("foo @User baz");
|
||||
RunPartialParseTest(new TextChange(7, 2, old, 0, changed),
|
||||
new MarkupBlock(
|
||||
factory.Markup("foo "),
|
||||
new ExpressionBlock(
|
||||
factory.CodeTransition(),
|
||||
factory.Code("Us")
|
||||
.AsImplicitExpression(VBCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
factory.Markup(" baz")));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ImplicitExpressionProvisionallyAcceptsMultipleInsertionIfItCausesIdentifierExpansionAndTrailingDot()
|
||||
{
|
||||
var factory = SpanFactory.CreateVbHtml();
|
||||
StringTextBuffer changed = new StringTextBuffer("foo @User. baz");
|
||||
StringTextBuffer old = new StringTextBuffer("foo @U baz");
|
||||
RunPartialParseTest(new TextChange(6, 0, old, 4, changed),
|
||||
new MarkupBlock(
|
||||
factory.Markup("foo "),
|
||||
new ExpressionBlock(
|
||||
factory.CodeTransition(),
|
||||
factory.Code("User.")
|
||||
.AsImplicitExpression(VBCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
factory.Markup(" baz")),
|
||||
additionalFlags: PartialParseResult.Provisional);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ImplicitExpressionAcceptsMultipleInsertionIfItOnlyCausesIdentifierExpansion()
|
||||
{
|
||||
var factory = SpanFactory.CreateVbHtml();
|
||||
StringTextBuffer changed = new StringTextBuffer("foo @barbiz baz");
|
||||
StringTextBuffer old = new StringTextBuffer("foo @bar baz");
|
||||
RunPartialParseTest(new TextChange(8, 0, old, 3, changed),
|
||||
new MarkupBlock(
|
||||
factory.Markup("foo "),
|
||||
new ExpressionBlock(
|
||||
factory.CodeTransition(),
|
||||
factory.Code("barbiz")
|
||||
.AsImplicitExpression(VBCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
factory.Markup(" baz")));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ImplicitExpressionRejectsChangeWhichWouldHaveBeenAcceptedIfLastChangeWasProvisionallyAcceptedOnDifferentSpan()
|
||||
{
|
||||
var factory = SpanFactory.CreateVbHtml();
|
||||
|
||||
// Arrange
|
||||
TextChange dotTyped = new TextChange(8, 0, new StringTextBuffer("foo @foo @bar"), 1, new StringTextBuffer("foo @foo. @bar"));
|
||||
TextChange charTyped = new TextChange(14, 0, new StringTextBuffer("foo @foo. @barb"), 1, new StringTextBuffer("foo @foo. @barb"));
|
||||
TestParserManager manager = CreateParserManager();
|
||||
manager.InitializeWithDocument(dotTyped.OldBuffer);
|
||||
|
||||
// Apply the dot change
|
||||
Assert.Equal(PartialParseResult.Provisional | PartialParseResult.Accepted, manager.CheckForStructureChangesAndWait(dotTyped));
|
||||
|
||||
// Act (apply the identifier start char change)
|
||||
PartialParseResult result = manager.CheckForStructureChangesAndWait(charTyped);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(PartialParseResult.Rejected, result);
|
||||
Assert.False(manager.Parser.LastResultProvisional, "LastResultProvisional flag should have been cleared but it was not");
|
||||
ParserTestBase.EvaluateParseTree(manager.Parser.CurrentParseTree,
|
||||
new MarkupBlock(
|
||||
factory.Markup("foo "),
|
||||
new ExpressionBlock(
|
||||
factory.CodeTransition(),
|
||||
factory.Code("foo")
|
||||
.AsImplicitExpression(VBCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
factory.Markup(". "),
|
||||
new ExpressionBlock(
|
||||
factory.CodeTransition(),
|
||||
factory.Code("barb")
|
||||
.AsImplicitExpression(VBCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
factory.EmptyHtml()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ImplicitExpressionAcceptsIdentifierTypedAfterDotIfLastChangeWasProvisionalAcceptanceOfDot()
|
||||
{
|
||||
var factory = SpanFactory.CreateVbHtml();
|
||||
|
||||
// Arrange
|
||||
TextChange dotTyped = new TextChange(8, 0, new StringTextBuffer("foo @foo bar"), 1, new StringTextBuffer("foo @foo. bar"));
|
||||
TextChange charTyped = new TextChange(9, 0, new StringTextBuffer("foo @foo. bar"), 1, new StringTextBuffer("foo @foo.b bar"));
|
||||
TestParserManager manager = CreateParserManager();
|
||||
manager.InitializeWithDocument(dotTyped.OldBuffer);
|
||||
|
||||
// Apply the dot change
|
||||
Assert.Equal(PartialParseResult.Provisional | PartialParseResult.Accepted, manager.CheckForStructureChangesAndWait(dotTyped));
|
||||
|
||||
// Act (apply the identifier start char change)
|
||||
PartialParseResult result = manager.CheckForStructureChangesAndWait(charTyped);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(PartialParseResult.Accepted, result);
|
||||
Assert.False(manager.Parser.LastResultProvisional, "LastResultProvisional flag should have been cleared but it was not");
|
||||
ParserTestBase.EvaluateParseTree(manager.Parser.CurrentParseTree,
|
||||
new MarkupBlock(
|
||||
factory.Markup("foo "),
|
||||
new ExpressionBlock(
|
||||
factory.CodeTransition(),
|
||||
factory.Code("foo.b")
|
||||
.AsImplicitExpression(VBCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
factory.Markup(" bar")));
|
||||
}
|
||||
[Fact]
|
||||
public void ImplicitExpressionAcceptsIdentifierExpansionAtEndOfNonWhitespaceCharacters()
|
||||
{
|
||||
var factory = SpanFactory.CreateVbHtml();
|
||||
StringTextBuffer changed = new StringTextBuffer("@Code" + Environment.NewLine
|
||||
+ " @food" + Environment.NewLine
|
||||
+ "End Code");
|
||||
StringTextBuffer old = new StringTextBuffer("@Code" + Environment.NewLine
|
||||
+ " @foo" + Environment.NewLine
|
||||
+ "End Code");
|
||||
RunPartialParseTest(new TextChange(15, 0, old, 1, changed),
|
||||
new MarkupBlock(
|
||||
factory.EmptyHtml(),
|
||||
new StatementBlock(
|
||||
factory.CodeTransition(),
|
||||
factory.MetaCode("Code")
|
||||
.Accepts(AcceptedCharacters.None),
|
||||
factory.Code("\r\n ").AsStatement(),
|
||||
new ExpressionBlock(
|
||||
factory.CodeTransition(),
|
||||
factory.Code("food")
|
||||
.AsImplicitExpression(VBCodeParser.DefaultKeywords, acceptTrailingDot: true)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
factory.Code("\r\n").AsStatement(),
|
||||
factory.MetaCode("End Code").Accepts(AcceptedCharacters.None)),
|
||||
factory.EmptyHtml()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ImplicitExpressionProvisionallyAcceptsDotAfterIdentifierInMarkup()
|
||||
{
|
||||
var factory = SpanFactory.CreateVbHtml();
|
||||
StringTextBuffer changed = new StringTextBuffer("foo @foo. bar");
|
||||
StringTextBuffer old = new StringTextBuffer("foo @foo bar");
|
||||
RunPartialParseTest(new TextChange(8, 0, old, 1, changed),
|
||||
new MarkupBlock(
|
||||
factory.Markup("foo "),
|
||||
new ExpressionBlock(
|
||||
factory.CodeTransition(),
|
||||
factory.Code("foo.")
|
||||
.AsImplicitExpression(VBCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
factory.Markup(" bar")),
|
||||
additionalFlags: PartialParseResult.Provisional);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ImplicitExpressionAcceptsAdditionalIdentifierCharactersIfEndOfSpanIsIdentifier()
|
||||
{
|
||||
var factory = SpanFactory.CreateVbHtml();
|
||||
StringTextBuffer changed = new StringTextBuffer("foo @foob baz");
|
||||
StringTextBuffer old = new StringTextBuffer("foo @foo bar");
|
||||
RunPartialParseTest(new TextChange(8, 0, old, 1, changed),
|
||||
new MarkupBlock(
|
||||
factory.Markup("foo "),
|
||||
new ExpressionBlock(
|
||||
factory.CodeTransition(),
|
||||
factory.Code("foob")
|
||||
.AsImplicitExpression(VBCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
factory.Markup(" bar")));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ImplicitExpressionAcceptsAdditionalIdentifierStartCharactersIfEndOfSpanIsDot()
|
||||
{
|
||||
var factory = SpanFactory.CreateVbHtml();
|
||||
StringTextBuffer changed = new StringTextBuffer("@Code @foo.b End Code");
|
||||
StringTextBuffer old = new StringTextBuffer("@Code @foo. End Code");
|
||||
RunPartialParseTest(new TextChange(11, 0, old, 1, changed),
|
||||
new MarkupBlock(
|
||||
factory.EmptyHtml(),
|
||||
new StatementBlock(
|
||||
factory.CodeTransition(),
|
||||
factory.MetaCode("Code").Accepts(AcceptedCharacters.None),
|
||||
factory.Code(" ").AsStatement(),
|
||||
new ExpressionBlock(
|
||||
factory.CodeTransition(),
|
||||
factory.Code("foo.b")
|
||||
.AsImplicitExpression(VBCodeParser.DefaultKeywords, acceptTrailingDot: true)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
factory.Code(" ").AsStatement(),
|
||||
factory.MetaCode("End Code").Accepts(AcceptedCharacters.None)),
|
||||
factory.EmptyHtml()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ImplicitExpressionAcceptsDotIfTrailingDotsAreAllowed()
|
||||
{
|
||||
var factory = SpanFactory.CreateVbHtml();
|
||||
StringTextBuffer changed = new StringTextBuffer("@Code @foo. End Code");
|
||||
StringTextBuffer old = new StringTextBuffer("@Code @foo End Code");
|
||||
RunPartialParseTest(new TextChange(10, 0, old, 1, changed),
|
||||
new MarkupBlock(
|
||||
factory.EmptyHtml(),
|
||||
new StatementBlock(
|
||||
factory.CodeTransition(),
|
||||
factory.MetaCode("Code").Accepts(AcceptedCharacters.None),
|
||||
factory.Code(" ").AsStatement(),
|
||||
new ExpressionBlock(
|
||||
factory.CodeTransition(),
|
||||
factory.Code("foo.")
|
||||
.AsImplicitExpression(VBCodeParser.DefaultKeywords, acceptTrailingDot: true)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
factory.Code(" ").AsStatement(),
|
||||
factory.MetaCode("End Code").Accepts(AcceptedCharacters.None)),
|
||||
factory.EmptyHtml()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ImplicitExpressionCorrectlyTriggersReparseIfFunctionsKeywordTyped()
|
||||
{
|
||||
RunTypeKeywordTest("functions");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ImplicitExpressionCorrectlyTriggersReparseIfCodeKeywordTyped()
|
||||
{
|
||||
RunTypeKeywordTest("code");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ImplicitExpressionCorrectlyTriggersReparseIfSectionKeywordTyped()
|
||||
{
|
||||
RunTypeKeywordTest("section");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ImplicitExpressionCorrectlyTriggersReparseIfDoKeywordTyped()
|
||||
{
|
||||
RunTypeKeywordTest("do");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ImplicitExpressionCorrectlyTriggersReparseIfWhileKeywordTyped()
|
||||
{
|
||||
RunTypeKeywordTest("while");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ImplicitExpressionCorrectlyTriggersReparseIfIfKeywordTyped()
|
||||
{
|
||||
RunTypeKeywordTest("if");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ImplicitExpressionCorrectlyTriggersReparseIfSelectKeywordTyped()
|
||||
{
|
||||
RunTypeKeywordTest("select");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ImplicitExpressionCorrectlyTriggersReparseIfForKeywordTyped()
|
||||
{
|
||||
RunTypeKeywordTest("for");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ImplicitExpressionCorrectlyTriggersReparseIfTryKeywordTyped()
|
||||
{
|
||||
RunTypeKeywordTest("try");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ImplicitExpressionCorrectlyTriggersReparseIfWithKeywordTyped()
|
||||
{
|
||||
RunTypeKeywordTest("with");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ImplicitExpressionCorrectlyTriggersReparseIfSyncLockKeywordTyped()
|
||||
{
|
||||
RunTypeKeywordTest("synclock");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ImplicitExpressionCorrectlyTriggersReparseIfUsingKeywordTyped()
|
||||
{
|
||||
RunTypeKeywordTest("using");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ImplicitExpressionCorrectlyTriggersReparseIfImportsKeywordTyped()
|
||||
{
|
||||
RunTypeKeywordTest("imports");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ImplicitExpressionCorrectlyTriggersReparseIfInheritsKeywordTyped()
|
||||
{
|
||||
RunTypeKeywordTest("inherits");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ImplicitExpressionCorrectlyTriggersReparseIfOptionKeywordTyped()
|
||||
{
|
||||
RunTypeKeywordTest("option");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ImplicitExpressionCorrectlyTriggersReparseIfHelperKeywordTyped()
|
||||
{
|
||||
RunTypeKeywordTest("helper");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ImplicitExpressionCorrectlyTriggersReparseIfNamespaceKeywordTyped()
|
||||
{
|
||||
RunTypeKeywordTest("namespace");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ImplicitExpressionCorrectlyTriggersReparseIfClassKeywordTyped()
|
||||
{
|
||||
RunTypeKeywordTest("class");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ImplicitExpressionCorrectlyTriggersReparseIfLayoutKeywordTyped()
|
||||
{
|
||||
RunTypeKeywordTest("layout");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,136 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using Microsoft.AspNet.Razor.Parser;
|
||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||
using Microsoft.AspNet.Razor.Test.Framework;
|
||||
using Microsoft.TestCommon;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Test.Parser
|
||||
{
|
||||
public class RazorParserTest
|
||||
{
|
||||
[Fact]
|
||||
public void ConstructorRequiresNonNullCodeParser()
|
||||
{
|
||||
Assert.ThrowsArgumentNull(() => new RazorParser(null, new HtmlMarkupParser()), "codeParser");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ConstructorRequiresNonNullMarkupParser()
|
||||
{
|
||||
Assert.ThrowsArgumentNull(() => new RazorParser(new CSharpCodeParser(), null), "markupParser");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseMethodCallsParseDocumentOnMarkupParserAndReturnsResults()
|
||||
{
|
||||
var factory = SpanFactory.CreateCsHtml();
|
||||
|
||||
// Arrange
|
||||
RazorParser parser = new RazorParser(new CSharpCodeParser(), new HtmlMarkupParser());
|
||||
|
||||
// Act/Assert
|
||||
ParserTestBase.EvaluateResults(parser.Parse(new StringReader("foo @bar baz")),
|
||||
new MarkupBlock(
|
||||
factory.Markup("foo "),
|
||||
new ExpressionBlock(
|
||||
factory.CodeTransition(),
|
||||
factory.Code("bar")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
factory.Markup(" baz")));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseMethodUsesProvidedParserListenerIfSpecified()
|
||||
{
|
||||
var factory = SpanFactory.CreateCsHtml();
|
||||
|
||||
// Arrange
|
||||
RazorParser parser = new RazorParser(new CSharpCodeParser(), new HtmlMarkupParser());
|
||||
|
||||
// Act
|
||||
ParserResults results = parser.Parse(new StringReader("foo @bar baz"));
|
||||
|
||||
// Assert
|
||||
ParserTestBase.EvaluateResults(results,
|
||||
new MarkupBlock(
|
||||
factory.Markup("foo "),
|
||||
new ExpressionBlock(
|
||||
factory.CodeTransition(),
|
||||
factory.Code("bar")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
factory.Markup(" baz")));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseMethodSetsUpRunWithSpecifiedCodeParserMarkupParserAndListenerAndPassesToMarkupParser()
|
||||
{
|
||||
RunParseWithListenerTest((parser, reader) => parser.Parse(reader));
|
||||
}
|
||||
|
||||
private static void RunParseWithListenerTest(Action<RazorParser, TextReader> parserAction)
|
||||
{
|
||||
// Arrange
|
||||
ParserBase markupParser = new MockMarkupParser();
|
||||
ParserBase codeParser = new CSharpCodeParser();
|
||||
RazorParser parser = new RazorParser(codeParser, markupParser);
|
||||
TextReader expectedReader = new StringReader("foo");
|
||||
|
||||
// Act
|
||||
parserAction(parser, expectedReader);
|
||||
|
||||
// Assert
|
||||
ParserContext actualContext = markupParser.Context;
|
||||
Assert.NotNull(actualContext);
|
||||
Assert.Same(markupParser, actualContext.MarkupParser);
|
||||
Assert.Same(markupParser, actualContext.ActiveParser);
|
||||
Assert.Same(codeParser, actualContext.CodeParser);
|
||||
}
|
||||
|
||||
private class MockMarkupParser : ParserBase
|
||||
{
|
||||
public override bool IsMarkupParser
|
||||
{
|
||||
get
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public override void ParseDocument()
|
||||
{
|
||||
using (Context.StartBlock(BlockType.Markup))
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public override void ParseSection(Tuple<string, string> nestingSequences, bool caseSensitive = true)
|
||||
{
|
||||
using (Context.StartBlock(BlockType.Markup))
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public override void ParseBlock()
|
||||
{
|
||||
using (Context.StartBlock(BlockType.Markup))
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
protected override ParserBase OtherParser
|
||||
{
|
||||
get { return Context.CodeParser; }
|
||||
}
|
||||
|
||||
public override void BuildSpan(SpanBuilder span, Razor.Text.SourceLocation start, string content)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,156 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.AspNet.Razor.Generator;
|
||||
using Microsoft.AspNet.Razor.Parser;
|
||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||
using Microsoft.AspNet.Razor.Resources;
|
||||
using Microsoft.AspNet.Razor.Test.Framework;
|
||||
using Microsoft.AspNet.Razor.Text;
|
||||
using Microsoft.AspNet.Razor.Tokenizer.Symbols;
|
||||
using Microsoft.TestCommon;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Test.Parser.VB
|
||||
{
|
||||
public class VBAutoCompleteTest : VBHtmlCodeParserTestBase
|
||||
{
|
||||
[Fact]
|
||||
public void FunctionsDirective_AutoComplete_At_EOF()
|
||||
{
|
||||
ParseBlockTest("@Functions",
|
||||
new FunctionsBlock(
|
||||
Factory.CodeTransition("@")
|
||||
.Accepts(AcceptedCharacters.None),
|
||||
Factory.MetaCode("Functions")
|
||||
.Accepts(AcceptedCharacters.None),
|
||||
Factory.EmptyVB()
|
||||
.AsFunctionsBody()
|
||||
.With(new AutoCompleteEditHandler(CSharpLanguageCharacteristics.Instance.TokenizeString)
|
||||
{
|
||||
AutoCompleteString = SyntaxConstants.VB.EndFunctionsKeyword
|
||||
})),
|
||||
new RazorError(
|
||||
String.Format(RazorResources.ParseError_BlockNotTerminated, "Functions", "End Functions"),
|
||||
1, 0, 1));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void HelperDirective_AutoComplete_At_EOF()
|
||||
{
|
||||
ParseBlockTest("@Helper Strong(value As String)",
|
||||
new HelperBlock(new HelperCodeGenerator(new LocationTagged<string>("Strong(value As String)", 8, 0, 8), headerComplete: true),
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("Helper ")
|
||||
.Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("Strong(value As String)")
|
||||
.Hidden()
|
||||
.Accepts(AcceptedCharacters.None)
|
||||
.With(new AutoCompleteEditHandler(CSharpLanguageCharacteristics.Instance.TokenizeString) { AutoCompleteString = SyntaxConstants.VB.EndHelperKeyword }),
|
||||
new StatementBlock()),
|
||||
new RazorError(
|
||||
String.Format(RazorResources.ParseError_BlockNotTerminated, "Helper", "End Helper"),
|
||||
1, 0, 1));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SectionDirective_AutoComplete_At_EOF()
|
||||
{
|
||||
ParseBlockTest("@Section Header",
|
||||
new SectionBlock(new SectionCodeGenerator("Header"),
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("Section Header")
|
||||
.With(new AutoCompleteEditHandler(CSharpLanguageCharacteristics.Instance.TokenizeString) { AutoCompleteString = SyntaxConstants.VB.EndSectionKeyword }),
|
||||
new MarkupBlock()),
|
||||
new RazorError(
|
||||
String.Format(RazorResources.ParseError_BlockNotTerminated, "Section", "End Section"),
|
||||
1, 0, 1));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VerbatimBlock_AutoComplete_At_EOF()
|
||||
{
|
||||
ParseBlockTest("@Code",
|
||||
new StatementBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("Code").Accepts(AcceptedCharacters.None),
|
||||
Factory.Span(SpanKind.Code, new VBSymbol(5, 0, 5, String.Empty, VBSymbolType.Unknown))
|
||||
.With(new StatementCodeGenerator())
|
||||
.With(new AutoCompleteEditHandler(CSharpLanguageCharacteristics.Instance.TokenizeString) { AutoCompleteString = SyntaxConstants.VB.EndCodeKeyword })),
|
||||
new RazorError(
|
||||
String.Format(RazorResources.ParseError_BlockNotTerminated, "Code", "End Code"),
|
||||
1, 0, 1));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FunctionsDirective_AutoComplete_At_StartOfFile()
|
||||
{
|
||||
ParseBlockTest("@Functions" + Environment.NewLine
|
||||
+ "foo",
|
||||
new FunctionsBlock(
|
||||
Factory.CodeTransition("@").Accepts(AcceptedCharacters.None),
|
||||
Factory.MetaCode("Functions").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("\r\nfoo")
|
||||
.AsFunctionsBody()
|
||||
.With(new AutoCompleteEditHandler(CSharpLanguageCharacteristics.Instance.TokenizeString)
|
||||
{
|
||||
AutoCompleteString = SyntaxConstants.VB.EndFunctionsKeyword
|
||||
})),
|
||||
new RazorError(
|
||||
String.Format(RazorResources.ParseError_BlockNotTerminated, "Functions", "End Functions"),
|
||||
1, 0, 1));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void HelperDirective_AutoComplete_At_StartOfFile()
|
||||
{
|
||||
ParseBlockTest("@Helper Strong(value As String)" + Environment.NewLine
|
||||
+ "Foo",
|
||||
new HelperBlock(new HelperCodeGenerator(new LocationTagged<string>("Strong(value As String)", 8, 0, 8), headerComplete: true),
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("Helper ")
|
||||
.Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("Strong(value As String)")
|
||||
.Hidden()
|
||||
.Accepts(AcceptedCharacters.None)
|
||||
.With(new AutoCompleteEditHandler(CSharpLanguageCharacteristics.Instance.TokenizeString) { AutoCompleteString = SyntaxConstants.VB.EndHelperKeyword }),
|
||||
new StatementBlock(
|
||||
Factory.Code("\r\nFoo").AsStatement())),
|
||||
new RazorError(
|
||||
String.Format(RazorResources.ParseError_BlockNotTerminated, "Helper", "End Helper"),
|
||||
1, 0, 1));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SectionDirective_AutoComplete_At_StartOfFile()
|
||||
{
|
||||
ParseBlockTest("@Section Header" + Environment.NewLine
|
||||
+ "Foo",
|
||||
new SectionBlock(new SectionCodeGenerator("Header"),
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("Section Header")
|
||||
.With(new AutoCompleteEditHandler(CSharpLanguageCharacteristics.Instance.TokenizeString) { AutoCompleteString = SyntaxConstants.VB.EndSectionKeyword }),
|
||||
new MarkupBlock(
|
||||
Factory.Markup("\r\nFoo")
|
||||
.With(new MarkupCodeGenerator()))),
|
||||
new RazorError(
|
||||
String.Format(RazorResources.ParseError_BlockNotTerminated, "Section", "End Section"),
|
||||
1, 0, 1));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VerbatimBlock_AutoComplete_At_StartOfFile()
|
||||
{
|
||||
ParseBlockTest("@Code" + Environment.NewLine
|
||||
+ "Foo",
|
||||
new StatementBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("Code").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("\r\nFoo")
|
||||
.AsStatement()
|
||||
.With(new AutoCompleteEditHandler(CSharpLanguageCharacteristics.Instance.TokenizeString) { AutoCompleteString = SyntaxConstants.VB.EndCodeKeyword })),
|
||||
new RazorError(
|
||||
String.Format(RazorResources.ParseError_BlockNotTerminated, "Code", "End Code"),
|
||||
1, 0, 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,367 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.AspNet.Razor.Parser;
|
||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||
using Microsoft.AspNet.Razor.Resources;
|
||||
using Microsoft.AspNet.Razor.Test.Framework;
|
||||
using Microsoft.AspNet.Razor.Text;
|
||||
using Microsoft.TestCommon;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Test.Parser.VB
|
||||
{
|
||||
public class VBBlockTest : VBHtmlCodeParserTestBase
|
||||
{
|
||||
[Fact]
|
||||
public void ParseBlockMethodThrowsArgNullExceptionOnNullContext()
|
||||
{
|
||||
// Arrange
|
||||
VBCodeParser parser = new VBCodeParser();
|
||||
|
||||
// Act and Assert
|
||||
Assert.Throws<InvalidOperationException>(() => parser.ParseBlock(), RazorResources.Parser_Context_Not_Set);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockAcceptsImplicitExpression()
|
||||
{
|
||||
ParseBlockTest("If True Then" + Environment.NewLine
|
||||
+ " @foo" + Environment.NewLine
|
||||
+ "End If",
|
||||
new StatementBlock(
|
||||
Factory.Code("If True Then\r\n ").AsStatement(),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("foo")
|
||||
.AsImplicitExpression(VBCodeParser.DefaultKeywords, acceptTrailingDot: true)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
Factory.Code("\r\nEnd If")
|
||||
.AsStatement()
|
||||
.Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockAcceptsIfStatementWithinCodeBlockIfInDesignTimeMode()
|
||||
{
|
||||
ParseBlockTest("If True Then" + Environment.NewLine
|
||||
+ " @If True Then" + Environment.NewLine
|
||||
+ " End If" + Environment.NewLine
|
||||
+ "End If",
|
||||
new StatementBlock(
|
||||
Factory.Code("If True Then\r\n ").AsStatement(),
|
||||
new StatementBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("If True Then\r\n End If\r\n")
|
||||
.AsStatement()
|
||||
.Accepts(AcceptedCharacters.None)),
|
||||
Factory.Code(@"End If")
|
||||
.AsStatement()
|
||||
.Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockSupportsSpacesInStrings()
|
||||
{
|
||||
ParseBlockTest("for each p in db.Query(\"SELECT * FROM PRODUCTS\")" + Environment.NewLine
|
||||
+ " @<p>@p.Name</p>" + Environment.NewLine
|
||||
+ "next",
|
||||
new StatementBlock(
|
||||
Factory.Code("for each p in db.Query(\"SELECT * FROM PRODUCTS\")\r\n")
|
||||
.AsStatement(),
|
||||
new MarkupBlock(
|
||||
Factory.Markup(" "),
|
||||
Factory.MarkupTransition(),
|
||||
Factory.Markup("<p>"),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("p.Name")
|
||||
.AsImplicitExpression(VBCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
Factory.Markup("</p>\r\n").Accepts(AcceptedCharacters.None)),
|
||||
Factory.Code("next")
|
||||
.AsStatement()
|
||||
.Accepts(AcceptedCharacters.WhiteSpace | AcceptedCharacters.NonWhiteSpace)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockSupportsSimpleCodeBlock()
|
||||
{
|
||||
ParseBlockTest("Code" + Environment.NewLine
|
||||
+ " If foo IsNot Nothing" + Environment.NewLine
|
||||
+ " Bar(foo)" + Environment.NewLine
|
||||
+ " End If" + Environment.NewLine
|
||||
+ "End Code",
|
||||
new StatementBlock(
|
||||
Factory.MetaCode("Code").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("\r\n If foo IsNot Nothing\r\n Bar(foo)\r\n End If\r\n")
|
||||
.AsStatement(),
|
||||
Factory.MetaCode("End Code").Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockRejectsNewlineBetweenEndAndCodeIfNotPrefixedWithUnderscore()
|
||||
{
|
||||
ParseBlockTest("Code" + Environment.NewLine
|
||||
+ " If foo IsNot Nothing" + Environment.NewLine
|
||||
+ " Bar(foo)" + Environment.NewLine
|
||||
+ " End If" + Environment.NewLine
|
||||
+ "End" + Environment.NewLine
|
||||
+ "Code",
|
||||
new StatementBlock(
|
||||
Factory.MetaCode("Code").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("\r\n If foo IsNot Nothing\r\n Bar(foo)\r\n End If\r\nEnd\r\nCode")
|
||||
.AsStatement()),
|
||||
new RazorError(
|
||||
String.Format(RazorResources.ParseError_BlockNotTerminated, "Code", "End Code"),
|
||||
SourceLocation.Zero));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockAcceptsNewlineBetweenEndAndCodeIfPrefixedWithUnderscore()
|
||||
{
|
||||
ParseBlockTest("Code" + Environment.NewLine
|
||||
+ " If foo IsNot Nothing" + Environment.NewLine
|
||||
+ " Bar(foo)" + Environment.NewLine
|
||||
+ " End If" + Environment.NewLine
|
||||
+ "End _" + Environment.NewLine
|
||||
+ "_" + Environment.NewLine
|
||||
+ " _" + Environment.NewLine
|
||||
+ "Code",
|
||||
new StatementBlock(
|
||||
Factory.MetaCode("Code").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("\r\n If foo IsNot Nothing\r\n Bar(foo)\r\n End If\r\n")
|
||||
.AsStatement(),
|
||||
Factory.MetaCode("End _\r\n_\r\n _\r\nCode").Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockSupportsSimpleFunctionsBlock()
|
||||
{
|
||||
ParseBlockTest("Functions" + Environment.NewLine
|
||||
+ " Public Sub Foo()" + Environment.NewLine
|
||||
+ " Bar()" + Environment.NewLine
|
||||
+ " End Sub" + Environment.NewLine
|
||||
+ Environment.NewLine
|
||||
+ " Private Function Bar() As Object" + Environment.NewLine
|
||||
+ " Return Nothing" + Environment.NewLine
|
||||
+ " End Function" + Environment.NewLine
|
||||
+ "End Functions",
|
||||
new FunctionsBlock(
|
||||
Factory.MetaCode("Functions").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("\r\n Public Sub Foo()\r\n Bar()\r\n End Sub\r\n\r\n Private Function Bar() As Object\r\n Return Nothing\r\n End Function\r\n")
|
||||
.AsFunctionsBody(),
|
||||
Factory.MetaCode("End Functions").Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockRejectsNewlineBetweenEndAndFunctionsIfNotPrefixedWithUnderscore()
|
||||
{
|
||||
ParseBlockTest("Functions" + Environment.NewLine
|
||||
+ " If foo IsNot Nothing" + Environment.NewLine
|
||||
+ " Bar(foo)" + Environment.NewLine
|
||||
+ " End If" + Environment.NewLine
|
||||
+ "End" + Environment.NewLine
|
||||
+ "Functions",
|
||||
new FunctionsBlock(
|
||||
Factory.MetaCode("Functions").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("\r\n If foo IsNot Nothing\r\n Bar(foo)\r\n End If\r\nEnd\r\nFunctions")
|
||||
.AsFunctionsBody()),
|
||||
new RazorError(
|
||||
String.Format(RazorResources.ParseError_BlockNotTerminated, "Functions", "End Functions"),
|
||||
SourceLocation.Zero));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockAcceptsNewlineBetweenEndAndFunctionsIfPrefixedWithUnderscore()
|
||||
{
|
||||
ParseBlockTest("Functions" + Environment.NewLine
|
||||
+ " If foo IsNot Nothing" + Environment.NewLine
|
||||
+ " Bar(foo)" + Environment.NewLine
|
||||
+ " End If" + Environment.NewLine
|
||||
+ "End _" + Environment.NewLine
|
||||
+ "_" + Environment.NewLine
|
||||
+ " _" + Environment.NewLine
|
||||
+ "Functions",
|
||||
new FunctionsBlock(
|
||||
Factory.MetaCode("Functions").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("\r\n If foo IsNot Nothing\r\n Bar(foo)\r\n End If\r\n")
|
||||
.AsFunctionsBody(),
|
||||
Factory.MetaCode("End _\r\n_\r\n _\r\nFunctions").Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockCorrectlyHandlesExtraEndsInEndCode()
|
||||
{
|
||||
ParseBlockTest("Code" + Environment.NewLine
|
||||
+ " Bar End" + Environment.NewLine
|
||||
+ "End Code",
|
||||
new StatementBlock(
|
||||
Factory.MetaCode("Code").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("\r\n Bar End\r\n").AsStatement(),
|
||||
Factory.MetaCode("End Code").Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockCorrectlyHandlesExtraEndsInEndFunctions()
|
||||
{
|
||||
ParseBlockTest("Functions" + Environment.NewLine
|
||||
+ " Bar End" + Environment.NewLine
|
||||
+ "End Functions",
|
||||
new FunctionsBlock(
|
||||
Factory.MetaCode("Functions").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("\r\n Bar End\r\n").AsFunctionsBody().AutoCompleteWith(null, atEndOfSpan: false),
|
||||
Factory.MetaCode("End Functions").Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("If", "End", "If")]
|
||||
[InlineData("Try", "End", "Try")]
|
||||
[InlineData("While", "End", "While")]
|
||||
[InlineData("Using", "End", "Using")]
|
||||
[InlineData("With", "End", "With")]
|
||||
public void KeywordAllowsNewlinesIfPrefixedByUnderscore(string startKeyword, string endKeyword1, string endKeyword2)
|
||||
{
|
||||
string code = startKeyword + Environment.NewLine
|
||||
+ " ' In the block" + Environment.NewLine
|
||||
+ endKeyword1 + " _" + Environment.NewLine
|
||||
+ "_" + Environment.NewLine
|
||||
+ "_" + Environment.NewLine
|
||||
+ "_" + Environment.NewLine
|
||||
+ "_" + Environment.NewLine
|
||||
+ "_" + Environment.NewLine
|
||||
+ " " + endKeyword2 + Environment.NewLine;
|
||||
ParseBlockTest(code + "foo bar baz",
|
||||
new StatementBlock(
|
||||
Factory.Code(code)
|
||||
.AsStatement()
|
||||
.Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("While", "EndWhile", "End While")]
|
||||
[InlineData("If", "EndIf", "End If")]
|
||||
[InlineData("Select", "EndSelect", "End Select")]
|
||||
[InlineData("Try", "EndTry", "End Try")]
|
||||
[InlineData("With", "EndWith", "End With")]
|
||||
[InlineData("Using", "EndUsing", "End Using")]
|
||||
public void EndTerminatedKeywordRequiresSpaceBetweenEndAndKeyword(string startKeyword, string wrongEndKeyword, string endKeyword)
|
||||
{
|
||||
string code = startKeyword + Environment.NewLine
|
||||
+ " ' This should not end the code" + Environment.NewLine
|
||||
+ " " + wrongEndKeyword + Environment.NewLine
|
||||
+ " ' But this should" + Environment.NewLine
|
||||
+ endKeyword;
|
||||
ParseBlockTest(code,
|
||||
new StatementBlock(
|
||||
Factory.Code(code)
|
||||
.AsStatement()
|
||||
.Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("While", "End While", false)]
|
||||
[InlineData("Do", "Loop", true)]
|
||||
[InlineData("If", "End If", false)]
|
||||
[InlineData("Select", "End Select", false)]
|
||||
[InlineData("For", "Next", true)]
|
||||
[InlineData("Try", "End Try", false)]
|
||||
[InlineData("With", "End With", false)]
|
||||
[InlineData("Using", "End Using", false)]
|
||||
public void EndSequenceInString(string keyword, string endSequence, bool acceptToEndOfLine)
|
||||
{
|
||||
string code = keyword + Environment.NewLine
|
||||
+ " \"" + endSequence + "\"" + Environment.NewLine
|
||||
+ endSequence + (acceptToEndOfLine ? " foo bar baz" : "") + Environment.NewLine;
|
||||
ParseBlockTest(code + "biz boz",
|
||||
new StatementBlock(
|
||||
Factory.Code(code).AsStatement().Accepts(GetAcceptedCharacters(acceptToEndOfLine))));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("While", "End While", false)]
|
||||
[InlineData("Do", "Loop", true)]
|
||||
[InlineData("If", "End If", false)]
|
||||
[InlineData("Select", "End Select", false)]
|
||||
[InlineData("For", "Next", true)]
|
||||
[InlineData("Try", "End Try", false)]
|
||||
[InlineData("With", "End With", false)]
|
||||
[InlineData("Using", "End Using", false)]
|
||||
private void CommentedEndSequence(string keyword, string endSequence, bool acceptToEndOfLine)
|
||||
{
|
||||
string code = keyword + Environment.NewLine
|
||||
+ " '" + endSequence + Environment.NewLine
|
||||
+ endSequence + (acceptToEndOfLine ? @" foo bar baz" : "") + Environment.NewLine;
|
||||
ParseBlockTest(code + "biz boz",
|
||||
new StatementBlock(
|
||||
Factory.Code(code).AsStatement().Accepts(GetAcceptedCharacters(acceptToEndOfLine))));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("While", "End While", false)]
|
||||
[InlineData("Do", "Loop", true)]
|
||||
[InlineData("If", "End If", false)]
|
||||
[InlineData("Select", "End Select", false)]
|
||||
[InlineData("For", "Next", true)]
|
||||
[InlineData("Try", "End Try", false)]
|
||||
[InlineData("With", "End With", false)]
|
||||
[InlineData("SyncLock", "End SyncLock", false)]
|
||||
[InlineData("Using", "End Using", false)]
|
||||
private void NestedKeywordBlock(string keyword, string endSequence, bool acceptToEndOfLine)
|
||||
{
|
||||
string code = keyword + Environment.NewLine
|
||||
+ " " + keyword + Environment.NewLine
|
||||
+ " Bar(foo)" + Environment.NewLine
|
||||
+ " " + endSequence + Environment.NewLine
|
||||
+ endSequence + (acceptToEndOfLine ? " foo bar baz" : "") + Environment.NewLine;
|
||||
ParseBlockTest(code + "biz boz",
|
||||
new StatementBlock(
|
||||
Factory.Code(code).AsStatement().Accepts(GetAcceptedCharacters(acceptToEndOfLine))));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("While True", "End While", false)]
|
||||
[InlineData("Do", "Loop", true)]
|
||||
[InlineData("If foo IsNot Nothing", "End If", false)]
|
||||
[InlineData("Select Case foo", "End Select", false)]
|
||||
[InlineData("For Each p in Products", "Next", true)]
|
||||
[InlineData("Try", "End Try", false)]
|
||||
[InlineData("With", "End With", false)]
|
||||
[InlineData("SyncLock", "End SyncLock", false)]
|
||||
[InlineData("Using", "End Using", false)]
|
||||
private void SimpleKeywordBlock(string keyword, string endSequence, bool acceptToEndOfLine)
|
||||
{
|
||||
string code = keyword + Environment.NewLine
|
||||
+ " Bar(foo)" + Environment.NewLine
|
||||
+ endSequence + (acceptToEndOfLine ? " foo bar baz" : "") + Environment.NewLine;
|
||||
ParseBlockTest(code + "biz boz",
|
||||
new StatementBlock(
|
||||
Factory.Code(code).AsStatement().Accepts(GetAcceptedCharacters(acceptToEndOfLine))));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("While True", "Exit While", "End While", false)]
|
||||
[InlineData("Do", "Exit Do", "Loop", true)]
|
||||
[InlineData("For Each p in Products", "Exit For", "Next", true)]
|
||||
[InlineData("While True", "Continue While", "End While", false)]
|
||||
[InlineData("Do", "Continue Do", "Loop", true)]
|
||||
[InlineData("For Each p in Products", "Continue For", "Next", true)]
|
||||
private void KeywordWithExitOrContinue(string startKeyword, string exitKeyword, string endKeyword, bool acceptToEndOfLine)
|
||||
{
|
||||
string code = startKeyword + Environment.NewLine
|
||||
+ " ' This is before the exit" + Environment.NewLine
|
||||
+ " " + exitKeyword + Environment.NewLine
|
||||
+ " ' This is after the exit" + Environment.NewLine
|
||||
+ endKeyword + Environment.NewLine;
|
||||
ParseBlockTest(code + "foo bar baz",
|
||||
new StatementBlock(
|
||||
Factory.Code(code).AsStatement().Accepts(GetAcceptedCharacters(acceptToEndOfLine))));
|
||||
}
|
||||
|
||||
private AcceptedCharacters GetAcceptedCharacters(bool acceptToEndOfLine)
|
||||
{
|
||||
return acceptToEndOfLine ?
|
||||
AcceptedCharacters.WhiteSpace | AcceptedCharacters.NonWhiteSpace :
|
||||
AcceptedCharacters.None;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.AspNet.Razor.Parser;
|
||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||
using Microsoft.AspNet.Razor.Test.Framework;
|
||||
using Microsoft.TestCommon;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Test.Parser.VB
|
||||
{
|
||||
// VB Continue Statement: http://msdn.microsoft.com/en-us/library/801hyx6f.aspx
|
||||
public class VBContinueStatementTest : VBHtmlCodeParserTestBase
|
||||
{
|
||||
[Fact]
|
||||
public void VB_Do_Statement_With_Continue()
|
||||
{
|
||||
ParseBlockTest("@Do While True" + Environment.NewLine
|
||||
+ " Continue Do" + Environment.NewLine
|
||||
+ "Loop" + Environment.NewLine
|
||||
+ "' Not in the block!",
|
||||
new StatementBlock(
|
||||
Factory.CodeTransition(SyntaxConstants.TransitionString)
|
||||
.Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("Do While True\r\n Continue Do\r\nLoop\r\n")
|
||||
.AsStatement()
|
||||
.Accepts(AcceptedCharacters.AnyExceptNewline)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VB_For_Statement_With_Continue()
|
||||
{
|
||||
ParseBlockTest("@For i = 1 To 12" + Environment.NewLine
|
||||
+ " Continue For" + Environment.NewLine
|
||||
+ "Next i" + Environment.NewLine
|
||||
+ "' Not in the block!",
|
||||
new StatementBlock(
|
||||
Factory.CodeTransition(SyntaxConstants.TransitionString)
|
||||
.Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("For i = 1 To 12\r\n Continue For\r\nNext i\r\n")
|
||||
.AsStatement()
|
||||
.Accepts(AcceptedCharacters.AnyExceptNewline)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VB_While_Statement_With_Continue()
|
||||
{
|
||||
ParseBlockTest("@While True" + Environment.NewLine
|
||||
+ " Continue While" + Environment.NewLine
|
||||
+ "End While" + Environment.NewLine
|
||||
+ "' Not in the block!",
|
||||
new StatementBlock(
|
||||
Factory.CodeTransition(SyntaxConstants.TransitionString)
|
||||
.Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("While True\r\n Continue While\r\nEnd While\r\n")
|
||||
.AsStatement()
|
||||
.Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,128 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.AspNet.Razor.Generator;
|
||||
using Microsoft.AspNet.Razor.Parser;
|
||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||
using Microsoft.AspNet.Razor.Test.Framework;
|
||||
using Microsoft.AspNet.Razor.Text;
|
||||
using Microsoft.TestCommon;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Test.Parser.VB
|
||||
{
|
||||
public class VBDirectiveTest : VBHtmlCodeParserTestBase
|
||||
{
|
||||
[Fact]
|
||||
public void VB_Code_Directive()
|
||||
{
|
||||
ParseBlockTest("@Code" + Environment.NewLine
|
||||
+ " foo()" + Environment.NewLine
|
||||
+ "End Code" + Environment.NewLine
|
||||
+ "' Not part of the block",
|
||||
new StatementBlock(
|
||||
Factory.CodeTransition(SyntaxConstants.TransitionString)
|
||||
.Accepts(AcceptedCharacters.None),
|
||||
Factory.MetaCode("Code")
|
||||
.Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("\r\n foo()\r\n")
|
||||
.AsStatement()
|
||||
.With(new AutoCompleteEditHandler(VBLanguageCharacteristics.Instance.TokenizeString)),
|
||||
Factory.MetaCode("End Code")
|
||||
.Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VB_Functions_Directive()
|
||||
{
|
||||
ParseBlockTest("@Functions" + Environment.NewLine
|
||||
+ " Public Function Foo() As String" + Environment.NewLine
|
||||
+ " Return \"Foo\"" + Environment.NewLine
|
||||
+ " End Function" + Environment.NewLine
|
||||
+ Environment.NewLine
|
||||
+ " Public Sub Bar()" + Environment.NewLine
|
||||
+ " End Sub" + Environment.NewLine
|
||||
+ "End Functions" + Environment.NewLine
|
||||
+ "' Not part of the block",
|
||||
new FunctionsBlock(
|
||||
Factory.CodeTransition(SyntaxConstants.TransitionString)
|
||||
.Accepts(AcceptedCharacters.None),
|
||||
Factory.MetaCode("Functions")
|
||||
.Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("\r\n Public Function Foo() As String\r\n Return \"Foo\"\r\n End Function\r\n\r\n Public Sub Bar()\r\n End Sub\r\n")
|
||||
.AsFunctionsBody(),
|
||||
Factory.MetaCode("End Functions")
|
||||
.Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VB_Section_Directive()
|
||||
{
|
||||
ParseBlockTest("@Section Header" + Environment.NewLine
|
||||
+ " <p>Foo</p>" + Environment.NewLine
|
||||
+ "End Section",
|
||||
new SectionBlock(new SectionCodeGenerator("Header"),
|
||||
Factory.CodeTransition(SyntaxConstants.TransitionString),
|
||||
Factory.MetaCode("Section Header"),
|
||||
new MarkupBlock(
|
||||
Factory.Markup("\r\n <p>Foo</p>\r\n")),
|
||||
Factory.MetaCode("End Section")
|
||||
.Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SessionStateDirectiveWorks()
|
||||
{
|
||||
ParseBlockTest("@SessionState InProc" + Environment.NewLine,
|
||||
new DirectiveBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("SessionState ")
|
||||
.Accepts(AcceptedCharacters.None),
|
||||
Factory.MetaCode("InProc\r\n")
|
||||
.Accepts(AcceptedCharacters.None)
|
||||
.With(new RazorDirectiveAttributeCodeGenerator("SessionState", "InProc"))
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SessionStateDirectiveIsCaseInsensitive()
|
||||
{
|
||||
ParseBlockTest("@sessionstate disabled" + Environment.NewLine,
|
||||
new DirectiveBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("sessionstate ")
|
||||
.Accepts(AcceptedCharacters.None),
|
||||
Factory.MetaCode("disabled\r\n")
|
||||
.Accepts(AcceptedCharacters.None)
|
||||
.With(new RazorDirectiveAttributeCodeGenerator("SessionState", "disabled"))
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VB_Helper_Directive()
|
||||
{
|
||||
ParseBlockTest("@Helper Strong(s as String)" + Environment.NewLine
|
||||
+ " s = s.ToUpperCase()" + Environment.NewLine
|
||||
+ " @<strong>s</strong>" + Environment.NewLine
|
||||
+ "End Helper",
|
||||
new HelperBlock(new HelperCodeGenerator(new LocationTagged<string>("Strong(s as String)", 8, 0, 8), headerComplete: true),
|
||||
Factory.CodeTransition(SyntaxConstants.TransitionString),
|
||||
Factory.MetaCode("Helper ")
|
||||
.Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("Strong(s as String)").Hidden(),
|
||||
new StatementBlock(
|
||||
Factory.Code("\r\n s = s.ToUpperCase()\r\n")
|
||||
.AsStatement(),
|
||||
new MarkupBlock(
|
||||
Factory.Markup(" "),
|
||||
Factory.MarkupTransition(SyntaxConstants.TransitionString),
|
||||
Factory.Markup("<strong>s</strong>\r\n")
|
||||
.Accepts(AcceptedCharacters.None)),
|
||||
Factory.EmptyVB()
|
||||
.AsStatement(),
|
||||
Factory.MetaCode("End Helper")
|
||||
.Accepts(AcceptedCharacters.None))));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,174 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.AspNet.Razor.Editor;
|
||||
using Microsoft.AspNet.Razor.Parser;
|
||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||
using Microsoft.AspNet.Razor.Resources;
|
||||
using Microsoft.AspNet.Razor.Test.Framework;
|
||||
using Microsoft.AspNet.Razor.Text;
|
||||
using Microsoft.TestCommon;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Test.Parser.VB
|
||||
{
|
||||
public class VBErrorTest : VBHtmlCodeParserTestBase
|
||||
{
|
||||
[Fact]
|
||||
public void ParserOutputsErrorAndRecoversToEndOfLineIfExplicitExpressionUnterminated()
|
||||
{
|
||||
ParseBlockTest(@"(foo
|
||||
bar",
|
||||
new ExpressionBlock(
|
||||
Factory.MetaCode("(").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("foo").AsExpression()),
|
||||
new RazorError(
|
||||
String.Format(
|
||||
RazorResources.ParseError_Expected_EndOfBlock_Before_EOF,
|
||||
RazorResources.BlockName_ExplicitExpression,
|
||||
")", "("),
|
||||
SourceLocation.Zero));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParserOutputsZeroLengthCodeSpanIfEofReachedAfterStartOfExplicitExpression()
|
||||
{
|
||||
ParseBlockTest("(",
|
||||
new ExpressionBlock(
|
||||
Factory.MetaCode("(").Accepts(AcceptedCharacters.None),
|
||||
Factory.EmptyVB().AsExpression()),
|
||||
new RazorError(
|
||||
String.Format(RazorResources.ParseError_Expected_EndOfBlock_Before_EOF, "explicit expression", ")", "("),
|
||||
SourceLocation.Zero));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParserOutputsZeroLengthCodeSpanIfEofReachedAfterAtSign()
|
||||
{
|
||||
ParseBlockTest(String.Empty,
|
||||
new ExpressionBlock(
|
||||
Factory.EmptyVB().AsImplicitExpression(KeywordSet).Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
new RazorError(
|
||||
RazorResources.ParseError_Unexpected_EndOfFile_At_Start_Of_CodeBlock,
|
||||
SourceLocation.Zero));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParserOutputsZeroLengthCodeSpanIfOnlyWhitespaceFoundAfterAtSign()
|
||||
{
|
||||
ParseBlockTest(" ",
|
||||
new ExpressionBlock(
|
||||
Factory.EmptyVB().AsImplicitExpression(KeywordSet).Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
new RazorError(
|
||||
RazorResources.ParseError_Unexpected_WhiteSpace_At_Start_Of_CodeBlock_VB,
|
||||
SourceLocation.Zero));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParserOutputsZeroLengthCodeSpanIfInvalidCharacterFoundAfterAtSign()
|
||||
{
|
||||
ParseBlockTest("!!!",
|
||||
new ExpressionBlock(
|
||||
Factory.EmptyVB().AsImplicitExpression(KeywordSet).Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
new RazorError(
|
||||
String.Format(RazorResources.ParseError_Unexpected_Character_At_Start_Of_CodeBlock_VB, "!"),
|
||||
SourceLocation.Zero));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("Code", "End Code", true, true)]
|
||||
[InlineData("Do", "Loop", false, false)]
|
||||
[InlineData("While", "End While", false, false)]
|
||||
[InlineData("If", "End If", false, false)]
|
||||
[InlineData("Select Case", "End Select", false, false)]
|
||||
[InlineData("For", "Next", false, false)]
|
||||
[InlineData("Try", "End Try", false, false)]
|
||||
[InlineData("With", "End With", false, false)]
|
||||
[InlineData("Using", "End Using", false, false)]
|
||||
public void EofBlock(string keyword, string expectedTerminator, bool autoComplete, bool keywordIsMetaCode)
|
||||
{
|
||||
EofBlockCore(keyword, expectedTerminator, autoComplete, BlockType.Statement, keywordIsMetaCode, c => c.AsStatement());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EofFunctionsBlock()
|
||||
{
|
||||
EofBlockCore("Functions", "End Functions", true, BlockType.Functions, true, c => c.AsFunctionsBody());
|
||||
}
|
||||
|
||||
private void EofBlockCore(string keyword, string expectedTerminator, bool autoComplete, BlockType blockType, bool keywordIsMetaCode, Func<UnclassifiedCodeSpanConstructor, SpanConstructor> classifier)
|
||||
{
|
||||
BlockBuilder expected = new BlockBuilder();
|
||||
expected.Type = blockType;
|
||||
if (keywordIsMetaCode)
|
||||
{
|
||||
expected.Children.Add(Factory.MetaCode(keyword).Accepts(AcceptedCharacters.None));
|
||||
expected.Children.Add(
|
||||
classifier(Factory.EmptyVB())
|
||||
.With((SpanEditHandler)(
|
||||
autoComplete ?
|
||||
new AutoCompleteEditHandler(CSharpLanguageCharacteristics.Instance.TokenizeString) { AutoCompleteString = expectedTerminator } :
|
||||
SpanEditHandler.CreateDefault())));
|
||||
}
|
||||
else
|
||||
{
|
||||
expected.Children.Add(
|
||||
classifier(Factory.Code(keyword))
|
||||
.With((SpanEditHandler)(
|
||||
autoComplete ?
|
||||
new AutoCompleteEditHandler(CSharpLanguageCharacteristics.Instance.TokenizeString) { AutoCompleteString = expectedTerminator } :
|
||||
SpanEditHandler.CreateDefault())));
|
||||
}
|
||||
|
||||
ParseBlockTest(keyword,
|
||||
expected.Build(),
|
||||
new RazorError(
|
||||
String.Format(RazorResources.ParseError_BlockNotTerminated, keyword, expectedTerminator),
|
||||
SourceLocation.Zero));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("Code", "End Code", true)]
|
||||
[InlineData("Do", "Loop", false)]
|
||||
[InlineData("While", "End While", false)]
|
||||
[InlineData("If", "End If", false)]
|
||||
[InlineData("Select Case", "End Select", false)]
|
||||
[InlineData("For", "Next", false)]
|
||||
[InlineData("Try", "End Try", false)]
|
||||
[InlineData("With", "End With", false)]
|
||||
[InlineData("Using", "End Using", false)]
|
||||
public void UnterminatedBlock(string keyword, string expectedTerminator, bool keywordIsMetaCode)
|
||||
{
|
||||
UnterminatedBlockCore(keyword, expectedTerminator, BlockType.Statement, keywordIsMetaCode, c => c.AsStatement());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void UnterminatedFunctionsBlock()
|
||||
{
|
||||
UnterminatedBlockCore("Functions", "End Functions", BlockType.Functions, true, c => c.AsFunctionsBody());
|
||||
}
|
||||
|
||||
private void UnterminatedBlockCore(string keyword, string expectedTerminator, BlockType blockType, bool keywordIsMetaCode, Func<UnclassifiedCodeSpanConstructor, SpanConstructor> classifier)
|
||||
{
|
||||
const string blockBody = @"
|
||||
' This block is not correctly terminated!";
|
||||
|
||||
BlockBuilder expected = new BlockBuilder();
|
||||
expected.Type = blockType;
|
||||
if (keywordIsMetaCode)
|
||||
{
|
||||
expected.Children.Add(Factory.MetaCode(keyword).Accepts(AcceptedCharacters.None));
|
||||
expected.Children.Add(classifier(Factory.Code(blockBody)));
|
||||
}
|
||||
else
|
||||
{
|
||||
expected.Children.Add(classifier(Factory.Code(keyword + blockBody)));
|
||||
}
|
||||
|
||||
ParseBlockTest(keyword + blockBody,
|
||||
expected.Build(),
|
||||
new RazorError(
|
||||
String.Format(RazorResources.ParseError_BlockNotTerminated, keyword, expectedTerminator),
|
||||
SourceLocation.Zero));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,97 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.AspNet.Razor.Parser;
|
||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||
using Microsoft.AspNet.Razor.Test.Framework;
|
||||
using Microsoft.TestCommon;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Test.Parser.VB
|
||||
{
|
||||
// VB Exit Statement: http://msdn.microsoft.com/en-us/library/t2at9t47.aspx
|
||||
public class VBExitStatementTest : VBHtmlCodeParserTestBase
|
||||
{
|
||||
[Fact]
|
||||
public void VB_Do_Statement_With_Exit()
|
||||
{
|
||||
ParseBlockTest("@Do While True" + Environment.NewLine
|
||||
+ " Exit Do" + Environment.NewLine
|
||||
+ "Loop" + Environment.NewLine
|
||||
+ "' Not in the block!",
|
||||
new StatementBlock(
|
||||
Factory.CodeTransition(SyntaxConstants.TransitionString)
|
||||
.Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("Do While True\r\n Exit Do\r\nLoop\r\n")
|
||||
.AsStatement()
|
||||
.Accepts(AcceptedCharacters.AnyExceptNewline)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VB_For_Statement_With_Exit()
|
||||
{
|
||||
ParseBlockTest("@For i = 1 To 12" + Environment.NewLine
|
||||
+ " Exit For" + Environment.NewLine
|
||||
+ "Next i" + Environment.NewLine
|
||||
+ "' Not in the block!",
|
||||
new StatementBlock(
|
||||
Factory.CodeTransition(SyntaxConstants.TransitionString)
|
||||
.Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("For i = 1 To 12\r\n Exit For\r\nNext i\r\n")
|
||||
.AsStatement()
|
||||
.Accepts(AcceptedCharacters.AnyExceptNewline)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VB_Select_Statement_With_Exit()
|
||||
{
|
||||
ParseBlockTest("@Select Case Foo" + Environment.NewLine
|
||||
+ " Case 1" + Environment.NewLine
|
||||
+ " Exit Select" + Environment.NewLine
|
||||
+ " Case 2" + Environment.NewLine
|
||||
+ " Exit Select" + Environment.NewLine
|
||||
+ "End Select" + Environment.NewLine
|
||||
+ "' Not in the block!",
|
||||
new StatementBlock(
|
||||
Factory.CodeTransition(SyntaxConstants.TransitionString)
|
||||
.Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("Select Case Foo\r\n Case 1\r\n Exit Select\r\n Case 2\r\n Exit Select\r\nEnd Select\r\n")
|
||||
.AsStatement()
|
||||
.Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VB_Try_Statement_With_Exit()
|
||||
{
|
||||
ParseBlockTest("@Try" + Environment.NewLine
|
||||
+ " Foo()" + Environment.NewLine
|
||||
+ " Exit Try" + Environment.NewLine
|
||||
+ "Catch Bar" + Environment.NewLine
|
||||
+ " Throw Bar" + Environment.NewLine
|
||||
+ "Finally" + Environment.NewLine
|
||||
+ " Baz()" + Environment.NewLine
|
||||
+ "End Try" + Environment.NewLine
|
||||
+ "' Not in the block!",
|
||||
new StatementBlock(
|
||||
Factory.CodeTransition(SyntaxConstants.TransitionString)
|
||||
.Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("Try\r\n Foo()\r\n Exit Try\r\nCatch Bar\r\n Throw Bar\r\nFinally\r\n Baz()\r\nEnd Try\r\n")
|
||||
.AsStatement()
|
||||
.Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VB_While_Statement_With_Exit()
|
||||
{
|
||||
ParseBlockTest("@While True" + Environment.NewLine
|
||||
+ " Exit While" + Environment.NewLine
|
||||
+ "End While" + Environment.NewLine
|
||||
+ "' Not in the block!",
|
||||
new StatementBlock(
|
||||
Factory.CodeTransition(SyntaxConstants.TransitionString)
|
||||
.Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("While True\r\n Exit While\r\nEnd While\r\n")
|
||||
.AsStatement()
|
||||
.Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||
using Microsoft.AspNet.Razor.Test.Framework;
|
||||
using Microsoft.TestCommon;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Test.Parser.VB
|
||||
{
|
||||
public class VBExplicitExpressionTest : VBHtmlCodeParserTestBase
|
||||
{
|
||||
[Fact]
|
||||
public void VB_Simple_ExplicitExpression()
|
||||
{
|
||||
ParseBlockTest("@(foo)",
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("(").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("foo").AsExpression(),
|
||||
Factory.MetaCode(")").Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,111 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||
using Microsoft.AspNet.Razor.Resources;
|
||||
using Microsoft.AspNet.Razor.Test.Framework;
|
||||
using Microsoft.AspNet.Razor.Text;
|
||||
using Microsoft.TestCommon;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Test.Parser.VB
|
||||
{
|
||||
public class VBExpressionTest : VBHtmlCodeParserTestBase
|
||||
{
|
||||
[Fact]
|
||||
public void ParseBlockCorrectlyHandlesCodeBlockInBodyOfExplicitExpressionDueToUnclosedExpression()
|
||||
{
|
||||
ParseBlockTest(@"(
|
||||
@Code
|
||||
Dim foo = bar
|
||||
End Code",
|
||||
new ExpressionBlock(
|
||||
Factory.MetaCode("(").Accepts(AcceptedCharacters.None),
|
||||
Factory.EmptyVB().AsExpression()),
|
||||
new RazorError(
|
||||
String.Format(
|
||||
RazorResources.ParseError_Expected_EndOfBlock_Before_EOF,
|
||||
RazorResources.BlockName_ExplicitExpression,
|
||||
")", "("),
|
||||
SourceLocation.Zero));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockAcceptsNonEnglishCharactersThatAreValidIdentifiers()
|
||||
{
|
||||
ImplicitExpressionTest("हळूँजद॔.", "हळूँजद॔");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockDoesNotTreatXmlAxisPropertyAsTransitionToMarkup()
|
||||
{
|
||||
SingleSpanBlockTest(
|
||||
@"If foo Is Nothing Then
|
||||
Dim bar As XElement
|
||||
Dim foo = bar.<foo>
|
||||
End If",
|
||||
BlockType.Statement,
|
||||
SpanKind.Code,
|
||||
acceptedCharacters: AcceptedCharacters.None);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockDoesNotTreatXmlAttributePropertyAsTransitionToMarkup()
|
||||
{
|
||||
SingleSpanBlockTest(
|
||||
@"If foo Is Nothing Then
|
||||
Dim bar As XElement
|
||||
Dim foo = bar.@foo
|
||||
End If",
|
||||
BlockType.Statement,
|
||||
SpanKind.Code,
|
||||
acceptedCharacters: AcceptedCharacters.None);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockSupportsSimpleImplicitExpression()
|
||||
{
|
||||
ImplicitExpressionTest("Foo");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockSupportsImplicitExpressionWithDots()
|
||||
{
|
||||
ImplicitExpressionTest("Foo.Bar.Baz");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockSupportsImplicitExpressionWithParens()
|
||||
{
|
||||
ImplicitExpressionTest("Foo().Bar().Baz()");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockSupportsImplicitExpressionWithStuffInParens()
|
||||
{
|
||||
ImplicitExpressionTest("Foo().Bar(sdfkhj sdfksdfjs \")\" sjdfkjsdf).Baz()");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockSupportsImplicitExpressionWithCommentInParens()
|
||||
{
|
||||
ImplicitExpressionTest("Foo().Bar(sdfkhj sdfksdfjs \")\" '))))))))\r\nsjdfkjsdf).Baz()");
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("Foo")]
|
||||
[InlineData("Foo(Of String).Bar(1, 2, 3).Biz")]
|
||||
[InlineData("Foo(Of String).Bar(\")\").Biz")]
|
||||
[InlineData("Foo(Of String).Bar(\"Foo\"\"Bar)\"\"Baz\").Biz")]
|
||||
[InlineData("\"foo\r\nbar")]
|
||||
[InlineData("Foo.Bar. _\r\nREM )\r\nBaz()\r\n")]
|
||||
[InlineData("Foo.Bar. _\r\n' )\r\nBaz()\r\n")]
|
||||
public void ValidExplicitExpressions(string body)
|
||||
{
|
||||
ParseBlockTest("(" + body + ")",
|
||||
new ExpressionBlock(
|
||||
Factory.MetaCode("(").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code(body).AsExpression(),
|
||||
Factory.MetaCode(")").Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,121 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.AspNet.Razor.Parser;
|
||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||
using Microsoft.AspNet.Razor.Resources;
|
||||
using Microsoft.AspNet.Razor.Test.Framework;
|
||||
using Microsoft.TestCommon;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Test.Parser.VB
|
||||
{
|
||||
public class VBExpressionsInCodeTest : VBHtmlCodeParserTestBase
|
||||
{
|
||||
[Fact]
|
||||
public void InnerImplicitExpressionWithOnlySingleAtAcceptsSingleSpaceOrNewlineAtDesignTime()
|
||||
{
|
||||
ParseBlockTest("Code" + Environment.NewLine
|
||||
+ " @" + Environment.NewLine
|
||||
+ "End Code",
|
||||
new StatementBlock(
|
||||
Factory.MetaCode("Code").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("\r\n ").AsStatement(),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.EmptyVB()
|
||||
.AsImplicitExpression(VBCodeParser.DefaultKeywords, acceptTrailingDot: true)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
Factory.Code("\r\n").AsStatement(),
|
||||
Factory.MetaCode("End Code").Accepts(AcceptedCharacters.None)),
|
||||
designTimeParser: true,
|
||||
expectedErrors: new[]
|
||||
{
|
||||
new RazorError(RazorResources.ParseError_Unexpected_WhiteSpace_At_Start_Of_CodeBlock_VB, 11, 1, 5)
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InnerImplicitExpressionDoesNotAcceptDotAfterAt()
|
||||
{
|
||||
ParseBlockTest("Code" + Environment.NewLine
|
||||
+ " @." + Environment.NewLine
|
||||
+ "End Code",
|
||||
new StatementBlock(
|
||||
Factory.MetaCode("Code").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("\r\n ").AsStatement(),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.EmptyVB()
|
||||
.AsImplicitExpression(VBCodeParser.DefaultKeywords, acceptTrailingDot: true)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
Factory.Code(".\r\n").AsStatement(),
|
||||
Factory.MetaCode("End Code").Accepts(AcceptedCharacters.None)),
|
||||
designTimeParser: true,
|
||||
expectedErrors: new[]
|
||||
{
|
||||
new RazorError(
|
||||
String.Format(RazorResources.ParseError_Unexpected_Character_At_Start_Of_CodeBlock_VB, "."),
|
||||
11, 1, 5)
|
||||
});
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("Foo.Bar.", true)]
|
||||
[InlineData("Foo", true)]
|
||||
[InlineData("Foo.Bar.Baz", true)]
|
||||
[InlineData("Foo().Bar().Baz()", true)]
|
||||
[InlineData("Foo().Bar(sdfkhj sdfksdfjs \")\" sjdfkjsdf).Baz()", true)]
|
||||
[InlineData("Foo().Bar(sdfkhj sdfksdfjs \")\" '))))))))\r\nsjdfkjsdf).Baz()", true)]
|
||||
[InlineData("Foo", false)]
|
||||
[InlineData("Foo(Of String).Bar(1, 2, 3).Biz", false)]
|
||||
[InlineData("Foo(Of String).Bar(\")\").Biz", false)]
|
||||
[InlineData("Foo(Of String).Bar(\"Foo\"\"Bar)\"\"Baz\").Biz", false)]
|
||||
[InlineData("Foo.Bar. _\r\nREM )\r\nBaz()\r\n", false)]
|
||||
[InlineData("Foo.Bar. _\r\n' )\r\nBaz()\r\n", false)]
|
||||
public void ExpressionInCode(string expression, bool isImplicit)
|
||||
{
|
||||
ExpressionBlock expressionBlock;
|
||||
if (isImplicit)
|
||||
{
|
||||
expressionBlock =
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code(expression)
|
||||
.AsImplicitExpression(VBCodeParser.DefaultKeywords, acceptTrailingDot: true)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace));
|
||||
}
|
||||
else
|
||||
{
|
||||
expressionBlock =
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("(").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code(expression).AsExpression(),
|
||||
Factory.MetaCode(")").Accepts(AcceptedCharacters.None));
|
||||
}
|
||||
|
||||
string code;
|
||||
if (isImplicit)
|
||||
{
|
||||
code = "If foo IsNot Nothing Then" + Environment.NewLine
|
||||
+ " @" + expression + Environment.NewLine
|
||||
+ "End If";
|
||||
}
|
||||
else
|
||||
{
|
||||
code = "If foo IsNot Nothing Then" + Environment.NewLine
|
||||
+ " @(" + expression + ")" + Environment.NewLine
|
||||
+ "End If";
|
||||
}
|
||||
|
||||
ParseBlockTest(code,
|
||||
new StatementBlock(
|
||||
Factory.Code("If foo IsNot Nothing Then\r\n ")
|
||||
.AsStatement(),
|
||||
expressionBlock,
|
||||
Factory.Code("\r\nEnd If")
|
||||
.AsStatement()
|
||||
.Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,324 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.AspNet.Razor.Generator;
|
||||
using Microsoft.AspNet.Razor.Parser;
|
||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||
using Microsoft.AspNet.Razor.Resources;
|
||||
using Microsoft.AspNet.Razor.Test.Framework;
|
||||
using Microsoft.AspNet.Razor.Text;
|
||||
using Microsoft.TestCommon;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Test.Parser.VB
|
||||
{
|
||||
public class VBHelperTest : VBHtmlMarkupParserTestBase
|
||||
{
|
||||
[Fact]
|
||||
public void ParseHelperOutputsErrorButContinuesIfLParenFoundAfterHelperKeyword()
|
||||
{
|
||||
ParseDocumentTest("@Helper ()",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new HelperBlock(new HelperCodeGenerator(new LocationTagged<string>("()", 8, 0, 8), headerComplete: true),
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("Helper ").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("()").Hidden().AutoCompleteWith(SyntaxConstants.VB.EndHelperKeyword),
|
||||
new StatementBlock())),
|
||||
new RazorError(
|
||||
String.Format(
|
||||
RazorResources.ParseError_Unexpected_Character_At_Helper_Name_Start,
|
||||
String.Format(RazorResources.ErrorComponent_Character, "(")),
|
||||
8, 0, 8),
|
||||
new RazorError(
|
||||
String.Format(RazorResources.ParseError_BlockNotTerminated, "Helper", "End Helper"),
|
||||
1, 0, 1));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseHelperStatementOutputsMarkerHelperHeaderSpanOnceKeywordComplete()
|
||||
{
|
||||
ParseDocumentTest("@Helper ",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new HelperBlock(new HelperCodeGenerator(new LocationTagged<string>(String.Empty, 8, 0, 8), headerComplete: false),
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("Helper ").Accepts(AcceptedCharacters.None),
|
||||
Factory.EmptyVB().Hidden())),
|
||||
new RazorError(
|
||||
String.Format(RazorResources.ParseError_Unexpected_Character_At_Helper_Name_Start, RazorResources.ErrorComponent_EndOfFile),
|
||||
8, 0, 8));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseHelperStatementMarksHelperSpanAsCanGrowIfMissingTrailingSpace()
|
||||
{
|
||||
ParseDocumentTest("@Helper",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new HelperBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("Helper"))),
|
||||
new RazorError(
|
||||
String.Format(RazorResources.ParseError_Unexpected_Character_At_Helper_Name_Start, RazorResources.ErrorComponent_EndOfFile),
|
||||
7, 0, 7));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseHelperStatementTerminatesEarlyIfHeaderNotComplete()
|
||||
{
|
||||
ParseDocumentTest("@Helper" + Environment.NewLine
|
||||
+ "@Helper",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new HelperBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("Helper\r\n").Accepts(AcceptedCharacters.None),
|
||||
Factory.EmptyVB().Hidden()),
|
||||
new HelperBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("Helper"))),
|
||||
designTimeParser: true,
|
||||
expectedErrors: new[]
|
||||
{
|
||||
new RazorError(
|
||||
String.Format(
|
||||
RazorResources.ParseError_Unexpected_Character_At_Helper_Name_Start,
|
||||
String.Format(RazorResources.ErrorComponent_Character, "@")),
|
||||
9, 1, 0),
|
||||
new RazorError(
|
||||
String.Format(
|
||||
RazorResources.ParseError_Unexpected_Character_At_Helper_Name_Start,
|
||||
RazorResources.ErrorComponent_EndOfFile),
|
||||
16, 1, 7)
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseHelperStatementTerminatesEarlyIfHeaderNotCompleteWithSpace()
|
||||
{
|
||||
ParseDocumentTest(@"@Helper @Helper",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new HelperBlock(new HelperCodeGenerator(new LocationTagged<string>(String.Empty, 8, 0, 8), headerComplete: false),
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode(@"Helper ").Accepts(AcceptedCharacters.None),
|
||||
Factory.EmptyVB().Hidden()),
|
||||
new HelperBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("Helper").Accepts(AcceptedCharacters.Any))),
|
||||
designTimeParser: true,
|
||||
expectedErrors: new[]
|
||||
{
|
||||
new RazorError(
|
||||
String.Format(
|
||||
RazorResources.ParseError_Unexpected_Character_At_Helper_Name_Start,
|
||||
String.Format(RazorResources.ErrorComponent_Character, "@")),
|
||||
8, 0, 8),
|
||||
new RazorError(
|
||||
String.Format(
|
||||
RazorResources.ParseError_Unexpected_Character_At_Helper_Name_Start,
|
||||
RazorResources.ErrorComponent_EndOfFile),
|
||||
15, 0, 15)
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseHelperStatementAllowsDifferentlyCasedEndHelperKeyword()
|
||||
{
|
||||
ParseDocumentTest("@Helper Foo()" + Environment.NewLine
|
||||
+ "end helper",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new HelperBlock(new HelperCodeGenerator(new LocationTagged<string>("Foo()", 8, 0, 8), headerComplete: true),
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("Helper ").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("Foo()").Hidden(),
|
||||
new StatementBlock(
|
||||
Factory.Code("\r\n").AsStatement(),
|
||||
Factory.MetaCode("end helper").Accepts(AcceptedCharacters.None))),
|
||||
Factory.EmptyHtml()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseHelperStatementCapturesWhitespaceToEndOfLineIfHelperStatementMissingName()
|
||||
{
|
||||
ParseDocumentTest("@Helper " + Environment.NewLine
|
||||
+ " ",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new HelperBlock(new HelperCodeGenerator(new LocationTagged<string>(" ", 8, 0, 8), headerComplete: false),
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("Helper ").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code(" ").Hidden()),
|
||||
Factory.Markup("\r\n ")),
|
||||
new RazorError(
|
||||
String.Format(
|
||||
RazorResources.ParseError_Unexpected_Character_At_Helper_Name_Start,
|
||||
RazorResources.ErrorComponent_Newline),
|
||||
30, 0, 30));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseHelperStatementCapturesWhitespaceToEndOfLineIfHelperStatementMissingOpenParen()
|
||||
{
|
||||
ParseDocumentTest("@Helper Foo " + Environment.NewLine
|
||||
+ " ",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new HelperBlock(new HelperCodeGenerator(new LocationTagged<string>("Foo ", 8, 0, 8), headerComplete: false),
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("Helper ").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("Foo ").Hidden()),
|
||||
Factory.Markup("\r\n ")),
|
||||
new RazorError(
|
||||
String.Format(RazorResources.ParseError_MissingCharAfterHelperName, "("),
|
||||
15, 0, 15));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseHelperStatementCapturesAllContentToEndOfFileIfHelperStatementMissingCloseParenInParameterList()
|
||||
{
|
||||
ParseDocumentTest("@Helper Foo(Foo Bar" + Environment.NewLine
|
||||
+ "Biz" + Environment.NewLine
|
||||
+ "Boz",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new HelperBlock(new HelperCodeGenerator(new LocationTagged<string>("Foo(Foo Bar\r\nBiz\r\nBoz", 8, 0, 8), headerComplete: false),
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("Helper ").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("Foo(Foo Bar\r\nBiz\r\nBoz").Hidden())),
|
||||
new RazorError(RazorResources.ParseError_UnterminatedHelperParameterList, 11, 0, 11));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseHelperStatementCapturesWhitespaceToEndOfLineIfHelperStatementMissingOpenBraceAfterParameterList()
|
||||
{
|
||||
ParseDocumentTest("@Helper Foo(foo as String) " + Environment.NewLine,
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new HelperBlock(new HelperCodeGenerator(new LocationTagged<string>("Foo(foo as String)", 8, 0, 8), headerComplete: true),
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("Helper ").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("Foo(foo as String)")
|
||||
.Hidden()
|
||||
.AutoCompleteWith(SyntaxConstants.VB.EndHelperKeyword),
|
||||
new StatementBlock(
|
||||
Factory.Code(" \r\n").AsStatement()))),
|
||||
new RazorError(
|
||||
String.Format(RazorResources.ParseError_BlockNotTerminated, "Helper", "End Helper"),
|
||||
1, 0, 1));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseHelperStatementContinuesParsingHelperUntilEOF()
|
||||
{
|
||||
ParseDocumentTest("@Helper Foo(foo as String)" + Environment.NewLine
|
||||
+ " @<p>Foo</p>",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new HelperBlock(new HelperCodeGenerator(new LocationTagged<string>("Foo(foo as String)", 8, 0, 8), headerComplete: true),
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("Helper ").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("Foo(foo as String)")
|
||||
.Hidden()
|
||||
.AutoCompleteWith(SyntaxConstants.VB.EndHelperKeyword),
|
||||
new StatementBlock(
|
||||
Factory.Code("\r\n").AsStatement(),
|
||||
new MarkupBlock(
|
||||
Factory.Markup(" "),
|
||||
Factory.MarkupTransition(),
|
||||
Factory.Markup("<p>Foo</p>").Accepts(AcceptedCharacters.None)),
|
||||
Factory.EmptyVB().AsStatement()))),
|
||||
new RazorError(
|
||||
String.Format(RazorResources.ParseError_BlockNotTerminated, "Helper", "End Helper"),
|
||||
1, 0, 1));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseHelperStatementCorrectlyParsesHelperWithEmbeddedCode()
|
||||
{
|
||||
ParseDocumentTest("@Helper Foo(foo as String, bar as String)" + Environment.NewLine
|
||||
+ " @<p>@foo</p>" + Environment.NewLine
|
||||
+ "End Helper",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new HelperBlock(new HelperCodeGenerator(new LocationTagged<string>("Foo(foo as String, bar as String)", 8, 0, 8), headerComplete: true),
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("Helper ").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("Foo(foo as String, bar as String)").Hidden(),
|
||||
new StatementBlock(
|
||||
Factory.Code("\r\n").AsStatement(),
|
||||
new MarkupBlock(
|
||||
Factory.Markup(" "),
|
||||
Factory.MarkupTransition(),
|
||||
Factory.Markup("<p>"),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("foo")
|
||||
.AsImplicitExpression(VBCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
Factory.Markup("</p>\r\n").Accepts(AcceptedCharacters.None)),
|
||||
Factory.EmptyVB().AsStatement(),
|
||||
Factory.MetaCode("End Helper").Accepts(AcceptedCharacters.None))),
|
||||
Factory.EmptyHtml()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseHelperStatementGivesWhitespaceAfterCloseParenToMarkup()
|
||||
{
|
||||
ParseDocumentTest("@Helper Foo(string foo) " + Environment.NewLine
|
||||
+ " ",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new HelperBlock(new HelperCodeGenerator(new LocationTagged<string>("Foo(string foo)", 8, 0, 8), headerComplete: true),
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("Helper ").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("Foo(string foo)")
|
||||
.Hidden()
|
||||
.AutoCompleteWith(SyntaxConstants.VB.EndHelperKeyword),
|
||||
new StatementBlock(
|
||||
Factory.Code(" \r\n ").AsStatement()))),
|
||||
designTimeParser: true,
|
||||
expectedErrors:
|
||||
new RazorError(
|
||||
String.Format(
|
||||
RazorResources.ParseError_BlockNotTerminated,
|
||||
"Helper", "End Helper"),
|
||||
1, 0, 1));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseHelperAcceptsNestedHelpersButOutputsError()
|
||||
{
|
||||
ParseDocumentTest("@Helper Foo(string foo)" + Environment.NewLine
|
||||
+ " @Helper Bar(string baz)" + Environment.NewLine
|
||||
+ " End Helper" + Environment.NewLine
|
||||
+ "End Helper",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new HelperBlock(new HelperCodeGenerator(new LocationTagged<string>("Foo(string foo)", 8, 0, 8), headerComplete: true),
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("Helper ").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("Foo(string foo)").Hidden(),
|
||||
new StatementBlock(
|
||||
Factory.Code("\r\n ").AsStatement(),
|
||||
new HelperBlock(new HelperCodeGenerator(new LocationTagged<string>("Bar(string baz)", 37, 1, 12), headerComplete: true),
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("Helper ").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("Bar(string baz)").Hidden(),
|
||||
new StatementBlock(
|
||||
Factory.Code("\r\n ").AsStatement(),
|
||||
Factory.MetaCode("End Helper").Accepts(AcceptedCharacters.None))),
|
||||
Factory.Code("\r\n").AsStatement(),
|
||||
Factory.MetaCode("End Helper").Accepts(AcceptedCharacters.None))),
|
||||
Factory.EmptyHtml()),
|
||||
designTimeParser: true,
|
||||
expectedErrors: new[]
|
||||
{
|
||||
new RazorError(
|
||||
RazorResources.ParseError_Helpers_Cannot_Be_Nested,
|
||||
30, 1, 5)
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,251 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||
using Microsoft.AspNet.Razor.Test.Framework;
|
||||
using Microsoft.AspNet.Razor.Tokenizer.Symbols;
|
||||
using Microsoft.TestCommon;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Test.Parser.VB
|
||||
{
|
||||
public class VBHtmlDocumentTest : VBHtmlMarkupParserTestBase
|
||||
{
|
||||
[Fact]
|
||||
public void BlockCommentInMarkupDocumentIsHandledCorrectly()
|
||||
{
|
||||
ParseDocumentTest(@"<ul>" + Environment.NewLine
|
||||
+ @" @* This is a block comment </ul> *@ foo",
|
||||
new MarkupBlock(
|
||||
Factory.Markup("<ul>" + Environment.NewLine + " "),
|
||||
new CommentBlock(
|
||||
Factory.MarkupTransition(HtmlSymbolType.RazorCommentTransition),
|
||||
Factory.MetaMarkup("*", HtmlSymbolType.RazorCommentStar).Accepts(AcceptedCharacters.None),
|
||||
Factory.Comment(" This is a block comment </ul> ", HtmlSymbolType.RazorComment),
|
||||
Factory.MetaMarkup("*", HtmlSymbolType.RazorCommentStar).Accepts(AcceptedCharacters.None),
|
||||
Factory.MarkupTransition(HtmlSymbolType.RazorCommentTransition)),
|
||||
Factory.Markup(" foo")));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BlockCommentInMarkupBlockIsHandledCorrectly()
|
||||
{
|
||||
ParseBlockTest(@"<ul>" + Environment.NewLine
|
||||
+ @" @* This is a block comment </ul> *@ foo </ul>",
|
||||
new MarkupBlock(
|
||||
Factory.Markup("<ul>" + Environment.NewLine + " "),
|
||||
new CommentBlock(
|
||||
Factory.MarkupTransition(HtmlSymbolType.RazorCommentTransition),
|
||||
Factory.MetaMarkup("*", HtmlSymbolType.RazorCommentStar).Accepts(AcceptedCharacters.None),
|
||||
Factory.Comment(" This is a block comment </ul> ", HtmlSymbolType.RazorComment),
|
||||
Factory.MetaMarkup("*", HtmlSymbolType.RazorCommentStar).Accepts(AcceptedCharacters.None),
|
||||
Factory.MarkupTransition(HtmlSymbolType.RazorCommentTransition)),
|
||||
Factory.Markup(" foo </ul>").Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BlockCommentAtStatementStartInCodeBlockIsHandledCorrectly()
|
||||
{
|
||||
ParseDocumentTest(@"@If Request.IsAuthenticated Then" + Environment.NewLine
|
||||
+ @" @* User is logged in! End If *@" + Environment.NewLine
|
||||
+ @" Write(""Hello friend!"")" + Environment.NewLine
|
||||
+ @"End If",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new StatementBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("If Request.IsAuthenticated Then" + Environment.NewLine + " ").AsStatement(),
|
||||
new CommentBlock(
|
||||
Factory.CodeTransition(VBSymbolType.RazorCommentTransition),
|
||||
Factory.MetaCode("*", VBSymbolType.RazorCommentStar).Accepts(AcceptedCharacters.None),
|
||||
Factory.Comment(" User is logged in! End If ", VBSymbolType.RazorComment),
|
||||
Factory.MetaCode("*", VBSymbolType.RazorCommentStar).Accepts(AcceptedCharacters.None),
|
||||
Factory.CodeTransition(VBSymbolType.RazorCommentTransition)),
|
||||
Factory.Code("" + Environment.NewLine + " Write(\"Hello friend!\")" + Environment.NewLine + "End If")
|
||||
.AsStatement()
|
||||
.Accepts(AcceptedCharacters.None)),
|
||||
Factory.EmptyHtml()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BlockCommentInStatementInCodeBlockIsHandledCorrectly()
|
||||
{
|
||||
ParseDocumentTest(@"@If Request.IsAuthenticated Then" + Environment.NewLine
|
||||
+ @" Dim foo = @* User is logged in! End If *@ bar" + Environment.NewLine
|
||||
+ @" Write(""Hello friend!"")" + Environment.NewLine
|
||||
+ @"End If",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new StatementBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("If Request.IsAuthenticated Then" + Environment.NewLine + " Dim foo = ").AsStatement(),
|
||||
new CommentBlock(
|
||||
Factory.CodeTransition(VBSymbolType.RazorCommentTransition),
|
||||
Factory.MetaCode("*", VBSymbolType.RazorCommentStar).Accepts(AcceptedCharacters.None),
|
||||
Factory.Comment(" User is logged in! End If ", VBSymbolType.RazorComment),
|
||||
Factory.MetaCode("*", VBSymbolType.RazorCommentStar).Accepts(AcceptedCharacters.None),
|
||||
Factory.CodeTransition(VBSymbolType.RazorCommentTransition)),
|
||||
Factory.Code(" bar" + Environment.NewLine + " Write(\"Hello friend!\")" + Environment.NewLine + "End If")
|
||||
.AsStatement()
|
||||
.Accepts(AcceptedCharacters.None)),
|
||||
Factory.EmptyHtml()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BlockCommentInStringInCodeBlockIsIgnored()
|
||||
{
|
||||
ParseDocumentTest(@"@If Request.IsAuthenticated Then" + Environment.NewLine
|
||||
+ @" Dim foo = ""@* User is logged in! End If *@ bar""" + Environment.NewLine
|
||||
+ @" Write(""Hello friend!"")" + Environment.NewLine
|
||||
+ @"End If",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new StatementBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("If Request.IsAuthenticated Then" + Environment.NewLine + " Dim foo = \"@* User is logged in! End If *@ bar\"" + Environment.NewLine + " Write(\"Hello friend!\")" + Environment.NewLine + "End If")
|
||||
.AsStatement()
|
||||
.Accepts(AcceptedCharacters.None)),
|
||||
Factory.EmptyHtml()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BlockCommentInTickCommentInCodeBlockIsIgnored()
|
||||
{
|
||||
ParseDocumentTest(@"@If Request.IsAuthenticated Then" + Environment.NewLine
|
||||
+ @" Dim foo = '@* User is logged in! End If *@ bar" + Environment.NewLine
|
||||
+ @" Write(""Hello friend!"")" + Environment.NewLine
|
||||
+ @"End If",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new StatementBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("If Request.IsAuthenticated Then" + Environment.NewLine + " Dim foo = '@* User is logged in! End If *@ bar" + Environment.NewLine + " Write(\"Hello friend!\")" + Environment.NewLine + "End If")
|
||||
.AsStatement()
|
||||
.Accepts(AcceptedCharacters.None)),
|
||||
Factory.EmptyHtml()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BlockCommentInRemCommentInCodeBlockIsIgnored()
|
||||
{
|
||||
ParseDocumentTest(@"@If Request.IsAuthenticated Then" + Environment.NewLine
|
||||
+ @" Dim foo = REM @* User is logged in! End If *@ bar" + Environment.NewLine
|
||||
+ @" Write(""Hello friend!"")" + Environment.NewLine
|
||||
+ @"End If",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new StatementBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("If Request.IsAuthenticated Then" + Environment.NewLine + " Dim foo = REM @* User is logged in! End If *@ bar" + Environment.NewLine + " Write(\"Hello friend!\")" + Environment.NewLine + "End If")
|
||||
.AsStatement()
|
||||
.Accepts(AcceptedCharacters.None)),
|
||||
Factory.EmptyHtml()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BlockCommentInImplicitExpressionIsHandledCorrectly()
|
||||
{
|
||||
ParseDocumentTest("@Html.Foo@*bar*@",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("Html.Foo")
|
||||
.AsImplicitExpression(KeywordSet)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
Factory.EmptyHtml(),
|
||||
new CommentBlock(
|
||||
Factory.MarkupTransition(HtmlSymbolType.RazorCommentTransition),
|
||||
Factory.MetaMarkup("*", HtmlSymbolType.RazorCommentStar).Accepts(AcceptedCharacters.None),
|
||||
Factory.Comment("bar", HtmlSymbolType.RazorComment),
|
||||
Factory.MetaMarkup("*", HtmlSymbolType.RazorCommentStar).Accepts(AcceptedCharacters.None),
|
||||
Factory.MarkupTransition(HtmlSymbolType.RazorCommentTransition)),
|
||||
Factory.EmptyHtml()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BlockCommentAfterDotOfImplicitExpressionIsHandledCorrectly()
|
||||
{
|
||||
ParseDocumentTest("@Html.@*bar*@",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("Html")
|
||||
.AsImplicitExpression(KeywordSet)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
Factory.Markup("."),
|
||||
new CommentBlock(
|
||||
Factory.MarkupTransition(HtmlSymbolType.RazorCommentTransition),
|
||||
Factory.MetaMarkup("*", HtmlSymbolType.RazorCommentStar).Accepts(AcceptedCharacters.None),
|
||||
Factory.Comment("bar", HtmlSymbolType.RazorComment),
|
||||
Factory.MetaMarkup("*", HtmlSymbolType.RazorCommentStar).Accepts(AcceptedCharacters.None),
|
||||
Factory.MarkupTransition(HtmlSymbolType.RazorCommentTransition)),
|
||||
Factory.EmptyHtml()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BlockCommentInParensOfImplicitExpressionIsHandledCorrectly()
|
||||
{
|
||||
ParseDocumentTest("@Html.Foo(@*bar*@ 4)",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("Html.Foo(")
|
||||
.AsImplicitExpression(KeywordSet)
|
||||
.Accepts(AcceptedCharacters.Any),
|
||||
new CommentBlock(
|
||||
Factory.CodeTransition(VBSymbolType.RazorCommentTransition),
|
||||
Factory.MetaCode("*", VBSymbolType.RazorCommentStar).Accepts(AcceptedCharacters.None),
|
||||
Factory.Comment("bar", VBSymbolType.RazorComment),
|
||||
Factory.MetaCode("*", VBSymbolType.RazorCommentStar).Accepts(AcceptedCharacters.None),
|
||||
Factory.CodeTransition(VBSymbolType.RazorCommentTransition)),
|
||||
Factory.Code(" 4)")
|
||||
.AsImplicitExpression(KeywordSet)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
Factory.EmptyHtml()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BlockCommentInConditionIsHandledCorrectly()
|
||||
{
|
||||
ParseDocumentTest("@If @*bar*@ Then End If",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new StatementBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("If ").AsStatement(),
|
||||
new CommentBlock(
|
||||
Factory.CodeTransition(VBSymbolType.RazorCommentTransition),
|
||||
Factory.MetaCode("*", VBSymbolType.RazorCommentStar).Accepts(AcceptedCharacters.None),
|
||||
Factory.Comment("bar", VBSymbolType.RazorComment),
|
||||
Factory.MetaCode("*", VBSymbolType.RazorCommentStar).Accepts(AcceptedCharacters.None),
|
||||
Factory.CodeTransition(VBSymbolType.RazorCommentTransition)),
|
||||
Factory.Code(" Then End If").AsStatement().Accepts(AcceptedCharacters.None)),
|
||||
Factory.EmptyHtml()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BlockCommentInExplicitExpressionIsHandledCorrectly()
|
||||
{
|
||||
ParseDocumentTest(@"@(1 + @*bar*@ 1)",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("(").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code(@"1 + ").AsExpression(),
|
||||
new CommentBlock(
|
||||
Factory.CodeTransition(VBSymbolType.RazorCommentTransition),
|
||||
Factory.MetaCode("*", VBSymbolType.RazorCommentStar).Accepts(AcceptedCharacters.None),
|
||||
Factory.Comment("bar", VBSymbolType.RazorComment),
|
||||
Factory.MetaCode("*", VBSymbolType.RazorCommentStar).Accepts(AcceptedCharacters.None),
|
||||
Factory.CodeTransition(VBSymbolType.RazorCommentTransition)
|
||||
),
|
||||
Factory.Code(" 1").AsExpression(),
|
||||
Factory.MetaCode(")").Accepts(AcceptedCharacters.None)
|
||||
),
|
||||
Factory.EmptyHtml()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNet.Razor.Parser;
|
||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||
using Microsoft.AspNet.Razor.Test.Framework;
|
||||
using Microsoft.TestCommon;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Test.Parser.VB
|
||||
{
|
||||
public class VBImplicitExpressionTest : VBHtmlCodeParserTestBase
|
||||
{
|
||||
[Fact]
|
||||
public void VB_Simple_ImplicitExpression()
|
||||
{
|
||||
ParseBlockTest("@foo not-part-of-the-block",
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("foo")
|
||||
.AsImplicitExpression(VBCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VB_ImplicitExpression_With_Keyword_At_Start()
|
||||
{
|
||||
ParseBlockTest("@Partial",
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("Partial")
|
||||
.AsImplicitExpression(VBCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VB_ImplicitExpression_With_Keyword_In_Body()
|
||||
{
|
||||
ParseBlockTest("@Html.Partial",
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("Html.Partial")
|
||||
.AsImplicitExpression(VBCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VB_ImplicitExpression_With_MethodCallOrArrayIndex()
|
||||
{
|
||||
ParseBlockTest("@foo(42) not-part-of-the-block",
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("foo(42)")
|
||||
.AsImplicitExpression(VBCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VB_ImplicitExpression_Terminates_If_Trailing_Dot_Not_Followed_By_Valid_Token()
|
||||
{
|
||||
ParseBlockTest("@foo(42). ",
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("foo(42)")
|
||||
.AsImplicitExpression(VBCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VB_ImplicitExpression_Supports_Complex_Expressions()
|
||||
{
|
||||
ParseBlockTest("@foo(42).bar(Biz.Boz / 42 * 8)(1).Burf not part of the block",
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition()
|
||||
.Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("foo(42).bar(Biz.Boz / 42 * 8)(1).Burf")
|
||||
.AsImplicitExpression(VBCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.AspNet.Razor.Editor;
|
||||
using Microsoft.AspNet.Razor.Generator;
|
||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||
using Microsoft.AspNet.Razor.Test.Framework;
|
||||
using Microsoft.TestCommon;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Test.Parser.VB
|
||||
{
|
||||
public class VBLayoutDirectiveTest : VBHtmlCodeParserTestBase
|
||||
{
|
||||
[Theory]
|
||||
[InlineData("layout")]
|
||||
[InlineData("Layout")]
|
||||
[InlineData("LAYOUT")]
|
||||
[InlineData("layOut")]
|
||||
[InlineData("LayOut")]
|
||||
[InlineData("LaYoUt")]
|
||||
[InlineData("lAyOuT")]
|
||||
public void LayoutDirectiveSupportsAnyCasingOfKeyword(string keyword)
|
||||
{
|
||||
ParseBlockTest("@" + keyword,
|
||||
new DirectiveBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode(keyword)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void LayoutDirectiveAcceptsAllTextToEndOfLine()
|
||||
{
|
||||
ParseBlockTest("@Layout Foo Bar Baz",
|
||||
new DirectiveBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("Layout ").Accepts(AcceptedCharacters.None),
|
||||
Factory.MetaCode("Foo Bar Baz")
|
||||
.With(new SetLayoutCodeGenerator("Foo Bar Baz"))
|
||||
.WithEditorHints(EditorHints.VirtualPath | EditorHints.LayoutPage)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void LayoutDirectiveAcceptsAnyIfNoWhitespaceFollowingLayoutKeyword()
|
||||
{
|
||||
ParseBlockTest("@Layout",
|
||||
new DirectiveBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("Layout")
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void LayoutDirectiveOutputsMarkerSpanIfAnyWhitespaceAfterLayoutKeyword()
|
||||
{
|
||||
ParseBlockTest("@Layout ",
|
||||
new DirectiveBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("Layout ").Accepts(AcceptedCharacters.None),
|
||||
Factory.EmptyVB()
|
||||
.AsMetaCode()
|
||||
.With(new SetLayoutCodeGenerator(String.Empty))
|
||||
.WithEditorHints(EditorHints.VirtualPath | EditorHints.LayoutPage)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void LayoutDirectiveAcceptsTrailingNewlineButDoesNotIncludeItInLayoutPath()
|
||||
{
|
||||
ParseBlockTest("@Layout Foo" + Environment.NewLine,
|
||||
new DirectiveBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("Layout ").Accepts(AcceptedCharacters.None),
|
||||
Factory.MetaCode("Foo\r\n")
|
||||
.With(new SetLayoutCodeGenerator("Foo"))
|
||||
.Accepts(AcceptedCharacters.None)
|
||||
.WithEditorHints(EditorHints.VirtualPath | EditorHints.LayoutPage)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,170 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||
using Microsoft.AspNet.Razor.Test.Framework;
|
||||
using Microsoft.AspNet.Razor.Tokenizer.Symbols;
|
||||
using Microsoft.TestCommon;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Test.Parser.VB
|
||||
{
|
||||
public class VBNestedStatementsTest : VBHtmlCodeParserTestBase
|
||||
{
|
||||
[Fact]
|
||||
public void VB_Nested_If_Statement()
|
||||
{
|
||||
ParseBlockTest("@If True Then" + Environment.NewLine
|
||||
+ " If False Then" + Environment.NewLine
|
||||
+ " End If" + Environment.NewLine
|
||||
+ "End If",
|
||||
new StatementBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("If True Then\r\n If False Then\r\n End If\r\nEnd If")
|
||||
.AsStatement()
|
||||
.Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VB_Nested_Do_Statement()
|
||||
{
|
||||
ParseBlockTest("@Do While True" + Environment.NewLine
|
||||
+ " Do" + Environment.NewLine
|
||||
+ " Loop Until False" + Environment.NewLine
|
||||
+ "Loop",
|
||||
new StatementBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("Do While True\r\n Do\r\n Loop Until False\r\nLoop")
|
||||
.AsStatement()
|
||||
.Accepts(AcceptedCharacters.AnyExceptNewline)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VB_Nested_Markup_Statement_In_If()
|
||||
{
|
||||
ParseBlockTest("@If True Then" + Environment.NewLine
|
||||
+ " @<p>Tag</p>" + Environment.NewLine
|
||||
+ "End If",
|
||||
new StatementBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("If True Then\r\n")
|
||||
.AsStatement(),
|
||||
new MarkupBlock(
|
||||
Factory.Markup(" "),
|
||||
Factory.MarkupTransition(),
|
||||
Factory.Markup("<p>Tag</p>\r\n")
|
||||
.Accepts(AcceptedCharacters.None)),
|
||||
Factory.Code("End If")
|
||||
.AsStatement()
|
||||
.Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VB_Nested_Markup_Statement_In_Code()
|
||||
{
|
||||
ParseBlockTest("@Code" + Environment.NewLine
|
||||
+ " Foo()" + Environment.NewLine
|
||||
+ " @<p>Tag</p>" + Environment.NewLine
|
||||
+ " Bar()" + Environment.NewLine
|
||||
+ "End Code",
|
||||
new StatementBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("Code")
|
||||
.Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("\r\n Foo()\r\n")
|
||||
.AsStatement(),
|
||||
new MarkupBlock(
|
||||
Factory.Markup(" "),
|
||||
Factory.MarkupTransition(),
|
||||
Factory.Markup("<p>Tag</p>\r\n")
|
||||
.Accepts(AcceptedCharacters.None)),
|
||||
Factory.Code(" Bar()\r\n")
|
||||
.AsStatement(),
|
||||
Factory.MetaCode("End Code")
|
||||
.Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VB_Nested_Markup_Statement_In_Do()
|
||||
{
|
||||
ParseBlockTest("@Do" + Environment.NewLine
|
||||
+ " @<p>Tag</p>" + Environment.NewLine
|
||||
+ "Loop While True",
|
||||
new StatementBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("Do\r\n")
|
||||
.AsStatement(),
|
||||
new MarkupBlock(
|
||||
Factory.Markup(" "),
|
||||
Factory.MarkupTransition(),
|
||||
Factory.Markup("<p>Tag</p>\r\n")
|
||||
.Accepts(AcceptedCharacters.None)),
|
||||
Factory.Code("Loop While True")
|
||||
.AsStatement()
|
||||
.Accepts(AcceptedCharacters.AnyExceptNewline)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VB_Nested_Single_Line_Markup_Statement_In_Do()
|
||||
{
|
||||
ParseBlockTest("@Do" + Environment.NewLine
|
||||
+ " @:<p>Tag" + Environment.NewLine
|
||||
+ "Loop While True",
|
||||
new StatementBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("Do\r\n")
|
||||
.AsStatement(),
|
||||
new MarkupBlock(
|
||||
Factory.Markup(" "),
|
||||
Factory.MarkupTransition(),
|
||||
Factory.MetaMarkup(":", HtmlSymbolType.Colon),
|
||||
Factory.Markup("<p>Tag\r\n")
|
||||
.Accepts(AcceptedCharacters.None)),
|
||||
Factory.Code("Loop While True")
|
||||
.AsStatement()
|
||||
.Accepts(AcceptedCharacters.AnyExceptNewline)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VB_Nested_Implicit_Expression_In_If()
|
||||
{
|
||||
ParseBlockTest("@If True Then" + Environment.NewLine
|
||||
+ " @Foo.Bar" + Environment.NewLine
|
||||
+ "End If",
|
||||
new StatementBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("If True Then\r\n ")
|
||||
.AsStatement(),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("Foo.Bar")
|
||||
.AsExpression()
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
Factory.Code("\r\nEnd If")
|
||||
.AsStatement()
|
||||
.Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VB_Nested_Explicit_Expression_In_If()
|
||||
{
|
||||
ParseBlockTest("@If True Then" + Environment.NewLine
|
||||
+ " @(Foo.Bar + 42)" + Environment.NewLine
|
||||
+ "End If",
|
||||
new StatementBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("If True Then\r\n ")
|
||||
.AsStatement(),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("(")
|
||||
.Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("Foo.Bar + 42")
|
||||
.AsExpression(),
|
||||
Factory.MetaCode(")")
|
||||
.Accepts(AcceptedCharacters.None)),
|
||||
Factory.Code("\r\nEnd If")
|
||||
.AsStatement()
|
||||
.Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,175 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.AspNet.Razor.Parser;
|
||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||
using Microsoft.AspNet.Razor.Resources;
|
||||
using Microsoft.AspNet.Razor.Test.Framework;
|
||||
using Microsoft.AspNet.Razor.Tokenizer.Symbols;
|
||||
using Microsoft.TestCommon;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Test.Parser.VB
|
||||
{
|
||||
public class VBRazorCommentsTest : VBHtmlMarkupParserTestBase
|
||||
{
|
||||
[Fact]
|
||||
public void UnterminatedRazorComment()
|
||||
{
|
||||
ParseDocumentTest("@*",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new CommentBlock(
|
||||
Factory.MarkupTransition(HtmlSymbolType.RazorCommentTransition)
|
||||
.Accepts(AcceptedCharacters.None),
|
||||
Factory.MetaMarkup("*", HtmlSymbolType.RazorCommentStar)
|
||||
.Accepts(AcceptedCharacters.None),
|
||||
Factory.Span(SpanKind.Comment, new HtmlSymbol(
|
||||
Factory.LocationTracker.CurrentLocation,
|
||||
String.Empty,
|
||||
HtmlSymbolType.Unknown))
|
||||
.Accepts(AcceptedCharacters.Any))),
|
||||
new RazorError(RazorResources.ParseError_RazorComment_Not_Terminated, 0, 0, 0));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EmptyRazorComment()
|
||||
{
|
||||
ParseDocumentTest("@**@",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new CommentBlock(
|
||||
Factory.MarkupTransition(HtmlSymbolType.RazorCommentTransition)
|
||||
.Accepts(AcceptedCharacters.None),
|
||||
Factory.MetaMarkup("*", HtmlSymbolType.RazorCommentStar)
|
||||
.Accepts(AcceptedCharacters.None),
|
||||
Factory.Span(SpanKind.Comment, new HtmlSymbol(
|
||||
Factory.LocationTracker.CurrentLocation,
|
||||
String.Empty,
|
||||
HtmlSymbolType.Unknown))
|
||||
.Accepts(AcceptedCharacters.Any),
|
||||
Factory.MetaMarkup("*", HtmlSymbolType.RazorCommentStar)
|
||||
.Accepts(AcceptedCharacters.None),
|
||||
Factory.MarkupTransition(HtmlSymbolType.RazorCommentTransition)
|
||||
.Accepts(AcceptedCharacters.None)),
|
||||
Factory.EmptyHtml()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RazorCommentInImplicitExpressionMethodCall()
|
||||
{
|
||||
ParseDocumentTest(@"@foo(@**@",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("foo(")
|
||||
.AsImplicitExpression(VBCodeParser.DefaultKeywords),
|
||||
new CommentBlock(
|
||||
Factory.CodeTransition(VBSymbolType.RazorCommentTransition)
|
||||
.Accepts(AcceptedCharacters.None),
|
||||
Factory.MetaCode("*", VBSymbolType.RazorCommentStar)
|
||||
.Accepts(AcceptedCharacters.None),
|
||||
Factory.Span(SpanKind.Comment, new VBSymbol(
|
||||
Factory.LocationTracker.CurrentLocation,
|
||||
String.Empty,
|
||||
VBSymbolType.Unknown))
|
||||
.Accepts(AcceptedCharacters.Any),
|
||||
Factory.MetaCode("*", VBSymbolType.RazorCommentStar)
|
||||
.Accepts(AcceptedCharacters.None),
|
||||
Factory.CodeTransition(VBSymbolType.RazorCommentTransition)
|
||||
.Accepts(AcceptedCharacters.None)),
|
||||
Factory.EmptyVB()
|
||||
.AsImplicitExpression(VBCodeParser.DefaultKeywords))),
|
||||
new RazorError(
|
||||
String.Format(RazorResources.ParseError_Expected_CloseBracket_Before_EOF, "(", ")"),
|
||||
4, 0, 4));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void UnterminatedRazorCommentInImplicitExpressionMethodCall()
|
||||
{
|
||||
ParseDocumentTest("@foo(@*",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("foo(")
|
||||
.AsImplicitExpression(VBCodeParser.DefaultKeywords),
|
||||
new CommentBlock(
|
||||
Factory.CodeTransition(VBSymbolType.RazorCommentTransition)
|
||||
.Accepts(AcceptedCharacters.None),
|
||||
Factory.MetaCode("*", VBSymbolType.RazorCommentStar)
|
||||
.Accepts(AcceptedCharacters.None),
|
||||
Factory.Span(SpanKind.Comment, new VBSymbol(
|
||||
Factory.LocationTracker.CurrentLocation,
|
||||
String.Empty,
|
||||
VBSymbolType.Unknown))
|
||||
.Accepts(AcceptedCharacters.Any)))),
|
||||
new RazorError(RazorResources.ParseError_RazorComment_Not_Terminated, 5, 0, 5),
|
||||
new RazorError(String.Format(RazorResources.ParseError_Expected_CloseBracket_Before_EOF, "(", ")"), 4, 0, 4));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RazorCommentInVerbatimBlock()
|
||||
{
|
||||
ParseDocumentTest("@Code" + Environment.NewLine
|
||||
+ " @<text" + Environment.NewLine
|
||||
+ " @**@" + Environment.NewLine
|
||||
+ "End Code",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new StatementBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("Code").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("\r\n").AsStatement(),
|
||||
new MarkupBlock(
|
||||
Factory.Markup(" "),
|
||||
Factory.MarkupTransition("@"),
|
||||
Factory.MarkupTransition("<text").Accepts(AcceptedCharacters.Any),
|
||||
Factory.Markup("\r\n "),
|
||||
new CommentBlock(
|
||||
Factory.MarkupTransition(HtmlSymbolType.RazorCommentTransition)
|
||||
.Accepts(AcceptedCharacters.None),
|
||||
Factory.MetaMarkup("*", HtmlSymbolType.RazorCommentStar)
|
||||
.Accepts(AcceptedCharacters.None),
|
||||
Factory.Span(SpanKind.Comment, new HtmlSymbol(
|
||||
Factory.LocationTracker.CurrentLocation,
|
||||
String.Empty,
|
||||
HtmlSymbolType.Unknown))
|
||||
.Accepts(AcceptedCharacters.Any),
|
||||
Factory.MetaMarkup("*", HtmlSymbolType.RazorCommentStar)
|
||||
.Accepts(AcceptedCharacters.None),
|
||||
Factory.MarkupTransition(HtmlSymbolType.RazorCommentTransition)
|
||||
.Accepts(AcceptedCharacters.None)),
|
||||
Factory.Markup("\r\nEnd Code")))),
|
||||
new RazorError(RazorResources.ParseError_TextTagCannotContainAttributes, 12, 1, 5),
|
||||
new RazorError(String.Format(RazorResources.ParseError_MissingEndTag, "text"), 12, 1, 5),
|
||||
new RazorError(String.Format(RazorResources.ParseError_BlockNotTerminated, SyntaxConstants.VB.CodeKeyword, SyntaxConstants.VB.EndCodeKeyword), 1, 0, 1));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void UnterminatedRazorCommentInVerbatimBlock()
|
||||
{
|
||||
ParseDocumentTest("@Code" + Environment.NewLine
|
||||
+ "@*",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new StatementBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("Code").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("\r\n")
|
||||
.AsStatement(),
|
||||
new CommentBlock(
|
||||
Factory.CodeTransition(VBSymbolType.RazorCommentTransition)
|
||||
.Accepts(AcceptedCharacters.None),
|
||||
Factory.MetaCode("*", VBSymbolType.RazorCommentStar)
|
||||
.Accepts(AcceptedCharacters.None),
|
||||
Factory.Span(SpanKind.Comment, new VBSymbol(Factory.LocationTracker.CurrentLocation,
|
||||
String.Empty,
|
||||
VBSymbolType.Unknown))
|
||||
.Accepts(AcceptedCharacters.Any)))),
|
||||
new RazorError(RazorResources.ParseError_RazorComment_Not_Terminated, 7, 1, 0),
|
||||
new RazorError(String.Format(RazorResources.ParseError_BlockNotTerminated, SyntaxConstants.VB.CodeKeyword, SyntaxConstants.VB.EndCodeKeyword), 1, 0, 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||
using Microsoft.AspNet.Razor.Resources;
|
||||
using Microsoft.AspNet.Razor.Test.Framework;
|
||||
using Microsoft.AspNet.Razor.Text;
|
||||
using Microsoft.TestCommon;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Test.Parser.VB
|
||||
{
|
||||
public class VBReservedWordsTest : VBHtmlCodeParserTestBase
|
||||
{
|
||||
[Theory]
|
||||
[InlineData("Namespace")]
|
||||
[InlineData("Class")]
|
||||
[InlineData("NAMESPACE")]
|
||||
[InlineData("CLASS")]
|
||||
[InlineData("NameSpace")]
|
||||
[InlineData("nameSpace")]
|
||||
private void ReservedWords(string word)
|
||||
{
|
||||
ParseBlockTest(word,
|
||||
new DirectiveBlock(
|
||||
Factory.MetaCode(word).Accepts(AcceptedCharacters.None)),
|
||||
new RazorError(
|
||||
String.Format(RazorResources.ParseError_ReservedWord, word),
|
||||
SourceLocation.Zero));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,277 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.AspNet.Razor.Generator;
|
||||
using Microsoft.AspNet.Razor.Parser;
|
||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||
using Microsoft.AspNet.Razor.Resources;
|
||||
using Microsoft.AspNet.Razor.Test.Framework;
|
||||
using Microsoft.TestCommon;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Test.Parser.VB
|
||||
{
|
||||
public class VBSectionTest : VBHtmlMarkupParserTestBase
|
||||
{
|
||||
[Fact]
|
||||
public void ParseSectionBlockCapturesNewlineImmediatelyFollowing()
|
||||
{
|
||||
ParseDocumentTest("@Section" + Environment.NewLine,
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new SectionBlock(new SectionCodeGenerator(String.Empty),
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("Section\r\n"),
|
||||
new MarkupBlock())),
|
||||
new RazorError(
|
||||
String.Format(
|
||||
RazorResources.ParseError_Unexpected_Character_At_Section_Name_Start,
|
||||
RazorResources.ErrorComponent_EndOfFile),
|
||||
10, 1, 0),
|
||||
new RazorError(
|
||||
String.Format(
|
||||
RazorResources.ParseError_BlockNotTerminated,
|
||||
"Section", "End Section"),
|
||||
1, 0, 1));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseSectionRequiresNameBeOnSameLineAsSectionKeyword()
|
||||
{
|
||||
ParseDocumentTest("@Section " + Environment.NewLine
|
||||
+ "Foo" + Environment.NewLine
|
||||
+ " <p>Body</p>" + Environment.NewLine
|
||||
+ "End Section",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new SectionBlock(new SectionCodeGenerator(String.Empty),
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("Section "),
|
||||
new MarkupBlock(
|
||||
Factory.Markup("\r\nFoo\r\n <p>Body</p>\r\n")),
|
||||
Factory.MetaCode("End Section").Accepts(AcceptedCharacters.None)),
|
||||
Factory.EmptyHtml()),
|
||||
new RazorError(
|
||||
String.Format(
|
||||
RazorResources.ParseError_Unexpected_Character_At_Section_Name_Start,
|
||||
RazorResources.ErrorComponent_Newline),
|
||||
9, 0, 9));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseSectionAllowsNameToBeOnDifferentLineAsSectionKeywordIfUnderscoresUsed()
|
||||
{
|
||||
ParseDocumentTest("@Section _" + Environment.NewLine
|
||||
+ "_" + Environment.NewLine
|
||||
+ "Foo" + Environment.NewLine
|
||||
+ " <p>Body</p>" + Environment.NewLine
|
||||
+ "End Section",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new SectionBlock(new SectionCodeGenerator("Foo"),
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("Section _\r\n_\r\nFoo"),
|
||||
new MarkupBlock(
|
||||
Factory.Markup("\r\n <p>Body</p>\r\n")),
|
||||
Factory.MetaCode("End Section").Accepts(AcceptedCharacters.None)),
|
||||
Factory.EmptyHtml()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseSectionReportsErrorAndTerminatesSectionBlockIfKeywordNotFollowedByIdentifierStartCharacter()
|
||||
{
|
||||
ParseDocumentTest("@Section 9" + Environment.NewLine
|
||||
+ " <p>Foo</p>" + Environment.NewLine
|
||||
+ "End Section",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new SectionBlock(new SectionCodeGenerator(String.Empty),
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("Section "),
|
||||
new MarkupBlock(
|
||||
Factory.Markup("9\r\n <p>Foo</p>\r\n")),
|
||||
Factory.MetaCode("End Section").Accepts(AcceptedCharacters.None)),
|
||||
Factory.EmptyHtml()),
|
||||
new RazorError(
|
||||
String.Format(
|
||||
RazorResources.ParseError_Unexpected_Character_At_Section_Name_Start,
|
||||
String.Format(RazorResources.ErrorComponent_Character, "9")),
|
||||
9, 0, 9));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParserOutputsErrorOnNestedSections()
|
||||
{
|
||||
ParseDocumentTest("@Section foo" + Environment.NewLine
|
||||
+ " @Section bar" + Environment.NewLine
|
||||
+ " <p>Foo</p>" + Environment.NewLine
|
||||
+ " End Section" + Environment.NewLine
|
||||
+ "End Section",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new SectionBlock(new SectionCodeGenerator("foo"),
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("Section foo"),
|
||||
new MarkupBlock(
|
||||
Factory.Markup("\r\n"),
|
||||
new SectionBlock(new SectionCodeGenerator("bar"),
|
||||
Factory.Code(" ").AsStatement(),
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("Section bar"),
|
||||
new MarkupBlock(
|
||||
Factory.Markup("\r\n <p>Foo</p>\r\n ")),
|
||||
Factory.MetaCode("End Section").Accepts(AcceptedCharacters.None)),
|
||||
Factory.Markup("\r\n")),
|
||||
Factory.MetaCode("End Section").Accepts(AcceptedCharacters.None)),
|
||||
Factory.EmptyHtml()),
|
||||
new RazorError(
|
||||
String.Format(
|
||||
RazorResources.ParseError_Sections_Cannot_Be_Nested,
|
||||
RazorResources.SectionExample_VB),
|
||||
26, 1, 12));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseSectionHandlesEOFAfterIdentifier()
|
||||
{
|
||||
ParseDocumentTest("@Section foo",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new SectionBlock(new SectionCodeGenerator("foo"),
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("Section foo")
|
||||
.AutoCompleteWith(SyntaxConstants.VB.EndSectionKeyword),
|
||||
new MarkupBlock())),
|
||||
new RazorError(
|
||||
String.Format(
|
||||
RazorResources.ParseError_BlockNotTerminated,
|
||||
"Section", "End Section"),
|
||||
1, 0, 1));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseSectionHandlesUnterminatedSection()
|
||||
{
|
||||
ParseDocumentTest("@Section foo" + Environment.NewLine
|
||||
+ " <p>Foo</p>",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new SectionBlock(new SectionCodeGenerator("foo"),
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("Section foo")
|
||||
.AutoCompleteWith(SyntaxConstants.VB.EndSectionKeyword),
|
||||
new MarkupBlock(
|
||||
Factory.Markup("\r\n <p>Foo</p>")))),
|
||||
new RazorError(
|
||||
String.Format(
|
||||
RazorResources.ParseError_BlockNotTerminated,
|
||||
"Section", "End Section"),
|
||||
1, 0, 1));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseDocumentParsesNamedSectionCorrectly()
|
||||
{
|
||||
ParseDocumentTest("@Section foo" + Environment.NewLine
|
||||
+ " <p>Foo</p>" + Environment.NewLine
|
||||
+ "End Section",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new SectionBlock(new SectionCodeGenerator("foo"),
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("Section foo"),
|
||||
new MarkupBlock(
|
||||
Factory.Markup("\r\n <p>Foo</p>\r\n")),
|
||||
Factory.MetaCode("End Section").Accepts(AcceptedCharacters.None)),
|
||||
Factory.EmptyHtml()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseSectionTerminatesOnFirstEndSection()
|
||||
{
|
||||
ParseDocumentTest("@Section foo" + Environment.NewLine
|
||||
+ " <p>End Section</p>",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new SectionBlock(new SectionCodeGenerator("foo"),
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("Section foo"),
|
||||
new MarkupBlock(
|
||||
Factory.Markup("\r\n <p>")),
|
||||
Factory.MetaCode("End Section").Accepts(AcceptedCharacters.None)),
|
||||
Factory.Markup("</p>")));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseSectionAllowsEndSectionInVBExpression()
|
||||
{
|
||||
ParseDocumentTest("@Section foo" + Environment.NewLine
|
||||
+ " I really want to render the word @(\"End Section\"), so this is how I do it" + Environment.NewLine
|
||||
+ "End Section",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new SectionBlock(new SectionCodeGenerator("foo"),
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("Section foo"),
|
||||
new MarkupBlock(
|
||||
Factory.Markup("\r\n I really want to render the word "),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("(").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("\"End Section\"").AsExpression(),
|
||||
Factory.MetaCode(")").Accepts(AcceptedCharacters.None)),
|
||||
Factory.Markup(", so this is how I do it\r\n")),
|
||||
Factory.MetaCode("End Section").Accepts(AcceptedCharacters.None)),
|
||||
Factory.EmptyHtml()));
|
||||
}
|
||||
|
||||
// These are tests that are normally in HtmlToCodeSwitchTest, but we want to verify them for VB
|
||||
// since VB has slightly different section terminating behavior which follow slightly different
|
||||
// code paths
|
||||
|
||||
[Fact]
|
||||
public void SectionBodyTreatsTwoAtSignsAsEscapeSequence()
|
||||
{
|
||||
ParseDocumentTest("@Section Foo" + Environment.NewLine
|
||||
+ " <foo>@@bar</foo>" + Environment.NewLine
|
||||
+ "End Section",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new SectionBlock(new SectionCodeGenerator("Foo"),
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("Section Foo").AutoCompleteWith(null),
|
||||
new MarkupBlock(
|
||||
Factory.Markup("\r\n <foo>"),
|
||||
Factory.Markup("@").Hidden(),
|
||||
Factory.Markup("@bar</foo>\r\n")),
|
||||
Factory.MetaCode("End Section").Accepts(AcceptedCharacters.None)),
|
||||
Factory.EmptyHtml()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SectionBodyTreatsPairsOfAtSignsAsEscapeSequence()
|
||||
{
|
||||
ParseDocumentTest("@Section Foo" + Environment.NewLine
|
||||
+ " <foo>@@@@@bar</foo>" + Environment.NewLine
|
||||
+ "End Section",
|
||||
new MarkupBlock(
|
||||
Factory.EmptyHtml(),
|
||||
new SectionBlock(new SectionCodeGenerator("Foo"),
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("Section Foo").AutoCompleteWith(null),
|
||||
new MarkupBlock(
|
||||
Factory.Markup("\r\n <foo>"),
|
||||
Factory.Markup("@").Hidden(),
|
||||
Factory.Markup("@"),
|
||||
Factory.Markup("@").Hidden(),
|
||||
Factory.Markup("@"),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("bar")
|
||||
.AsImplicitExpression(VBCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
Factory.Markup("</foo>\r\n")),
|
||||
Factory.MetaCode("End Section").Accepts(AcceptedCharacters.None)),
|
||||
Factory.EmptyHtml()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,172 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.AspNet.Razor.Generator;
|
||||
using Microsoft.AspNet.Razor.Parser;
|
||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||
using Microsoft.AspNet.Razor.Resources;
|
||||
using Microsoft.AspNet.Razor.Test.Framework;
|
||||
using Microsoft.TestCommon;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Test.Parser.VB
|
||||
{
|
||||
public class VBSpecialKeywordsTest : VBHtmlCodeParserTestBase
|
||||
{
|
||||
[Fact]
|
||||
public void ParseInheritsStatementMarksInheritsSpanAsCanGrowIfMissingTrailingSpace()
|
||||
{
|
||||
ParseBlockTest("inherits",
|
||||
new DirectiveBlock(
|
||||
Factory.MetaCode("inherits")),
|
||||
new RazorError(
|
||||
RazorResources.ParseError_InheritsKeyword_Must_Be_Followed_By_TypeName,
|
||||
8, 0, 8));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InheritsBlockAcceptsMultipleGenericArguments()
|
||||
{
|
||||
ParseBlockTest("inherits Foo.Bar(Of Biz(Of Qux), String, Integer).Baz",
|
||||
new DirectiveBlock(
|
||||
Factory.MetaCode("inherits ").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("Foo.Bar(Of Biz(Of Qux), String, Integer).Baz")
|
||||
.AsBaseType("Foo.Bar(Of Biz(Of Qux), String, Integer).Baz")));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InheritsDirectiveSupportsVSTemplateTokens()
|
||||
{
|
||||
ParseBlockTest("@Inherits $rootnamespace$.MyBase",
|
||||
new DirectiveBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("Inherits ")
|
||||
.Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("$rootnamespace$.MyBase")
|
||||
.AsBaseType("$rootnamespace$.MyBase")));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InheritsBlockOutputsErrorIfInheritsNotFollowedByTypeButAcceptsEntireLineAsCode()
|
||||
{
|
||||
ParseBlockTest("inherits " + Environment.NewLine
|
||||
+ "foo",
|
||||
new DirectiveBlock(
|
||||
Factory.MetaCode("inherits ").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("\r\n").AsBaseType(String.Empty)),
|
||||
new RazorError(
|
||||
RazorResources.ParseError_InheritsKeyword_Must_Be_Followed_By_TypeName,
|
||||
8, 0, 8));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockShouldSupportNamespaceImports()
|
||||
{
|
||||
ParseBlockTest("Imports Foo.Bar.Baz.Biz.Boz",
|
||||
new DirectiveBlock(
|
||||
Factory.MetaCode("Imports Foo.Bar.Baz.Biz.Boz")
|
||||
.With(new AddImportCodeGenerator(
|
||||
ns: " Foo.Bar.Baz.Biz.Boz",
|
||||
namespaceKeywordLength: SyntaxConstants.VB.ImportsKeywordLength))));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockShowsErrorIfNamespaceNotOnSameLineAsImportsKeyword()
|
||||
{
|
||||
ParseBlockTest("Imports" + Environment.NewLine
|
||||
+ "Foo",
|
||||
new DirectiveBlock(
|
||||
Factory.MetaCode("Imports\r\n")
|
||||
.With(new AddImportCodeGenerator(
|
||||
ns: "\r\n",
|
||||
namespaceKeywordLength: SyntaxConstants.VB.ImportsKeywordLength))),
|
||||
new RazorError(
|
||||
RazorResources.ParseError_NamespaceOrTypeAliasExpected,
|
||||
7, 0, 7));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockShowsErrorIfTypeBeingAliasedNotOnSameLineAsImportsKeyword()
|
||||
{
|
||||
ParseBlockTest("Imports Foo =" + Environment.NewLine
|
||||
+ "System.Bar",
|
||||
new DirectiveBlock(
|
||||
Factory.MetaCode("Imports Foo =\r\n")
|
||||
.With(new AddImportCodeGenerator(
|
||||
ns: " Foo =\r\n",
|
||||
namespaceKeywordLength: SyntaxConstants.VB.ImportsKeywordLength))));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockShouldSupportTypeAliases()
|
||||
{
|
||||
ParseBlockTest("Imports Foo = Bar.Baz.Biz.Boz",
|
||||
new DirectiveBlock(
|
||||
Factory.MetaCode("Imports Foo = Bar.Baz.Biz.Boz")
|
||||
.With(new AddImportCodeGenerator(
|
||||
ns: " Foo = Bar.Baz.Biz.Boz",
|
||||
namespaceKeywordLength: SyntaxConstants.VB.ImportsKeywordLength))));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockThrowsErrorIfOptionIsNotFollowedByStrictOrExplicit()
|
||||
{
|
||||
ParseBlockTest("Option FizzBuzz On",
|
||||
new DirectiveBlock(
|
||||
Factory.MetaCode("Option FizzBuzz On")
|
||||
.With(new SetVBOptionCodeGenerator(optionName: null, value: true))),
|
||||
new RazorError(
|
||||
String.Format(RazorResources.ParseError_UnknownOption, "FizzBuzz"),
|
||||
7, 0, 7));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockThrowsErrorIfOptionStrictIsNotFollowedByOnOrOff()
|
||||
{
|
||||
ParseBlockTest("Option Strict Yes",
|
||||
new DirectiveBlock(
|
||||
Factory.MetaCode("Option Strict Yes")
|
||||
.With(SetVBOptionCodeGenerator.Strict(true))),
|
||||
new RazorError(
|
||||
String.Format(
|
||||
RazorResources.ParseError_InvalidOptionValue,
|
||||
"Strict", "Yes"),
|
||||
14, 0, 14));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockReadsToAfterOnKeywordIfOptionStrictBlock()
|
||||
{
|
||||
ParseBlockTest("Option Strict On Foo Bar Baz",
|
||||
new DirectiveBlock(
|
||||
Factory.MetaCode("Option Strict On")
|
||||
.With(SetVBOptionCodeGenerator.Strict(true))));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockReadsToAfterOffKeywordIfOptionStrictBlock()
|
||||
{
|
||||
ParseBlockTest("Option Strict Off Foo Bar Baz",
|
||||
new DirectiveBlock(
|
||||
Factory.MetaCode("Option Strict Off")
|
||||
.With(SetVBOptionCodeGenerator.Strict(false))));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockReadsToAfterOnKeywordIfOptionExplicitBlock()
|
||||
{
|
||||
ParseBlockTest("Option Explicit On Foo Bar Baz",
|
||||
new DirectiveBlock(
|
||||
Factory.MetaCode("Option Explicit On")
|
||||
.With(SetVBOptionCodeGenerator.Explicit(true))));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockReadsToAfterOffKeywordIfOptionExplicitBlock()
|
||||
{
|
||||
ParseBlockTest("Option Explicit Off Foo Bar Baz",
|
||||
new DirectiveBlock(
|
||||
Factory.MetaCode("Option Explicit Off")
|
||||
.With(SetVBOptionCodeGenerator.Explicit(false))));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,221 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.AspNet.Razor.Generator;
|
||||
using Microsoft.AspNet.Razor.Parser;
|
||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||
using Microsoft.AspNet.Razor.Test.Framework;
|
||||
using Microsoft.TestCommon;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Test.Parser.VB
|
||||
{
|
||||
public class VBStatementTest : VBHtmlCodeParserTestBase
|
||||
{
|
||||
[Fact]
|
||||
public void VB_Inherits_Statement()
|
||||
{
|
||||
ParseBlockTest("@Inherits System.Foo.Bar(Of Baz)",
|
||||
new DirectiveBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("Inherits ").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("System.Foo.Bar(Of Baz)")
|
||||
.AsBaseType("System.Foo.Bar(Of Baz)")));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InheritsDirectiveSupportsArrays()
|
||||
{
|
||||
ParseBlockTest("@Inherits System.String(())()",
|
||||
new DirectiveBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("Inherits ")
|
||||
.Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("System.String(())()")
|
||||
.AsBaseType("System.String(())()")));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InheritsDirectiveSupportsNestedGenerics()
|
||||
{
|
||||
ParseBlockTest("@Inherits System.Web.Mvc.WebViewPage(Of IEnumerable(Of MvcApplication2.Models.RegisterModel))",
|
||||
new DirectiveBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("Inherits ")
|
||||
.Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("System.Web.Mvc.WebViewPage(Of IEnumerable(Of MvcApplication2.Models.RegisterModel))")
|
||||
.AsBaseType("System.Web.Mvc.WebViewPage(Of IEnumerable(Of MvcApplication2.Models.RegisterModel))")));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InheritsDirectiveSupportsTypeKeywords()
|
||||
{
|
||||
ParseBlockTest("@Inherits String",
|
||||
new DirectiveBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("Inherits ").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("String").AsBaseType("String")));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VB_Option_Strict_Statement()
|
||||
{
|
||||
ParseBlockTest("@Option Strict Off",
|
||||
new DirectiveBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("Option Strict Off")
|
||||
.With(SetVBOptionCodeGenerator.Strict(false))));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VB_Option_Explicit_Statement()
|
||||
{
|
||||
ParseBlockTest("@Option Explicit Off",
|
||||
new DirectiveBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("Option Explicit Off")
|
||||
.With(SetVBOptionCodeGenerator.Explicit(false))));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VB_Imports_Statement()
|
||||
{
|
||||
ParseBlockTest("@Imports Biz = System.Foo.Bar(Of Boz.Baz(Of Qux))",
|
||||
new DirectiveBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode("Imports Biz = System.Foo.Bar(Of Boz.Baz(Of Qux))")
|
||||
.With(new AddImportCodeGenerator(
|
||||
ns: " Biz = System.Foo.Bar(Of Boz.Baz(Of Qux))",
|
||||
namespaceKeywordLength: SyntaxConstants.VB.ImportsKeywordLength))));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VB_Using_Statement()
|
||||
{
|
||||
ParseBlockTest("@Using foo as Bar" + Environment.NewLine
|
||||
+ " foo()" + Environment.NewLine
|
||||
+ "End Using",
|
||||
new StatementBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("Using foo as Bar\r\n foo()\r\nEnd Using")
|
||||
.AsStatement()
|
||||
.Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VB_Do_Loop_Statement()
|
||||
{
|
||||
ParseBlockTest("@Do" + Environment.NewLine
|
||||
+ " foo()" + Environment.NewLine
|
||||
+ "Loop While True",
|
||||
new StatementBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("Do\r\n foo()\r\nLoop While True")
|
||||
.AsStatement()
|
||||
.Accepts(AcceptedCharacters.AnyExceptNewline)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VB_While_Statement()
|
||||
{
|
||||
ParseBlockTest("@While True" + Environment.NewLine
|
||||
+ " foo()" + Environment.NewLine
|
||||
+ "End While",
|
||||
new StatementBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("While True\r\n foo()\r\nEnd While")
|
||||
.AsStatement()
|
||||
.Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VB_If_Statement()
|
||||
{
|
||||
ParseBlockTest("@If True Then" + Environment.NewLine
|
||||
+ " foo()" + Environment.NewLine
|
||||
+ "ElseIf False Then" + Environment.NewLine
|
||||
+ " bar()" + Environment.NewLine
|
||||
+ "Else" + Environment.NewLine
|
||||
+ " baz()" + Environment.NewLine
|
||||
+ "End If",
|
||||
new StatementBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("If True Then\r\n foo()\r\nElseIf False Then\r\n bar()\r\nElse\r\n baz()\r\nEnd If")
|
||||
.AsStatement()
|
||||
.Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VB_Select_Statement()
|
||||
{
|
||||
ParseBlockTest("@Select Case foo" + Environment.NewLine
|
||||
+ " Case 1" + Environment.NewLine
|
||||
+ " foo()" + Environment.NewLine
|
||||
+ " Case 2" + Environment.NewLine
|
||||
+ " bar()" + Environment.NewLine
|
||||
+ " Case Else" + Environment.NewLine
|
||||
+ " baz()" + Environment.NewLine
|
||||
+ "End Select",
|
||||
new StatementBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("Select Case foo\r\n Case 1\r\n foo()\r\n Case 2\r\n bar()\r\n Case Else\r\n baz()\r\nEnd Select")
|
||||
.AsStatement()
|
||||
.Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VB_For_Statement()
|
||||
{
|
||||
ParseBlockTest("@For Each foo In bar" + Environment.NewLine
|
||||
+ " baz()" + Environment.NewLine
|
||||
+ "Next",
|
||||
new StatementBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("For Each foo In bar\r\n baz()\r\nNext")
|
||||
.AsStatement()
|
||||
.Accepts(AcceptedCharacters.AnyExceptNewline)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VB_Try_Statement()
|
||||
{
|
||||
ParseBlockTest("@Try" + Environment.NewLine
|
||||
+ " foo()" + Environment.NewLine
|
||||
+ "Catch ex as Exception" + Environment.NewLine
|
||||
+ " bar()" + Environment.NewLine
|
||||
+ "Finally" + Environment.NewLine
|
||||
+ " baz()" + Environment.NewLine
|
||||
+ "End Try",
|
||||
new StatementBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("Try\r\n foo()\r\nCatch ex as Exception\r\n bar()\r\nFinally\r\n baz()\r\nEnd Try")
|
||||
.AsStatement()
|
||||
.Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VB_With_Statement()
|
||||
{
|
||||
ParseBlockTest("@With foo" + Environment.NewLine
|
||||
+ " .bar()" + Environment.NewLine
|
||||
+ "End With",
|
||||
new StatementBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("With foo\r\n .bar()\r\nEnd With")
|
||||
.AsStatement()
|
||||
.Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VB_SyncLock_Statement()
|
||||
{
|
||||
ParseBlockTest("@SyncLock foo" + Environment.NewLine
|
||||
+ " foo.bar()" + Environment.NewLine
|
||||
+ "End SyncLock",
|
||||
new StatementBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("SyncLock foo\r\n foo.bar()\r\nEnd SyncLock")
|
||||
.AsStatement()
|
||||
.Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,214 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.AspNet.Razor.Generator;
|
||||
using Microsoft.AspNet.Razor.Parser;
|
||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||
using Microsoft.AspNet.Razor.Resources;
|
||||
using Microsoft.AspNet.Razor.Test.Framework;
|
||||
using Microsoft.TestCommon;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Test.Parser.VB
|
||||
{
|
||||
public class VBTemplateTest : VBHtmlCodeParserTestBase
|
||||
{
|
||||
private const string TestTemplateCode = "@@<p>Foo #@item</p>";
|
||||
|
||||
private TemplateBlock TestTemplate()
|
||||
{
|
||||
return new TemplateBlock(new TemplateBlockCodeGenerator(),
|
||||
new MarkupBlock(
|
||||
Factory.MarkupTransition(),
|
||||
Factory.MetaMarkup("@"),
|
||||
Factory.Markup("<p>Foo #"),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("item")
|
||||
.AsImplicitExpression(VBCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
Factory.Markup("</p>").Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
|
||||
private const string TestNestedTemplateCode = "@@<p>Foo #@Html.Repeat(10,@@<p>@item</p>)</p>";
|
||||
|
||||
private TemplateBlock TestNestedTemplate()
|
||||
{
|
||||
return new TemplateBlock(new TemplateBlockCodeGenerator(),
|
||||
new MarkupBlock(
|
||||
Factory.MarkupTransition(),
|
||||
Factory.MetaMarkup("@"),
|
||||
Factory.Markup("<p>Foo #"),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("Html.Repeat(10,")
|
||||
.AsImplicitExpression(VBCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.Any),
|
||||
new TemplateBlock(new TemplateBlockCodeGenerator(),
|
||||
new MarkupBlock(
|
||||
Factory.MarkupTransition(),
|
||||
Factory.MetaMarkup("@"),
|
||||
Factory.Markup("<p>"),
|
||||
new ExpressionBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.Code("item")
|
||||
.AsImplicitExpression(VBCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
Factory.Markup("</p>").Accepts(AcceptedCharacters.None))),
|
||||
Factory.Code(")")
|
||||
.AsImplicitExpression(VBCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
Factory.Markup("</p>").Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockHandlesSimpleAnonymousSectionInExplicitExpressionParens()
|
||||
{
|
||||
ParseBlockTest("(Html.Repeat(10," + TestTemplateCode + "))",
|
||||
new ExpressionBlock(
|
||||
Factory.MetaCode("(").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("Html.Repeat(10,").AsExpression(),
|
||||
TestTemplate(),
|
||||
Factory.Code(")").AsExpression(),
|
||||
Factory.MetaCode(")").Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockHandlesSimpleAnonymousSectionInImplicitExpressionParens()
|
||||
{
|
||||
ParseBlockTest("Html.Repeat(10," + TestTemplateCode + ")",
|
||||
new ExpressionBlock(
|
||||
Factory.Code("Html.Repeat(10,").AsImplicitExpression(KeywordSet),
|
||||
TestTemplate(),
|
||||
Factory.Code(")").AsImplicitExpression(KeywordSet).Accepts(AcceptedCharacters.NonWhiteSpace)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockHandlesTwoAnonymousSectionsInImplicitExpressionParens()
|
||||
{
|
||||
ParseBlockTest("Html.Repeat(10," + TestTemplateCode + "," + TestTemplateCode + ")",
|
||||
new ExpressionBlock(
|
||||
Factory.Code("Html.Repeat(10,").AsImplicitExpression(KeywordSet),
|
||||
TestTemplate(),
|
||||
Factory.Code(",").AsImplicitExpression(KeywordSet),
|
||||
TestTemplate(),
|
||||
Factory.Code(")").AsImplicitExpression(KeywordSet).Accepts(AcceptedCharacters.NonWhiteSpace)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockProducesErrorButCorrectlyParsesNestedAnonymousSectionInImplicitExpressionParens()
|
||||
{
|
||||
ParseBlockTest("Html.Repeat(10," + TestNestedTemplateCode + ")",
|
||||
new ExpressionBlock(
|
||||
Factory.Code("Html.Repeat(10,").AsImplicitExpression(KeywordSet),
|
||||
TestNestedTemplate(),
|
||||
Factory.Code(")").AsImplicitExpression(KeywordSet).Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
GetNestedSectionError(41, 0, 41));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockHandlesSimpleAnonymousSectionInStatementWithinCodeBlock()
|
||||
{
|
||||
ParseBlockTest("For Each foo in Bar " + Environment.NewLine
|
||||
+ " Html.ExecuteTemplate(foo," + TestTemplateCode + ")" + Environment.NewLine
|
||||
+ "Next foo",
|
||||
new StatementBlock(
|
||||
Factory.Code("For Each foo in Bar \r\n Html.ExecuteTemplate(foo,")
|
||||
.AsStatement(),
|
||||
TestTemplate(),
|
||||
Factory.Code(")\r\nNext foo")
|
||||
.AsStatement()
|
||||
.Accepts(AcceptedCharacters.WhiteSpace | AcceptedCharacters.NonWhiteSpace)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockHandlesTwoAnonymousSectionsInStatementWithinCodeBlock()
|
||||
{
|
||||
ParseBlockTest("For Each foo in Bar " + Environment.NewLine
|
||||
+ " Html.ExecuteTemplate(foo," + TestTemplateCode + "," + TestTemplateCode + ")" + Environment.NewLine
|
||||
+ "Next foo",
|
||||
new StatementBlock(
|
||||
Factory.Code("For Each foo in Bar \r\n Html.ExecuteTemplate(foo,")
|
||||
.AsStatement(),
|
||||
TestTemplate(),
|
||||
Factory.Code(",").AsStatement(),
|
||||
TestTemplate(),
|
||||
Factory.Code(")\r\nNext foo")
|
||||
.AsStatement()
|
||||
.Accepts(AcceptedCharacters.WhiteSpace | AcceptedCharacters.NonWhiteSpace)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockProducesErrorButCorrectlyParsesNestedAnonymousSectionInStatementWithinCodeBlock()
|
||||
{
|
||||
ParseBlockTest("For Each foo in Bar " + Environment.NewLine
|
||||
+ " Html.ExecuteTemplate(foo," + TestNestedTemplateCode + ")" + Environment.NewLine
|
||||
+ "Next foo",
|
||||
new StatementBlock(
|
||||
Factory.Code("For Each foo in Bar \r\n Html.ExecuteTemplate(foo,")
|
||||
.AsStatement(),
|
||||
TestNestedTemplate(),
|
||||
Factory.Code(")\r\nNext foo")
|
||||
.AsStatement()
|
||||
.Accepts(AcceptedCharacters.WhiteSpace | AcceptedCharacters.NonWhiteSpace)),
|
||||
GetNestedSectionError(77, 1, 55));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockHandlesSimpleAnonymousSectionInStatementWithinStatementBlock()
|
||||
{
|
||||
ParseBlockTest("Code " + Environment.NewLine
|
||||
+ " Dim foo = bar" + Environment.NewLine
|
||||
+ " Html.ExecuteTemplate(foo," + TestTemplateCode + ")" + Environment.NewLine
|
||||
+ "End Code",
|
||||
new StatementBlock(
|
||||
Factory.MetaCode("Code").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code(" \r\n Dim foo = bar\r\n Html.ExecuteTemplate(foo,")
|
||||
.AsStatement(),
|
||||
TestTemplate(),
|
||||
Factory.Code(")\r\n").AsStatement(),
|
||||
Factory.MetaCode("End Code").Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockHandlessTwoAnonymousSectionsInStatementWithinStatementBlock()
|
||||
{
|
||||
ParseBlockTest("Code" + Environment.NewLine
|
||||
+ " Dim foo = bar" + Environment.NewLine
|
||||
+ " Html.ExecuteTemplate(foo," + TestTemplateCode + "," + TestTemplateCode + ")" + Environment.NewLine
|
||||
+ "End Code",
|
||||
new StatementBlock(
|
||||
Factory.MetaCode("Code").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("\r\n Dim foo = bar\r\n Html.ExecuteTemplate(foo,")
|
||||
.AsStatement(),
|
||||
TestTemplate(),
|
||||
Factory.Code(",").AsStatement(),
|
||||
TestTemplate(),
|
||||
Factory.Code(")\r\n").AsStatement(),
|
||||
Factory.MetaCode("End Code").Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockProducesErrorButCorrectlyParsesNestedAnonymousSectionInStatementWithinStatementBlock()
|
||||
{
|
||||
ParseBlockTest("Code" + Environment.NewLine
|
||||
+ " Dim foo = bar" + Environment.NewLine
|
||||
+ " Html.ExecuteTemplate(foo," + TestNestedTemplateCode + ")" + Environment.NewLine
|
||||
+ "End Code",
|
||||
new StatementBlock(
|
||||
Factory.MetaCode("Code").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("\r\n Dim foo = bar\r\n Html.ExecuteTemplate(foo,")
|
||||
.AsStatement(),
|
||||
TestNestedTemplate(),
|
||||
Factory.Code(")\r\n").AsStatement(),
|
||||
Factory.MetaCode("End Code").Accepts(AcceptedCharacters.None)),
|
||||
GetNestedSectionError(80, 2, 55));
|
||||
}
|
||||
|
||||
private static RazorError GetNestedSectionError(int absoluteIndex, int lineIndex, int characterIndex)
|
||||
{
|
||||
return new RazorError(
|
||||
RazorResources.ParseError_InlineMarkup_Blocks_Cannot_Be_Nested,
|
||||
absoluteIndex, lineIndex, characterIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,105 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.AspNet.Razor.Editor;
|
||||
using Microsoft.AspNet.Razor.Parser;
|
||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||
using Microsoft.AspNet.Razor.Test.Framework;
|
||||
using Microsoft.AspNet.Razor.Tokenizer.Symbols;
|
||||
using Microsoft.TestCommon;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Test.Parser.VB
|
||||
{
|
||||
public class VBToMarkupSwitchTest : VBHtmlCodeParserTestBase
|
||||
{
|
||||
[Fact]
|
||||
public void ParseBlockSwitchesToMarkupWhenAtSignFollowedByLessThanInStatementBlock()
|
||||
{
|
||||
ParseBlockTest("Code" + Environment.NewLine
|
||||
+ " If True Then" + Environment.NewLine
|
||||
+ " @<p>It's True!</p>" + Environment.NewLine
|
||||
+ " End If" + Environment.NewLine
|
||||
+ "End Code",
|
||||
new StatementBlock(
|
||||
Factory.MetaCode("Code").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("\r\n If True Then\r\n").AsStatement(),
|
||||
new MarkupBlock(
|
||||
Factory.Markup(" "),
|
||||
Factory.MarkupTransition(),
|
||||
Factory.Markup("<p>It's True!</p>\r\n").Accepts(AcceptedCharacters.None)),
|
||||
Factory.Code(" End If\r\n").AsStatement(),
|
||||
Factory.MetaCode("End Code").Accepts(AcceptedCharacters.None)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseBlockGivesWhiteSpacePreceedingMarkupBlockToCodeInDesignTimeMode()
|
||||
{
|
||||
ParseBlockTest("Code" + Environment.NewLine
|
||||
+ " @<p>Foo</p>" + Environment.NewLine
|
||||
+ "End Code",
|
||||
new StatementBlock(
|
||||
Factory.MetaCode("Code").Accepts(AcceptedCharacters.None),
|
||||
Factory.Code("\r\n ").AsStatement(),
|
||||
new MarkupBlock(
|
||||
Factory.MarkupTransition(),
|
||||
Factory.Markup("<p>Foo</p>").Accepts(AcceptedCharacters.None)),
|
||||
Factory.Code("\r\n").AsStatement(),
|
||||
Factory.MetaCode("End Code").Accepts(AcceptedCharacters.None)),
|
||||
designTimeParser: true);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("While", "End While", AcceptedCharacters.None)]
|
||||
[InlineData("If", "End If", AcceptedCharacters.None)]
|
||||
[InlineData("Select", "End Select", AcceptedCharacters.None)]
|
||||
[InlineData("For", "Next", AcceptedCharacters.WhiteSpace | AcceptedCharacters.NonWhiteSpace)]
|
||||
[InlineData("Try", "End Try", AcceptedCharacters.None)]
|
||||
[InlineData("With", "End With", AcceptedCharacters.None)]
|
||||
[InlineData("Using", "End Using", AcceptedCharacters.None)]
|
||||
public void SimpleMarkupSwitch(string keyword, string endSequence, AcceptedCharacters acceptedCharacters)
|
||||
{
|
||||
ParseBlockTest(keyword + Environment.NewLine
|
||||
+ " If True Then" + Environment.NewLine
|
||||
+ " @<p>It's True!</p>" + Environment.NewLine
|
||||
+ " End If" + Environment.NewLine
|
||||
+ endSequence,
|
||||
new StatementBlock(
|
||||
Factory.Code(keyword + "\r\n If True Then\r\n").AsStatement(),
|
||||
new MarkupBlock(
|
||||
Factory.Markup(" "),
|
||||
Factory.MarkupTransition(),
|
||||
Factory.Markup("<p>It's True!</p>\r\n").Accepts(AcceptedCharacters.None)),
|
||||
Factory.Code(" End If\r\n" + endSequence).AsStatement().Accepts(acceptedCharacters)));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("While", "End While", AcceptedCharacters.None)]
|
||||
[InlineData("If", "End If", AcceptedCharacters.None)]
|
||||
[InlineData("Select", "End Select", AcceptedCharacters.None)]
|
||||
[InlineData("For", "Next", AcceptedCharacters.WhiteSpace | AcceptedCharacters.NonWhiteSpace)]
|
||||
[InlineData("Try", "End Try", AcceptedCharacters.None)]
|
||||
[InlineData("With", "End With", AcceptedCharacters.None)]
|
||||
[InlineData("Using", "End Using", AcceptedCharacters.None)]
|
||||
public void SingleLineMarkupSwitch(string keyword, string endSequence, AcceptedCharacters acceptedCharacters)
|
||||
{
|
||||
ParseBlockTest(keyword + Environment.NewLine
|
||||
+ " If True Then" + Environment.NewLine
|
||||
+ " @:<p>It's True!</p>" + Environment.NewLine
|
||||
+ " This is code!" + Environment.NewLine
|
||||
+ " End If" + Environment.NewLine
|
||||
+ endSequence,
|
||||
new StatementBlock(
|
||||
Factory.Code(keyword + "\r\n If True Then\r\n").AsStatement(),
|
||||
new MarkupBlock(
|
||||
Factory.Markup(" "),
|
||||
Factory.MarkupTransition(),
|
||||
Factory.MetaMarkup(":", HtmlSymbolType.Colon),
|
||||
Factory.Markup("<p>It's True!</p>\r\n")
|
||||
.With(new SingleLineMarkupEditHandler(CSharpLanguageCharacteristics.Instance.TokenizeString))
|
||||
.Accepts(AcceptedCharacters.None)),
|
||||
Factory.Code(" This is code!\r\n End If\r\n" + endSequence)
|
||||
.AsStatement()
|
||||
.Accepts(acceptedCharacters)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNet.Razor.Parser;
|
||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||
using Microsoft.AspNet.Razor.Test.Framework;
|
||||
using Microsoft.TestCommon;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Test.Parser
|
||||
{
|
||||
public class WhitespaceRewriterTest
|
||||
{
|
||||
[Fact]
|
||||
public void Constructor_Requires_NonNull_SymbolConverter()
|
||||
{
|
||||
Assert.ThrowsArgumentNull(() => new WhiteSpaceRewriter(null), "markupSpanFactory");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Rewrite_Moves_Whitespace_Preceeding_ExpressionBlock_To_Parent_Block()
|
||||
{
|
||||
// Arrange
|
||||
var factory = SpanFactory.CreateCsHtml();
|
||||
Block start = new MarkupBlock(
|
||||
factory.Markup("test"),
|
||||
new ExpressionBlock(
|
||||
factory.Code(" ").AsExpression(),
|
||||
factory.CodeTransition(SyntaxConstants.TransitionString),
|
||||
factory.Code("foo").AsExpression()
|
||||
),
|
||||
factory.Markup("test")
|
||||
);
|
||||
WhiteSpaceRewriter rewriter = new WhiteSpaceRewriter(new HtmlMarkupParser().BuildSpan);
|
||||
|
||||
// Act
|
||||
Block actual = rewriter.Rewrite(start);
|
||||
|
||||
factory.Reset();
|
||||
|
||||
// Assert
|
||||
ParserTestBase.EvaluateParseTree(actual, new MarkupBlock(
|
||||
factory.Markup("test"),
|
||||
factory.Markup(" "),
|
||||
new ExpressionBlock(
|
||||
factory.CodeTransition(SyntaxConstants.TransitionString),
|
||||
factory.Code("foo").AsExpression()
|
||||
),
|
||||
factory.Markup("test")
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.TestCommon;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Test
|
||||
{
|
||||
public class RazorCodeLanguageTest
|
||||
{
|
||||
[Fact]
|
||||
public void ServicesPropertyContainsEntriesForCSharpCodeLanguageService()
|
||||
{
|
||||
// Assert
|
||||
Assert.Equal(2, RazorCodeLanguage.Languages.Count);
|
||||
Assert.IsType<CSharpRazorCodeLanguage>(RazorCodeLanguage.Languages["cshtml"]);
|
||||
Assert.IsType<VBRazorCodeLanguage>(RazorCodeLanguage.Languages["vbhtml"]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetServiceByExtensionReturnsEntryMatchingExtensionWithoutPreceedingDot()
|
||||
{
|
||||
Assert.IsType<CSharpRazorCodeLanguage>(RazorCodeLanguage.GetLanguageByExtension("cshtml"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetServiceByExtensionReturnsEntryMatchingExtensionWithPreceedingDot()
|
||||
{
|
||||
Assert.IsType<CSharpRazorCodeLanguage>(RazorCodeLanguage.GetLanguageByExtension(".cshtml"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetServiceByExtensionReturnsNullIfNoServiceForSpecifiedExtension()
|
||||
{
|
||||
Assert.Null(RazorCodeLanguage.GetLanguageByExtension("foobar"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MultipleCallsToGetServiceWithSameExtensionReturnSameObject()
|
||||
{
|
||||
// Arrange
|
||||
RazorCodeLanguage expected = RazorCodeLanguage.GetLanguageByExtension("cshtml");
|
||||
|
||||
// Act
|
||||
RazorCodeLanguage actual = RazorCodeLanguage.GetLanguageByExtension("cshtml");
|
||||
|
||||
// Assert
|
||||
Assert.Same(expected, actual);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Microsoft.TestCommon;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Test
|
||||
{
|
||||
public class RazorDirectiveAttributeTest
|
||||
{
|
||||
[Fact]
|
||||
public void ConstructorThrowsIfNameIsNullOrEmpty()
|
||||
{
|
||||
// Act and Assert
|
||||
Assert.ThrowsArgumentNullOrEmptyString(() => new RazorDirectiveAttribute(name: null, value: "blah"), "name");
|
||||
Assert.ThrowsArgumentNullOrEmptyString(() => new RazorDirectiveAttribute(name: "", value: "blah"), "name");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EnsureRazorDirectiveProperties()
|
||||
{
|
||||
// Arrange
|
||||
var attribute = (AttributeUsageAttribute)typeof(RazorDirectiveAttribute).GetCustomAttributes(typeof(AttributeUsageAttribute), inherit: false)
|
||||
.SingleOrDefault();
|
||||
|
||||
// Assert
|
||||
Assert.True(attribute.AllowMultiple);
|
||||
Assert.True(attribute.ValidOn == AttributeTargets.Class);
|
||||
Assert.True(attribute.Inherited);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EqualsAndGetHashCodeIgnoresCase()
|
||||
{
|
||||
// Arrange
|
||||
var attribute1 = new RazorDirectiveAttribute("foo", "bar");
|
||||
var attribute2 = new RazorDirectiveAttribute("fOo", "BAr");
|
||||
|
||||
// Act
|
||||
var hashCode1 = attribute1.GetHashCode();
|
||||
var hashCode2 = attribute2.GetHashCode();
|
||||
|
||||
// Assert
|
||||
Assert.Equal(attribute1, attribute2);
|
||||
Assert.Equal(hashCode1, hashCode2);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EqualsAndGetHashCodeDoNotThrowIfValueIsNullOrEmpty()
|
||||
{
|
||||
// Arrange
|
||||
var attribute1 = new RazorDirectiveAttribute("foo", null);
|
||||
var attribute2 = new RazorDirectiveAttribute("foo", "BAr");
|
||||
|
||||
// Act
|
||||
bool result = attribute1.Equals(attribute2);
|
||||
var hashCode = attribute1.GetHashCode();
|
||||
|
||||
// Assert
|
||||
Assert.False(result);
|
||||
// If we've got this far, GetHashCode did not throw
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EqualsAndGetHashCodeReturnDifferentValuesForNullAndEmpty()
|
||||
{
|
||||
// Arrange
|
||||
var attribute1 = new RazorDirectiveAttribute("foo", null);
|
||||
var attribute2 = new RazorDirectiveAttribute("foo", "");
|
||||
|
||||
// Act
|
||||
bool result = attribute1.Equals(attribute2);
|
||||
var hashCode1 = attribute1.GetHashCode();
|
||||
var hashCode2 = attribute2.GetHashCode();
|
||||
|
||||
// Assert
|
||||
Assert.False(result);
|
||||
Assert.NotEqual(hashCode1, hashCode2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,187 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using System.CodeDom;
|
||||
using Microsoft.AspNet.Razor.Generator;
|
||||
using Microsoft.AspNet.Razor.Parser;
|
||||
using Microsoft.TestCommon;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Test
|
||||
{
|
||||
public class RazorEngineHostTest
|
||||
{
|
||||
[Fact]
|
||||
public void ConstructorRequiresNonNullCodeLanguage()
|
||||
{
|
||||
Assert.ThrowsArgumentNull(() => new RazorEngineHost(null), "codeLanguage");
|
||||
Assert.ThrowsArgumentNull(() => new RazorEngineHost(null, () => new HtmlMarkupParser()), "codeLanguage");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ConstructorRequiresNonNullMarkupParser()
|
||||
{
|
||||
Assert.ThrowsArgumentNull(() => new RazorEngineHost(new CSharpRazorCodeLanguage(), null), "markupParserFactory");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ConstructorWithCodeLanguageSetsPropertiesAppropriately()
|
||||
{
|
||||
// Arrange
|
||||
RazorCodeLanguage language = new CSharpRazorCodeLanguage();
|
||||
|
||||
// Act
|
||||
RazorEngineHost host = new RazorEngineHost(language);
|
||||
|
||||
// Assert
|
||||
VerifyCommonDefaults(host);
|
||||
Assert.Same(language, host.CodeLanguage);
|
||||
Assert.IsType<HtmlMarkupParser>(host.CreateMarkupParser());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ConstructorWithCodeLanguageAndMarkupParserSetsPropertiesAppropriately()
|
||||
{
|
||||
// Arrange
|
||||
RazorCodeLanguage language = new CSharpRazorCodeLanguage();
|
||||
ParserBase expected = new HtmlMarkupParser();
|
||||
|
||||
// Act
|
||||
RazorEngineHost host = new RazorEngineHost(language, () => expected);
|
||||
|
||||
// Assert
|
||||
VerifyCommonDefaults(host);
|
||||
Assert.Same(language, host.CodeLanguage);
|
||||
Assert.Same(expected, host.CreateMarkupParser());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DecorateCodeParserRequiresNonNullCodeParser()
|
||||
{
|
||||
Assert.ThrowsArgumentNull(() => CreateHost().DecorateCodeParser(null), "incomingCodeParser");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DecorateMarkupParserRequiresNonNullMarkupParser()
|
||||
{
|
||||
Assert.ThrowsArgumentNull(() => CreateHost().DecorateMarkupParser(null), "incomingMarkupParser");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DecorateCodeGeneratorRequiresNonNullCodeGenerator()
|
||||
{
|
||||
Assert.ThrowsArgumentNull(() => CreateHost().DecorateCodeGenerator(null), "incomingCodeGenerator");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PostProcessGeneratedCodeRequiresNonNullCompileUnit()
|
||||
{
|
||||
Assert.ThrowsArgumentNull(() => CreateHost().PostProcessGeneratedCode(codeCompileUnit: null,
|
||||
generatedNamespace: new CodeNamespace(),
|
||||
generatedClass: new CodeTypeDeclaration(),
|
||||
executeMethod: new CodeMemberMethod()),
|
||||
"codeCompileUnit");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PostProcessGeneratedCodeRequiresNonNullGeneratedNamespace()
|
||||
{
|
||||
Assert.ThrowsArgumentNull(() => CreateHost().PostProcessGeneratedCode(codeCompileUnit: new CodeCompileUnit(),
|
||||
generatedNamespace: null,
|
||||
generatedClass: new CodeTypeDeclaration(),
|
||||
executeMethod: new CodeMemberMethod()),
|
||||
"generatedNamespace");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PostProcessGeneratedCodeRequiresNonNullGeneratedClass()
|
||||
{
|
||||
Assert.ThrowsArgumentNull(() => CreateHost().PostProcessGeneratedCode(codeCompileUnit: new CodeCompileUnit(),
|
||||
generatedNamespace: new CodeNamespace(),
|
||||
generatedClass: null,
|
||||
executeMethod: new CodeMemberMethod()),
|
||||
"generatedClass");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PostProcessGeneratedCodeRequiresNonNullExecuteMethod()
|
||||
{
|
||||
Assert.ThrowsArgumentNull(() => CreateHost().PostProcessGeneratedCode(codeCompileUnit: new CodeCompileUnit(),
|
||||
generatedNamespace: new CodeNamespace(),
|
||||
generatedClass: new CodeTypeDeclaration(),
|
||||
executeMethod: null),
|
||||
"executeMethod");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DecorateCodeParserDoesNotModifyIncomingParser()
|
||||
{
|
||||
// Arrange
|
||||
ParserBase expected = new CSharpCodeParser();
|
||||
|
||||
// Act
|
||||
ParserBase actual = CreateHost().DecorateCodeParser(expected);
|
||||
|
||||
// Assert
|
||||
Assert.Same(expected, actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DecorateMarkupParserReturnsIncomingParser()
|
||||
{
|
||||
// Arrange
|
||||
ParserBase expected = new HtmlMarkupParser();
|
||||
|
||||
// Act
|
||||
ParserBase actual = CreateHost().DecorateMarkupParser(expected);
|
||||
|
||||
// Assert
|
||||
Assert.Same(expected, actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DecorateCodeGeneratorReturnsIncomingCodeGenerator()
|
||||
{
|
||||
// Arrange
|
||||
RazorCodeGenerator expected = new CSharpRazorCodeGenerator("Foo", "Bar", "Baz", CreateHost());
|
||||
|
||||
// Act
|
||||
RazorCodeGenerator actual = CreateHost().DecorateCodeGenerator(expected);
|
||||
|
||||
// Assert
|
||||
Assert.Same(expected, actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PostProcessGeneratedCodeDoesNotModifyCode()
|
||||
{
|
||||
// Arrange
|
||||
CodeCompileUnit compileUnit = new CodeCompileUnit();
|
||||
CodeNamespace ns = new CodeNamespace();
|
||||
CodeTypeDeclaration typeDecl = new CodeTypeDeclaration();
|
||||
CodeMemberMethod execMethod = new CodeMemberMethod();
|
||||
|
||||
// Act
|
||||
CreateHost().PostProcessGeneratedCode(compileUnit, ns, typeDecl, execMethod);
|
||||
|
||||
// Assert
|
||||
Assert.Empty(compileUnit.Namespaces);
|
||||
Assert.Empty(ns.Imports);
|
||||
Assert.Empty(ns.Types);
|
||||
Assert.Empty(typeDecl.Members);
|
||||
Assert.Empty(execMethod.Statements);
|
||||
}
|
||||
|
||||
private static RazorEngineHost CreateHost()
|
||||
{
|
||||
return new RazorEngineHost(new CSharpRazorCodeLanguage());
|
||||
}
|
||||
|
||||
private static void VerifyCommonDefaults(RazorEngineHost host)
|
||||
{
|
||||
Assert.Equal(GeneratedClassContext.Default, host.GeneratedClassContext);
|
||||
Assert.Empty(host.NamespaceImports);
|
||||
Assert.False(host.DesignTimeMode);
|
||||
Assert.Equal(RazorEngineHost.InternalDefaultClassName, host.DefaultClassName);
|
||||
Assert.Equal(RazorEngineHost.InternalDefaultNamespace, host.DefaultNamespace);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,198 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using Microsoft.AspNet.Razor.Generator;
|
||||
using Microsoft.AspNet.Razor.Parser;
|
||||
using Microsoft.AspNet.Razor.Text;
|
||||
using System.Web.WebPages.TestUtils;
|
||||
using Microsoft.TestCommon;
|
||||
using Moq;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Test
|
||||
{
|
||||
public class RazorTemplateEngineTest
|
||||
{
|
||||
[Fact]
|
||||
public void ConstructorRequiresNonNullHost()
|
||||
{
|
||||
Assert.ThrowsArgumentNull(() => new RazorTemplateEngine(null), "host");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ConstructorInitializesHost()
|
||||
{
|
||||
// Arrange
|
||||
RazorEngineHost host = new RazorEngineHost(new CSharpRazorCodeLanguage());
|
||||
|
||||
// Act
|
||||
RazorTemplateEngine engine = new RazorTemplateEngine(host);
|
||||
|
||||
// Assert
|
||||
Assert.Same(host, engine.Host);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CreateParserMethodIsConstructedFromHost()
|
||||
{
|
||||
// Arrange
|
||||
RazorEngineHost host = CreateHost();
|
||||
RazorTemplateEngine engine = new RazorTemplateEngine(host);
|
||||
|
||||
// Act
|
||||
RazorParser parser = engine.CreateParser();
|
||||
|
||||
// Assert
|
||||
Assert.IsType<CSharpCodeParser>(parser.CodeParser);
|
||||
Assert.IsType<HtmlMarkupParser>(parser.MarkupParser);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CreateParserMethodSetsParserContextToDesignTimeModeIfHostSetToDesignTimeMode()
|
||||
{
|
||||
// Arrange
|
||||
RazorEngineHost host = CreateHost();
|
||||
RazorTemplateEngine engine = new RazorTemplateEngine(host);
|
||||
host.DesignTimeMode = true;
|
||||
|
||||
// Act
|
||||
RazorParser parser = engine.CreateParser();
|
||||
|
||||
// Assert
|
||||
Assert.True(parser.DesignTimeMode);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CreateParserMethodPassesParsersThroughDecoratorMethodsOnHost()
|
||||
{
|
||||
// Arrange
|
||||
ParserBase expectedCode = new Mock<ParserBase>().Object;
|
||||
ParserBase expectedMarkup = new Mock<ParserBase>().Object;
|
||||
|
||||
var mockHost = new Mock<RazorEngineHost>(new CSharpRazorCodeLanguage()) { CallBase = true };
|
||||
mockHost.Setup(h => h.DecorateCodeParser(It.IsAny<CSharpCodeParser>()))
|
||||
.Returns(expectedCode);
|
||||
mockHost.Setup(h => h.DecorateMarkupParser(It.IsAny<HtmlMarkupParser>()))
|
||||
.Returns(expectedMarkup);
|
||||
RazorTemplateEngine engine = new RazorTemplateEngine(mockHost.Object);
|
||||
|
||||
// Act
|
||||
RazorParser actual = engine.CreateParser();
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expectedCode, actual.CodeParser);
|
||||
Assert.Equal(expectedMarkup, actual.MarkupParser);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CreateCodeGeneratorMethodPassesCodeGeneratorThroughDecorateMethodOnHost()
|
||||
{
|
||||
// Arrange
|
||||
var mockHost = new Mock<RazorEngineHost>(new CSharpRazorCodeLanguage()) { CallBase = true };
|
||||
|
||||
RazorCodeGenerator expected = new Mock<RazorCodeGenerator>("Foo", "Bar", "Baz", mockHost.Object).Object;
|
||||
|
||||
mockHost.Setup(h => h.DecorateCodeGenerator(It.IsAny<CSharpRazorCodeGenerator>()))
|
||||
.Returns(expected);
|
||||
RazorTemplateEngine engine = new RazorTemplateEngine(mockHost.Object);
|
||||
|
||||
// Act
|
||||
RazorCodeGenerator actual = engine.CreateCodeGenerator("Foo", "Bar", "Baz");
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expected, actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseTemplateCopiesTextReaderContentToSeekableTextReaderAndPassesToParseTemplateCore()
|
||||
{
|
||||
// Arrange
|
||||
Mock<RazorTemplateEngine> mockEngine = new Mock<RazorTemplateEngine>(CreateHost());
|
||||
TextReader reader = new StringReader("foo");
|
||||
CancellationTokenSource source = new CancellationTokenSource();
|
||||
|
||||
// Act
|
||||
mockEngine.Object.ParseTemplate(reader, cancelToken: source.Token);
|
||||
|
||||
// Assert
|
||||
mockEngine.Verify(e => e.ParseTemplateCore(It.Is<SeekableTextReader>(l => l.ReadToEnd() == "foo"),
|
||||
source.Token));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GenerateCodeCopiesTextReaderContentToSeekableTextReaderAndPassesToGenerateCodeCore()
|
||||
{
|
||||
// Arrange
|
||||
Mock<RazorTemplateEngine> mockEngine = new Mock<RazorTemplateEngine>(CreateHost());
|
||||
TextReader reader = new StringReader("foo");
|
||||
CancellationTokenSource source = new CancellationTokenSource();
|
||||
string className = "Foo";
|
||||
string ns = "Bar";
|
||||
string src = "Baz";
|
||||
|
||||
// Act
|
||||
mockEngine.Object.GenerateCode(reader, className: className, rootNamespace: ns, sourceFileName: src, cancelToken: source.Token);
|
||||
|
||||
// Assert
|
||||
mockEngine.Verify(e => e.GenerateCodeCore(It.Is<SeekableTextReader>(l => l.ReadToEnd() == "foo"),
|
||||
className, ns, src, source.Token));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseTemplateOutputsResultsOfParsingProvidedTemplateSource()
|
||||
{
|
||||
// Arrange
|
||||
RazorTemplateEngine engine = new RazorTemplateEngine(CreateHost());
|
||||
|
||||
// Act
|
||||
ParserResults results = engine.ParseTemplate(new StringTextBuffer("foo @bar("));
|
||||
|
||||
// Assert
|
||||
Assert.False(results.Success);
|
||||
Assert.Single(results.ParserErrors);
|
||||
Assert.NotNull(results.Document);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GenerateOutputsResultsOfParsingAndGeneration()
|
||||
{
|
||||
// Arrange
|
||||
RazorTemplateEngine engine = new RazorTemplateEngine(CreateHost());
|
||||
|
||||
// Act
|
||||
GeneratorResults results = engine.GenerateCode(new StringTextBuffer("foo @bar("));
|
||||
|
||||
// Assert
|
||||
Assert.False(results.Success);
|
||||
Assert.Single(results.ParserErrors);
|
||||
Assert.NotNull(results.Document);
|
||||
Assert.NotNull(results.GeneratedCode);
|
||||
Assert.Null(results.DesignTimeLineMappings);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GenerateOutputsDesignTimeMappingsIfDesignTimeSetOnHost()
|
||||
{
|
||||
// Arrange
|
||||
RazorTemplateEngine engine = new RazorTemplateEngine(CreateHost(designTime: true));
|
||||
|
||||
// Act
|
||||
GeneratorResults results = engine.GenerateCode(new StringTextBuffer("foo @bar()"), className: null, rootNamespace: null, sourceFileName: "foo.cshtml");
|
||||
|
||||
// Assert
|
||||
Assert.True(results.Success);
|
||||
Assert.Empty(results.ParserErrors);
|
||||
Assert.NotNull(results.Document);
|
||||
Assert.NotNull(results.GeneratedCode);
|
||||
Assert.NotNull(results.DesignTimeLineMappings);
|
||||
}
|
||||
|
||||
private static RazorEngineHost CreateHost(bool designTime = false)
|
||||
{
|
||||
return new RazorEngineHost(new CSharpRazorCodeLanguage())
|
||||
{
|
||||
DesignTimeMode = designTime
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNet.Razor.Text;
|
||||
|
||||
namespace System.Web.WebPages.TestUtils
|
||||
{
|
||||
public class StringTextBuffer : ITextBuffer, IDisposable
|
||||
{
|
||||
private string _buffer;
|
||||
public bool Disposed { get; set; }
|
||||
|
||||
public StringTextBuffer(string buffer)
|
||||
{
|
||||
_buffer = buffer;
|
||||
}
|
||||
|
||||
public int Length
|
||||
{
|
||||
get { return _buffer.Length; }
|
||||
}
|
||||
|
||||
public int Position { get; set; }
|
||||
|
||||
public int Read()
|
||||
{
|
||||
if (Position >= _buffer.Length)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
return _buffer[Position++];
|
||||
}
|
||||
|
||||
public int Peek()
|
||||
{
|
||||
if (Position >= _buffer.Length)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
return _buffer[Position];
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Disposed = true;
|
||||
}
|
||||
|
||||
public object VersionToken
|
||||
{
|
||||
get { return _buffer; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,194 @@
|
|||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:N.N.NNNNN.N
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace TestOutput {
|
||||
using System;
|
||||
|
||||
public class Blocks {
|
||||
#line hidden
|
||||
public Blocks() {
|
||||
}
|
||||
public override void Execute() {
|
||||
|
||||
#line 1 "Blocks.cshtml"
|
||||
|
||||
int i = 1;
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
WriteLiteral("\r\n\r\n");
|
||||
|
||||
|
||||
#line 5 "Blocks.cshtml"
|
||||
while(i <= 10) {
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
WriteLiteral(" <p>Hello from C#, #");
|
||||
|
||||
|
||||
#line 6 "Blocks.cshtml"
|
||||
Write(i);
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
WriteLiteral("</p>\r\n");
|
||||
|
||||
|
||||
#line 7 "Blocks.cshtml"
|
||||
i += 1;
|
||||
}
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
WriteLiteral("\r\n");
|
||||
|
||||
|
||||
#line 10 "Blocks.cshtml"
|
||||
if(i == 11) {
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
WriteLiteral(" <p>We wrote 10 lines!</p>\r\n");
|
||||
|
||||
|
||||
#line 12 "Blocks.cshtml"
|
||||
}
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
WriteLiteral("\r\n");
|
||||
|
||||
|
||||
#line 14 "Blocks.cshtml"
|
||||
switch(i) {
|
||||
case 11:
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
WriteLiteral(" <p>No really, we wrote 10 lines!</p>\r\n");
|
||||
|
||||
|
||||
#line 17 "Blocks.cshtml"
|
||||
break;
|
||||
default:
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
WriteLiteral(" <p>Actually, we didn\'t...</p>\r\n");
|
||||
|
||||
|
||||
#line 20 "Blocks.cshtml"
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
WriteLiteral("\r\n");
|
||||
|
||||
|
||||
#line 23 "Blocks.cshtml"
|
||||
for(int j = 1; j <= 10; j += 2) {
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
WriteLiteral(" <p>Hello again from C#, #");
|
||||
|
||||
|
||||
#line 24 "Blocks.cshtml"
|
||||
Write(j);
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
WriteLiteral("</p>\r\n");
|
||||
|
||||
|
||||
#line 25 "Blocks.cshtml"
|
||||
}
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
WriteLiteral("\r\n");
|
||||
|
||||
|
||||
#line 27 "Blocks.cshtml"
|
||||
try {
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
WriteLiteral(" <p>That time, we wrote 5 lines!</p>\r\n");
|
||||
|
||||
|
||||
#line 29 "Blocks.cshtml"
|
||||
} catch(Exception ex) {
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
WriteLiteral(" <p>Oh no! An error occurred: ");
|
||||
|
||||
|
||||
#line 30 "Blocks.cshtml"
|
||||
Write(ex.Message);
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
WriteLiteral("</p>\r\n");
|
||||
|
||||
|
||||
#line 31 "Blocks.cshtml"
|
||||
}
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
WriteLiteral("\r\n<p>i is now ");
|
||||
|
||||
|
||||
#line 33 "Blocks.cshtml"
|
||||
Write(i);
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
WriteLiteral("</p>\r\n\r\n");
|
||||
|
||||
|
||||
#line 35 "Blocks.cshtml"
|
||||
lock(new object()) {
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
WriteLiteral(" <p>This block is locked, for your security!</p>\r\n");
|
||||
|
||||
|
||||
#line 37 "Blocks.cshtml"
|
||||
}
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:N.N.NNNNN.N
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace TestOutput {
|
||||
using System;
|
||||
|
||||
public class CodeBlock {
|
||||
#line hidden
|
||||
public CodeBlock() {
|
||||
}
|
||||
public override void Execute() {
|
||||
|
||||
#line 1 "CodeBlock.cshtml"
|
||||
|
||||
for(int i = 1; i <= 10; i++) {
|
||||
Output.Write("<p>Hello from C#, #" + i.ToString() + "</p>");
|
||||
}
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:N.N.NNNNN.N
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace TestOutput {
|
||||
using System;
|
||||
|
||||
public class CodeBlockAtEOF {
|
||||
#line hidden
|
||||
public CodeBlockAtEOF() {
|
||||
}
|
||||
public override void Execute() {
|
||||
|
||||
#line 1 "CodeBlockAtEOF.cshtml"
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:N.N.NNNNN.N
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace TestOutput {
|
||||
using System;
|
||||
|
||||
public class Comments {
|
||||
public override void Execute() {
|
||||
|
||||
|
||||
#line 1 "Comments.cshtml"
|
||||
//This is not going to be rendered
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
WriteLiteral("<p>This is going to be rendered</p>\r\n");
|
||||
|
||||
|
||||
|
||||
#line 3 "Comments.cshtml"
|
||||
/* Neither is this
|
||||
nor this
|
||||
nor this */
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,197 @@
|
|||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:N.N.NNNNN.N
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace TestOutput {
|
||||
using System;
|
||||
|
||||
public class ConditionalAttributes {
|
||||
#line hidden
|
||||
public ConditionalAttributes() {
|
||||
}
|
||||
public override void Execute() {
|
||||
|
||||
#line 1 "ConditionalAttributes.cshtml"
|
||||
|
||||
var ch = true;
|
||||
var cls = "bar";
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
WriteLiteral(" <a");
|
||||
|
||||
WriteLiteral(" href=\"Foo\"");
|
||||
|
||||
WriteLiteral(" />\r\n");
|
||||
|
||||
WriteLiteral(" <p");
|
||||
|
||||
WriteAttribute("class", Tuple.Create(" class=\"", 74), Tuple.Create("\"", 86)
|
||||
|
||||
#line 5 "ConditionalAttributes.cshtml"
|
||||
, Tuple.Create(Tuple.Create("", 82), Tuple.Create<System.Object, System.Int32>(cls
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
, 82), false)
|
||||
);
|
||||
|
||||
WriteLiteral(" />\r\n");
|
||||
|
||||
WriteLiteral(" <p");
|
||||
|
||||
WriteAttribute("class", Tuple.Create(" class=\"", 98), Tuple.Create("\"", 114)
|
||||
, Tuple.Create(Tuple.Create("", 106), Tuple.Create("foo", 106), true)
|
||||
|
||||
#line 6 "ConditionalAttributes.cshtml"
|
||||
, Tuple.Create(Tuple.Create(" ", 109), Tuple.Create<System.Object, System.Int32>(cls
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
, 110), false)
|
||||
);
|
||||
|
||||
WriteLiteral(" />\r\n");
|
||||
|
||||
WriteLiteral(" <p");
|
||||
|
||||
WriteAttribute("class", Tuple.Create(" class=\"", 126), Tuple.Create("\"", 142)
|
||||
|
||||
#line 7 "ConditionalAttributes.cshtml"
|
||||
, Tuple.Create(Tuple.Create("", 134), Tuple.Create<System.Object, System.Int32>(cls
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
, 134), false)
|
||||
, Tuple.Create(Tuple.Create(" ", 138), Tuple.Create("foo", 139), true)
|
||||
);
|
||||
|
||||
WriteLiteral(" />\r\n");
|
||||
|
||||
WriteLiteral(" <input");
|
||||
|
||||
WriteLiteral(" type=\"checkbox\"");
|
||||
|
||||
WriteAttribute("checked", Tuple.Create(" checked=\"", 174), Tuple.Create("\"", 187)
|
||||
|
||||
#line 8 "ConditionalAttributes.cshtml"
|
||||
, Tuple.Create(Tuple.Create("", 184), Tuple.Create<System.Object, System.Int32>(ch
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
, 184), false)
|
||||
);
|
||||
|
||||
WriteLiteral(" />\r\n");
|
||||
|
||||
WriteLiteral(" <input");
|
||||
|
||||
WriteLiteral(" type=\"checkbox\"");
|
||||
|
||||
WriteAttribute("checked", Tuple.Create(" checked=\"", 219), Tuple.Create("\"", 236)
|
||||
, Tuple.Create(Tuple.Create("", 229), Tuple.Create("foo", 229), true)
|
||||
|
||||
#line 9 "ConditionalAttributes.cshtml"
|
||||
, Tuple.Create(Tuple.Create(" ", 232), Tuple.Create<System.Object, System.Int32>(ch
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
, 233), false)
|
||||
);
|
||||
|
||||
WriteLiteral(" />\r\n");
|
||||
|
||||
WriteLiteral(" <p");
|
||||
|
||||
WriteAttribute("class", Tuple.Create(" class=\"", 248), Tuple.Create("\"", 281)
|
||||
, Tuple.Create(Tuple.Create("", 256), Tuple.Create<System.Object, System.Int32>(new Template(__razor_attribute_value_writer => {
|
||||
|
||||
|
||||
#line 10 "ConditionalAttributes.cshtml"
|
||||
if(cls != null) {
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 10 "ConditionalAttributes.cshtml"
|
||||
WriteTo(__razor_attribute_value_writer, cls);
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 10 "ConditionalAttributes.cshtml"
|
||||
}
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
}), 256), false)
|
||||
);
|
||||
|
||||
WriteLiteral(" />\r\n");
|
||||
|
||||
WriteLiteral(" <a");
|
||||
|
||||
WriteAttribute("href", Tuple.Create(" href=\"", 293), Tuple.Create("\"", 305)
|
||||
, Tuple.Create(Tuple.Create("", 300), Tuple.Create<System.Object, System.Int32>(Href("~/Foo")
|
||||
, 300), false)
|
||||
);
|
||||
|
||||
WriteLiteral(" />\r\n");
|
||||
|
||||
WriteLiteral(" <script");
|
||||
|
||||
WriteAttribute("src", Tuple.Create(" src=\"", 322), Tuple.Create("\"", 373)
|
||||
|
||||
#line 12 "ConditionalAttributes.cshtml"
|
||||
, Tuple.Create(Tuple.Create("", 328), Tuple.Create<System.Object, System.Int32>(Url.Content("~/Scripts/jquery-1.6.2.min.js")
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
, 328), false)
|
||||
);
|
||||
|
||||
WriteLiteral(" type=\"text/javascript\"");
|
||||
|
||||
WriteLiteral("></script>\r\n");
|
||||
|
||||
WriteLiteral(" <script");
|
||||
|
||||
WriteAttribute("src", Tuple.Create(" src=\"", 420), Tuple.Create("\"", 487)
|
||||
|
||||
#line 13 "ConditionalAttributes.cshtml"
|
||||
, Tuple.Create(Tuple.Create("", 426), Tuple.Create<System.Object, System.Int32>(Url.Content("~/Scripts/modernizr-2.0.6-development-only.js")
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
, 426), false)
|
||||
);
|
||||
|
||||
WriteLiteral(" type=\"text/javascript\"");
|
||||
|
||||
WriteLiteral("></script>\r\n");
|
||||
|
||||
WriteLiteral(" <script");
|
||||
|
||||
WriteLiteral(" src=\"http://ajax.aspnetcdn.com/ajax/jquery.ui/1.8.16/jquery-ui.min.js\"");
|
||||
|
||||
WriteLiteral(" type=\"text/javascript\"");
|
||||
|
||||
WriteLiteral("></script>\r\n");
|
||||
|
||||
|
||||
#line 15 "ConditionalAttributes.cshtml"
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,110 @@
|
|||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:N.N.NNNNN.N
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace TestOutput {
|
||||
using System;
|
||||
|
||||
public class DesignTime {
|
||||
private static object @__o;
|
||||
#line hidden
|
||||
#line 9 "DesignTime.cshtml"
|
||||
public static Template Foo() {
|
||||
#line default
|
||||
#line hidden
|
||||
return new Template(__razor_helper_writer => {
|
||||
|
||||
#line 10 "DesignTime.cshtml"
|
||||
|
||||
if(true) {
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 11 "DesignTime.cshtml"
|
||||
|
||||
}
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
});
|
||||
|
||||
#line 12 "DesignTime.cshtml"
|
||||
}
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
public DesignTime() {
|
||||
}
|
||||
public override void Execute() {
|
||||
|
||||
#line 1 "DesignTime.cshtml"
|
||||
for(int i = 1; i <= 10; i++) {
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 2 "DesignTime.cshtml"
|
||||
__o = i;
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 3 "DesignTime.cshtml"
|
||||
|
||||
}
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 4 "DesignTime.cshtml"
|
||||
__o = Foo(Bar.Baz);
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 5 "DesignTime.cshtml"
|
||||
__o = Foo(item => new Template(__razor_template_writer => {
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 6 "DesignTime.cshtml"
|
||||
__o = baz;
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 7 "DesignTime.cshtml"
|
||||
}));
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
DefineSection("Footer", () => {
|
||||
|
||||
|
||||
#line 8 "DesignTime.cshtml"
|
||||
__o = bar;
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,110 @@
|
|||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:N.N.NNNNN.N
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace TestOutput {
|
||||
using System;
|
||||
|
||||
public class DesignTime {
|
||||
private static object @__o;
|
||||
#line hidden
|
||||
#line 9 "DesignTime.cshtml"
|
||||
public static Template Foo() {
|
||||
#line default
|
||||
#line hidden
|
||||
return new Template(__razor_helper_writer => {
|
||||
|
||||
#line 10 "DesignTime.cshtml"
|
||||
|
||||
if(true) {
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 11 "DesignTime.cshtml"
|
||||
|
||||
}
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
});
|
||||
|
||||
#line 12 "DesignTime.cshtml"
|
||||
}
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
public DesignTime() {
|
||||
}
|
||||
public override void Execute() {
|
||||
|
||||
#line 1 "DesignTime.cshtml"
|
||||
for(int i = 1; i <= 10; i++) {
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 2 "DesignTime.cshtml"
|
||||
__o = i;
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 3 "DesignTime.cshtml"
|
||||
|
||||
}
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 4 "DesignTime.cshtml"
|
||||
__o = Foo(Bar.Baz);
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 5 "DesignTime.cshtml"
|
||||
__o = Foo(item => new Template(__razor_template_writer => {
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 6 "DesignTime.cshtml"
|
||||
__o = baz;
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 7 "DesignTime.cshtml"
|
||||
}));
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
DefineSection("Footer", () => {
|
||||
|
||||
|
||||
#line 8 "DesignTime.cshtml"
|
||||
__o = bar;
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:N.N.NNNNN.N
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace TestOutput {
|
||||
using System;
|
||||
|
||||
public class EmptyCodeBlock {
|
||||
#line hidden
|
||||
public EmptyCodeBlock() {
|
||||
}
|
||||
public override void Execute() {
|
||||
|
||||
#line 1 "EmptyCodeBlock.cshtml"
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:N.N.NNNNN.N
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace TestOutput {
|
||||
using System;
|
||||
|
||||
public class EmptyExplicitExpression {
|
||||
private static object @__o;
|
||||
#line hidden
|
||||
public EmptyExplicitExpression() {
|
||||
}
|
||||
public override void Execute() {
|
||||
|
||||
#line 1 "EmptyExplicitExpression.cshtml"
|
||||
__o = ;
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:N.N.NNNNN.N
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace TestOutput {
|
||||
using System;
|
||||
|
||||
public class EmptyImplicitExpression {
|
||||
private static object @__o;
|
||||
#line hidden
|
||||
public EmptyImplicitExpression() {
|
||||
}
|
||||
public override void Execute() {
|
||||
|
||||
#line 1 "EmptyImplicitExpression.cshtml"
|
||||
__o = ;
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:N.N.NNNNN.N
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace TestOutput {
|
||||
using System;
|
||||
|
||||
public class EmptyImplicitExpressionInCode {
|
||||
private static object @__o;
|
||||
#line hidden
|
||||
public EmptyImplicitExpressionInCode() {
|
||||
}
|
||||
public override void Execute() {
|
||||
|
||||
#line 1 "EmptyImplicitExpressionInCode.cshtml"
|
||||
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 2 "EmptyImplicitExpressionInCode.cshtml"
|
||||
__o = ;
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 3 "EmptyImplicitExpressionInCode.cshtml"
|
||||
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:N.N.NNNNN.N
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace TestOutput {
|
||||
using System;
|
||||
|
||||
public class EmptyImplicitExpressionInCode {
|
||||
private static object @__o;
|
||||
#line hidden
|
||||
public EmptyImplicitExpressionInCode() {
|
||||
}
|
||||
public override void Execute() {
|
||||
|
||||
#line 1 "EmptyImplicitExpressionInCode.cshtml"
|
||||
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 2 "EmptyImplicitExpressionInCode.cshtml"
|
||||
__o = ;
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 3 "EmptyImplicitExpressionInCode.cshtml"
|
||||
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:N.N.NNNNN.N
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace TestOutput {
|
||||
using System;
|
||||
|
||||
public class ExplicitExpression {
|
||||
#line hidden
|
||||
public ExplicitExpression() {
|
||||
}
|
||||
public override void Execute() {
|
||||
WriteLiteral("1 + 1 = ");
|
||||
|
||||
|
||||
#line 1 "ExplicitExpression.cshtml"
|
||||
Write(1+1);
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue