Addressed code review comments.

This commit is contained in:
N. Taylor Mullen 2015-05-28 15:15:02 -07:00
parent 6df8bc23f1
commit ed92b6992d
79 changed files with 366 additions and 212 deletions

View File

@ -2,7 +2,7 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNet.Razor.Chunks.Generators;
using Microsoft.AspNet.Razor.CodeGeneration;
using Microsoft.AspNet.Razor.CodeGenerators;
using Microsoft.AspNet.Razor.Parser;
#if NET45
@ -36,7 +36,11 @@ namespace Microsoft.AspNet.Razor
/// <summary>
/// Constructs a new instance of the chunk generator for this language with the specified settings
/// </summary>
public override RazorChunkGenerator CreateChunkGenerator(string className, string rootNamespaceName, string sourceFileName, RazorEngineHost host)
public override RazorChunkGenerator CreateChunkGenerator(
string className,
string rootNamespaceName,
string sourceFileName,
RazorEngineHost host)
{
return new RazorChunkGenerator(className, rootNamespaceName, sourceFileName, host);
}

View File

@ -8,13 +8,13 @@ namespace Microsoft.AspNet.Razor.Chunks
{
public class ChunkTreeBuilder
{
private readonly Stack<ParentChunk> _parentChain;
private readonly Stack<ParentChunk> _parentStack;
private Chunk _lastChunk;
public ChunkTreeBuilder()
{
ChunkTree = new ChunkTree();
_parentChain = new Stack<ParentChunk>();
_parentStack = new Stack<ParentChunk>();
}
public ChunkTree ChunkTree { get; private set; }
@ -27,13 +27,13 @@ namespace Microsoft.AspNet.Razor.Chunks
chunk.Association = association;
// If we're not in the middle of a chunk block
if (_parentChain.Count == 0 || topLevel == true)
if (_parentStack.Count == 0 || topLevel == true)
{
ChunkTree.Chunks.Add(chunk);
}
else
{
_parentChain.Peek().Children.Add(chunk);
_parentStack.Peek().Children.Add(chunk);
}
}
@ -164,14 +164,14 @@ namespace Microsoft.AspNet.Razor.Chunks
{
AddChunk(parentChunk, association, topLevel);
_parentChain.Push(parentChunk);
_parentStack.Push(parentChunk);
return parentChunk;
}
public void EndParentChunk()
{
_lastChunk = _parentChain.Pop();
_lastChunk = _parentStack.Pop();
}
}
}

View File

@ -33,11 +33,11 @@ namespace Microsoft.AspNet.Razor.Chunks.Generators
public string SourceFile { get; internal set; }
public string RootNamespace { get; private set; }
public string RootNamespace { get; }
public string ClassName { get; private set; }
public string ClassName { get; }
public RazorEngineHost Host { get; private set; }
public RazorEngineHost Host { get; }
public ChunkTreeBuilder ChunkTreeBuilder { get; set; }
}

View File

@ -5,21 +5,21 @@ using Microsoft.AspNet.Razor.Parser.SyntaxTree;
namespace Microsoft.AspNet.Razor.Chunks.Generators
{
public class ExpressionChunkGenerator : HybridChunkGenerator
public class ExpressionChunkGenerator : ISpanChunkGenerator, IParentChunkGenerator
{
private static readonly int TypeHashCode = typeof(ExpressionChunkGenerator).GetHashCode();
public override void GenerateStartParentChunk(Block target, ChunkGeneratorContext context)
public void GenerateStartParentChunk(Block target, ChunkGeneratorContext context)
{
context.ChunkTreeBuilder.StartParentChunk<ExpressionBlockChunk>(target);
}
public override void GenerateChunk(Span target, ChunkGeneratorContext context)
public void GenerateChunk(Span target, ChunkGeneratorContext context)
{
context.ChunkTreeBuilder.AddExpressionChunk(target.Content, target);
}
public override void GenerateEndParentChunk(Block target, ChunkGeneratorContext context)
public void GenerateEndParentChunk(Block target, ChunkGeneratorContext context)
{
context.ChunkTreeBuilder.EndParentChunk();
}

View File

@ -1,22 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
namespace Microsoft.AspNet.Razor.Chunks.Generators
{
public abstract class HybridChunkGenerator : ISpanChunkGenerator, IParentChunkGenerator
{
public virtual void GenerateStartParentChunk(Block target, ChunkGeneratorContext context)
{
}
public virtual void GenerateEndParentChunk(Block target, ChunkGeneratorContext context)
{
}
public virtual void GenerateChunk(Span target, ChunkGeneratorContext context)
{
}
}
}

View File

@ -10,7 +10,9 @@ namespace Microsoft.AspNet.Razor.Chunks.Generators
{
public class LiteralAttributeChunkGenerator : SpanChunkGenerator
{
public LiteralAttributeChunkGenerator(LocationTagged<string> prefix, LocationTagged<SpanChunkGenerator> valueGenerator)
public LiteralAttributeChunkGenerator(
LocationTagged<string> prefix,
LocationTagged<SpanChunkGenerator> valueGenerator)
{
Prefix = prefix;
ValueGenerator = valueGenerator;

View File

@ -10,7 +10,10 @@ namespace Microsoft.AspNet.Razor.Chunks.Generators
{
private static readonly int TypeHashCode = typeof(ParentChunkGenerator).GetHashCode();
[SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "This class has no instance state")]
[SuppressMessage(
"Microsoft.Security",
"CA2104:DoNotDeclareReadOnlyMutableReferenceTypes",
Justification = "This class has no instance state")]
public static readonly IParentChunkGenerator Null = new NullParentChunkGenerator();
public virtual void GenerateStartParentChunk(Block target, ChunkGeneratorContext context)

View File

@ -10,7 +10,10 @@ namespace Microsoft.AspNet.Razor.Chunks.Generators
{
private static readonly int TypeHashCode = typeof(SpanChunkGenerator).GetHashCode();
[SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "This class has no instance state")]
[SuppressMessage(
"Microsoft.Security",
"CA2104:DoNotDeclareReadOnlyMutableReferenceTypes",
Justification = "This class has no instance state")]
public static readonly ISpanChunkGenerator Null = new NullSpanChunkGenerator();
public virtual void GenerateChunk(Span target, ChunkGeneratorContext context)

View File

@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
using Microsoft.AspNet.Razor.Parser.TagHelpers;
@ -40,11 +41,9 @@ namespace Microsoft.AspNet.Razor.Chunks.Generators
{
var tagHelperBlock = target as TagHelperBlock;
if (tagHelperBlock == null)
{
throw new ArgumentException(
RazorResources.TagHelpers_TagHelperCodeGeneartorMustBeAssociatedWithATagHelperBlock);
}
Debug.Assert(
tagHelperBlock != null,
$"A {nameof(TagHelperChunkGenerator)} must only be used with {nameof(TagHelperBlock)}s.");
var attributes = new List<KeyValuePair<string, Chunk>>();
@ -60,7 +59,7 @@ namespace Microsoft.AspNet.Razor.Chunks.Generators
if (attribute.Value != null)
{
// Populates the code tree with chunks associated with attributes
// Populates the chunk tree with chunks associated with attributes
attribute.Value.Accept(chunkGenerator);
var chunks = chunkGenerator.Context.ChunkTreeBuilder.ChunkTree.Chunks;
@ -76,7 +75,7 @@ namespace Microsoft.AspNet.Razor.Chunks.Generators
attributes.Add(new KeyValuePair<string, Chunk>(attribute.Key, attributeChunkValue));
// Reset the code tree builder so we can build a new one for the next attribute
// Reset the chunk tree builder so we can build a new one for the next attribute
chunkGenerator.Context.ChunkTreeBuilder = new ChunkTreeBuilder();
}

View File

@ -5,10 +5,10 @@ using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNet.Razor.Chunks;
using Microsoft.AspNet.Razor.CodeGeneration.Visitors;
using Microsoft.AspNet.Razor.CodeGenerators.Visitors;
using Microsoft.Framework.Internal;
namespace Microsoft.AspNet.Razor.CodeGeneration
namespace Microsoft.AspNet.Razor.CodeGenerators
{
public class CSharpCodeGenerator : CodeGenerator
{

View File

@ -10,7 +10,7 @@ using Microsoft.AspNet.Razor.Parser.SyntaxTree;
using Microsoft.AspNet.Razor.Text;
using Microsoft.Framework.Internal;
namespace Microsoft.AspNet.Razor.CodeGeneration
namespace Microsoft.AspNet.Razor.CodeGenerators
{
public class CSharpCodeWriter : CodeWriter
{
@ -464,7 +464,10 @@ namespace Microsoft.AspNet.Razor.CodeGeneration
Write("\"");
}
public void WriteStartInstrumentationContext(ChunkGeneratorContext context, SyntaxTreeNode syntaxNode, bool isLiteral)
public void WriteStartInstrumentationContext(
ChunkGeneratorContext context,
SyntaxTreeNode syntaxNode,
bool isLiteral)
{
WriteStartMethodInvocation(context.Host.GeneratedClassContext.BeginContextMethodName);
Write(syntaxNode.Start.AbsoluteIndex.ToString(CultureInfo.InvariantCulture));

View File

@ -4,7 +4,7 @@
using System;
using System.Linq;
namespace Microsoft.AspNet.Razor.CodeGeneration
namespace Microsoft.AspNet.Razor.CodeGenerators
{
public struct CSharpCodeWritingScope : IDisposable
{

View File

@ -3,7 +3,7 @@
using System;
namespace Microsoft.AspNet.Razor.CodeGeneration
namespace Microsoft.AspNet.Razor.CodeGenerators
{
public struct CSharpDisableWarningScope : IDisposable
{

View File

@ -4,7 +4,7 @@
using System;
using Microsoft.Framework.Internal;
namespace Microsoft.AspNet.Razor.CodeGeneration
namespace Microsoft.AspNet.Razor.CodeGenerators
{
public class CSharpLineMappingWriter : IDisposable
{

View File

@ -6,7 +6,7 @@ using Microsoft.AspNet.Razor.Parser;
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
using Microsoft.Framework.Internal;
namespace Microsoft.AspNet.Razor.CodeGeneration
namespace Microsoft.AspNet.Razor.CodeGenerators
{
public class CSharpPaddingBuilder
{

View File

@ -6,11 +6,11 @@ using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using Microsoft.AspNet.Razor.Chunks;
using Microsoft.AspNet.Razor.CodeGeneration.Visitors;
using Microsoft.AspNet.Razor.CodeGenerators.Visitors;
using Microsoft.AspNet.Razor.TagHelpers;
using Microsoft.Framework.Internal;
namespace Microsoft.AspNet.Razor.CodeGeneration
namespace Microsoft.AspNet.Razor.CodeGenerators
{
/// <summary>
/// Renders tag helper rendering code.

View File

@ -1,7 +1,7 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
namespace Microsoft.AspNet.Razor.CodeGeneration
namespace Microsoft.AspNet.Razor.CodeGenerators
{
public abstract class CodeGenerator
{

View File

@ -3,7 +3,7 @@
using Microsoft.AspNet.Razor.Chunks.Generators;
namespace Microsoft.AspNet.Razor.CodeGeneration
namespace Microsoft.AspNet.Razor.CodeGenerators
{
/// <summary>
/// Context object with information used to generate a Razor page.
@ -26,12 +26,13 @@ namespace Microsoft.AspNet.Razor.CodeGeneration
}
// Internal for testing.
internal CodeGeneratorContext(RazorEngineHost host,
string className,
string rootNamespace,
string sourceFile,
bool shouldGenerateLinePragmas,
ErrorSink errorSink)
internal CodeGeneratorContext(
RazorEngineHost host,
string className,
string rootNamespace,
string sourceFile,
bool shouldGenerateLinePragmas,
ErrorSink errorSink)
: base(host, className, rootNamespace, sourceFile, shouldGenerateLinePragmas)
{
ErrorSink = errorSink;

View File

@ -3,7 +3,7 @@
using System.Collections.Generic;
namespace Microsoft.AspNet.Razor.CodeGeneration
namespace Microsoft.AspNet.Razor.CodeGenerators
{
public class CodeGeneratorResult
{

View File

@ -4,7 +4,7 @@
using System;
using System.IO;
namespace Microsoft.AspNet.Razor.CodeGeneration
namespace Microsoft.AspNet.Razor.CodeGenerators
{
public class CodeWriter : IDisposable
{

View File

@ -1,7 +1,7 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
namespace Microsoft.AspNet.Razor.CodeGeneration
namespace Microsoft.AspNet.Razor.CodeGenerators
{
public enum ExpressionRenderingMode
{

View File

@ -6,7 +6,7 @@ using System.Diagnostics.CodeAnalysis;
using Microsoft.Framework.Internal;
using Microsoft.Internal.Web.Utils;
namespace Microsoft.AspNet.Razor.CodeGeneration
namespace Microsoft.AspNet.Razor.CodeGenerators
{
public struct GeneratedClassContext
{

View File

@ -1,7 +1,7 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
namespace Microsoft.AspNet.Razor.CodeGeneration
namespace Microsoft.AspNet.Razor.CodeGenerators
{
/// <summary>
/// Contains necessary information for the tag helper code generation process.

View File

@ -3,12 +3,11 @@
using System.Collections.Generic;
using Microsoft.AspNet.Razor.Chunks;
using Microsoft.AspNet.Razor.CodeGeneration;
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
using Microsoft.AspNet.Razor.TagHelpers;
using Microsoft.Framework.Internal;
namespace Microsoft.AspNet.Razor
namespace Microsoft.AspNet.Razor.CodeGenerators
{
/// <summary>
/// The results of parsing and generating code for a Razor document.

View File

@ -4,7 +4,7 @@
using System.Globalization;
using Microsoft.Internal.Web.Utils;
namespace Microsoft.AspNet.Razor.CodeGeneration
namespace Microsoft.AspNet.Razor.CodeGenerators
{
public class LineMapping
{

View File

@ -3,7 +3,7 @@
using System.Collections.Generic;
namespace Microsoft.AspNet.Razor.CodeGeneration
namespace Microsoft.AspNet.Razor.CodeGenerators
{
public class LineMappingManager
{

View File

@ -4,7 +4,7 @@
using System.Globalization;
using Microsoft.Internal.Web.Utils;
namespace Microsoft.AspNet.Razor.CodeGeneration
namespace Microsoft.AspNet.Razor.CodeGenerators
{
public class MappingLocation
{

View File

@ -5,7 +5,7 @@ using System;
using Microsoft.AspNet.Razor.TagHelpers;
using Microsoft.Framework.Internal;
namespace Microsoft.AspNet.Razor.CodeGeneration
namespace Microsoft.AspNet.Razor.CodeGenerators
{
/// <summary>
/// Renders code for tag helper property initialization.
@ -20,8 +20,8 @@ namespace Microsoft.AspNet.Razor.CodeGeneration
/// The <see cref="TagHelperAttributeDescriptor"/> to generate code for.
/// </param>
/// <param name="writer">The <see cref="CSharpCodeWriter"/> that's used to write code.</param>
/// <param name="context">A <see cref="Chunks.Generators.ChunkGeneratorContext"/> instance that contains information about
/// the current code generation process.</param>
/// <param name="context">A <see cref="Chunks.Generators.ChunkGeneratorContext"/> instance that contains
/// information about the current code generation process.</param>
/// <param name="renderAttributeValue">
/// <see cref="Action"/> that renders the raw value of the HTML attribute.
/// </param>

View File

@ -4,7 +4,7 @@
using Microsoft.AspNet.Razor.Chunks;
using Microsoft.Framework.Internal;
namespace Microsoft.AspNet.Razor.CodeGeneration.Visitors
namespace Microsoft.AspNet.Razor.CodeGenerators.Visitors
{
public class CSharpBaseTypeVisitor : CodeVisitor<CSharpCodeWriter>
{

View File

@ -7,7 +7,7 @@ using Microsoft.AspNet.Razor.Chunks;
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
using Microsoft.Framework.Internal;
namespace Microsoft.AspNet.Razor.CodeGeneration.Visitors
namespace Microsoft.AspNet.Razor.CodeGenerators.Visitors
{
public class CSharpCodeVisitor : CodeVisitor<CSharpCodeWriter>
{

View File

@ -6,7 +6,7 @@ using System.Globalization;
using Microsoft.AspNet.Razor.Chunks;
using Microsoft.Framework.Internal;
namespace Microsoft.AspNet.Razor.CodeGeneration.Visitors
namespace Microsoft.AspNet.Razor.CodeGenerators.Visitors
{
public class CSharpDesignTimeHelpersVisitor : CodeVisitor<CSharpCodeWriter>
{

View File

@ -6,7 +6,7 @@ using Microsoft.AspNet.Razor.Parser;
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
using Microsoft.Framework.Internal;
namespace Microsoft.AspNet.Razor.CodeGeneration.Visitors
namespace Microsoft.AspNet.Razor.CodeGenerators.Visitors
{
/// <summary>
/// <see cref="CodeVisitor{CSharpCodeWriter}"/> that writes code for a non-<see langword="string"/> tag helper
@ -98,7 +98,7 @@ namespace Microsoft.AspNet.Razor.CodeGeneration.Visitors
/// <param name="chunk">The <see cref="ResolveUrlChunk"/> to render.</param>
/// <remarks>
/// Allowed to support future C# extensions. Likely "~/..." will lead to a C# compilation error but that is up
/// to the .
/// to the compiler.
/// </remarks>
protected override void Visit(ResolveUrlChunk chunk)
{

View File

@ -6,7 +6,7 @@ using System.Collections.Generic;
using Microsoft.AspNet.Razor.Chunks;
using Microsoft.Framework.Internal;
namespace Microsoft.AspNet.Razor.CodeGeneration.Visitors
namespace Microsoft.AspNet.Razor.CodeGenerators.Visitors
{
public class CSharpTagHelperFieldDeclarationVisitor : CodeVisitor<CSharpCodeWriter>
{

View File

@ -4,7 +4,7 @@
using Microsoft.AspNet.Razor.Chunks;
using Microsoft.Framework.Internal;
namespace Microsoft.AspNet.Razor.CodeGeneration.Visitors
namespace Microsoft.AspNet.Razor.CodeGenerators.Visitors
{
/// <summary>
/// The <see cref="CodeVisitor{T}"/> that generates the code to initialize the TagHelperRunner.

View File

@ -4,7 +4,7 @@
using Microsoft.AspNet.Razor.Chunks;
using Microsoft.Framework.Internal;
namespace Microsoft.AspNet.Razor.CodeGeneration.Visitors
namespace Microsoft.AspNet.Razor.CodeGenerators.Visitors
{
public class CSharpTypeMemberVisitor : CodeVisitor<CSharpCodeWriter>
{

View File

@ -7,7 +7,7 @@ using Microsoft.AspNet.Razor.Chunks;
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
using Microsoft.Framework.Internal;
namespace Microsoft.AspNet.Razor.CodeGeneration.Visitors
namespace Microsoft.AspNet.Razor.CodeGenerators.Visitors
{
public class CSharpUsingVisitor : CodeVisitor<CSharpCodeWriter>
{

View File

@ -5,7 +5,7 @@ using System.Collections.Generic;
using Microsoft.AspNet.Razor.Chunks;
using Microsoft.Framework.Internal;
namespace Microsoft.AspNet.Razor.CodeGeneration.Visitors
namespace Microsoft.AspNet.Razor.CodeGenerators.Visitors
{
public abstract class ChunkVisitor<TWriter> : IChunkVisitor
where TWriter : CodeWriter

View File

@ -4,7 +4,7 @@
using Microsoft.AspNet.Razor.Chunks;
using Microsoft.Framework.Internal;
namespace Microsoft.AspNet.Razor.CodeGeneration.Visitors
namespace Microsoft.AspNet.Razor.CodeGenerators.Visitors
{
public class CodeVisitor<TWriter> : ChunkVisitor<TWriter>
where TWriter : CodeWriter

View File

@ -4,7 +4,7 @@
using System.Collections.Generic;
using Microsoft.AspNet.Razor.Chunks;
namespace Microsoft.AspNet.Razor.CodeGeneration.Visitors
namespace Microsoft.AspNet.Razor.CodeGenerators.Visitors
{
public interface IChunkVisitor
{

View File

@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using Microsoft.AspNet.Razor.CodeGenerators;
using Microsoft.AspNet.Razor.Text;
namespace Microsoft.AspNet.Razor

View File

@ -9,6 +9,7 @@ using System.Globalization;
using System.IO;
using System.Linq;
using System.Threading;
using Microsoft.AspNet.Razor.CodeGenerators;
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
using Microsoft.AspNet.Razor.Text;
using Microsoft.AspNet.Razor.Utils;

View File

@ -222,7 +222,9 @@ namespace Microsoft.AspNet.Razor.Parser
protected void InheritsDirectiveCore()
{
BaseTypeDirective(RazorResources.ParseError_InheritsKeyword_Must_Be_Followed_By_TypeName, baseType => new SetBaseTypeChunkGenerator(baseType));
BaseTypeDirective(
RazorResources.ParseError_InheritsKeyword_Must_Be_Followed_By_TypeName,
baseType => new SetBaseTypeChunkGenerator(baseType));
}
protected void BaseTypeDirective(string noTypeNameError, Func<string, SpanChunkGenerator> createChunkGenerator)

View File

@ -334,7 +334,10 @@ namespace Microsoft.AspNet.Razor.Parser
using (PushSpanConfig(span =>
{
span.EditHandler = new ImplicitExpressionEditHandler(Language.TokenizeString, Keywords, acceptTrailingDot: IsNested);
span.EditHandler = new ImplicitExpressionEditHandler(
Language.TokenizeString,
Keywords,
acceptTrailingDot: IsNested);
span.EditHandler.AcceptedCharacters = acceptedCharacters;
span.ChunkGenerator = new ExpressionChunkGenerator();
}))

View File

@ -635,17 +635,20 @@ namespace Microsoft.AspNet.Razor.Parser
Accept(prefix);
// Literal value
// 'quote' should be "Unknown" if not quoted and symbols coming from the tokenizer should never have "Unknown" type.
// 'quote' should be "Unknown" if not quoted and symbols coming from the tokenizer should never have
// "Unknown" type.
var value = ReadWhile(sym =>
// These three conditions find separators which break the attribute value into portions
sym.Type != HtmlSymbolType.WhiteSpace &&
sym.Type != HtmlSymbolType.NewLine &&
sym.Type != HtmlSymbolType.Transition &&
// This condition checks for the end of the attribute value (it repeats some of the checks above
// but for now that's ok)
!IsEndOfAttributeValue(quote, sym));
// These three conditions find separators which break the attribute value into portions
sym.Type != HtmlSymbolType.WhiteSpace &&
sym.Type != HtmlSymbolType.NewLine &&
sym.Type != HtmlSymbolType.Transition &&
// This condition checks for the end of the attribute value (it repeats some of the checks above
// but for now that's ok)
!IsEndOfAttributeValue(quote, sym));
Accept(value);
Span.ChunkGenerator = new LiteralAttributeChunkGenerator(prefix.GetContent(prefixStart), value.GetContent(prefixStart));
Span.ChunkGenerator = new LiteralAttributeChunkGenerator(
prefix.GetContent(prefixStart),
value.GetContent(prefixStart));
}
Output(SpanKind.Markup);
}

View File

@ -45,7 +45,11 @@ namespace Microsoft.AspNet.Razor.Parser.SyntaxTree
Children = contents;
}
[SuppressMessage("Microsoft.Naming", "CA1721:PropertyNamesShouldNotMatchGetMethods", Justification = "Type is the most appropriate name for this property and there is little chance of confusion with GetType")]
[SuppressMessage(
"Microsoft.Naming",
"CA1721:PropertyNamesShouldNotMatchGetMethods",
Justification = "Type is the most appropriate name for this property and there is little chance of " +
"confusion with GetType")]
public BlockType Type { get; }
public IEnumerable<SyntaxTreeNode> Children { get; }
@ -105,7 +109,13 @@ namespace Microsoft.AspNet.Razor.Parser.SyntaxTree
public override string ToString()
{
return string.Format(CultureInfo.CurrentCulture, "{0} Block at {1}::{2} (Gen:{3})", Type, Start, Length, ChunkGenerator);
return string.Format(
CultureInfo.CurrentCulture,
"{0} Block at {1}::{2} (Gen:{3})",
Type,
Start,
Length,
ChunkGenerator);
}
public override bool Equals(object obj)

View File

@ -21,7 +21,11 @@ namespace Microsoft.AspNet.Razor.Parser.SyntaxTree
ChunkGenerator = original.ChunkGenerator;
}
[SuppressMessage("Microsoft.Naming", "CA1721:PropertyNamesShouldNotMatchGetMethods", Justification = "Type is the most appropriate name for this property and there is little chance of confusion with GetType")]
[SuppressMessage(
"Microsoft.Naming",
"CA1721:PropertyNamesShouldNotMatchGetMethods",
Justification = "Type is the most appropriate name for this property and there is little chance of " +
"confusion with GetType")]
public BlockType? Type { get; set; }
public IList<SyntaxTreeNode> Children { get; private set; }
public IParentChunkGenerator ChunkGenerator { get; set; }

View File

@ -4,7 +4,7 @@
using System;
using System.Collections.Generic;
using Microsoft.AspNet.Razor.Chunks.Generators;
using Microsoft.AspNet.Razor.CodeGeneration;
using Microsoft.AspNet.Razor.CodeGenerators;
using Microsoft.AspNet.Razor.Parser;
namespace Microsoft.AspNet.Razor
@ -14,7 +14,8 @@ namespace Microsoft.AspNet.Razor
/// </summary>
public abstract class RazorCodeLanguage
{
private static IDictionary<string, RazorCodeLanguage> _services = new Dictionary<string, RazorCodeLanguage>(StringComparer.OrdinalIgnoreCase)
private static IDictionary<string, RazorCodeLanguage> _services =
new Dictionary<string, RazorCodeLanguage>(StringComparer.OrdinalIgnoreCase)
{
{ "cshtml", new CSharpRazorCodeLanguage() }
};
@ -52,7 +53,11 @@ namespace Microsoft.AspNet.Razor
/// <summary>
/// Constructs the chunk generator. Must return a new instance on EVERY call to ensure thread-safety
/// </summary>
public abstract RazorChunkGenerator CreateChunkGenerator(string className, string rootNamespaceName, string sourceFileName, RazorEngineHost host);
public abstract RazorChunkGenerator CreateChunkGenerator(
string className,
string rootNamespaceName,
string sourceFileName,
RazorEngineHost host);
public abstract CodeGenerator CreateCodeGenerator(CodeGeneratorContext chunkGeneratorContext);
}

View File

@ -5,7 +5,7 @@ using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using Microsoft.AspNet.Razor.Chunks.Generators;
using Microsoft.AspNet.Razor.CodeGeneration;
using Microsoft.AspNet.Razor.CodeGenerators;
using Microsoft.AspNet.Razor.Parser;
using Microsoft.AspNet.Razor.TagHelpers;
using Microsoft.Framework.Internal;
@ -36,7 +36,10 @@ namespace Microsoft.AspNet.Razor
private int _tabSize = 4;
[SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors", Justification = "The code path is safe, it is a property setter and not dependent on other state")]
[SuppressMessage(
"Microsoft.Usage",
"CA2214:DoNotCallOverridableMethodsInConstructors",
Justification = "The code path is safe, it is a property setter and not dependent on other state")]
protected RazorEngineHost()
{
GeneratedClassContext = GeneratedClassContext.Default;

View File

@ -375,9 +375,6 @@ Instead, wrap the contents of the block in "{{}}":
<data name="TagHelpers_CannotHaveCSharpInTagDeclaration" xml:space="preserve">
<value>The tag helper '{0}' must not have C# in the element's attribute declaration area.</value>
</data>
<data name="TagHelpers_TagHelperCodeGeneartorMustBeAssociatedWithATagHelperBlock" xml:space="preserve">
<value>A TagHelperChunkGenerator must only be used with TagHelperBlocks.</value>
</data>
<data name="ParseError_DirectiveMustHaveValue" xml:space="preserve">
<value>Directive '{0}' must have a value.</value>
</data>

View File

@ -8,7 +8,7 @@ using System.Security.Cryptography;
using System.Text;
using System.Threading;
using Microsoft.AspNet.Razor.Chunks.Generators;
using Microsoft.AspNet.Razor.CodeGeneration;
using Microsoft.AspNet.Razor.CodeGenerators;
using Microsoft.AspNet.Razor.Parser;
using Microsoft.AspNet.Razor.Text;
using Microsoft.Framework.Internal;

View File

@ -2,7 +2,7 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNet.Razor.Chunks.Generators;
using Microsoft.AspNet.Razor.CodeGeneration;
using Microsoft.AspNet.Razor.CodeGenerators;
using Microsoft.AspNet.Razor.Parser;
using Xunit;

View File

@ -7,7 +7,7 @@ using Microsoft.AspNet.Razor.Parser.SyntaxTree;
using Microsoft.AspNet.Razor.Test.Framework;
using Xunit;
namespace Microsoft.AspNet.Razor.Chunks
namespace Microsoft.AspNet.Razor.Chunks.Generators
{
public class ChunkTreeBuilderTest
{

View File

@ -2,13 +2,13 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
#if !DNXCORE50
using Microsoft.AspNet.Razor.CodeGeneration;
using Microsoft.AspNet.Razor.CodeGeneration.Visitors;
using Microsoft.AspNet.Razor.CodeGenerators;
using Microsoft.AspNet.Razor.CodeGenerators.Visitors;
using Moq;
using Moq.Protected;
using Xunit;
namespace Microsoft.AspNet.Razor.Chunks
namespace Microsoft.AspNet.Razor.Chunks.Generators
{
public class ChunkVisitorTests
{

View File

@ -9,7 +9,7 @@ using Microsoft.AspNet.Razor.Test.Utils;
using Moq;
using Xunit;
namespace Microsoft.AspNet.Razor.CodeGeneration
namespace Microsoft.AspNet.Razor.CodeGenerators
{
public class CSharpCodeGeneratorTest
{

View File

@ -3,7 +3,7 @@
using Xunit;
namespace Microsoft.AspNet.Razor.CodeGeneration
namespace Microsoft.AspNet.Razor.CodeGenerators
{
public class CSharpCodeWriterTest
{

View File

@ -4,7 +4,7 @@
using System;
using Xunit;
namespace Microsoft.AspNet.Razor.CodeGeneration
namespace Microsoft.AspNet.Razor.CodeGenerators
{
public class CSharpLineMappingWriterTest
{

View File

@ -5,7 +5,7 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Microsoft.AspNet.Razor.CodeGeneration;
using Microsoft.AspNet.Razor.CodeGenerators;
using Microsoft.AspNet.Razor.Parser;
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
using Xunit;

View File

@ -4,7 +4,7 @@
using System;
using System.Collections.Generic;
using Microsoft.AspNet.Razor.Chunks.Generators;
using Microsoft.AspNet.Razor.CodeGeneration;
using Microsoft.AspNet.Razor.CodeGenerators;
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
using Xunit;
@ -33,13 +33,17 @@ namespace Microsoft.AspNet.Razor.Test.Generator
[Fact]
public void ConstructorRequiresNonNullClassName()
{
Assert.Throws<ArgumentException>("className", () => new RazorChunkGenerator(null, TestRootNamespaceName, TestPhysicalPath, CreateHost()));
Assert.Throws<ArgumentException>(
"className",
() => new RazorChunkGenerator(null, TestRootNamespaceName, TestPhysicalPath, CreateHost()));
}
[Fact]
public void ConstructorRequiresNonEmptyClassName()
{
Assert.Throws<ArgumentException>("className", () => new RazorChunkGenerator(string.Empty, TestRootNamespaceName, TestPhysicalPath, CreateHost()));
Assert.Throws<ArgumentException>(
"className",
() => new RazorChunkGenerator(string.Empty, TestRootNamespaceName, TestPhysicalPath, CreateHost()));
}
[Fact]

View File

@ -6,7 +6,7 @@ using System.Linq;
#if DNXCORE50
using System.Reflection;
#endif
using Microsoft.AspNet.Razor.CodeGeneration;
using Microsoft.AspNet.Razor.CodeGenerators;
using Microsoft.AspNet.Razor.TagHelpers;
using Xunit;

View File

@ -1,8 +1,8 @@
using System.Collections.Generic;
using Microsoft.AspNet.Razor.Chunks;
using Microsoft.AspNet.Razor.Chunks.Generators;
using Microsoft.AspNet.Razor.CodeGeneration;
using Microsoft.AspNet.Razor.CodeGeneration.Visitors;
using Microsoft.AspNet.Razor.CodeGenerators;
using Microsoft.AspNet.Razor.CodeGenerators.Visitors;
using Microsoft.AspNet.Razor.TagHelpers;
using Xunit;

View File

@ -1,7 +1,7 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNet.Razor.CodeGeneration;
using Microsoft.AspNet.Razor.CodeGenerators;
namespace Microsoft.AspNet.Razor.Test.Generator
{

View File

@ -1,7 +1,7 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNet.Razor.CodeGeneration;
using Microsoft.AspNet.Razor.CodeGenerators;
namespace Microsoft.AspNet.Razor.Test.Generator
{

View File

@ -5,7 +5,7 @@ using System;
using System.Collections.Generic;
using Xunit;
namespace Microsoft.AspNet.Razor.CodeGeneration
namespace Microsoft.AspNet.Razor.CodeGenerators
{
public class CodeWriterTest
{

View File

@ -1,7 +1,7 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNet.Razor.CodeGeneration;
using Microsoft.AspNet.Razor.CodeGenerators;
using Xunit;
namespace Microsoft.AspNet.Razor.Test.Generator

View File

@ -6,7 +6,7 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Microsoft.AspNet.Razor.CodeGeneration;
using Microsoft.AspNet.Razor.CodeGenerators;
using Microsoft.AspNet.Razor.Test.Utils;
using Microsoft.AspNet.Testing;
using Xunit;
@ -127,7 +127,9 @@ namespace Microsoft.AspNet.Razor.Test.Generator
}
var sourceLocation = string.Format("TestFiles/CodeGenerator/Source/{0}.{1}", name, FileExtension);
var expectedOutput = TestFile.Create(string.Format("TestFiles/CodeGenerator/Output/{0}.{1}", baselineName, BaselineExtension)).ReadAllText();
var expectedOutput = TestFile
.Create(string.Format("TestFiles/CodeGenerator/Output/{0}.{1}", baselineName, BaselineExtension))
.ReadAllText();
// Set up the host and engine
var host = CreateHost();
@ -171,10 +173,19 @@ namespace Microsoft.AspNet.Razor.Test.Generator
{
var sourceFile = NormalizeNewLines(source);
var sourceFileName = generatePragmas ? string.Format("{0}.{1}", name, FileExtension) : null;
results = engine.GenerateCode(sourceFile, className: name, rootNamespace: TestRootNamespaceName, sourceFileName: sourceFileName);
results = engine.GenerateCode(
sourceFile,
className: name,
rootNamespace: TestRootNamespaceName,
sourceFileName: sourceFileName);
}
// Only called if GENERATE_BASELINES is set, otherwise compiled out.
BaselineWriter.WriteBaseline(string.Format(@"test\Microsoft.AspNet.Razor.Test\TestFiles\ChunkGenerator\Output\{0}.{1}", baselineName, BaselineExtension), results.GeneratedCode);
BaselineWriter.WriteBaseline(
string.Format(
@"test\Microsoft.AspNet.Razor.Test\TestFiles\ChunkGenerator\Output\{0}.{1}",
baselineName,
BaselineExtension),
results.GeneratedCode);
#if !GENERATE_BASELINES
var textOutput = results.GeneratedCode;

View File

@ -5,8 +5,8 @@ using System;
#if DNXCORE50
using System.Reflection;
#endif
using Microsoft.AspNet.Razor.CodeGeneration;
using Microsoft.AspNet.Razor.CodeGeneration.Visitors;
using Microsoft.AspNet.Razor.CodeGenerators;
using Microsoft.AspNet.Razor.CodeGenerators.Visitors;
using Microsoft.AspNet.Razor.TagHelpers;
using Xunit;
@ -58,7 +58,9 @@ namespace Microsoft.AspNet.Razor.Test.Generator
GeneratedClassContext = originalHost.GeneratedClassContext;
}
public override CodeGenerator DecorateCodeGenerator(CodeGenerator incomingBuilder, CodeGeneratorContext context)
public override CodeGenerator DecorateCodeGenerator(
CodeGenerator incomingBuilder,
CodeGeneratorContext context)
{
return new AttributeChunkGeneratorReplacingCodeGenerator(context);
}

View File

@ -4,8 +4,8 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNet.Razor.CodeGeneration;
using Microsoft.AspNet.Razor.CodeGeneration.Visitors;
using Microsoft.AspNet.Razor.CodeGenerators;
using Microsoft.AspNet.Razor.CodeGenerators.Visitors;
using Microsoft.AspNet.Razor.Parser;
using Microsoft.AspNet.Razor.TagHelpers;
@ -100,7 +100,9 @@ namespace Microsoft.AspNet.Razor.Test.Generator
}
protected override CSharpCodeVisitor CreateCSharpCodeVisitor(CSharpCodeWriter writer, CodeGeneratorContext context)
protected override CSharpCodeVisitor CreateCSharpCodeVisitor(
CSharpCodeWriter writer,
CodeGeneratorContext context)
{
var visitor = base.CreateCSharpCodeVisitor(writer, context);
visitor.TagHelperRenderer = new NoUniqueIdsTagHelperCodeRenderer(visitor, writer, context);

View File

@ -124,7 +124,10 @@ namespace Microsoft.AspNet.Razor.Test.Framework
{
private const BlockType ThisBlockType = BlockType.Markup;
public MarkupBlock(BlockType blockType, IParentChunkGenerator chunkGenerator, IEnumerable<SyntaxTreeNode> children)
public MarkupBlock(
BlockType blockType,
IParentChunkGenerator chunkGenerator,
IEnumerable<SyntaxTreeNode> children)
: base(blockType, children, chunkGenerator)
{
}

View File

@ -19,12 +19,17 @@ namespace Microsoft.AspNet.Razor.Test.Framework
public static UnclassifiedCodeSpanConstructor EmptyCSharp(this SpanFactory self)
{
return new UnclassifiedCodeSpanConstructor(
self.Span(SpanKind.Code, new CSharpSymbol(self.LocationTracker.CurrentLocation, string.Empty, CSharpSymbolType.Unknown)));
self.Span(
SpanKind.Code,
new CSharpSymbol(self.LocationTracker.CurrentLocation, string.Empty, CSharpSymbolType.Unknown)));
}
public static SpanConstructor EmptyHtml(this SpanFactory self)
{
return self.Span(SpanKind.Markup, new HtmlSymbol(self.LocationTracker.CurrentLocation, string.Empty, HtmlSymbolType.Unknown))
return self
.Span(
SpanKind.Markup,
new HtmlSymbol(self.LocationTracker.CurrentLocation, string.Empty, HtmlSymbolType.Unknown))
.With(new MarkupChunkGenerator());
}
@ -36,7 +41,9 @@ namespace Microsoft.AspNet.Razor.Test.Framework
public static SpanConstructor CodeTransition(this SpanFactory self)
{
return self.Span(SpanKind.Transition, SyntaxConstants.TransitionString, markup: false).Accepts(AcceptedCharacters.None);
return self
.Span(SpanKind.Transition, SyntaxConstants.TransitionString, markup: false)
.Accepts(AcceptedCharacters.None);
}
public static SpanConstructor CodeTransition(this SpanFactory self, string content)
@ -46,7 +53,9 @@ namespace Microsoft.AspNet.Razor.Test.Framework
public static SpanConstructor CodeTransition(this SpanFactory self, CSharpSymbolType type)
{
return self.Span(SpanKind.Transition, SyntaxConstants.TransitionString, type).Accepts(AcceptedCharacters.None);
return self
.Span(SpanKind.Transition, SyntaxConstants.TransitionString, type)
.Accepts(AcceptedCharacters.None);
}
public static SpanConstructor CodeTransition(this SpanFactory self, string content, CSharpSymbolType type)
@ -56,7 +65,9 @@ namespace Microsoft.AspNet.Razor.Test.Framework
public static SpanConstructor MarkupTransition(this SpanFactory self)
{
return self.Span(SpanKind.Transition, SyntaxConstants.TransitionString, markup: true).Accepts(AcceptedCharacters.None);
return self
.Span(SpanKind.Transition, SyntaxConstants.TransitionString, markup: true)
.Accepts(AcceptedCharacters.None);
}
public static SpanConstructor MarkupTransition(this SpanFactory self, string content)
@ -66,7 +77,9 @@ namespace Microsoft.AspNet.Razor.Test.Framework
public static SpanConstructor MarkupTransition(this SpanFactory self, HtmlSymbolType type)
{
return self.Span(SpanKind.Transition, SyntaxConstants.TransitionString, type).Accepts(AcceptedCharacters.None);
return self
.Span(SpanKind.Transition, SyntaxConstants.TransitionString, type)
.Accepts(AcceptedCharacters.None);
}
public static SpanConstructor MarkupTransition(this SpanFactory self, string content, HtmlSymbolType type)
@ -241,7 +254,10 @@ namespace Microsoft.AspNet.Razor.Test.Framework
return AutoCompleteWith(self, autoCompleteString, atEndOfSpan: false);
}
public static SpanConstructor AutoCompleteWith(this SpanConstructor self, string autoCompleteString, bool atEndOfSpan)
public static SpanConstructor AutoCompleteWith(
this SpanConstructor self,
string autoCompleteString,
bool atEndOfSpan)
{
return self.With(new AutoCompleteEditHandler(
SpanConstructor.TestTokenizer,
@ -289,7 +305,8 @@ namespace Microsoft.AspNet.Razor.Test.Framework
public SpanConstructor AsImplicitExpression(ISet<string> keywords, bool acceptTrailingDot)
{
return _self.With(new ImplicitExpressionEditHandler(SpanConstructor.TestTokenizer, keywords, acceptTrailingDot))
return _self
.With(new ImplicitExpressionEditHandler(SpanConstructor.TestTokenizer, keywords, acceptTrailingDot))
.With(new ExpressionChunkGenerator());
}

View File

@ -61,37 +61,58 @@ namespace Microsoft.AspNet.Razor.Test.Parser.CSharp
[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);
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);
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);
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);
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);
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);
SingleSpanBlockTest(
"if(int i = 0; i < 10; new Foo { Bar = \"baz\" }) { Debug.WriteLine(@\"foo } bar\"); }",
BlockType.Statement,
SpanKind.Code);
}
[Fact]
@ -113,31 +134,46 @@ namespace Microsoft.AspNet.Razor.Test.Parser.CSharp
[Fact]
public void ParseBlockSupportsBlockCommentBetweenIfAndElseClause()
{
SingleSpanBlockTest("if(foo) { bar(); } /* Foo */ /* Bar */ else { baz(); }", BlockType.Statement, SpanKind.Code, acceptedCharacters: AcceptedCharacters.None);
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);
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);
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);
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);
SingleSpanBlockTest(
"if(foo) { bar(); } /* Foo */ /* Bar */ else if(bar) { baz(); }",
BlockType.Statement,
SpanKind.Code);
}
[Fact]
@ -228,7 +264,9 @@ else if(bar) { baz(); }", BlockType.Statement, SpanKind.Code);
const string document = ifStatement + elseIfBranch + elseBranch + elseIfBranch;
const string expected = ifStatement + elseIfBranch + elseBranch;
ParseBlockTest(document, new StatementBlock(Factory.Code(expected).AsStatement().Accepts(AcceptedCharacters.None)));
ParseBlockTest(
document,
new StatementBlock(Factory.Code(expected).AsStatement().Accepts(AcceptedCharacters.None)));
}
[Fact]
@ -244,7 +282,8 @@ else if(bar) { baz(); }", 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
// 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"");
}";
@ -257,7 +296,11 @@ else if(bar) { baz(); }", BlockType.Statement, SpanKind.Code);
[Fact]
public void ParseBlockCorrectlyParsesDoWhileBlock()
{
SingleSpanBlockTest("do { var foo = bar; } while(foo != bar);", BlockType.Statement, SpanKind.Code, acceptedCharacters: AcceptedCharacters.None);
SingleSpanBlockTest(
"do { var foo = bar; } while(foo != bar);",
BlockType.Statement,
SpanKind.Code,
acceptedCharacters: AcceptedCharacters.None);
}
[Fact]
@ -275,7 +318,11 @@ else if(bar) { baz(); }", BlockType.Statement, SpanKind.Code);
[Fact]
public void ParseBlockCorrectlyParsesDoWhileBlockMissingWhileConditionWithSemicolon()
{
SingleSpanBlockTest("do { var foo = bar; } while;", BlockType.Statement, SpanKind.Code, acceptedCharacters: AcceptedCharacters.None);
SingleSpanBlockTest(
"do { var foo = bar; } while;",
BlockType.Statement,
SpanKind.Code,
acceptedCharacters: AcceptedCharacters.None);
}
[Fact]
@ -287,7 +334,11 @@ else if(bar) { baz(); }", BlockType.Statement, SpanKind.Code);
[Fact]
public void ParseBlockSupportsBlockCommentBetweenDoAndWhileClause()
{
SingleSpanBlockTest("do { var foo = bar; } /* Foo */ /* Bar */ while(true);", BlockType.Statement, SpanKind.Code, acceptedCharacters: AcceptedCharacters.None);
SingleSpanBlockTest(
"do { var foo = bar; } /* Foo */ /* Bar */ while(true);",
BlockType.Statement,
SpanKind.Code,
acceptedCharacters: AcceptedCharacters.None);
}
[Fact]
@ -302,7 +353,9 @@ while(true);", BlockType.Statement, SpanKind.Code, acceptedCharacters: AcceptedC
[Fact]
public void ParseBlockSupportsRazorCommentBetweenDoAndWhileClause()
{
RunRazorCommentBetweenClausesTest("do { var foo = bar; } ", " while(true);", acceptedCharacters: AcceptedCharacters.None);
RunRazorCommentBetweenClausesTest(
"do { var foo = bar; } ", " while(true);",
acceptedCharacters: AcceptedCharacters.None);
}
[Fact]
@ -343,25 +396,40 @@ while(true);", BlockType.Statement, SpanKind.Code, acceptedCharacters: AcceptedC
[Fact]
public void ParseBlockSkipsParenthesisedExpressionAndThenBalancesBracesIfFirstIdentifierIsLockKeyword()
{
SingleSpanBlockTest("lock(foo) { Debug.WriteLine(@\"foo } bar\"); }", BlockType.Statement, SpanKind.Code, acceptedCharacters: AcceptedCharacters.None);
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));
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));
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);
NamespaceImportTest(
"using Foo.Bar.Baz;",
" Foo.Bar.Baz",
AcceptedCharacters.NonWhiteSpace | AcceptedCharacters.WhiteSpace);
}
[Fact]
@ -377,7 +445,10 @@ while(true);", BlockType.Statement, SpanKind.Code, acceptedCharacters: AcceptedC
[Fact]
public void ParseBlockParsesNamespaceAliasWithSemicolonForUsingKeywordIfIsInValidFormat()
{
NamespaceImportTest("using FooBarBaz = FooBarBaz;", " FooBarBaz = FooBarBaz", AcceptedCharacters.NonWhiteSpace | AcceptedCharacters.WhiteSpace);
NamespaceImportTest(
"using FooBarBaz = FooBarBaz;",
" FooBarBaz = FooBarBaz",
AcceptedCharacters.NonWhiteSpace | AcceptedCharacters.WhiteSpace);
}
[Fact]
@ -390,17 +461,29 @@ while(true);", BlockType.Statement, SpanKind.Code, acceptedCharacters: AcceptedC
public void ParseBlockTerminatesSingleLineCommentAtEndOfFile()
{
const string document = "foreach(var f in Foo) { // foo bar baz";
SingleSpanBlockTest(document, document, BlockType.Statement, SpanKind.Code,
new RazorError(RazorResources.FormatParseError_Expected_EndOfBlock_Before_EOF("foreach", '}', '{'), SourceLocation.Zero));
SingleSpanBlockTest(
document,
document,
BlockType.Statement,
SpanKind.Code,
new RazorError(
RazorResources.FormatParseError_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(RazorResources.ParseError_BlockComment_Not_Terminated, 24, 0, 24),
new RazorError(RazorResources.FormatParseError_Expected_EndOfBlock_Before_EOF("foreach", '}', '{'), SourceLocation.Zero));
SingleSpanBlockTest(
document,
document,
BlockType.Statement,
SpanKind.Code,
new RazorError(RazorResources.ParseError_BlockComment_Not_Terminated, 24, 0, 24),
new RazorError(
RazorResources.FormatParseError_Expected_EndOfBlock_Before_EOF("foreach", '}', '{'),
SourceLocation.Zero));
}
[Fact]
@ -426,13 +509,19 @@ while(true);", BlockType.Statement, SpanKind.Code, acceptedCharacters: AcceptedC
[Fact]
public void ParseBlockSupportsBlockCommentBetweenCatchAndFinallyClause()
{
SingleSpanBlockTest("try { bar(); } catch(bar) { baz(); } /* Foo */ /* Bar */ finally { biz(); }", BlockType.Statement, SpanKind.Code, acceptedCharacters: AcceptedCharacters.None);
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);
RunRazorCommentBetweenClausesTest(
"try { bar(); } catch(bar) { baz(); } ", " finally { biz(); }",
acceptedCharacters: AcceptedCharacters.None);
}
[Fact]
@ -519,7 +608,11 @@ catch(bar) { baz(); }", BlockType.Statement, SpanKind.Code);
[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);
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]
@ -532,7 +625,8 @@ catch(bar) { baz(); }", BlockType.Statement, SpanKind.Code);
public void ParseBlockSupportsMarkupWithinAdditionalCatchClauses()
{
RunSimpleWrappedMarkupTest(
prefix: "try { var foo = new { } } catch(Foo Bar Baz) { var foo = new { } } catch(Foo Bar Baz) { var foo = new { } } catch(Foo Bar Baz) {",
prefix: "try { var foo = new { } } catch(Foo Bar Baz) { var foo = new { } } catch(Foo Bar Baz) " +
"{ var foo = new { } } catch(Foo Bar Baz) {",
markup: " <p>Foo</p> ",
suffix: "}",
expectedMarkup: new MarkupBlock(

View File

@ -4,7 +4,7 @@
using System;
using System.Threading;
using System.Web.WebPages.TestUtils;
using Microsoft.AspNet.Razor.CodeGeneration;
using Microsoft.AspNet.Razor.CodeGenerators;
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
using Microsoft.AspNet.Razor.Test.Framework;
using Microsoft.AspNet.Razor.Test.Utils;

View File

@ -2,7 +2,7 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNet.Razor.Chunks.Generators;
using Microsoft.AspNet.Razor.CodeGeneration;
using Microsoft.AspNet.Razor.CodeGenerators;
using Microsoft.AspNet.Razor.Parser;
using Xunit;

View File

@ -8,7 +8,7 @@ using System.Text;
using System.Threading;
using System.Web.WebPages.TestUtils;
using Microsoft.AspNet.Razor.Chunks.Generators;
using Microsoft.AspNet.Razor.CodeGeneration;
using Microsoft.AspNet.Razor.CodeGenerators;
using Microsoft.AspNet.Razor.Parser;
using Microsoft.AspNet.Razor.Text;
using Moq;