Implement consistent error story for directives.

- Added error case that enforces whitespace in between directive tokens.
- Upon encountering invalid directive tokens/states we bail out of parsing and log an appropriate error.
- Raised directive parse errors to the IR layer. This is slightly hacky given the parsers limitations; we swap out the error sink temporarily to capture all directive parser errors and then shove the errors collected onto the directives chunk generator.
- Added a `MalformedDiretiveIRNode` and corresponding pass to represent directives that are in an invalid state. Chose to not take the path of using the default `DirectiveIRNode.Diagnostics` member to enable users who are extending directives to only ever have to work with "valid" directives. If they want to work with malformed directives they can search the IR document for their malformed counterpart and handle it separately.
- Updated existing test expectations
- Removed some existing tests that were no longer valid (we don't call into user code if a directive is malformed).

#1173
This commit is contained in:
N. Taylor Mullen 2017-05-22 10:17:22 -07:00
parent dd4e163173
commit 132c8c7a7e
46 changed files with 1337 additions and 839 deletions

View File

@ -24,18 +24,8 @@ namespace Microsoft.AspNetCore.Razor.Language
throw new ArgumentNullException(nameof(syntaxTree));
}
var errorSink = new ErrorSink();
var sectionVerifier = new NestedSectionVerifier();
sectionVerifier.Verify(syntaxTree, errorSink);
if (errorSink.Errors.Count > 0)
{
// Temporary code while we're still using legacy diagnostics in the SyntaxTree.
var errors = errorSink.Errors.Select(error => RazorDiagnostic.Create(error));
var combinedErrors = syntaxTree.Diagnostics.Concat(errors);
syntaxTree = RazorSyntaxTree.Create(syntaxTree.Root, syntaxTree.Source, combinedErrors, syntaxTree.Options);
}
sectionVerifier.Verify(syntaxTree);
return syntaxTree;
}
@ -43,11 +33,9 @@ namespace Microsoft.AspNetCore.Razor.Language
private class NestedSectionVerifier : ParserVisitor
{
private int _nestedLevel;
private ErrorSink _errorSink;
public void Verify(RazorSyntaxTree tree, ErrorSink errorSink)
public void Verify(RazorSyntaxTree tree)
{
_errorSink = errorSink;
tree.Root.Accept(this);
}
@ -57,10 +45,12 @@ namespace Microsoft.AspNetCore.Razor.Language
{
var directiveStart = block.Children.First(child => !child.IsBlock && ((Span)child).Kind == SpanKindInternal.Transition).Start;
var errorLength = /* @ */ 1 + SectionDirective.Directive.Directive.Length;
_errorSink.OnError(
directiveStart,
LegacyResources.FormatParseError_Sections_Cannot_Be_Nested(LegacyResources.SectionExample_CS),
errorLength);
var error = RazorDiagnostic.Create(
new RazorError(
LegacyResources.FormatParseError_Sections_Cannot_Be_Nested(LegacyResources.SectionExample_CS),
directiveStart,
errorLength));
chunkGenerator.Diagnostics.Add(error);
}
_nestedLevel++;

View File

@ -131,12 +131,32 @@ namespace Microsoft.AspNetCore.Razor.Language
public override void VisitAddTagHelperSpan(AddTagHelperChunkGenerator chunkGenerator, Span span)
{
_builder.Push(new DirectiveIRNode()
RazorIRNode directiveNode;
if (IsMalformed(chunkGenerator.Diagnostics))
{
Name = CSharpCodeParser.AddTagHelperDirectiveDescriptor.Directive,
Descriptor = CSharpCodeParser.AddTagHelperDirectiveDescriptor,
Source = BuildSourceSpanFromNode(span),
});
directiveNode = new MalformedDirectiveIRNode()
{
Name = CSharpCodeParser.AddTagHelperDirectiveDescriptor.Directive,
Descriptor = CSharpCodeParser.AddTagHelperDirectiveDescriptor,
Source = BuildSourceSpanFromNode(span),
};
}
else
{
directiveNode = new DirectiveIRNode()
{
Name = CSharpCodeParser.AddTagHelperDirectiveDescriptor.Directive,
Descriptor = CSharpCodeParser.AddTagHelperDirectiveDescriptor,
Source = BuildSourceSpanFromNode(span),
};
}
for (var i = 0; i < chunkGenerator.Diagnostics.Count; i++)
{
directiveNode.Diagnostics.Add(chunkGenerator.Diagnostics[i]);
}
_builder.Push(directiveNode);
_builder.Add(new DirectiveTokenIRNode()
{
@ -150,12 +170,32 @@ namespace Microsoft.AspNetCore.Razor.Language
public override void VisitRemoveTagHelperSpan(RemoveTagHelperChunkGenerator chunkGenerator, Span span)
{
_builder.Push(new DirectiveIRNode()
RazorIRNode directiveNode;
if (IsMalformed(chunkGenerator.Diagnostics))
{
Name = CSharpCodeParser.RemoveTagHelperDirectiveDescriptor.Directive,
Descriptor = CSharpCodeParser.RemoveTagHelperDirectiveDescriptor,
Source = BuildSourceSpanFromNode(span),
});
directiveNode = new MalformedDirectiveIRNode()
{
Name = CSharpCodeParser.RemoveTagHelperDirectiveDescriptor.Directive,
Descriptor = CSharpCodeParser.RemoveTagHelperDirectiveDescriptor,
Source = BuildSourceSpanFromNode(span),
};
}
else
{
directiveNode = new DirectiveIRNode()
{
Name = CSharpCodeParser.RemoveTagHelperDirectiveDescriptor.Directive,
Descriptor = CSharpCodeParser.RemoveTagHelperDirectiveDescriptor,
Source = BuildSourceSpanFromNode(span),
};
}
for (var i = 0; i < chunkGenerator.Diagnostics.Count; i++)
{
directiveNode.Diagnostics.Add(chunkGenerator.Diagnostics[i]);
}
_builder.Push(directiveNode);
_builder.Add(new DirectiveTokenIRNode()
{
@ -169,12 +209,32 @@ namespace Microsoft.AspNetCore.Razor.Language
public override void VisitTagHelperPrefixDirectiveSpan(TagHelperPrefixDirectiveChunkGenerator chunkGenerator, Span span)
{
_builder.Push(new DirectiveIRNode()
RazorIRNode directiveNode;
if (IsMalformed(chunkGenerator.Diagnostics))
{
Name = CSharpCodeParser.TagHelperPrefixDirectiveDescriptor.Directive,
Descriptor = CSharpCodeParser.TagHelperPrefixDirectiveDescriptor,
Source = BuildSourceSpanFromNode(span),
});
directiveNode = new MalformedDirectiveIRNode()
{
Name = CSharpCodeParser.TagHelperPrefixDirectiveDescriptor.Directive,
Descriptor = CSharpCodeParser.TagHelperPrefixDirectiveDescriptor,
Source = BuildSourceSpanFromNode(span),
};
}
else
{
directiveNode = new DirectiveIRNode()
{
Name = CSharpCodeParser.TagHelperPrefixDirectiveDescriptor.Directive,
Descriptor = CSharpCodeParser.TagHelperPrefixDirectiveDescriptor,
Source = BuildSourceSpanFromNode(span),
};
}
for (var i = 0; i < chunkGenerator.Diagnostics.Count; i++)
{
directiveNode.Diagnostics.Add(chunkGenerator.Diagnostics[i]);
}
_builder.Push(directiveNode);
_builder.Add(new DirectiveTokenIRNode()
{
@ -235,12 +295,32 @@ namespace Microsoft.AspNetCore.Razor.Language
{
_insideLineDirective = true;
_builder.Push(new DirectiveIRNode()
RazorIRNode directiveNode;
if (IsMalformed(chunkGenerator.Diagnostics))
{
Name = chunkGenerator.Descriptor.Directive,
Descriptor = chunkGenerator.Descriptor,
Source = BuildSourceSpanFromNode(block),
});
directiveNode = new MalformedDirectiveIRNode()
{
Name = chunkGenerator.Descriptor.Directive,
Descriptor = chunkGenerator.Descriptor,
Source = BuildSourceSpanFromNode(block),
};
}
else
{
directiveNode = new DirectiveIRNode()
{
Name = chunkGenerator.Descriptor.Directive,
Descriptor = chunkGenerator.Descriptor,
Source = BuildSourceSpanFromNode(block),
};
}
for (var i = 0; i < chunkGenerator.Diagnostics.Count; i++)
{
directiveNode.Diagnostics.Add(chunkGenerator.Diagnostics[i]);
}
_builder.Push(directiveNode);
base.VisitDirectiveBlock(chunkGenerator, block);
@ -274,12 +354,32 @@ namespace Microsoft.AspNetCore.Razor.Language
public override void VisitDirectiveBlock(DirectiveChunkGenerator chunkGenerator, Block block)
{
_builder.Push(new DirectiveIRNode()
RazorIRNode directiveNode;
if (IsMalformed(chunkGenerator.Diagnostics))
{
Name = chunkGenerator.Descriptor.Directive,
Descriptor = chunkGenerator.Descriptor,
Source = BuildSourceSpanFromNode(block),
});
directiveNode = new MalformedDirectiveIRNode()
{
Name = chunkGenerator.Descriptor.Directive,
Descriptor = chunkGenerator.Descriptor,
Source = BuildSourceSpanFromNode(block),
};
}
else
{
directiveNode = new DirectiveIRNode()
{
Name = chunkGenerator.Descriptor.Directive,
Descriptor = chunkGenerator.Descriptor,
Source = BuildSourceSpanFromNode(block),
};
}
for (var i = 0; i < chunkGenerator.Diagnostics.Count; i++)
{
directiveNode.Diagnostics.Add(chunkGenerator.Diagnostics[i]);
}
_builder.Push(directiveNode);
VisitDefault(block);
@ -675,5 +775,8 @@ namespace Microsoft.AspNetCore.Razor.Language
}
}
}
private static bool IsMalformed(List<RazorDiagnostic> diagnostics)
=> diagnostics.Count > 0 && diagnostics.Any(diagnostic => diagnostic.Severity == RazorDiagnosticSeverity.Error);
}
}

View File

@ -47,11 +47,10 @@ namespace Microsoft.AspNetCore.Razor.Language
var errorList = new List<RazorDiagnostic>();
var descriptors = feature.GetDescriptors();
var errorSink = new ErrorSink();
var directives = visitor.Directives;
descriptors = ProcessDirectives(directives, descriptors, errorSink);
descriptors = ProcessDirectives(directives, descriptors);
var tagHelperPrefix = ProcessTagHelperPrefix(directives, codeDocument, errorSink);
var tagHelperPrefix = ProcessTagHelperPrefix(directives, codeDocument);
var root = syntaxTree.Root;
var context = TagHelperDocumentContext.Create(tagHelperPrefix, descriptors);
@ -59,18 +58,14 @@ namespace Microsoft.AspNetCore.Razor.Language
if (descriptors.Count == 0)
{
if (errorSink.Errors.Count == 0 && errorList.Count == 0)
{
// No TagHelpers and errors, no op.
return;
}
}
else
{
var rewriter = new TagHelperParseTreeRewriter(tagHelperPrefix, descriptors);
root = rewriter.Rewrite(root, errorSink);
// No descriptors, no-op.
return;
}
var errorSink = new ErrorSink();
var rewriter = new TagHelperParseTreeRewriter(tagHelperPrefix, descriptors);
root = rewriter.Rewrite(root, errorSink);
// Temporary code while we're still using legacy diagnostics in the SyntaxTree.
errorList.AddRange(errorSink.Errors.Select(error => RazorDiagnostic.Create(error)));
@ -83,7 +78,7 @@ namespace Microsoft.AspNetCore.Razor.Language
}
// Internal for testing
internal string ProcessTagHelperPrefix(List<TagHelperDirectiveDescriptor> directives, RazorCodeDocument codeDocument, ErrorSink errorSink)
internal string ProcessTagHelperPrefix(List<TagHelperDirectiveDescriptor> directives, RazorCodeDocument codeDocument)
{
// We only support a single prefix directive.
TagHelperDirectiveDescriptor prefixDirective = null;
@ -97,7 +92,7 @@ namespace Microsoft.AspNetCore.Razor.Language
}
var prefix = prefixDirective?.DirectiveText;
if (prefix != null && !IsValidTagHelperPrefix(prefix, prefixDirective.Location, errorSink))
if (prefix != null && !IsValidTagHelperPrefix(prefix, prefixDirective.Location, prefixDirective.Diagnostics))
{
prefix = null;
}
@ -112,8 +107,7 @@ namespace Microsoft.AspNetCore.Razor.Language
internal IReadOnlyList<TagHelperDescriptor> ProcessDirectives(
IReadOnlyList<TagHelperDirectiveDescriptor> directives,
IReadOnlyList<TagHelperDescriptor> tagHelpers,
ErrorSink errorSink)
IReadOnlyList<TagHelperDescriptor> tagHelpers)
{
var matches = new HashSet<TagHelperDescriptor>(TagHelperDescriptorComparer.Default);
@ -126,7 +120,7 @@ namespace Microsoft.AspNetCore.Razor.Language
{
case TagHelperDirectiveType.AddTagHelper:
parsed = ParseAddOrRemoveDirective(directive, errorSink);
parsed = ParseAddOrRemoveDirective(directive);
if (parsed == null)
{
// Skip this one, it's an error
@ -152,7 +146,7 @@ namespace Microsoft.AspNetCore.Razor.Language
case TagHelperDirectiveType.RemoveTagHelper:
parsed = ParseAddOrRemoveDirective(directive, errorSink);
parsed = ParseAddOrRemoveDirective(directive);
if (parsed == null)
{
// Skip this one, it's an error
@ -196,7 +190,7 @@ namespace Microsoft.AspNetCore.Razor.Language
}
// Internal for testing
internal ParsedDirective ParseAddOrRemoveDirective(TagHelperDirectiveDescriptor directive, ErrorSink errorSink)
internal ParsedDirective ParseAddOrRemoveDirective(TagHelperDirectiveDescriptor directive)
{
var text = directive.DirectiveText;
var lookupStrings = text?.Split(new[] { ',' });
@ -206,10 +200,12 @@ namespace Microsoft.AspNetCore.Razor.Language
lookupStrings.Any(string.IsNullOrWhiteSpace) ||
lookupStrings.Length != 2)
{
errorSink.OnError(
directive.Location,
Resources.FormatInvalidTagHelperLookupText(text),
Math.Max(text.Length, 1));
directive.Diagnostics.Add(
RazorDiagnostic.Create(
new RazorError(
Resources.FormatInvalidTagHelperLookupText(text),
directive.Location,
Math.Max(text.Length, 1))));
return null;
}
@ -238,20 +234,19 @@ namespace Microsoft.AspNetCore.Razor.Language
internal bool IsValidTagHelperPrefix(
string prefix,
SourceLocation directiveLocation,
ErrorSink errorSink)
List<RazorDiagnostic> diagnostics)
{
foreach (var character in prefix)
{
// Prefixes are correlated with tag names, tag names cannot have whitespace.
if (char.IsWhiteSpace(character) || InvalidNonWhitespaceNameCharacters.Contains(character))
{
errorSink.OnError(
directiveLocation,
Resources.FormatInvalidTagHelperPrefixValue(
SyntaxConstants.CSharp.TagHelperPrefixKeyword,
character,
prefix),
prefix.Length);
diagnostics.Add(
RazorDiagnostic.Create(
new RazorError(
Resources.FormatInvalidTagHelperPrefixValue(SyntaxConstants.CSharp.TagHelperPrefixKeyword, character, prefix),
directiveLocation,
prefix.Length)));
return false;
}
@ -323,23 +318,27 @@ namespace Microsoft.AspNetCore.Razor.Language
public override void VisitAddTagHelperSpan(AddTagHelperChunkGenerator chunkGenerator, Span span)
{
Directives.Add(CreateDirective(span, chunkGenerator.LookupText, TagHelperDirectiveType.AddTagHelper));
var directive = CreateDirective(span, chunkGenerator.LookupText, TagHelperDirectiveType.AddTagHelper, chunkGenerator.Diagnostics);
Directives.Add(directive);
}
public override void VisitRemoveTagHelperSpan(RemoveTagHelperChunkGenerator chunkGenerator, Span span)
{
Directives.Add(CreateDirective(span, chunkGenerator.LookupText, TagHelperDirectiveType.RemoveTagHelper));
var directive = CreateDirective(span, chunkGenerator.LookupText, TagHelperDirectiveType.RemoveTagHelper, chunkGenerator.Diagnostics);
Directives.Add(directive);
}
public override void VisitTagHelperPrefixDirectiveSpan(TagHelperPrefixDirectiveChunkGenerator chunkGenerator, Span span)
{
Directives.Add(CreateDirective(span, chunkGenerator.Prefix, TagHelperDirectiveType.TagHelperPrefix));
var directive = CreateDirective(span, chunkGenerator.Prefix, TagHelperDirectiveType.TagHelperPrefix, chunkGenerator.Diagnostics);
Directives.Add(directive);
}
private TagHelperDirectiveDescriptor CreateDirective(
Span span,
string directiveText,
TagHelperDirectiveType directiveType)
TagHelperDirectiveType directiveType,
List<RazorDiagnostic> diagnostics)
{
directiveText = directiveText.Trim();
if (directiveText.Length >= 2 &&
@ -375,6 +374,7 @@ namespace Microsoft.AspNetCore.Razor.Language
DirectiveText = directiveText,
Location = directiveStart,
DirectiveType = directiveType,
Diagnostics = diagnostics,
};
return directiveDescriptor;

View File

@ -15,19 +15,19 @@ namespace Microsoft.AspNetCore.Razor.Language
var visitor = new Visitor();
visitor.VisitDocument(irDocument);
foreach (var (node, parent) in visitor.DirectiveNodes)
foreach (var nodeReference in visitor.DirectiveNodes)
{
parent.Children.Remove(node);
nodeReference.Remove();
}
}
private class Visitor : RazorIRNodeWalker
{
public IList<(DirectiveIRNode node, RazorIRNode parent)> DirectiveNodes { get; } = new List<(DirectiveIRNode node, RazorIRNode parent)>();
public IList<RazorIRNodeReference> DirectiveNodes { get; } = new List<RazorIRNodeReference>();
public override void VisitDirective(DirectiveIRNode node)
{
DirectiveNodes.Add((node, Parent));
DirectiveNodes.Add(new RazorIRNodeReference(Parent, node));
}
}
}

View File

@ -0,0 +1,45 @@
// Copyright(c) .NET Foundation.All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Linq;
namespace Microsoft.AspNetCore.Razor.Language.Intermediate
{
public sealed class MalformedDirectiveIRNode : RazorIRNode
{
private RazorDiagnosticCollection _diagnostics;
public override ItemCollection Annotations { get; }
public override RazorDiagnosticCollection Diagnostics
{
get
{
if (_diagnostics == null)
{
_diagnostics = new DefaultDiagnosticCollection();
}
return _diagnostics;
}
}
public override RazorIRNodeCollection Children { get; } = new DefaultIRNodeCollection();
public override SourceSpan? Source { get; set; }
public override bool HasDiagnostics => _diagnostics != null && _diagnostics.Count > 0;
public string Name { get; set; }
public IEnumerable<DirectiveTokenIRNode> Tokens => Children.OfType<DirectiveTokenIRNode>();
public DirectiveDescriptor Descriptor { get; set; }
public override void Accept(RazorIRNodeVisitor visitor)
{
visitor.VisitMalformedDirective(this);
}
}
}

View File

@ -29,6 +29,11 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
VisitDefault(node);
}
public virtual void VisitMalformedDirective(MalformedDirectiveIRNode node)
{
VisitDefault(node);
}
public virtual void VisitExtension(ExtensionIRNode node)
{
VisitDefault(node);

View File

@ -2,19 +2,24 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Extensions.Internal;
namespace Microsoft.AspNetCore.Razor.Language.Legacy
{
internal class AddTagHelperChunkGenerator : SpanChunkGenerator
{
public AddTagHelperChunkGenerator(string lookupText)
public AddTagHelperChunkGenerator(string lookupText, List<RazorDiagnostic> diagnostics)
{
LookupText = lookupText;
Diagnostics = diagnostics;
}
public string LookupText { get; }
public List<RazorDiagnostic> Diagnostics { get; }
public override void Accept(ParserVisitor visitor, Span span)
{
visitor.VisitAddTagHelperSpan(this, span);
@ -25,6 +30,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
{
var other = obj as AddTagHelperChunkGenerator;
return base.Equals(other) &&
Enumerable.SequenceEqual(Diagnostics, other.Diagnostics) &&
string.Equals(LookupText, other.LookupText, StringComparison.Ordinal);
}

View File

@ -91,11 +91,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
{
foreach (var directive in directives)
{
_directiveParsers.Add(directive, () =>
{
EnsureDirectiveIsAtStartOfLine();
handler();
});
_directiveParsers.Add(directive, handler);
Keywords.Add(directive);
// These C# keywords are reserved for use in directives. It's an error to use them outside of
@ -1576,166 +1572,198 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
private void HandleDirective(DirectiveDescriptor descriptor)
{
Context.Builder.CurrentBlock.Type = BlockKindInternal.Directive;
Context.Builder.CurrentBlock.ChunkGenerator = new DirectiveChunkGenerator(descriptor);
AssertDirective(descriptor.Directive);
AcceptAndMoveNext();
Output(SpanKindInternal.MetaCode, AcceptedCharactersInternal.None);
var directiveErrorSink = new ErrorSink();
var savedErrorSink = Context.ErrorSink;
Context.ErrorSink = directiveErrorSink;
for (var i = 0; i < descriptor.Tokens.Count; i++)
var directiveChunkGenerator = new DirectiveChunkGenerator(descriptor);
try
{
var tokenDescriptor = descriptor.Tokens[i];
AcceptWhile(IsSpacingToken(includeNewLines: false, includeComments: true));
EnsureDirectiveIsAtStartOfLine();
if (tokenDescriptor.Kind == DirectiveTokenKind.Member ||
tokenDescriptor.Kind == DirectiveTokenKind.Namespace ||
tokenDescriptor.Kind == DirectiveTokenKind.Type)
Context.Builder.CurrentBlock.Type = BlockKindInternal.Directive;
Context.Builder.CurrentBlock.ChunkGenerator = directiveChunkGenerator;
AcceptAndMoveNext();
Output(SpanKindInternal.MetaCode, AcceptedCharactersInternal.None);
for (var i = 0; i < descriptor.Tokens.Count; i++)
{
Span.ChunkGenerator = SpanChunkGenerator.Null;
Output(SpanKindInternal.Code, AcceptedCharactersInternal.WhiteSpace);
}
else
{
Span.ChunkGenerator = SpanChunkGenerator.Null;
Output(SpanKindInternal.Markup, AcceptedCharactersInternal.WhiteSpace);
}
if (tokenDescriptor.Optional && (EndOfFile || At(CSharpSymbolType.NewLine)))
{
break;
}
else if (EndOfFile)
{
Context.ErrorSink.OnError(
CurrentStart,
LegacyResources.FormatUnexpectedEOFAfterDirective(descriptor.Directive, tokenDescriptor.Kind.ToString().ToLowerInvariant()),
length: 1);
return;
}
switch (tokenDescriptor.Kind)
{
case DirectiveTokenKind.Type:
if (!NamespaceOrTypeName())
{
Context.ErrorSink.OnError(
CurrentStart,
LegacyResources.FormatDirectiveExpectsTypeName(descriptor.Directive),
CurrentSymbol.Content.Length);
return;
}
break;
case DirectiveTokenKind.Namespace:
if (!QualifiedIdentifier(out var identifierLength))
{
Context.ErrorSink.OnError(
CurrentStart,
LegacyResources.FormatDirectiveExpectsNamespace(descriptor.Directive),
identifierLength);
return;
}
break;
case DirectiveTokenKind.Member:
if (At(CSharpSymbolType.Identifier))
{
AcceptAndMoveNext();
}
else
{
Context.ErrorSink.OnError(
CurrentStart,
LegacyResources.FormatDirectiveExpectsIdentifier(descriptor.Directive),
CurrentSymbol.Content.Length);
return;
}
break;
case DirectiveTokenKind.String:
if (At(CSharpSymbolType.StringLiteral) && CurrentSymbol.Errors.Count == 0)
{
AcceptAndMoveNext();
}
else
{
Context.ErrorSink.OnError(
CurrentStart,
LegacyResources.FormatDirectiveExpectsQuotedStringLiteral(descriptor.Directive),
CurrentSymbol.Content.Length);
return;
}
break;
}
Span.ChunkGenerator = new DirectiveTokenChunkGenerator(tokenDescriptor);
Span.EditHandler = new DirectiveTokenEditHandler(Language.TokenizeString);
Output(SpanKindInternal.Code, AcceptedCharactersInternal.NonWhiteSpace);
}
AcceptWhile(IsSpacingToken(includeNewLines: false, includeComments: true));
Span.ChunkGenerator = SpanChunkGenerator.Null;
switch (descriptor.Kind)
{
case DirectiveKind.SingleLine:
Optional(CSharpSymbolType.Semicolon);
AcceptWhile(IsSpacingToken(includeNewLines: false, includeComments: true));
if (At(CSharpSymbolType.NewLine))
{
AcceptAndMoveNext();
}
else if (!EndOfFile)
if (!At(CSharpSymbolType.WhiteSpace) &&
!At(CSharpSymbolType.NewLine) &&
!EndOfFile)
{
Context.ErrorSink.OnError(
CurrentStart,
LegacyResources.FormatUnexpectedDirectiveLiteral(descriptor.Directive, LegacyResources.ErrorComponent_Newline),
CurrentSymbol.Content.Length);
Resources.FormatDirectiveTokensMustBeSeparatedByWhitespace(descriptor.Directive),
length: CurrentSymbol.Content.Length);
return;
}
Output(SpanKindInternal.MetaCode, AcceptedCharactersInternal.WhiteSpace);
break;
case DirectiveKind.RazorBlock:
AcceptWhile(IsSpacingToken(includeNewLines: true, includeComments: true));
Output(SpanKindInternal.Markup, AcceptedCharactersInternal.AllWhiteSpace);
var tokenDescriptor = descriptor.Tokens[i];
AcceptWhile(IsSpacingToken(includeNewLines: false, includeComments: true));
ParseDirectiveBlock(descriptor, parseChildren: (startingBraceLocation) =>
if (tokenDescriptor.Kind == DirectiveTokenKind.Member ||
tokenDescriptor.Kind == DirectiveTokenKind.Namespace ||
tokenDescriptor.Kind == DirectiveTokenKind.Type)
{
// When transitioning to the HTML parser we no longer want to act as if we're in a nested C# state.
// For instance, if <div>@hello.</div> is in a nested C# block we don't want the trailing '.' to be handled
// as C#; it should be handled as a period because it's wrapped in markup.
var wasNested = IsNested;
IsNested = false;
Span.ChunkGenerator = SpanChunkGenerator.Null;
Output(SpanKindInternal.Code, AcceptedCharactersInternal.WhiteSpace);
}
else
{
Span.ChunkGenerator = SpanChunkGenerator.Null;
Output(SpanKindInternal.Markup, AcceptedCharactersInternal.WhiteSpace);
}
using (PushSpanConfig())
if (tokenDescriptor.Optional && (EndOfFile || At(CSharpSymbolType.NewLine)))
{
break;
}
else if (EndOfFile)
{
Context.ErrorSink.OnError(
CurrentStart,
LegacyResources.FormatUnexpectedEOFAfterDirective(descriptor.Directive, tokenDescriptor.Kind.ToString().ToLowerInvariant()),
length: 1);
return;
}
switch (tokenDescriptor.Kind)
{
case DirectiveTokenKind.Type:
if (!NamespaceOrTypeName())
{
Context.ErrorSink.OnError(
CurrentStart,
LegacyResources.FormatDirectiveExpectsTypeName(descriptor.Directive),
CurrentSymbol.Content.Length);
return;
}
break;
case DirectiveTokenKind.Namespace:
if (!QualifiedIdentifier(out var identifierLength))
{
Context.ErrorSink.OnError(
CurrentStart,
LegacyResources.FormatDirectiveExpectsNamespace(descriptor.Directive),
identifierLength);
return;
}
break;
case DirectiveTokenKind.Member:
if (At(CSharpSymbolType.Identifier))
{
AcceptAndMoveNext();
}
else
{
Context.ErrorSink.OnError(
CurrentStart,
LegacyResources.FormatDirectiveExpectsIdentifier(descriptor.Directive),
CurrentSymbol.Content.Length);
return;
}
break;
case DirectiveTokenKind.String:
if (At(CSharpSymbolType.StringLiteral) && CurrentSymbol.Errors.Count == 0)
{
AcceptAndMoveNext();
}
else
{
Context.ErrorSink.OnError(
CurrentStart,
LegacyResources.FormatDirectiveExpectsQuotedStringLiteral(descriptor.Directive),
CurrentSymbol.Content.Length);
return;
}
break;
}
Span.ChunkGenerator = new DirectiveTokenChunkGenerator(tokenDescriptor);
Span.EditHandler = new DirectiveTokenEditHandler(Language.TokenizeString);
Output(SpanKindInternal.Code, AcceptedCharactersInternal.NonWhiteSpace);
}
AcceptWhile(IsSpacingToken(includeNewLines: false, includeComments: true));
Span.ChunkGenerator = SpanChunkGenerator.Null;
switch (descriptor.Kind)
{
case DirectiveKind.SingleLine:
Optional(CSharpSymbolType.Semicolon);
AcceptWhile(IsSpacingToken(includeNewLines: false, includeComments: true));
if (At(CSharpSymbolType.NewLine))
{
HtmlParser.ParseRazorBlock(Tuple.Create("{", "}"), caseSensitive: true);
AcceptAndMoveNext();
}
else if (!EndOfFile)
{
Context.ErrorSink.OnError(
CurrentStart,
LegacyResources.FormatUnexpectedDirectiveLiteral(descriptor.Directive, LegacyResources.ErrorComponent_Newline),
CurrentSymbol.Content.Length);
}
Span.Start = CurrentLocation;
Initialize(Span);
Output(SpanKindInternal.MetaCode, AcceptedCharactersInternal.WhiteSpace);
break;
case DirectiveKind.RazorBlock:
AcceptWhile(IsSpacingToken(includeNewLines: true, includeComments: true));
Output(SpanKindInternal.Markup, AcceptedCharactersInternal.AllWhiteSpace);
IsNested = wasNested;
ParseDirectiveBlock(descriptor, parseChildren: (startingBraceLocation) =>
{
// When transitioning to the HTML parser we no longer want to act as if we're in a nested C# state.
// For instance, if <div>@hello.</div> is in a nested C# block we don't want the trailing '.' to be handled
// as C#; it should be handled as a period because it's wrapped in markup.
var wasNested = IsNested;
IsNested = false;
NextToken();
});
break;
case DirectiveKind.CodeBlock:
AcceptWhile(IsSpacingToken(includeNewLines: true, includeComments: true));
Output(SpanKindInternal.Markup, AcceptedCharactersInternal.AllWhiteSpace);
using (PushSpanConfig())
{
HtmlParser.ParseRazorBlock(Tuple.Create("{", "}"), caseSensitive: true);
}
ParseDirectiveBlock(descriptor, parseChildren: (startingBraceLocation) =>
{
NextToken();
Balance(BalancingModes.NoErrorOnFailure, CSharpSymbolType.LeftBrace, CSharpSymbolType.RightBrace, startingBraceLocation);
Span.ChunkGenerator = new StatementChunkGenerator();
Output(SpanKindInternal.Code);
});
break;
Span.Start = CurrentLocation;
Initialize(Span);
IsNested = wasNested;
NextToken();
});
break;
case DirectiveKind.CodeBlock:
AcceptWhile(IsSpacingToken(includeNewLines: true, includeComments: true));
Output(SpanKindInternal.Markup, AcceptedCharactersInternal.AllWhiteSpace);
ParseDirectiveBlock(descriptor, parseChildren: (startingBraceLocation) =>
{
NextToken();
Balance(BalancingModes.NoErrorOnFailure, CSharpSymbolType.LeftBrace, CSharpSymbolType.RightBrace, startingBraceLocation);
Span.ChunkGenerator = new StatementChunkGenerator();
Output(SpanKindInternal.Code);
});
break;
}
}
finally
{
if (directiveErrorSink.Errors.Count > 0)
{
var directiveDiagnostics = directiveErrorSink.Errors.Select(error => RazorDiagnostic.Create(error));
directiveChunkGenerator.Diagnostics.AddRange(directiveDiagnostics);
}
Context.ErrorSink = savedErrorSink;
}
}
@ -1789,21 +1817,21 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
{
TagHelperDirective(
SyntaxConstants.CSharp.TagHelperPrefixKeyword,
prefix => new TagHelperPrefixDirectiveChunkGenerator(prefix));
(prefix, errors) => new TagHelperPrefixDirectiveChunkGenerator(prefix, errors));
}
protected virtual void AddTagHelperDirective()
{
TagHelperDirective(
SyntaxConstants.CSharp.AddTagHelperKeyword,
lookupText => new AddTagHelperChunkGenerator(lookupText));
(lookupText, errors) => new AddTagHelperChunkGenerator(lookupText, errors));
}
protected virtual void RemoveTagHelperDirective()
{
TagHelperDirective(
SyntaxConstants.CSharp.RemoveTagHelperKeyword,
lookupText => new RemoveTagHelperChunkGenerator(lookupText));
(lookupText, errors) => new RemoveTagHelperChunkGenerator(lookupText, errors));
}
[Conditional("DEBUG")]
@ -1866,63 +1894,86 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
Output(SpanKindInternal.Code, AcceptedCharactersInternal.AnyExceptNewline);
}
private void TagHelperDirective(string keyword, Func<string, ISpanChunkGenerator> chunkGeneratorFactory)
private void TagHelperDirective(string keyword, Func<string, List<RazorDiagnostic>, ISpanChunkGenerator> chunkGeneratorFactory)
{
AssertDirective(keyword);
var keywordStartLocation = CurrentStart;
// Accept the directive name
AcceptAndMoveNext();
var savedErrorSink = Context.ErrorSink;
var directiveErrorSink = new ErrorSink();
Context.ErrorSink = directiveErrorSink;
// Set the block type
Context.Builder.CurrentBlock.Type = BlockKindInternal.Directive;
var keywordLength = Span.End.AbsoluteIndex - Span.Start.AbsoluteIndex;
var foundWhitespace = At(CSharpSymbolType.WhiteSpace);
AcceptWhile(CSharpSymbolType.WhiteSpace);
// If we found whitespace then any content placed within the whitespace MAY cause a destructive change
// to the document. We can't accept it.
Output(SpanKindInternal.MetaCode, foundWhitespace ? AcceptedCharactersInternal.None : AcceptedCharactersInternal.AnyExceptNewline);
ISpanChunkGenerator chunkGenerator;
if (EndOfFile || At(CSharpSymbolType.NewLine))
string directiveValue = null;
try
{
Context.ErrorSink.OnError(
keywordStartLocation,
LegacyResources.FormatParseError_DirectiveMustHaveValue(keyword),
keywordLength);
EnsureDirectiveIsAtStartOfLine();
chunkGenerator = chunkGeneratorFactory(string.Empty);
}
else
{
// Need to grab the current location before we accept until the end of the line.
var startLocation = CurrentStart;
var keywordStartLocation = CurrentStart;
// Parse to the end of the line. Essentially accepts anything until end of line, comments, invalid code
// etc.
AcceptUntil(CSharpSymbolType.NewLine);
// Accept the directive name
AcceptAndMoveNext();
// Pull out the value and remove whitespaces and optional quotes
var rawValue = string.Concat(Span.Symbols.Select(s => s.Content)).Trim();
// Set the block type
Context.Builder.CurrentBlock.Type = BlockKindInternal.Directive;
var startsWithQuote = rawValue.StartsWith("\"", StringComparison.Ordinal);
var endsWithQuote = rawValue.EndsWith("\"", StringComparison.Ordinal);
if (startsWithQuote != endsWithQuote)
var keywordLength = Span.End.AbsoluteIndex - Span.Start.AbsoluteIndex;
var foundWhitespace = At(CSharpSymbolType.WhiteSpace);
AcceptWhile(CSharpSymbolType.WhiteSpace);
// If we found whitespace then any content placed within the whitespace MAY cause a destructive change
// to the document. We can't accept it.
Output(SpanKindInternal.MetaCode, foundWhitespace ? AcceptedCharactersInternal.None : AcceptedCharactersInternal.AnyExceptNewline);
if (EndOfFile || At(CSharpSymbolType.NewLine))
{
Context.ErrorSink.OnError(
startLocation,
LegacyResources.FormatParseError_IncompleteQuotesAroundDirective(keyword),
rawValue.Length);
keywordStartLocation,
LegacyResources.FormatParseError_DirectiveMustHaveValue(keyword),
keywordLength);
directiveValue = string.Empty;
}
else
{
// Need to grab the current location before we accept until the end of the line.
var startLocation = CurrentStart;
// Parse to the end of the line. Essentially accepts anything until end of line, comments, invalid code
// etc.
AcceptUntil(CSharpSymbolType.NewLine);
// Pull out the value and remove whitespaces and optional quotes
var rawValue = string.Concat(Span.Symbols.Select(s => s.Content)).Trim();
var startsWithQuote = rawValue.StartsWith("\"", StringComparison.Ordinal);
var endsWithQuote = rawValue.EndsWith("\"", StringComparison.Ordinal);
if (startsWithQuote != endsWithQuote)
{
Context.ErrorSink.OnError(
startLocation,
LegacyResources.FormatParseError_IncompleteQuotesAroundDirective(keyword),
rawValue.Length);
}
directiveValue = rawValue;
}
}
finally
{
List<RazorDiagnostic> directiveErrors;
if (directiveErrorSink.Errors.Count > 0)
{
directiveErrors = directiveErrorSink.Errors.Select(RazorDiagnostic.Create).ToList();
}
else
{
directiveErrors = new List<RazorDiagnostic>();
}
chunkGenerator = chunkGeneratorFactory(rawValue);
Span.ChunkGenerator = chunkGeneratorFactory(directiveValue, directiveErrors);
Context.ErrorSink = savedErrorSink;
}
Span.ChunkGenerator = chunkGenerator;
// Output the span and finish the block
CompleteBlock();
Output(SpanKindInternal.Code, AcceptedCharactersInternal.AnyExceptNewline);

View File

@ -2,6 +2,9 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Extensions.Internal;
namespace Microsoft.AspNetCore.Razor.Language.Legacy
@ -9,6 +12,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
internal class DirectiveChunkGenerator : ParentChunkGenerator
{
private static readonly Type Type = typeof(DirectiveChunkGenerator);
private List<RazorDiagnostic> _diagnostics;
public DirectiveChunkGenerator(DirectiveDescriptor descriptor)
{
@ -17,6 +21,19 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
public DirectiveDescriptor Descriptor { get; }
public List<RazorDiagnostic> Diagnostics
{
get
{
if (_diagnostics == null)
{
_diagnostics = new List<RazorDiagnostic>();
}
return _diagnostics;
}
}
public override void Accept(ParserVisitor visitor, Block block)
{
visitor.VisitDirectiveBlock(this, block);
@ -26,6 +43,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
{
var other = obj as DirectiveChunkGenerator;
return base.Equals(other) &&
Enumerable.SequenceEqual(Diagnostics, other.Diagnostics) &&
DirectiveDescriptorComparer.Default.Equals(Descriptor, other.Descriptor);
}
@ -37,5 +55,24 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
return combiner.CombinedHash;
}
public override string ToString()
{
// This is used primarily at test time to show an identifiable representation of the chunk generator.
var builder = new StringBuilder("Directive {");
builder.Append(Descriptor.Directive);
builder.Append("}");
if (Diagnostics.Count > 0)
{
builder.Append(" [");
var ids = string.Join(", ", Diagnostics.Select(diagnostic => diagnostic.Id));
builder.Append(ids);
builder.Append("]");
}
return builder.ToString();
}
}
}

View File

@ -29,7 +29,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
public SyntaxTreeBuilder Builder { get; }
public ErrorSink ErrorSink { get; }
public ErrorSink ErrorSink { get; set; }
public ITextDocument Source { get; }

View File

@ -2,19 +2,24 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Extensions.Internal;
namespace Microsoft.AspNetCore.Razor.Language.Legacy
{
internal class RemoveTagHelperChunkGenerator : SpanChunkGenerator
{
public RemoveTagHelperChunkGenerator(string lookupText)
public RemoveTagHelperChunkGenerator(string lookupText, List<RazorDiagnostic> diagnostics)
{
LookupText = lookupText;
Diagnostics = diagnostics;
}
public string LookupText { get; }
public List<RazorDiagnostic> Diagnostics { get; }
public override void Accept(ParserVisitor visitor, Span span)
{
visitor.VisitRemoveTagHelperSpan(this, span);
@ -25,6 +30,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
{
var other = obj as RemoveTagHelperChunkGenerator;
return base.Equals(other) &&
Enumerable.SequenceEqual(Diagnostics, other.Diagnostics) &&
string.Equals(LookupText, other.LookupText, StringComparison.Ordinal);
}

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 System.Collections.Generic;
namespace Microsoft.AspNetCore.Razor.Language.Legacy
{
@ -41,5 +42,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
/// The <see cref="TagHelperDirectiveType"/> of this directive.
/// </summary>
public TagHelperDirectiveType DirectiveType { get; set; }
public List<RazorDiagnostic> Diagnostics { get; set; }
}
}

View File

@ -2,19 +2,24 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Extensions.Internal;
namespace Microsoft.AspNetCore.Razor.Language.Legacy
{
internal class TagHelperPrefixDirectiveChunkGenerator : SpanChunkGenerator
{
public TagHelperPrefixDirectiveChunkGenerator(string prefix)
public TagHelperPrefixDirectiveChunkGenerator(string prefix, List<RazorDiagnostic> diagnostics)
{
Prefix = prefix;
Diagnostics = diagnostics;
}
public string Prefix { get; }
public List<RazorDiagnostic> Diagnostics { get; }
public override void Accept(ParserVisitor visitor, Span span)
{
visitor.VisitTagHelperPrefixDirectiveSpan(this, span);
@ -25,6 +30,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
{
var other = obj as TagHelperPrefixDirectiveChunkGenerator;
return base.Equals(other) &&
Enumerable.SequenceEqual(Diagnostics, other.Diagnostics) &&
string.Equals(Prefix, other.Prefix, StringComparison.Ordinal);
}

View File

@ -444,6 +444,20 @@ namespace Microsoft.AspNetCore.Razor.Language
internal static string FormatDirectiveMustAppearAtStartOfLine(object p0)
=> string.Format(CultureInfo.CurrentCulture, GetString("DirectiveMustAppearAtStartOfLine"), p0);
/// <summary>
/// The '{0}' directives value(s) must be separated by whitespace.
/// </summary>
internal static string DirectiveTokensMustBeSeparatedByWhitespace
{
get => GetString("DirectiveTokensMustBeSeparatedByWhitespace");
}
/// <summary>
/// The '{0}' directives value(s) must be separated by whitespace.
/// </summary>
internal static string FormatDirectiveTokensMustBeSeparatedByWhitespace(object p0)
=> string.Format(CultureInfo.CurrentCulture, GetString("DirectiveTokensMustBeSeparatedByWhitespace"), p0);
/// <summary>
/// The key must not be null.
/// </summary>

View File

@ -210,6 +210,9 @@
<data name="DirectiveMustAppearAtStartOfLine" xml:space="preserve">
<value>The '{0}` directive must appear at the start of the line.</value>
</data>
<data name="DirectiveTokensMustBeSeparatedByWhitespace" xml:space="preserve">
<value>The '{0}' directives value(s) must be separated by whitespace.</value>
</data>
<data name="KeyMustNotBeNull" xml:space="preserve">
<value>The key must not be null.</value>
</data>

View File

@ -28,10 +28,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions.IntegrationTests
public void InvalidNamespaceAtEOF_Runtime()
{
var references = CreateCompilationReferences(CurrentMvcShim);
RunRuntimeTest(references, expectedErrors: new[]
{
"Identifier expected"
});
RunRuntimeTest(references);
}
[Fact]
@ -44,10 +41,7 @@ public class MyService<TModel>
}";
var compilationReferences = CreateCompilationReferences(CurrentMvcShim, appCode);
RunRuntimeTest(compilationReferences, expectedErrors: new[]
{
"Identifier expected"
});
RunRuntimeTest(compilationReferences);
}
[Fact]
@ -267,7 +261,7 @@ public class AllTagHelper : {typeof(TagHelper).FullName}
public void InvalidNamespaceAtEOF_DesignTime()
{
var references = CreateCompilationReferences(CurrentMvcShim);
RunDesignTimeTest(references, expectedErrors: new[] { "Identifier expected" });
RunDesignTimeTest(references);
}
[Fact]
@ -281,12 +275,7 @@ public class MyService<TModel>
";
var references = CreateCompilationReferences(CurrentMvcShim, appCode);
RunDesignTimeTest(
references,
expectedErrors: new[]
{
"Identifier expected"
});
RunDesignTimeTest(references);
}
[Fact]

View File

@ -1,6 +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 System;
using Microsoft.AspNetCore.Razor.Language;
using Microsoft.AspNetCore.Razor.Language.Intermediate;
using Xunit;
@ -9,24 +10,6 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
{
public class PageDirectiveTest
{
[Fact]
public void TryGetPageDirective_CanHandleMalformedPageDirectives()
{
// Arrange
var content = "@page \"";
var sourceDocument = RazorSourceDocument.Create(content, "file");
var codeDocument = RazorCodeDocument.Create(sourceDocument);
var engine = CreateEngine();
var irDocument = CreateIRDocument(engine, codeDocument);
// Act
var result = PageDirective.TryGetPageDirective(irDocument, out var pageDirective);
// Assert
Assert.True(result);
Assert.Null(pageDirective.RouteTemplate);
}
[Fact]
public void TryGetPageDirective_ReturnsFalse_IfPageDoesNotHaveDirective()
{

View File

@ -1,4 +1,5 @@
namespace
[assembly:global::Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.RazorPageAttribute(null, typeof(AspNetCore.TestFiles_IntegrationTests_CodeGenerationIntegrationTest_IncompleteDirectives_cshtml), null)]
namespace AspNetCore
{
#line hidden
using TModel = global::System.Object;

View File

@ -1,5 +1,7 @@
Document -
NamespaceDeclaration - -
CSharpCode -
RazorIRToken - - CSharp - [assembly:global::Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.RazorPageAttribute(null, typeof(AspNetCore.TestFiles_IntegrationTests_CodeGenerationIntegrationTest_IncompleteDirectives_cshtml), null)]
NamespaceDeclaration - - AspNetCore
UsingStatement - - TModel = global::System.Object
UsingStatement - (1:0,1 [12] ) - System
UsingStatement - (16:1,1 [32] ) - System.Collections.Generic
@ -29,20 +31,29 @@ Document -
MethodDeclaration - - public - async, override - global::System.Threading.Tasks.Task - ExecuteAsync
HtmlContent - (83:0,83 [4] IncompleteDirectives.cshtml)
RazorIRToken - (83:0,83 [4] IncompleteDirectives.cshtml) - Html - \n\n
MalformedDirective - (102:4,0 [6] IncompleteDirectives.cshtml)
HtmlContent - (108:4,6 [5] IncompleteDirectives.cshtml)
RazorIRToken - (108:4,6 [5] IncompleteDirectives.cshtml) - Html - "\n\n
MalformedDirective - (113:6,0 [6] IncompleteDirectives.cshtml)
HtmlContent - (119:6,6 [2] IncompleteDirectives.cshtml)
RazorIRToken - (119:6,6 [2] IncompleteDirectives.cshtml) - Html - \n
MalformedDirective - (121:7,0 [7] IncompleteDirectives.cshtml)
HtmlContent - (128:7,7 [4] IncompleteDirectives.cshtml)
RazorIRToken - (128:7,7 [4] IncompleteDirectives.cshtml) - Html - \n\n
MalformedDirective - (132:9,0 [7] IncompleteDirectives.cshtml)
HtmlContent - (139:9,7 [2] IncompleteDirectives.cshtml)
RazorIRToken - (139:9,7 [2] IncompleteDirectives.cshtml) - Html - \n
MalformedDirective - (141:10,0 [8] IncompleteDirectives.cshtml)
HtmlContent - (149:10,8 [2] IncompleteDirectives.cshtml)
RazorIRToken - (149:10,8 [2] IncompleteDirectives.cshtml) - Html - \n
MalformedDirective - (151:11,0 [25] IncompleteDirectives.cshtml)
DirectiveToken - (159:11,8 [17] IncompleteDirectives.cshtml) - MyService<TModel>
HtmlContent - (176:11,25 [4] IncompleteDirectives.cshtml)
RazorIRToken - (176:11,25 [4] IncompleteDirectives.cshtml) - Html - \n\n
MalformedDirective - (180:13,0 [10] IncompleteDirectives.cshtml)
HtmlContent - (190:13,10 [2] IncompleteDirectives.cshtml)
RazorIRToken - (190:13,10 [2] IncompleteDirectives.cshtml) - Html - \n
MalformedDirective - (192:14,0 [11] IncompleteDirectives.cshtml)
HtmlContent - (203:14,11 [2] IncompleteDirectives.cshtml)
RazorIRToken - (203:14,11 [2] IncompleteDirectives.cshtml) - Html - \n
InjectDirective -

View File

@ -1,5 +1,5 @@
Source Location: (159:11,8 [17] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml)
|MyService<TModel>|
Generated Location: (616:16,0 [17] )
Generated Location: (833:17,0 [17] )
|MyService<TModel>|

View File

@ -1,5 +1,6 @@
#pragma checksum "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "fec5cf763044f842fa2114e997bb07e0bf280cd6"
namespace
[assembly:global::Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.RazorPageAttribute(null, typeof(AspNetCore.TestFiles_IntegrationTests_CodeGenerationIntegrationTest_IncompleteDirectives_cshtml), null)]
namespace AspNetCore
{
#line hidden
using System;

View File

@ -1,5 +1,7 @@
Document -
NamespaceDeclaration - -
CSharpCode -
RazorIRToken - - CSharp - [assembly:global::Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.RazorPageAttribute(null, typeof(AspNetCore.TestFiles_IntegrationTests_CodeGenerationIntegrationTest_IncompleteDirectives_cshtml), null)]
NamespaceDeclaration - - AspNetCore
UsingStatement - (1:0,1 [14] ) - System
UsingStatement - (16:1,1 [34] ) - System.Collections.Generic
UsingStatement - (51:2,1 [19] ) - System.Linq
@ -15,48 +17,57 @@ Document -
RazorIRToken - (83:0,83 [4] IncompleteDirectives.cshtml) - Html - \n\n
CSharpCode -
RazorIRToken - - CSharp - EndContext();
MalformedDirective - (102:4,0 [6] IncompleteDirectives.cshtml)
CSharpCode -
RazorIRToken - - CSharp - BeginContext(108, 5, true);
HtmlContent - (108:4,6 [5] IncompleteDirectives.cshtml)
RazorIRToken - (108:4,6 [5] IncompleteDirectives.cshtml) - Html - "\n\n
CSharpCode -
RazorIRToken - - CSharp - EndContext();
MalformedDirective - (113:6,0 [6] IncompleteDirectives.cshtml)
CSharpCode -
RazorIRToken - - CSharp - BeginContext(119, 2, true);
HtmlContent - (119:6,6 [2] IncompleteDirectives.cshtml)
RazorIRToken - (119:6,6 [2] IncompleteDirectives.cshtml) - Html - \n
CSharpCode -
RazorIRToken - - CSharp - EndContext();
MalformedDirective - (121:7,0 [7] IncompleteDirectives.cshtml)
CSharpCode -
RazorIRToken - - CSharp - BeginContext(128, 4, true);
HtmlContent - (128:7,7 [4] IncompleteDirectives.cshtml)
RazorIRToken - (128:7,7 [4] IncompleteDirectives.cshtml) - Html - \n\n
CSharpCode -
RazorIRToken - - CSharp - EndContext();
MalformedDirective - (132:9,0 [7] IncompleteDirectives.cshtml)
CSharpCode -
RazorIRToken - - CSharp - BeginContext(139, 2, true);
HtmlContent - (139:9,7 [2] IncompleteDirectives.cshtml)
RazorIRToken - (139:9,7 [2] IncompleteDirectives.cshtml) - Html - \n
CSharpCode -
RazorIRToken - - CSharp - EndContext();
MalformedDirective - (141:10,0 [8] IncompleteDirectives.cshtml)
CSharpCode -
RazorIRToken - - CSharp - BeginContext(149, 2, true);
HtmlContent - (149:10,8 [2] IncompleteDirectives.cshtml)
RazorIRToken - (149:10,8 [2] IncompleteDirectives.cshtml) - Html - \n
CSharpCode -
RazorIRToken - - CSharp - EndContext();
MalformedDirective - (151:11,0 [25] IncompleteDirectives.cshtml)
DirectiveToken - (159:11,8 [17] IncompleteDirectives.cshtml) - MyService<TModel>
CSharpCode -
RazorIRToken - - CSharp - BeginContext(176, 4, true);
HtmlContent - (176:11,25 [4] IncompleteDirectives.cshtml)
RazorIRToken - (176:11,25 [4] IncompleteDirectives.cshtml) - Html - \n\n
CSharpCode -
RazorIRToken - - CSharp - EndContext();
MalformedDirective - (180:13,0 [10] IncompleteDirectives.cshtml)
CSharpCode -
RazorIRToken - - CSharp - BeginContext(190, 2, true);
HtmlContent - (190:13,10 [2] IncompleteDirectives.cshtml)
RazorIRToken - (190:13,10 [2] IncompleteDirectives.cshtml) - Html - \n
CSharpCode -
RazorIRToken - - CSharp - EndContext();
MalformedDirective - (192:14,0 [11] IncompleteDirectives.cshtml)
CSharpCode -
RazorIRToken - - CSharp - BeginContext(203, 2, true);
HtmlContent - (203:14,11 [2] IncompleteDirectives.cshtml)

View File

@ -1,4 +1,5 @@
namespace
[assembly:global::Microsoft.AspNetCore.Mvc.Razor.Compilation.RazorViewAttribute(null, typeof(AspNetCore.TestFiles_IntegrationTests_CodeGenerationIntegrationTest_InvalidNamespaceAtEOF_cshtml))]
namespace AspNetCore
{
#line hidden
using TModel = global::System.Object;

View File

@ -1,5 +1,7 @@
Document -
NamespaceDeclaration - -
CSharpCode -
RazorIRToken - - CSharp - [assembly:global::Microsoft.AspNetCore.Mvc.Razor.Compilation.RazorViewAttribute(null, typeof(AspNetCore.TestFiles_IntegrationTests_CodeGenerationIntegrationTest_InvalidNamespaceAtEOF_cshtml))]
NamespaceDeclaration - - AspNetCore
UsingStatement - - TModel = global::System.Object
UsingStatement - (1:0,1 [12] ) - System
UsingStatement - (16:1,1 [32] ) - System.Collections.Generic
@ -26,6 +28,7 @@ Document -
CSharpCode -
RazorIRToken - - CSharp - private static System.Object __o = null;
MethodDeclaration - - public - async, override - global::System.Threading.Tasks.Task - ExecuteAsync
MalformedDirective - (0:0,0 [11] InvalidNamespaceAtEOF.cshtml)
HtmlContent - (11:0,11 [5] InvalidNamespaceAtEOF.cshtml)
RazorIRToken - (11:0,11 [5] InvalidNamespaceAtEOF.cshtml) - Html - Test.
InjectDirective -

View File

@ -1,5 +1,6 @@
#pragma checksum "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/InvalidNamespaceAtEOF.cshtml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "de132bd3e2a46a0d2ec953a168427c01e5829cde"
namespace
[assembly:global::Microsoft.AspNetCore.Mvc.Razor.Compilation.RazorViewAttribute(null, typeof(AspNetCore.TestFiles_IntegrationTests_CodeGenerationIntegrationTest_InvalidNamespaceAtEOF_cshtml))]
namespace AspNetCore
{
#line hidden
using System;

View File

@ -1,5 +1,7 @@
Document -
NamespaceDeclaration - -
CSharpCode -
RazorIRToken - - CSharp - [assembly:global::Microsoft.AspNetCore.Mvc.Razor.Compilation.RazorViewAttribute(null, typeof(AspNetCore.TestFiles_IntegrationTests_CodeGenerationIntegrationTest_InvalidNamespaceAtEOF_cshtml))]
NamespaceDeclaration - - AspNetCore
UsingStatement - (1:0,1 [14] ) - System
UsingStatement - (16:1,1 [34] ) - System.Collections.Generic
UsingStatement - (51:2,1 [19] ) - System.Linq
@ -9,6 +11,7 @@ Document -
UsingStatement - (178:6,1 [45] ) - Microsoft.AspNetCore.Mvc.ViewFeatures
ClassDeclaration - - public - TestFiles_IntegrationTests_CodeGenerationIntegrationTest_InvalidNamespaceAtEOF_cshtml - global::Microsoft.AspNetCore.Mvc.Razor.RazorPage<dynamic> -
MethodDeclaration - - public - async, override - global::System.Threading.Tasks.Task - ExecuteAsync
MalformedDirective - (0:0,0 [11] InvalidNamespaceAtEOF.cshtml)
CSharpCode -
RazorIRToken - - CSharp - BeginContext(11, 5, true);
HtmlContent - (11:0,11 [5] InvalidNamespaceAtEOF.cshtml)

View File

@ -1,4 +1,4 @@
[assembly:global::Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.RazorPageAttribute(null, typeof(AspNetCore.TestFiles_IntegrationTests_CodeGenerationIntegrationTest_MalformedPageDirective_cshtml), null)]
[assembly:global::Microsoft.AspNetCore.Mvc.Razor.Compilation.RazorViewAttribute(null, typeof(AspNetCore.TestFiles_IntegrationTests_CodeGenerationIntegrationTest_MalformedPageDirective_cshtml))]
namespace AspNetCore
{
#line hidden
@ -10,7 +10,7 @@ namespace AspNetCore
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
public class TestFiles_IntegrationTests_CodeGenerationIntegrationTest_MalformedPageDirective_cshtml : global::Microsoft.AspNetCore.Mvc.RazorPages.Page
public class TestFiles_IntegrationTests_CodeGenerationIntegrationTest_MalformedPageDirective_cshtml : global::Microsoft.AspNetCore.Mvc.Razor.RazorPage<dynamic>
{
#pragma warning disable 219
private void __RazorDirectiveTokenHelpers__() {
@ -31,8 +31,6 @@ namespace AspNetCore
[global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
public global::Microsoft.AspNetCore.Mvc.Rendering.IJsonHelper Json { get; private set; }
[global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
public global::Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper<TestFiles_IntegrationTests_CodeGenerationIntegrationTest_MalformedPageDirective_cshtml> Html { get; private set; }
public global::Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionary<TestFiles_IntegrationTests_CodeGenerationIntegrationTest_MalformedPageDirective_cshtml> ViewData => (global::Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionary<TestFiles_IntegrationTests_CodeGenerationIntegrationTest_MalformedPageDirective_cshtml>)PageContext?.ViewData;
public TestFiles_IntegrationTests_CodeGenerationIntegrationTest_MalformedPageDirective_cshtml Model => ViewData.Model;
public global::Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper<dynamic> Html { get; private set; }
}
}

View File

@ -1,6 +1,6 @@
Document -
CSharpCode -
RazorIRToken - - CSharp - [assembly:global::Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.RazorPageAttribute(null, typeof(AspNetCore.TestFiles_IntegrationTests_CodeGenerationIntegrationTest_MalformedPageDirective_cshtml), null)]
RazorIRToken - - CSharp - [assembly:global::Microsoft.AspNetCore.Mvc.Razor.Compilation.RazorViewAttribute(null, typeof(AspNetCore.TestFiles_IntegrationTests_CodeGenerationIntegrationTest_MalformedPageDirective_cshtml))]
NamespaceDeclaration - - AspNetCore
UsingStatement - - TModel = global::System.Object
UsingStatement - (1:0,1 [12] ) - System
@ -10,7 +10,7 @@ Document -
UsingStatement - (102:4,1 [30] ) - Microsoft.AspNetCore.Mvc
UsingStatement - (135:5,1 [40] ) - Microsoft.AspNetCore.Mvc.Rendering
UsingStatement - (178:6,1 [43] ) - Microsoft.AspNetCore.Mvc.ViewFeatures
ClassDeclaration - - public - TestFiles_IntegrationTests_CodeGenerationIntegrationTest_MalformedPageDirective_cshtml - global::Microsoft.AspNetCore.Mvc.RazorPages.Page -
ClassDeclaration - - public - TestFiles_IntegrationTests_CodeGenerationIntegrationTest_MalformedPageDirective_cshtml - global::Microsoft.AspNetCore.Mvc.Razor.RazorPage<dynamic> -
DesignTimeDirective -
DirectiveToken - (231:7,8 [62] ) - global::Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper<TModel>
DirectiveToken - (294:7,71 [4] ) - Html
@ -28,6 +28,7 @@ Document -
CSharpCode -
RazorIRToken - - CSharp - private static System.Object __o = null;
MethodDeclaration - - public - async, override - global::System.Threading.Tasks.Task - ExecuteAsync
MalformedDirective - (0:0,0 [6] MalformedPageDirective.cshtml)
HtmlContent - (6:0,6 [49] MalformedPageDirective.cshtml)
RazorIRToken - (6:0,6 [8] MalformedPageDirective.cshtml) - Html - "foo\n\n
RazorIRToken - (14:2,0 [4] MalformedPageDirective.cshtml) - Html - <h1>
@ -42,7 +43,3 @@ Document -
InjectDirective -
InjectDirective -
InjectDirective -
CSharpCode -
RazorIRToken - - CSharp - public global::Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionary<TestFiles_IntegrationTests_CodeGenerationIntegrationTest_MalformedPageDirective_cshtml> ViewData => (global::Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionary<TestFiles_IntegrationTests_CodeGenerationIntegrationTest_MalformedPageDirective_cshtml>)PageContext?.ViewData;
CSharpCode -
RazorIRToken - - CSharp - public TestFiles_IntegrationTests_CodeGenerationIntegrationTest_MalformedPageDirective_cshtml Model => ViewData.Model;

View File

@ -1,5 +1,5 @@
#pragma checksum "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/MalformedPageDirective.cshtml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "5a9ff8440150c6746e4a8ba63bc633ea84930405"
[assembly:global::Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.RazorPageAttribute(null, typeof(AspNetCore.TestFiles_IntegrationTests_CodeGenerationIntegrationTest_MalformedPageDirective_cshtml), null)]
[assembly:global::Microsoft.AspNetCore.Mvc.Razor.Compilation.RazorViewAttribute(null, typeof(AspNetCore.TestFiles_IntegrationTests_CodeGenerationIntegrationTest_MalformedPageDirective_cshtml))]
namespace AspNetCore
{
#line hidden
@ -10,7 +10,7 @@ namespace AspNetCore
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
public class TestFiles_IntegrationTests_CodeGenerationIntegrationTest_MalformedPageDirective_cshtml : global::Microsoft.AspNetCore.Mvc.RazorPages.Page
public class TestFiles_IntegrationTests_CodeGenerationIntegrationTest_MalformedPageDirective_cshtml : global::Microsoft.AspNetCore.Mvc.Razor.RazorPage<dynamic>
{
#pragma warning disable 1998
public async override global::System.Threading.Tasks.Task ExecuteAsync()
@ -29,8 +29,6 @@ namespace AspNetCore
[global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
public global::Microsoft.AspNetCore.Mvc.Rendering.IJsonHelper Json { get; private set; }
[global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]
public global::Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper<TestFiles_IntegrationTests_CodeGenerationIntegrationTest_MalformedPageDirective_cshtml> Html { get; private set; }
public global::Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionary<TestFiles_IntegrationTests_CodeGenerationIntegrationTest_MalformedPageDirective_cshtml> ViewData => (global::Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionary<TestFiles_IntegrationTests_CodeGenerationIntegrationTest_MalformedPageDirective_cshtml>)PageContext?.ViewData;
public TestFiles_IntegrationTests_CodeGenerationIntegrationTest_MalformedPageDirective_cshtml Model => ViewData.Model;
public global::Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper<dynamic> Html { get; private set; }
}
}

View File

@ -1,6 +1,6 @@
Document -
CSharpCode -
RazorIRToken - - CSharp - [assembly:global::Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.RazorPageAttribute(null, typeof(AspNetCore.TestFiles_IntegrationTests_CodeGenerationIntegrationTest_MalformedPageDirective_cshtml), null)]
RazorIRToken - - CSharp - [assembly:global::Microsoft.AspNetCore.Mvc.Razor.Compilation.RazorViewAttribute(null, typeof(AspNetCore.TestFiles_IntegrationTests_CodeGenerationIntegrationTest_MalformedPageDirective_cshtml))]
NamespaceDeclaration - - AspNetCore
UsingStatement - (1:0,1 [14] ) - System
UsingStatement - (16:1,1 [34] ) - System.Collections.Generic
@ -9,8 +9,9 @@ Document -
UsingStatement - (102:4,1 [32] ) - Microsoft.AspNetCore.Mvc
UsingStatement - (135:5,1 [42] ) - Microsoft.AspNetCore.Mvc.Rendering
UsingStatement - (178:6,1 [45] ) - Microsoft.AspNetCore.Mvc.ViewFeatures
ClassDeclaration - - public - TestFiles_IntegrationTests_CodeGenerationIntegrationTest_MalformedPageDirective_cshtml - global::Microsoft.AspNetCore.Mvc.RazorPages.Page -
ClassDeclaration - - public - TestFiles_IntegrationTests_CodeGenerationIntegrationTest_MalformedPageDirective_cshtml - global::Microsoft.AspNetCore.Mvc.Razor.RazorPage<dynamic> -
MethodDeclaration - - public - async, override - global::System.Threading.Tasks.Task - ExecuteAsync
MalformedDirective - (0:0,0 [6] MalformedPageDirective.cshtml)
CSharpCode -
RazorIRToken - - CSharp - BeginContext(6, 49, true);
HtmlContent - (6:0,6 [49] MalformedPageDirective.cshtml)
@ -29,7 +30,3 @@ Document -
InjectDirective -
InjectDirective -
InjectDirective -
CSharpCode -
RazorIRToken - - CSharp - public global::Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionary<TestFiles_IntegrationTests_CodeGenerationIntegrationTest_MalformedPageDirective_cshtml> ViewData => (global::Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionary<TestFiles_IntegrationTests_CodeGenerationIntegrationTest_MalformedPageDirective_cshtml>)PageContext?.ViewData;
CSharpCode -
RazorIRToken - - CSharp - public TestFiles_IntegrationTests_CodeGenerationIntegrationTest_MalformedPageDirective_cshtml Model => ViewData.Model;

View File

@ -7,7 +7,6 @@ using System.Linq;
using System.Text;
using Microsoft.AspNetCore.Razor.Language.Legacy;
using Xunit;
using Moq;
namespace Microsoft.AspNetCore.Razor.Language
{
@ -39,7 +38,7 @@ namespace Microsoft.AspNetCore.Razor.Language
new SourceLocation(14 + Environment.NewLine.Length, 1, 14),
length: 1))
};
var content =
@"
@ -54,7 +53,9 @@ namespace Microsoft.AspNetCore.Razor.Language
// Assert
var rewrittenTree = codeDocument.GetSyntaxTree();
Assert.Equal(expectedDiagnostics, rewrittenTree.Diagnostics);
var directiveValue = rewrittenTree.Root.Children.OfType<Block>().First().Children.Last() as Span;
var chunkGenerator = Assert.IsType<AddTagHelperChunkGenerator>(directiveValue.ChunkGenerator);
Assert.Equal(expectedDiagnostics, chunkGenerator.Diagnostics);
}
[Fact]
@ -98,7 +99,9 @@ namespace Microsoft.AspNetCore.Razor.Language
// Assert
var rewrittenTree = codeDocument.GetSyntaxTree();
Assert.Equal(expectedDiagnostics, rewrittenTree.Diagnostics);
var directiveValue = rewrittenTree.Root.Children.OfType<Block>().First().Children.Last() as Span;
var chunkGenerator = Assert.IsType<RemoveTagHelperChunkGenerator>(directiveValue.ChunkGenerator);
Assert.Equal(expectedDiagnostics, chunkGenerator.Diagnostics);
}
[Fact]
@ -142,7 +145,9 @@ namespace Microsoft.AspNetCore.Razor.Language
// Assert
var rewrittenTree = codeDocument.GetSyntaxTree();
Assert.Equal(expectedDiagnostics, rewrittenTree.Diagnostics);
var directiveValue = rewrittenTree.Root.Children.OfType<Block>().First().Children.Last() as Span;
var chunkGenerator = Assert.IsType<TagHelperPrefixDirectiveChunkGenerator>(directiveValue.ChunkGenerator);
Assert.Equal(expectedDiagnostics, chunkGenerator.Diagnostics);
}
[Fact]
@ -464,7 +469,6 @@ namespace Microsoft.AspNetCore.Razor.Language
public void ParseAddOrRemoveDirective_CalculatesAssemblyLocationInLookupText(string text, int assemblyLocation)
{
// Arrange
var errorSink = new ErrorSink();
var phase = new DefaultRazorTagHelperBinderPhase();
var directive = new TagHelperDirectiveDescriptor()
@ -472,15 +476,16 @@ namespace Microsoft.AspNetCore.Razor.Language
DirectiveText = text,
DirectiveType = TagHelperDirectiveType.AddTagHelper,
Location = SourceLocation.Zero,
Diagnostics = new List<RazorDiagnostic>(),
};
var expected = new SourceLocation(assemblyLocation, 0, assemblyLocation);
// Act
var result = phase.ParseAddOrRemoveDirective(directive, errorSink);
var result = phase.ParseAddOrRemoveDirective(directive);
// Assert
Assert.Empty(errorSink.Errors);
Assert.Empty(directive.Diagnostics);
Assert.Equal("foo", result.TypePattern);
Assert.Equal("assemblyName", result.AssemblyName);
Assert.Equal(expected, result.AssemblyNameLocation);
@ -505,7 +510,8 @@ namespace Microsoft.AspNetCore.Razor.Language
{
DirectiveText = "th ",
Location = directiveLocation1,
DirectiveType = TagHelperDirectiveType.TagHelperPrefix
DirectiveType = TagHelperDirectiveType.TagHelperPrefix,
Diagnostics = new List<RazorDiagnostic>(),
},
},
new[]
@ -527,7 +533,8 @@ namespace Microsoft.AspNetCore.Razor.Language
{
DirectiveText = "th\t",
Location = directiveLocation1,
DirectiveType = TagHelperDirectiveType.TagHelperPrefix
DirectiveType = TagHelperDirectiveType.TagHelperPrefix,
Diagnostics = new List<RazorDiagnostic>(),
}
},
new[]
@ -549,7 +556,8 @@ namespace Microsoft.AspNetCore.Razor.Language
{
DirectiveText = "th" + Environment.NewLine,
Location = directiveLocation1,
DirectiveType = TagHelperDirectiveType.TagHelperPrefix
DirectiveType = TagHelperDirectiveType.TagHelperPrefix,
Diagnostics = new List<RazorDiagnostic>(),
}
},
new[]
@ -571,7 +579,8 @@ namespace Microsoft.AspNetCore.Razor.Language
{
DirectiveText = " th ",
Location = directiveLocation1,
DirectiveType = TagHelperDirectiveType.TagHelperPrefix
DirectiveType = TagHelperDirectiveType.TagHelperPrefix,
Diagnostics = new List<RazorDiagnostic>(),
}
},
new[]
@ -593,7 +602,8 @@ namespace Microsoft.AspNetCore.Razor.Language
{
DirectiveText = "@",
Location = directiveLocation1,
DirectiveType = TagHelperDirectiveType.TagHelperPrefix
DirectiveType = TagHelperDirectiveType.TagHelperPrefix,
Diagnostics = new List<RazorDiagnostic>(),
}
},
new[]
@ -615,7 +625,8 @@ namespace Microsoft.AspNetCore.Razor.Language
{
DirectiveText = "t@h",
Location = directiveLocation1,
DirectiveType = TagHelperDirectiveType.TagHelperPrefix
DirectiveType = TagHelperDirectiveType.TagHelperPrefix,
Diagnostics = new List<RazorDiagnostic>(),
}
},
new[]
@ -637,7 +648,8 @@ namespace Microsoft.AspNetCore.Razor.Language
{
DirectiveText = "!",
Location = directiveLocation1,
DirectiveType = TagHelperDirectiveType.TagHelperPrefix
DirectiveType = TagHelperDirectiveType.TagHelperPrefix,
Diagnostics = new List<RazorDiagnostic>(),
}
},
new[]
@ -659,7 +671,8 @@ namespace Microsoft.AspNetCore.Razor.Language
{
DirectiveText = "!th",
Location = directiveLocation1,
DirectiveType = TagHelperDirectiveType.TagHelperPrefix
DirectiveType = TagHelperDirectiveType.TagHelperPrefix,
Diagnostics = new List<RazorDiagnostic>(),
}
},
new[]
@ -685,18 +698,18 @@ namespace Microsoft.AspNetCore.Razor.Language
object expectedErrors)
{
// Arrange
var errorSink = new ErrorSink();
var expectedDiagnostics = ((IEnumerable<RazorError>)expectedErrors).Select(RazorDiagnostic.Create);
var tagHelperDirectives = (IEnumerable<TagHelperDirectiveDescriptor>)directives;
var phase = new DefaultRazorTagHelperBinderPhase();
// Act
foreach (var directive in ((IEnumerable<TagHelperDirectiveDescriptor>)directives))
foreach (var directive in tagHelperDirectives)
{
Assert.False(phase.IsValidTagHelperPrefix(directive.DirectiveText, directive.Location, errorSink));
Assert.False(phase.IsValidTagHelperPrefix(directive.DirectiveText, directive.Location, directive.Diagnostics));
}
// Assert
Assert.Equal(((IEnumerable<RazorError>)expectedErrors).ToArray(), errorSink.Errors.ToArray());
Assert.Equal(expectedDiagnostics, tagHelperDirectives.SelectMany(directive => directive.Diagnostics));
}
private static string AssemblyA => "TestAssembly";
@ -836,15 +849,15 @@ namespace Microsoft.AspNetCore.Razor.Language
string expectedPrefix)
{
// Arrange
var errorSink = new ErrorSink();
var phase = new DefaultRazorTagHelperBinderPhase();
var document = RazorCodeDocument.Create(new StringSourceDocument("Test content", encoding: Encoding.UTF8, filePath: "TestFile"));
var tagHelperDirectives = (IEnumerable<TagHelperDirectiveDescriptor>)directiveDescriptors;
// Act
var prefix = phase.ProcessTagHelperPrefix(((IEnumerable<TagHelperDirectiveDescriptor>)directiveDescriptors).ToList(), document, errorSink);
var prefix = phase.ProcessTagHelperPrefix(((IEnumerable<TagHelperDirectiveDescriptor>)directiveDescriptors).ToList(), document);
// Assert
Assert.Empty(errorSink.Errors);
Assert.Empty(tagHelperDirectives.SelectMany(directive => directive.Diagnostics));
Assert.Equal(expectedPrefix, prefix);
}
@ -1056,20 +1069,17 @@ namespace Microsoft.AspNetCore.Razor.Language
object expectedDescriptors)
{
// Arrange
var errorSink = new ErrorSink();
var phase = new DefaultRazorTagHelperBinderPhase();
var tagHelperDirectives = (IEnumerable<TagHelperDirectiveDescriptor>)directiveDescriptors;
var expected = (IEnumerable<TagHelperDescriptor>)expectedDescriptors;
// Act
var results = phase.ProcessDirectives(
new List<TagHelperDirectiveDescriptor>((IEnumerable<TagHelperDirectiveDescriptor>)directiveDescriptors),
new List<TagHelperDescriptor>((IEnumerable<TagHelperDescriptor>)tagHelpers),
errorSink);
new List<TagHelperDirectiveDescriptor>(tagHelperDirectives),
new List<TagHelperDescriptor>((IEnumerable<TagHelperDescriptor>)tagHelpers));
// Assert
Assert.Empty(errorSink.Errors);
Assert.Empty(tagHelperDirectives.SelectMany(directive => directive.Diagnostics));
Assert.Equal(expected.Count(), results.Count());
foreach (var expectedDescriptor in expected)
@ -1224,15 +1234,13 @@ namespace Microsoft.AspNetCore.Razor.Language
object directiveDescriptors)
{
// Arrange
var errorSink = new ErrorSink();
var tagHelperDirectives = (IEnumerable<TagHelperDirectiveDescriptor>)directiveDescriptors;
var phase = new DefaultRazorTagHelperBinderPhase();
// Act
var results = phase.ProcessDirectives(
new List<TagHelperDirectiveDescriptor>((IEnumerable<TagHelperDirectiveDescriptor>)directiveDescriptors),
new List<TagHelperDescriptor>((IEnumerable<TagHelperDescriptor>)tagHelpers),
errorSink);
new List<TagHelperDirectiveDescriptor>(tagHelperDirectives),
new List<TagHelperDescriptor>((IEnumerable<TagHelperDescriptor>)tagHelpers));
// Assert
Assert.Empty(results);
@ -1264,26 +1272,24 @@ namespace Microsoft.AspNetCore.Razor.Language
public void ProcessDirectives_IgnoresSpaces(string directiveText)
{
// Arrange
var errorSink = new ErrorSink();
var phase = new DefaultRazorTagHelperBinderPhase();
var directives = new[]
{
new TagHelperDirectiveDescriptor()
{
DirectiveText = directiveText,
DirectiveType = TagHelperDirectiveType.AddTagHelper,
}
};
new TagHelperDirectiveDescriptor()
{
DirectiveText = directiveText,
DirectiveType = TagHelperDirectiveType.AddTagHelper,
Diagnostics = new List<RazorDiagnostic>(),
}
};
// Act
var results = phase.ProcessDirectives(
directives,
new[] { Valid_PlainTagHelperDescriptor, Valid_InheritedTagHelperDescriptor },
errorSink);
new[] { Valid_PlainTagHelperDescriptor, Valid_InheritedTagHelperDescriptor });
// Assert
Assert.Empty(errorSink.Errors);
Assert.Empty(directives[0].Diagnostics);
var single = Assert.Single(results);
Assert.Equal(Valid_PlainTagHelperDescriptor, single, TagHelperDescriptorComparer.Default);
@ -1305,7 +1311,6 @@ namespace Microsoft.AspNetCore.Razor.Language
public void DescriptorResolver_CreatesErrorIfInvalidLookupText_DoesNotThrow(string directiveText, int errorLength)
{
// Arrange
var errorSink = new ErrorSink();
var phase = new DefaultRazorTagHelperBinderPhase();
var directive = new TagHelperDirectiveDescriptor()
@ -1313,6 +1318,7 @@ namespace Microsoft.AspNetCore.Razor.Language
DirectiveText = directiveText,
DirectiveType = TagHelperDirectiveType.AddTagHelper,
Location = new SourceLocation(1, 2, 3),
Diagnostics = new List<RazorDiagnostic>(),
};
var expectedErrorMessage = string.Format(
@ -1320,16 +1326,21 @@ namespace Microsoft.AspNetCore.Razor.Language
"format is: \"typeName, assemblyName\".",
directiveText);
var expectedError = RazorDiagnostic.Create(
new RazorError(
expectedErrorMessage,
new SourceLocation(1, 2, 3),
errorLength));
// Act
var result = phase.ParseAddOrRemoveDirective(directive, errorSink);
var result = phase.ParseAddOrRemoveDirective(directive);
// Assert
Assert.Null(result);
var error = Assert.Single(errorSink.Errors);
Assert.Equal(errorLength, error.Length);
Assert.Equal(new SourceLocation(1, 2, 3), error.Location);
Assert.Equal(expectedErrorMessage, error.Message);
var error = Assert.Single(directive.Diagnostics);
Assert.Equal(expectedError, error);
}
private static TagHelperDescriptor CreatePrefixedValidPlainDescriptor(string prefix)
@ -1367,7 +1378,8 @@ namespace Microsoft.AspNetCore.Razor.Language
{
DirectiveText = directiveText,
Location = SourceLocation.Zero,
DirectiveType = directiveType
DirectiveType = directiveType,
Diagnostics = new List<RazorDiagnostic>(),
};
}
@ -1404,7 +1416,8 @@ namespace Microsoft.AspNetCore.Razor.Language
{
foreach (var ruleBuilder in ruleBuilders)
{
builder.TagMatchingRule(innerRuleBuilder => {
builder.TagMatchingRule(innerRuleBuilder =>
{
innerRuleBuilder.RequireTagName(tagName);
ruleBuilder(innerRuleBuilder);
});

View File

@ -13,25 +13,42 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
[Fact]
public void FunctionsDirectiveAutoCompleteAtEOF()
{
// Arrange
var chunkGenerator = new DirectiveChunkGenerator(FunctionsDirective.Directive);
chunkGenerator.Diagnostics.Add(
RazorDiagnostic.Create(
new RazorError(
LegacyResources.FormatParseError_Expected_EndOfBlock_Before_EOF(FunctionsDirective.Directive.Directive, "}", "{"),
new SourceLocation(10, 0, 10),
length: 1)));
// Act & Assert
ParseBlockTest(
"@functions{",
new[] { FunctionsDirective.Directive, },
new DirectiveBlock(new DirectiveChunkGenerator(FunctionsDirective.Directive),
new[] { FunctionsDirective.Directive },
new DirectiveBlock(chunkGenerator,
Factory.CodeTransition(),
Factory.MetaCode("functions").Accepts(AcceptedCharactersInternal.None),
Factory.MetaCode("{").AutoCompleteWith("}", atEndOfSpan: true).Accepts(AcceptedCharactersInternal.None)),
new RazorError(
LegacyResources.FormatParseError_Expected_EndOfBlock_Before_EOF(FunctionsDirective.Directive.Directive, "}", "{"),
new SourceLocation(10, 0, 10),
length: 1));
Factory.MetaCode("{").AutoCompleteWith("}", atEndOfSpan: true).Accepts(AcceptedCharactersInternal.None)));
}
[Fact]
public void SectionDirectiveAutoCompleteAtEOF()
{
ParseBlockTest("@section Header {",
new[] { SectionDirective.Directive, },
new DirectiveBlock(new DirectiveChunkGenerator(SectionDirective.Directive),
// Arrange
var chunkGenerator = new DirectiveChunkGenerator(SectionDirective.Directive);
chunkGenerator.Diagnostics.Add(
RazorDiagnostic.Create(
new RazorError(
LegacyResources.FormatParseError_Expected_EndOfBlock_Before_EOF("section", "}", "{"),
new SourceLocation(16, 0, 16),
length: 1)));
// Act & Assert
ParseBlockTest(
"@section Header {",
new[] { SectionDirective.Directive },
new DirectiveBlock(chunkGenerator,
Factory.CodeTransition(),
Factory.MetaCode("section").Accepts(AcceptedCharactersInternal.None),
Factory.Span(SpanKindInternal.Code, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.WhiteSpace),
@ -40,55 +57,67 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
Factory.Span(SpanKindInternal.Markup, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.AllWhiteSpace),
Factory.MetaCode("{").AutoCompleteWith("}", atEndOfSpan: true).Accepts(AcceptedCharactersInternal.None),
new MarkupBlock(
Factory.EmptyHtml())),
new RazorError(
LegacyResources.FormatParseError_Expected_EndOfBlock_Before_EOF("section", "}", "{"),
new SourceLocation(16, 0, 16),
length: 1));
Factory.EmptyHtml())));
}
[Fact]
public void VerbatimBlockAutoCompleteAtEOF()
{
ParseBlockTest("@{",
new StatementBlock(
Factory.CodeTransition(),
Factory.MetaCode("{").Accepts(AcceptedCharactersInternal.None),
Factory.EmptyCSharp()
.AsStatement()
.With(new AutoCompleteEditHandler(CSharpLanguageCharacteristics.Instance.TokenizeString) { AutoCompleteString = "}" })
),
new RazorError(
LegacyResources.FormatParseError_Expected_EndOfBlock_Before_EOF(
LegacyResources.BlockName_Code, "}", "{"),
new SourceLocation(1, 0, 1),
length: 1));
new StatementBlock(
Factory.CodeTransition(),
Factory.MetaCode("{").Accepts(AcceptedCharactersInternal.None),
Factory.EmptyCSharp()
.AsStatement()
.With(new AutoCompleteEditHandler(CSharpLanguageCharacteristics.Instance.TokenizeString) { AutoCompleteString = "}" })
),
new RazorError(
LegacyResources.FormatParseError_Expected_EndOfBlock_Before_EOF(
LegacyResources.BlockName_Code, "}", "{"),
new SourceLocation(1, 0, 1),
length: 1));
}
[Fact]
public void FunctionsDirectiveAutoCompleteAtStartOfFile()
{
ParseBlockTest(
"@functions{" + Environment.NewLine + "foo",
new[] { FunctionsDirective.Directive, },
new DirectiveBlock(new DirectiveChunkGenerator(FunctionsDirective.Directive),
Factory.CodeTransition(),
Factory.MetaCode("functions").Accepts(AcceptedCharactersInternal.None),
Factory.MetaCode("{").AutoCompleteWith("}", atEndOfSpan: true).Accepts(AcceptedCharactersInternal.None),
Factory.Code(Environment.NewLine + "foo").AsStatement()),
// Arrange
var chunkGenerator = new DirectiveChunkGenerator(FunctionsDirective.Directive);
chunkGenerator.Diagnostics.Add(
RazorDiagnostic.Create(
new RazorError(
LegacyResources.FormatParseError_Expected_EndOfBlock_Before_EOF("functions", "}", "{"),
new SourceLocation(10, 0, 10),
length: 1));
length: 1)));
// Act & Assert
ParseBlockTest(
"@functions{" + Environment.NewLine + "foo",
new[] { FunctionsDirective.Directive },
new DirectiveBlock(chunkGenerator,
Factory.CodeTransition(),
Factory.MetaCode("functions").Accepts(AcceptedCharactersInternal.None),
Factory.MetaCode("{").AutoCompleteWith("}", atEndOfSpan: true).Accepts(AcceptedCharactersInternal.None),
Factory.Code(Environment.NewLine + "foo").AsStatement()));
}
[Fact]
public void SectionDirectiveAutoCompleteAtStartOfFile()
{
ParseBlockTest("@section Header {" + Environment.NewLine
+ "<p>Foo</p>",
new[] { SectionDirective.Directive, },
new DirectiveBlock(new DirectiveChunkGenerator(SectionDirective.Directive),
// Arrange
var chunkGenerator = new DirectiveChunkGenerator(SectionDirective.Directive);
chunkGenerator.Diagnostics.Add(
RazorDiagnostic.Create(
new RazorError(
LegacyResources.FormatParseError_Expected_EndOfBlock_Before_EOF("section", "}", "{"),
new SourceLocation(16, 0, 16),
length: 1)));
// Act & Assert
ParseBlockTest(
"@section Header {" + Environment.NewLine + "<p>Foo</p>",
new[] { SectionDirective.Directive },
new DirectiveBlock(chunkGenerator,
Factory.CodeTransition(),
Factory.MetaCode("section").Accepts(AcceptedCharactersInternal.None),
Factory.Span(SpanKindInternal.Code, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.WhiteSpace),
@ -101,37 +130,33 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
Factory.Markup("<p>")),
Factory.Markup("Foo"),
new MarkupTagBlock(
Factory.Markup("</p>")))),
new RazorError(
LegacyResources.FormatParseError_Expected_EndOfBlock_Before_EOF("section", "}", "{"),
new SourceLocation(16, 0, 16),
length: 1));
Factory.Markup("</p>")))));
}
[Fact]
public void VerbatimBlockAutoCompleteAtStartOfFile()
{
ParseBlockTest("@{" + Environment.NewLine
+ "<p></p>",
new StatementBlock(
Factory.CodeTransition(),
Factory.MetaCode("{").Accepts(AcceptedCharactersInternal.None),
Factory.Code(Environment.NewLine)
.AsStatement()
.With(new AutoCompleteEditHandler(CSharpLanguageCharacteristics.Instance.TokenizeString) { AutoCompleteString = "}" }),
new MarkupBlock(
new MarkupTagBlock(
Factory.Markup("<p>").Accepts(AcceptedCharactersInternal.None)),
new MarkupTagBlock(
Factory.Markup("</p>").Accepts(AcceptedCharactersInternal.None))),
Factory.Span(SpanKindInternal.Code, new CSharpSymbol(string.Empty, CSharpSymbolType.Unknown))
.With(new StatementChunkGenerator())
),
new RazorError(
LegacyResources.FormatParseError_Expected_EndOfBlock_Before_EOF(
LegacyResources.BlockName_Code, "}", "{"),
new SourceLocation(1, 0, 1),
length: 1));
ParseBlockTest(
"@{" + Environment.NewLine + "<p></p>",
new StatementBlock(
Factory.CodeTransition(),
Factory.MetaCode("{").Accepts(AcceptedCharactersInternal.None),
Factory.Code(Environment.NewLine)
.AsStatement()
.With(new AutoCompleteEditHandler(CSharpLanguageCharacteristics.Instance.TokenizeString) { AutoCompleteString = "}" }),
new MarkupBlock(
new MarkupTagBlock(
Factory.Markup("<p>").Accepts(AcceptedCharactersInternal.None)),
new MarkupTagBlock(
Factory.Markup("</p>").Accepts(AcceptedCharactersInternal.None))),
Factory.Span(SpanKindInternal.Code, new CSharpSymbol(string.Empty, CSharpSymbolType.Unknown))
.With(new StatementChunkGenerator())
),
new RazorError(
LegacyResources.FormatParseError_Expected_EndOfBlock_Before_EOF(
LegacyResources.BlockName_Code, "}", "{"),
new SourceLocation(1, 0, 1),
length: 1));
}
}
}

View File

@ -11,6 +11,32 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
{
public class CSharpDirectivesTest : CsHtmlCodeParserTestBase
{
[Fact]
public void DirectiveDescriptor_TokensMustBeSeparatedBySpace()
{
// Arrange
var descriptor = DirectiveDescriptor.CreateDirective(
"custom",
DirectiveKind.SingleLine,
b => b.AddStringToken().AddStringToken());
var chunkGenerator = new DirectiveChunkGenerator(descriptor);
chunkGenerator.Diagnostics.Add(
RazorDiagnostic.Create(
new RazorError(
Resources.FormatDirectiveTokensMustBeSeparatedByWhitespace("custom"),
17, 0, 17, 9)));
// Act & Assert
ParseCodeBlockTest(
"@custom \"string1\"\"string2\"",
new[] { descriptor },
new DirectiveBlock(chunkGenerator,
Factory.CodeTransition(),
Factory.MetaCode("custom").Accepts(AcceptedCharactersInternal.None),
Factory.Span(SpanKindInternal.Markup, " ", markup: false).Accepts(AcceptedCharactersInternal.WhiteSpace),
Factory.Span(SpanKindInternal.Code, "\"string1\"", markup: false).AsDirectiveToken(descriptor.Tokens[0])));
}
[Fact]
public void DirectiveDescriptor_CanHandleEOFIncompleteNamespaceTokens()
{
@ -19,19 +45,21 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
"custom",
DirectiveKind.SingleLine,
b => b.AddNamespaceToken());
var chunkGenerator = new DirectiveChunkGenerator(descriptor);
chunkGenerator.Diagnostics.Add(
RazorDiagnostic.Create(
new RazorError(
LegacyResources.FormatDirectiveExpectsNamespace("custom"),
8, 0, 8, 7)));
// Act & Assert
ParseCodeBlockTest(
"@custom System.",
new[] { descriptor },
new DirectiveBlock(
new DirectiveChunkGenerator(descriptor),
new DirectiveBlock(chunkGenerator,
Factory.CodeTransition(),
Factory.MetaCode("custom").Accepts(AcceptedCharactersInternal.None),
Factory.Span(SpanKindInternal.Code, " ", markup: false).Accepts(AcceptedCharactersInternal.WhiteSpace)),
new RazorError(
LegacyResources.FormatDirectiveExpectsNamespace("custom"),
8, 0, 8, 7));
Factory.Span(SpanKindInternal.Code, " ", markup: false).Accepts(AcceptedCharactersInternal.WhiteSpace)));
}
[Fact]
@ -42,19 +70,21 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
"custom",
DirectiveKind.SingleLine,
b => b.AddNamespaceToken());
var chunkGenerator = new DirectiveChunkGenerator(descriptor);
chunkGenerator.Diagnostics.Add(
RazorDiagnostic.Create(
new RazorError(
LegacyResources.FormatDirectiveExpectsNamespace("custom"),
8, 0, 8, 7)));
// Act & Assert
ParseCodeBlockTest(
"@custom System<",
new[] { descriptor },
new DirectiveBlock(
new DirectiveChunkGenerator(descriptor),
new DirectiveBlock(chunkGenerator,
Factory.CodeTransition(),
Factory.MetaCode("custom").Accepts(AcceptedCharactersInternal.None),
Factory.Span(SpanKindInternal.Code, " ", markup: false).Accepts(AcceptedCharactersInternal.WhiteSpace)),
new RazorError(
LegacyResources.FormatDirectiveExpectsNamespace("custom"),
8, 0, 8, 7));
Factory.Span(SpanKindInternal.Code, " ", markup: false).Accepts(AcceptedCharactersInternal.WhiteSpace)));
}
[Fact]
public void DirectiveDescriptor_CanHandleIncompleteNamespaceTokens()
@ -64,19 +94,21 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
"custom",
DirectiveKind.SingleLine,
b => b.AddNamespaceToken());
var chunkGenerator = new DirectiveChunkGenerator(descriptor);
chunkGenerator.Diagnostics.Add(
RazorDiagnostic.Create(
new RazorError(
LegacyResources.FormatDirectiveExpectsNamespace("custom"),
8, 0, 8, 7)));
// Act & Assert
ParseCodeBlockTest(
"@custom System." + Environment.NewLine,
new[] { descriptor },
new DirectiveBlock(
new DirectiveChunkGenerator(descriptor),
new DirectiveBlock(chunkGenerator,
Factory.CodeTransition(),
Factory.MetaCode("custom").Accepts(AcceptedCharactersInternal.None),
Factory.Span(SpanKindInternal.Code, " ", markup: false).Accepts(AcceptedCharactersInternal.WhiteSpace)),
new RazorError(
LegacyResources.FormatDirectiveExpectsNamespace("custom"),
8, 0, 8, 7));
Factory.Span(SpanKindInternal.Code, " ", markup: false).Accepts(AcceptedCharactersInternal.WhiteSpace)));
}
[Fact]
@ -87,19 +119,21 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
"custom",
DirectiveKind.SingleLine,
b => b.AddNamespaceToken());
var chunkGenerator = new DirectiveChunkGenerator(descriptor);
chunkGenerator.Diagnostics.Add(
RazorDiagnostic.Create(
new RazorError(
LegacyResources.FormatDirectiveExpectsNamespace("custom"),
8, 0, 8, 7)));
// Act & Assert
ParseCodeBlockTest(
"@custom System<" + Environment.NewLine,
new[] { descriptor },
new DirectiveBlock(
new DirectiveChunkGenerator(descriptor),
new DirectiveBlock(chunkGenerator,
Factory.CodeTransition(),
Factory.MetaCode("custom").Accepts(AcceptedCharactersInternal.None),
Factory.Span(SpanKindInternal.Code, " ", markup: false).Accepts(AcceptedCharactersInternal.WhiteSpace)),
new RazorError(
LegacyResources.FormatDirectiveExpectsNamespace("custom"),
8, 0, 8, 7));
Factory.Span(SpanKindInternal.Code, " ", markup: false).Accepts(AcceptedCharactersInternal.WhiteSpace)));
}
[Fact]
@ -154,13 +188,11 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
Factory.MetaCode(SyntaxConstants.CSharp.AddTagHelperKeyword + " ")
.Accepts(AcceptedCharactersInternal.None),
Factory.Code("\"*, Foo\"")
.AsAddTagHelper("\"*, Foo\"")),
.AsAddTagHelper(
"\"*, Foo\"",
new RazorError(Resources.FormatDirectiveMustAppearAtStartOfLine("addTagHelper"), new SourceLocation(4, 0, 4), 12))),
Factory.Code(Environment.NewLine).AsStatement(),
Factory.MetaCode("}").Accepts(AcceptedCharactersInternal.None)),
new RazorError(
Resources.FormatDirectiveMustAppearAtStartOfLine("addTagHelper"),
new SourceLocation(4, 0, 4),
12));
Factory.MetaCode("}").Accepts(AcceptedCharactersInternal.None)));
}
[Fact]
@ -171,6 +203,13 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
"custom",
DirectiveKind.SingleLine,
b => b.AddTypeToken());
var chunkGenerator = new DirectiveChunkGenerator(descriptor);
chunkGenerator.Diagnostics.Add(
RazorDiagnostic.Create(
new RazorError(
Resources.FormatDirectiveMustAppearAtStartOfLine("custom"),
new SourceLocation(4, 0, 4),
6)));
// Act & Assert
ParseCodeBlockTest(
@ -181,19 +220,14 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
Factory.Code(" ")
.AsStatement()
.AutoCompleteWith(autoCompleteString: null, atEndOfSpan: false),
new DirectiveBlock(
new DirectiveChunkGenerator(descriptor),
new DirectiveBlock(chunkGenerator,
Factory.CodeTransition(),
Factory.MetaCode("custom").Accepts(AcceptedCharactersInternal.None),
Factory.Span(SpanKindInternal.Code, " ", markup: false).Accepts(AcceptedCharactersInternal.WhiteSpace),
Factory.Span(SpanKindInternal.Code, "System.Text.Encoding.ASCIIEncoding", markup: false).AsDirectiveToken(descriptor.Tokens[0]),
Factory.MetaCode(Environment.NewLine).Accepts(AcceptedCharactersInternal.WhiteSpace)),
Factory.EmptyCSharp().AsStatement(),
Factory.MetaCode("}").Accepts(AcceptedCharactersInternal.None)),
new RazorError(
Resources.FormatDirectiveMustAppearAtStartOfLine("custom"),
new SourceLocation(4, 0, 4),
6));
Factory.MetaCode("}").Accepts(AcceptedCharactersInternal.None)));
}
[Fact]
@ -309,21 +343,22 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
"custom",
DirectiveKind.SingleLine,
b => b.AddStringToken());
var expectedError = new RazorError(
LegacyResources.FormatDirectiveExpectsQuotedStringLiteral("custom"),
new SourceLocation(8, 0, 8),
length: 7);
var chunkGenerator = new DirectiveChunkGenerator(descriptor);
chunkGenerator.Diagnostics.Add(
RazorDiagnostic.Create(
new RazorError(
LegacyResources.FormatDirectiveExpectsQuotedStringLiteral("custom"),
new SourceLocation(8, 0, 8),
length: 7)));
// Act & Assert
ParseCodeBlockTest(
"@custom AString",
new[] { descriptor },
new DirectiveBlock(
new DirectiveChunkGenerator(descriptor),
new DirectiveBlock(chunkGenerator,
Factory.CodeTransition(),
Factory.MetaCode("custom").Accepts(AcceptedCharactersInternal.None),
Factory.Span(SpanKindInternal.Markup, " ", markup: false).Accepts(AcceptedCharactersInternal.WhiteSpace)), expectedError);
Factory.Span(SpanKindInternal.Markup, " ", markup: false).Accepts(AcceptedCharactersInternal.WhiteSpace)));
}
[Fact]
@ -334,21 +369,22 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
"custom",
DirectiveKind.SingleLine,
b => b.AddStringToken());
var expectedError = new RazorError(
LegacyResources.FormatDirectiveExpectsQuotedStringLiteral("custom"),
new SourceLocation(8, 0, 8),
length: 1);
var chunkGenerator = new DirectiveChunkGenerator(descriptor);
chunkGenerator.Diagnostics.Add(
RazorDiagnostic.Create(
new RazorError(
LegacyResources.FormatDirectiveExpectsQuotedStringLiteral("custom"),
new SourceLocation(8, 0, 8),
length: 1)));
// Act & Assert
ParseCodeBlockTest(
"@custom {foo?}",
new[] { descriptor },
new DirectiveBlock(
new DirectiveChunkGenerator(descriptor),
new DirectiveBlock(chunkGenerator,
Factory.CodeTransition(),
Factory.MetaCode("custom").Accepts(AcceptedCharactersInternal.None),
Factory.Span(SpanKindInternal.Markup, " ", markup: false).Accepts(AcceptedCharactersInternal.WhiteSpace)), expectedError);
Factory.Span(SpanKindInternal.Markup, " ", markup: false).Accepts(AcceptedCharactersInternal.WhiteSpace)));
}
[Fact]
@ -359,21 +395,22 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
"custom",
DirectiveKind.SingleLine,
b => b.AddStringToken());
var expectedError = new RazorError(
LegacyResources.FormatDirectiveExpectsQuotedStringLiteral("custom"),
new SourceLocation(8, 0, 8),
length: 9);
var chunkGenerator = new DirectiveChunkGenerator(descriptor);
chunkGenerator.Diagnostics.Add(
RazorDiagnostic.Create(
new RazorError(
LegacyResources.FormatDirectiveExpectsQuotedStringLiteral("custom"),
new SourceLocation(8, 0, 8),
length: 9)));
// Act & Assert
ParseCodeBlockTest(
"@custom 'AString'",
new[] { descriptor },
new DirectiveBlock(
new DirectiveChunkGenerator(descriptor),
new DirectiveBlock(chunkGenerator,
Factory.CodeTransition(),
Factory.MetaCode("custom").Accepts(AcceptedCharactersInternal.None),
Factory.Span(SpanKindInternal.Markup, " ", markup: false).Accepts(AcceptedCharactersInternal.WhiteSpace)), expectedError);
Factory.Span(SpanKindInternal.Markup, " ", markup: false).Accepts(AcceptedCharactersInternal.WhiteSpace)));
}
[Fact]
@ -384,22 +421,22 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
"custom",
DirectiveKind.SingleLine,
b => b.AddStringToken());
var expectedError = new RazorError(
LegacyResources.FormatDirectiveExpectsQuotedStringLiteral("custom"),
new SourceLocation(8, 0, 8),
length: 7);
var chunkGenerator = new DirectiveChunkGenerator(descriptor);
chunkGenerator.Diagnostics.Add(
RazorDiagnostic.Create(
new RazorError(
LegacyResources.FormatDirectiveExpectsQuotedStringLiteral("custom"),
new SourceLocation(8, 0, 8),
length: 7)));
// Act & Assert
ParseCodeBlockTest(
"@custom AString\"",
new[] { descriptor },
new DirectiveBlock(
new DirectiveChunkGenerator(descriptor),
new DirectiveBlock(chunkGenerator,
Factory.CodeTransition(),
Factory.MetaCode("custom").Accepts(AcceptedCharactersInternal.None),
Factory.Span(SpanKindInternal.Markup, " ", markup: false).Accepts(AcceptedCharactersInternal.WhiteSpace)),
expectedError);
Factory.Span(SpanKindInternal.Markup, " ", markup: false).Accepts(AcceptedCharactersInternal.WhiteSpace)));
}
[Fact]
@ -526,22 +563,22 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
"custom",
DirectiveKind.SingleLine,
b => b.AddMemberToken());
var expectedErorr = new RazorError(
LegacyResources.FormatDirectiveExpectsIdentifier("custom"),
new SourceLocation(8, 0, 8),
length: 1);
var chunkGenerator = new DirectiveChunkGenerator(descriptor);
chunkGenerator.Diagnostics.Add(
RazorDiagnostic.Create(
new RazorError(
LegacyResources.FormatDirectiveExpectsIdentifier("custom"),
new SourceLocation(8, 0, 8),
length: 1)));
// Act & Assert
ParseCodeBlockTest(
"@custom -Some_Member",
new[] { descriptor },
new DirectiveBlock(
new DirectiveChunkGenerator(descriptor),
new DirectiveBlock(chunkGenerator,
Factory.CodeTransition(),
Factory.MetaCode("custom").Accepts(AcceptedCharactersInternal.None),
Factory.Span(SpanKindInternal.Code, " ", markup: false).Accepts(AcceptedCharactersInternal.WhiteSpace)),
expectedErorr);
Factory.Span(SpanKindInternal.Code, " ", markup: false).Accepts(AcceptedCharactersInternal.WhiteSpace)));
}
[Fact]
@ -574,25 +611,25 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
"custom",
DirectiveKind.SingleLine,
b => b.AddStringToken());
var expectedErorr = new RazorError(
LegacyResources.FormatUnexpectedDirectiveLiteral("custom", "line break"),
new SourceLocation(16, 0, 16),
length: 7);
var chunkGenerator = new DirectiveChunkGenerator(descriptor);
chunkGenerator.Diagnostics.Add(
RazorDiagnostic.Create(
new RazorError(
LegacyResources.FormatUnexpectedDirectiveLiteral("custom", "line break"),
new SourceLocation(16, 0, 16),
length: 7)));
// Act & Assert
ParseCodeBlockTest(
"@custom \"hello\" \"world\"",
new[] { descriptor },
new DirectiveBlock(
new DirectiveChunkGenerator(descriptor),
new DirectiveBlock(chunkGenerator,
Factory.CodeTransition(),
Factory.MetaCode("custom").Accepts(AcceptedCharactersInternal.None),
Factory.Span(SpanKindInternal.Markup, " ", markup: false).Accepts(AcceptedCharactersInternal.WhiteSpace),
Factory.Span(SpanKindInternal.Code, "\"hello\"", markup: false).AsDirectiveToken(descriptor.Tokens[0]),
Factory.MetaCode(" ").Accepts(AcceptedCharactersInternal.WhiteSpace)),
expectedErorr);
Factory.MetaCode(" ").Accepts(AcceptedCharactersInternal.WhiteSpace)));
}
[Fact]
@ -603,25 +640,25 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
"custom",
DirectiveKind.CodeBlock,
b => b.AddStringToken());
var expectedErorr = new RazorError(
LegacyResources.FormatUnexpectedDirectiveLiteral("custom", "{"),
new SourceLocation(16, 0, 16),
length: 5);
var chunkGenerator = new DirectiveChunkGenerator(descriptor);
chunkGenerator.Diagnostics.Add(
RazorDiagnostic.Create(
new RazorError(
LegacyResources.FormatUnexpectedDirectiveLiteral("custom", "{"),
new SourceLocation(16, 0, 16),
length: 5)));
// Act & Assert
ParseCodeBlockTest(
"@custom \"Hello\" World { foo(); bar(); }",
new[] { descriptor },
new DirectiveBlock(
new DirectiveChunkGenerator(descriptor),
new DirectiveBlock(chunkGenerator,
Factory.CodeTransition(),
Factory.MetaCode("custom").Accepts(AcceptedCharactersInternal.None),
Factory.Span(SpanKindInternal.Markup, " ", markup: false).Accepts(AcceptedCharactersInternal.WhiteSpace),
Factory.Span(SpanKindInternal.Code, "\"Hello\"", markup: false).AsDirectiveToken(descriptor.Tokens[0]),
Factory.Span(SpanKindInternal.Markup, " ", markup: false).Accepts(AcceptedCharactersInternal.AllWhiteSpace)),
expectedErorr);
Factory.Span(SpanKindInternal.Markup, " ", markup: false).Accepts(AcceptedCharactersInternal.AllWhiteSpace)));
}
[Fact]
@ -632,23 +669,23 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
"custom",
DirectiveKind.CodeBlock,
b => b.AddStringToken());
var expectedErorr = new RazorError(
LegacyResources.FormatUnexpectedEOFAfterDirective("custom", "{"),
new SourceLocation(15, 0, 15),
length: 1);
var chunkGenerator = new DirectiveChunkGenerator(descriptor);
chunkGenerator.Diagnostics.Add(
RazorDiagnostic.Create(
new RazorError(
LegacyResources.FormatUnexpectedEOFAfterDirective("custom", "{"),
new SourceLocation(15, 0, 15),
length: 1)));
// Act & Assert
ParseCodeBlockTest(
"@custom \"Hello\"",
new[] { descriptor },
new DirectiveBlock(
new DirectiveChunkGenerator(descriptor),
new DirectiveBlock(chunkGenerator,
Factory.CodeTransition(),
Factory.MetaCode("custom").Accepts(AcceptedCharactersInternal.None),
Factory.Span(SpanKindInternal.Markup, " ", markup: false).Accepts(AcceptedCharactersInternal.WhiteSpace),
Factory.Span(SpanKindInternal.Code, "\"Hello\"", markup: false).AsDirectiveToken(descriptor.Tokens[0])),
expectedErorr);
Factory.Span(SpanKindInternal.Code, "\"Hello\"", markup: false).AsDirectiveToken(descriptor.Tokens[0])));
}
[Fact]
@ -659,18 +696,19 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
"custom",
DirectiveKind.CodeBlock,
b => b.AddStringToken());
var expectedErorr = new RazorError(
LegacyResources.FormatParseError_Expected_EndOfBlock_Before_EOF("custom", "}", "{"),
new SourceLocation(16, 0, 16),
length: 1);
var chunkGenerator = new DirectiveChunkGenerator(descriptor);
chunkGenerator.Diagnostics.Add(
RazorDiagnostic.Create(
new RazorError(
LegacyResources.FormatParseError_Expected_EndOfBlock_Before_EOF("custom", "}", "{"),
new SourceLocation(16, 0, 16),
length: 1)));
// Act & Assert
ParseCodeBlockTest(
"@custom \"Hello\" {",
new[] { descriptor },
new DirectiveBlock(
new DirectiveChunkGenerator(descriptor),
new DirectiveBlock(chunkGenerator,
Factory.CodeTransition(),
Factory.MetaCode("custom").Accepts(AcceptedCharactersInternal.None),
Factory.Span(SpanKindInternal.Markup, " ", markup: false).Accepts(AcceptedCharactersInternal.WhiteSpace),
@ -678,8 +716,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
Factory.Span(SpanKindInternal.Markup, " ", markup: false).Accepts(AcceptedCharactersInternal.AllWhiteSpace),
Factory.MetaCode("{")
.AutoCompleteWith("}", atEndOfSpan: true)
.Accepts(AcceptedCharactersInternal.None)),
expectedErorr);
.Accepts(AcceptedCharactersInternal.None)));
}
[Fact]
@ -724,6 +761,12 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
[Fact]
public void TagHelperPrefixDirective_RequiresValue()
{
// Arrange
var expectedError = new RazorError(
LegacyResources.FormatParseError_DirectiveMustHaveValue(SyntaxConstants.CSharp.TagHelperPrefixKeyword),
absoluteIndex: 1, lineIndex: 0, columnIndex: 1, length: 15);
// Act & Assert
ParseBlockTest("@tagHelperPrefix ",
new DirectiveBlock(
Factory.CodeTransition(),
@ -731,17 +774,25 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
.MetaCode(SyntaxConstants.CSharp.TagHelperPrefixKeyword + " ")
.Accepts(AcceptedCharactersInternal.None),
Factory.EmptyCSharp()
.AsTagHelperPrefixDirective(string.Empty)
.Accepts(AcceptedCharactersInternal.AnyExceptNewline)),
new RazorError(
LegacyResources.FormatParseError_DirectiveMustHaveValue(
SyntaxConstants.CSharp.TagHelperPrefixKeyword),
absoluteIndex: 1, lineIndex: 0, columnIndex: 1, length: 15));
.AsTagHelperPrefixDirective(string.Empty, expectedError)
.Accepts(AcceptedCharactersInternal.AnyExceptNewline)));
}
[Fact]
public void TagHelperPrefixDirective_StartQuoteRequiresDoubleQuotesAroundValue()
{
// Arrange
var expectedErrors = new[]
{
new RazorError(
LegacyResources.ParseError_Unterminated_String_Literal,
absoluteIndex: 17, lineIndex: 0, columnIndex: 17, length: 1),
new RazorError(
LegacyResources.FormatParseError_IncompleteQuotesAroundDirective(SyntaxConstants.CSharp.TagHelperPrefixKeyword),
absoluteIndex: 17, lineIndex: 0, columnIndex: 17, length: 4)
};
// Act & Assert
ParseBlockTest("@tagHelperPrefix \"Foo",
new DirectiveBlock(
Factory.CodeTransition(),
@ -749,19 +800,24 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
.MetaCode(SyntaxConstants.CSharp.TagHelperPrefixKeyword + " ")
.Accepts(AcceptedCharactersInternal.None),
Factory.Code("\"Foo")
.AsTagHelperPrefixDirective("\"Foo")),
new RazorError(
LegacyResources.ParseError_Unterminated_String_Literal,
absoluteIndex: 17, lineIndex: 0, columnIndex: 17, length: 1),
new RazorError(
LegacyResources.FormatParseError_IncompleteQuotesAroundDirective(
SyntaxConstants.CSharp.TagHelperPrefixKeyword),
absoluteIndex: 17, lineIndex: 0, columnIndex: 17, length: 4));
.AsTagHelperPrefixDirective("\"Foo", expectedErrors)));
}
[Fact]
public void TagHelperPrefixDirective_EndQuoteRequiresDoubleQuotesAroundValue()
{
// Arrange
var expectedErrors = new[]
{
new RazorError(
LegacyResources.ParseError_Unterminated_String_Literal,
absoluteIndex: 23, lineIndex: 0, columnIndex: 23, length: 1),
new RazorError(
LegacyResources.FormatParseError_IncompleteQuotesAroundDirective(SyntaxConstants.CSharp.TagHelperPrefixKeyword),
absoluteIndex: 17, lineIndex: 0, columnIndex: 17, length: 7)
};
// Act & Assert
ParseBlockTest("@tagHelperPrefix Foo \"",
new DirectiveBlock(
Factory.CodeTransition(),
@ -769,14 +825,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
.MetaCode(SyntaxConstants.CSharp.TagHelperPrefixKeyword + " ")
.Accepts(AcceptedCharactersInternal.None),
Factory.Code("Foo \"")
.AsTagHelperPrefixDirective("Foo \"")),
new RazorError(
LegacyResources.ParseError_Unterminated_String_Literal,
absoluteIndex: 23, lineIndex: 0, columnIndex: 23, length: 1),
new RazorError(
LegacyResources.FormatParseError_IncompleteQuotesAroundDirective(
SyntaxConstants.CSharp.TagHelperPrefixKeyword),
absoluteIndex: 17, lineIndex: 0, columnIndex: 17, length: 7));
.AsTagHelperPrefixDirective("Foo \"", expectedErrors)));
}
[Fact]
@ -831,57 +880,69 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
[Fact]
public void RemoveTagHelperDirective_RequiresValue()
{
// Arrange
var expectedError = new RazorError(
LegacyResources.FormatParseError_DirectiveMustHaveValue(SyntaxConstants.CSharp.RemoveTagHelperKeyword),
absoluteIndex: 1, lineIndex: 0, columnIndex: 1, length: 15);
// Act & Assert
ParseBlockTest("@removeTagHelper ",
new DirectiveBlock(
Factory.CodeTransition(),
Factory.MetaCode(SyntaxConstants.CSharp.RemoveTagHelperKeyword + " ")
.Accepts(AcceptedCharactersInternal.None),
Factory.EmptyCSharp()
.AsRemoveTagHelper(string.Empty)
.Accepts(AcceptedCharactersInternal.AnyExceptNewline)),
new RazorError(
LegacyResources.FormatParseError_DirectiveMustHaveValue(
SyntaxConstants.CSharp.RemoveTagHelperKeyword),
absoluteIndex: 1, lineIndex: 0, columnIndex: 1, length: 15));
.AsRemoveTagHelper(string.Empty, expectedError)
.Accepts(AcceptedCharactersInternal.AnyExceptNewline)));
}
[Fact]
public void RemoveTagHelperDirective_StartQuoteRequiresDoubleQuotesAroundValue()
{
// Arrange
var expectedErrors = new[]
{
new RazorError(
LegacyResources.ParseError_Unterminated_String_Literal,
absoluteIndex: 17, lineIndex: 0, columnIndex: 17, length: 1),
new RazorError(
LegacyResources.FormatParseError_IncompleteQuotesAroundDirective(SyntaxConstants.CSharp.RemoveTagHelperKeyword),
absoluteIndex: 17, lineIndex: 0, columnIndex: 17, length: 4)
};
// Act & Assert
ParseBlockTest("@removeTagHelper \"Foo",
new DirectiveBlock(
Factory.CodeTransition(),
Factory.MetaCode(SyntaxConstants.CSharp.RemoveTagHelperKeyword + " ")
.Accepts(AcceptedCharactersInternal.None),
Factory.Code("\"Foo")
.AsRemoveTagHelper("\"Foo")),
new RazorError(
LegacyResources.ParseError_Unterminated_String_Literal,
absoluteIndex: 17, lineIndex: 0, columnIndex: 17, length: 1),
new RazorError(
LegacyResources.FormatParseError_IncompleteQuotesAroundDirective(
SyntaxConstants.CSharp.RemoveTagHelperKeyword),
absoluteIndex: 17, lineIndex: 0, columnIndex: 17, length: 4));
.AsRemoveTagHelper("\"Foo", expectedErrors)));
}
[Fact]
public void RemoveTagHelperDirective_EndQuoteRequiresDoubleQuotesAroundValue()
{
// Arrange
var expectedErrors = new[]
{
new RazorError(
LegacyResources.ParseError_Unterminated_String_Literal,
absoluteIndex: 20, lineIndex: 0, columnIndex: 20, length: 1),
new RazorError(
LegacyResources.FormatParseError_IncompleteQuotesAroundDirective(SyntaxConstants.CSharp.RemoveTagHelperKeyword),
absoluteIndex: 17, lineIndex: 0, columnIndex: 17, length: 4)
};
// Act & Assert
ParseBlockTest("@removeTagHelper Foo\"",
new DirectiveBlock(
Factory.CodeTransition(),
Factory.MetaCode(SyntaxConstants.CSharp.RemoveTagHelperKeyword + " ")
.Accepts(AcceptedCharactersInternal.None),
Factory.Code("Foo\"")
.AsRemoveTagHelper("Foo\"")
.Accepts(AcceptedCharactersInternal.AnyExceptNewline)),
new RazorError(
LegacyResources.ParseError_Unterminated_String_Literal,
absoluteIndex: 20, lineIndex: 0, columnIndex: 20, length: 1),
new RazorError(
LegacyResources.FormatParseError_IncompleteQuotesAroundDirective(
SyntaxConstants.CSharp.RemoveTagHelperKeyword),
absoluteIndex: 17, lineIndex: 0, columnIndex: 17, length: 4));
.AsRemoveTagHelper("Foo\"", expectedErrors)
.Accepts(AcceptedCharactersInternal.AnyExceptNewline)));
}
[Fact]
@ -935,56 +996,69 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
[Fact]
public void AddTagHelperDirectiveRequiresValue()
{
// Arrange
var expectedError = new RazorError(
LegacyResources.FormatParseError_DirectiveMustHaveValue(SyntaxConstants.CSharp.AddTagHelperKeyword),
absoluteIndex: 1, lineIndex: 0, columnIndex: 1, length: 12);
// Act & Assert
ParseBlockTest("@addTagHelper ",
new DirectiveBlock(
Factory.CodeTransition(),
Factory.MetaCode(SyntaxConstants.CSharp.AddTagHelperKeyword + " ")
.Accepts(AcceptedCharactersInternal.None),
Factory.EmptyCSharp()
.AsAddTagHelper(string.Empty)
.Accepts(AcceptedCharactersInternal.AnyExceptNewline)),
new RazorError(
LegacyResources.FormatParseError_DirectiveMustHaveValue(SyntaxConstants.CSharp.AddTagHelperKeyword),
absoluteIndex: 1, lineIndex: 0, columnIndex: 1, length: 12));
.AsAddTagHelper(string.Empty, expectedError)
.Accepts(AcceptedCharactersInternal.AnyExceptNewline)));
}
[Fact]
public void AddTagHelperDirective_StartQuoteRequiresDoubleQuotesAroundValue()
{
// Arrange
var expectedErrors = new[]
{
new RazorError(
LegacyResources.ParseError_Unterminated_String_Literal,
absoluteIndex: 14, lineIndex: 0, columnIndex: 14, length: 1),
new RazorError(
LegacyResources.FormatParseError_IncompleteQuotesAroundDirective(SyntaxConstants.CSharp.AddTagHelperKeyword),
absoluteIndex: 14, lineIndex: 0, columnIndex: 14, length: 4)
};
// Act & Assert
ParseBlockTest("@addTagHelper \"Foo",
new DirectiveBlock(
Factory.CodeTransition(),
Factory.MetaCode(SyntaxConstants.CSharp.AddTagHelperKeyword + " ")
.Accepts(AcceptedCharactersInternal.None),
Factory.Code("\"Foo")
.AsAddTagHelper("\"Foo")),
new RazorError(
LegacyResources.ParseError_Unterminated_String_Literal,
absoluteIndex: 14, lineIndex: 0, columnIndex: 14, length: 1),
new RazorError(
LegacyResources.FormatParseError_IncompleteQuotesAroundDirective(
SyntaxConstants.CSharp.AddTagHelperKeyword),
absoluteIndex: 14, lineIndex: 0, columnIndex: 14, length: 4));
.AsAddTagHelper("\"Foo", expectedErrors)));
}
[Fact]
public void AddTagHelperDirective_EndQuoteRequiresDoubleQuotesAroundValue()
{
// Arrange
var expectedErrors = new[]
{
new RazorError(
LegacyResources.ParseError_Unterminated_String_Literal,
absoluteIndex: 17, lineIndex: 0, columnIndex: 17, length: 1),
new RazorError(
LegacyResources.FormatParseError_IncompleteQuotesAroundDirective(SyntaxConstants.CSharp.AddTagHelperKeyword),
absoluteIndex: 14, lineIndex: 0, columnIndex: 14, length: 4)
};
// Act & Assert
ParseBlockTest("@addTagHelper Foo\"",
new DirectiveBlock(
Factory.CodeTransition(),
Factory.MetaCode(SyntaxConstants.CSharp.AddTagHelperKeyword + " ")
.Accepts(AcceptedCharactersInternal.None),
Factory.Code("Foo\"")
.AsAddTagHelper("Foo\"")
.Accepts(AcceptedCharactersInternal.AnyExceptNewline)),
new RazorError(
LegacyResources.ParseError_Unterminated_String_Literal,
absoluteIndex: 17, lineIndex: 0, columnIndex: 17, length: 1),
new RazorError(
LegacyResources.FormatParseError_IncompleteQuotesAroundDirective(
SyntaxConstants.CSharp.AddTagHelperKeyword),
absoluteIndex: 14, lineIndex: 0, columnIndex: 14, length: 4));
.AsAddTagHelper("Foo\"", expectedErrors)
.Accepts(AcceptedCharactersInternal.AnyExceptNewline)));
}
[Fact]

View File

@ -299,18 +299,24 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
[Fact]
public void ParseBlockReportsErrorIfClassBlockUnterminatedAtEOF()
{
// Arrange
var chunkGenerator = new DirectiveChunkGenerator(FunctionsDirective.Directive);
chunkGenerator.Diagnostics.Add(
RazorDiagnostic.Create(
new RazorError(
LegacyResources.FormatParseError_Expected_EndOfBlock_Before_EOF("functions", '}', '{'),
new SourceLocation(10, 0, 10),
length: 1)));
// Act & Assert
ParseBlockTest(
"functions { var foo = bar; if(foo != null) { bar(); } ",
new[] { FunctionsDirective.Directive, },
new DirectiveBlock(new DirectiveChunkGenerator(FunctionsDirective.Directive),
new[] { FunctionsDirective.Directive },
new DirectiveBlock(chunkGenerator,
Factory.MetaCode("functions").Accepts(AcceptedCharactersInternal.None),
Factory.Span(SpanKindInternal.Markup, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.AllWhiteSpace),
Factory.MetaCode("{").AutoCompleteWith("}", atEndOfSpan: true).Accepts(AcceptedCharactersInternal.None),
Factory.Code(" var foo = bar; if(foo != null) { bar(); } ").AsStatement()),
new RazorError(
LegacyResources.FormatParseError_Expected_EndOfBlock_Before_EOF("functions", '}', '{'),
new SourceLocation(10, 0, 10),
length: 1));
Factory.Code(" var foo = bar; if(foo != null) { bar(); } ").AsStatement()));
}
[Fact]

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 System.Linq;
using Microsoft.AspNetCore.Razor.Language.Extensions;
using Xunit;
@ -12,59 +13,77 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
[Fact]
public void ParseSectionBlockCapturesNewlineImmediatelyFollowing()
{
// Arrange
var chunkGenerator = new DirectiveChunkGenerator(SectionDirective.Directive);
chunkGenerator.Diagnostics.Add(
RazorDiagnostic.Create(
new RazorError(
LegacyResources.FormatDirectiveExpectsIdentifier(SectionDirective.Directive.Directive),
new SourceLocation(8, 0, 8),
length: Environment.NewLine.Length)));
// Act & Assert
ParseDocumentTest(
"@section" + Environment.NewLine,
new[] { SectionDirective.Directive, },
new[] { SectionDirective.Directive },
new MarkupBlock(
Factory.EmptyHtml(),
new DirectiveBlock(new DirectiveChunkGenerator(SectionDirective.Directive),
new DirectiveBlock(chunkGenerator,
Factory.CodeTransition(),
Factory.MetaCode("section").Accepts(AcceptedCharactersInternal.None)),
Factory.Markup(Environment.NewLine)),
new RazorError(
LegacyResources.FormatDirectiveExpectsIdentifier(SectionDirective.Directive.Directive),
new SourceLocation(8, 0, 8),
length: Environment.NewLine.Length));
Factory.Markup(Environment.NewLine)));
}
[Fact]
public void ParseSectionBlockCapturesWhitespaceToEndOfLineInSectionStatementMissingOpenBrace()
{
// Arrange
var chunkGenerator = new DirectiveChunkGenerator(SectionDirective.Directive);
chunkGenerator.Diagnostics.Add(
RazorDiagnostic.Create(
new RazorError(
LegacyResources.FormatUnexpectedEOFAfterDirective(SectionDirective.Directive.Directive, "{"),
new SourceLocation(25 + Environment.NewLine.Length, 0, 25 + Environment.NewLine.Length),
length: 1)));
// Act & Assert
ParseDocumentTest(
"@section Foo " + Environment.NewLine + " ",
new[] { SectionDirective.Directive, },
new[] { SectionDirective.Directive },
new MarkupBlock(
Factory.EmptyHtml(),
new DirectiveBlock(new DirectiveChunkGenerator(SectionDirective.Directive),
new DirectiveBlock(chunkGenerator,
Factory.CodeTransition(),
Factory.MetaCode("section").Accepts(AcceptedCharactersInternal.None),
Factory.Span(SpanKindInternal.Code, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.WhiteSpace),
Factory.Span(SpanKindInternal.Code, "Foo", CSharpSymbolType.Identifier).AsDirectiveToken(SectionDirective.Directive.Tokens[0]),
Factory.Span(SpanKindInternal.Markup, " " + Environment.NewLine + " ", markup: false).Accepts(AcceptedCharactersInternal.AllWhiteSpace)),
Factory.EmptyHtml()),
new RazorError(
LegacyResources.FormatUnexpectedEOFAfterDirective(SectionDirective.Directive.Directive, "{"),
new SourceLocation(25 + Environment.NewLine.Length, 0, 25 + Environment.NewLine.Length),
length: 1));
Factory.EmptyHtml()));
}
[Fact]
public void ParseSectionBlockCapturesWhitespaceToEndOfLineInSectionStatementMissingName()
{
// Arrange
var chunkGenerator = new DirectiveChunkGenerator(SectionDirective.Directive);
chunkGenerator.Diagnostics.Add(
RazorDiagnostic.Create(
new RazorError(
LegacyResources.FormatDirectiveExpectsIdentifier(SectionDirective.Directive.Directive),
new SourceLocation(17, 0, 17),
length: Environment.NewLine.Length)));
// Act & Assert
ParseDocumentTest(
"@section " + Environment.NewLine + " ",
new[] { SectionDirective.Directive, },
new[] { SectionDirective.Directive },
new MarkupBlock(
Factory.EmptyHtml(),
new DirectiveBlock(new DirectiveChunkGenerator(SectionDirective.Directive),
new DirectiveBlock(chunkGenerator,
Factory.CodeTransition(),
Factory.MetaCode("section").Accepts(AcceptedCharactersInternal.None),
Factory.Span(SpanKindInternal.Code, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.WhiteSpace)),
Factory.Markup(Environment.NewLine + " ")),
new RazorError(
LegacyResources.FormatDirectiveExpectsIdentifier(SectionDirective.Directive.Directive),
new SourceLocation(17, 0, 17),
length: Environment.NewLine.Length));
Factory.Markup(Environment.NewLine + " ")));
}
[Fact]
@ -72,7 +91,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
{
ParseDocumentTest(
"@Section foo",
new[] { SectionDirective.Directive, },
new[] { SectionDirective.Directive },
new MarkupBlock(
Factory.EmptyHtml(),
new ExpressionBlock(
@ -86,12 +105,22 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
[Fact]
public void ParseSectionBlockReportsErrorAndTerminatesSectionBlockIfKeywordNotFollowedByIdentifierStartCharacter()
{
// Arrange
var chunkGenerator = new DirectiveChunkGenerator(SectionDirective.Directive);
chunkGenerator.Diagnostics.Add(
RazorDiagnostic.Create(
new RazorError(
LegacyResources.FormatDirectiveExpectsIdentifier(SectionDirective.Directive.Directive),
new SourceLocation(9, 0, 9),
length: 1)));
// Act & Assert
ParseDocumentTest(
"@section 9 { <p>Foo</p> }",
new[] { SectionDirective.Directive, },
new[] { SectionDirective.Directive },
new MarkupBlock(
Factory.EmptyHtml(),
new DirectiveBlock(new DirectiveChunkGenerator(SectionDirective.Directive),
new DirectiveBlock(chunkGenerator,
Factory.CodeTransition(),
Factory.MetaCode("section").Accepts(AcceptedCharactersInternal.None),
Factory.Span(SpanKindInternal.Code, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.WhiteSpace)),
@ -101,22 +130,28 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
Factory.Markup("Foo"),
new MarkupTagBlock(
Factory.Markup("</p>")),
Factory.Markup(" }")),
new RazorError(
LegacyResources.FormatDirectiveExpectsIdentifier(SectionDirective.Directive.Directive),
new SourceLocation(9, 0, 9),
length: 1));
Factory.Markup(" }")));
}
[Fact]
public void ParseSectionBlockReportsErrorAndTerminatesSectionBlockIfNameNotFollowedByOpenBrace()
{
// Arrange
var chunkGenerator = new DirectiveChunkGenerator(SectionDirective.Directive);
chunkGenerator.Diagnostics.Add(
RazorDiagnostic.Create(
new RazorError(
LegacyResources.FormatUnexpectedDirectiveLiteral(SectionDirective.Directive.Directive, "{"),
new SourceLocation(12, 0, 12),
length: 1)));
// Act & Assert
ParseDocumentTest(
"@section foo-bar { <p>Foo</p> }",
new[] { SectionDirective.Directive, },
new[] { SectionDirective.Directive },
new MarkupBlock(
Factory.EmptyHtml(),
new DirectiveBlock(new DirectiveChunkGenerator(SectionDirective.Directive),
new DirectiveBlock(chunkGenerator,
Factory.CodeTransition(),
Factory.MetaCode("section").Accepts(AcceptedCharactersInternal.None),
Factory.Span(SpanKindInternal.Code, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.WhiteSpace),
@ -127,19 +162,31 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
Factory.Markup("Foo"),
new MarkupTagBlock(
Factory.Markup("</p>")),
Factory.Markup(" }")),
new RazorError(
LegacyResources.FormatUnexpectedDirectiveLiteral(SectionDirective.Directive.Directive, "{"),
new SourceLocation(12, 0, 12),
length: 1));
Factory.Markup(" }")));
}
[Fact]
public void ParserOutputsErrorOnNestedSections()
{
// Arrange
var erroredChunkGenerator = new DirectiveChunkGenerator(SectionDirective.Directive);
erroredChunkGenerator.Diagnostics.Add(
RazorDiagnostic.Create(
new RazorError(
Resources.FormatDirectiveMustAppearAtStartOfLine("section"),
new SourceLocation(16, 0, 16),
7)));
erroredChunkGenerator.Diagnostics.Add(
RazorDiagnostic.Create(
new RazorError(
LegacyResources.FormatParseError_Sections_Cannot_Be_Nested(LegacyResources.SectionExample_CS),
new SourceLocation(15, 0, 15),
8)));
// Act & Assert
ParseDocumentTest(
"@section foo { @section bar { <p>Foo</p> } }",
new[] { SectionDirective.Directive, },
new[] { SectionDirective.Directive },
new MarkupBlock(
Factory.EmptyHtml(),
new DirectiveBlock(new DirectiveChunkGenerator(SectionDirective.Directive),
@ -151,7 +198,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
Factory.MetaCode("{").AutoCompleteWith(null, atEndOfSpan: true).Accepts(AcceptedCharactersInternal.None),
new MarkupBlock(
Factory.Markup(" "),
new DirectiveBlock(new DirectiveChunkGenerator(SectionDirective.Directive),
new DirectiveBlock(erroredChunkGenerator,
Factory.CodeTransition(),
Factory.MetaCode("section").Accepts(AcceptedCharactersInternal.None),
Factory.Span(SpanKindInternal.Code, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.WhiteSpace),
@ -169,26 +216,28 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
Factory.MetaCode("}").Accepts(AcceptedCharactersInternal.None)),
Factory.Markup(" ")),
Factory.MetaCode("}").Accepts(AcceptedCharactersInternal.None)),
Factory.EmptyHtml()),
new RazorError(
Resources.FormatDirectiveMustAppearAtStartOfLine("section"),
new SourceLocation(16, 0, 16),
7),
new RazorError(
LegacyResources.FormatParseError_Sections_Cannot_Be_Nested(LegacyResources.SectionExample_CS),
new SourceLocation(15, 0, 15),
8));
Factory.EmptyHtml()));
}
[Fact]
public void ParseSectionBlockHandlesEOFAfterOpenBrace()
{
// Arrange
var chunkGenerator = new DirectiveChunkGenerator(SectionDirective.Directive);
chunkGenerator.Diagnostics.Add(
RazorDiagnostic.Create(
new RazorError(
LegacyResources.FormatParseError_Expected_EndOfBlock_Before_EOF(SectionDirective.Directive.Directive, "}", "{"),
new SourceLocation(13, 0, 13),
length: 1)));
// Act & Assert
ParseDocumentTest(
"@section foo {",
new[] { SectionDirective.Directive, },
new[] { SectionDirective.Directive },
new MarkupBlock(
Factory.EmptyHtml(),
new DirectiveBlock(new DirectiveChunkGenerator(SectionDirective.Directive),
new DirectiveBlock(chunkGenerator,
Factory.CodeTransition(),
Factory.MetaCode("section").Accepts(AcceptedCharactersInternal.None),
Factory.Span(SpanKindInternal.Code, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.WhiteSpace),
@ -196,11 +245,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
Factory.Span(SpanKindInternal.Markup, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.AllWhiteSpace),
Factory.MetaCode("{").AutoCompleteWith("}", atEndOfSpan: true).Accepts(AcceptedCharactersInternal.None),
new MarkupBlock(
Factory.EmptyHtml()))),
new RazorError(
LegacyResources.FormatParseError_Expected_EndOfBlock_Before_EOF(SectionDirective.Directive.Directive, "}", "{"),
new SourceLocation(13, 0, 13),
length: 1));
Factory.EmptyHtml()))));
}
[Theory]
@ -210,12 +255,22 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
[InlineData(" \n abc")]
public void ParseSectionBlockHandlesEOFAfterOpenContent(string postStartBrace)
{
// Arrange
var chunkGenerator = new DirectiveChunkGenerator(SectionDirective.Directive);
chunkGenerator.Diagnostics.Add(
RazorDiagnostic.Create(
new RazorError(
LegacyResources.FormatParseError_Expected_EndOfBlock_Before_EOF("section", "}", "{"),
new SourceLocation(13, 0, 13),
length: 1)));
// Act & Assert
ParseDocumentTest(
"@section foo {" + postStartBrace,
new[] { SectionDirective.Directive, },
new[] { SectionDirective.Directive },
new MarkupBlock(
Factory.EmptyHtml(),
new DirectiveBlock(new DirectiveChunkGenerator(SectionDirective.Directive),
new DirectiveBlock(chunkGenerator,
Factory.CodeTransition(),
Factory.MetaCode("section").Accepts(AcceptedCharactersInternal.None),
Factory.Span(SpanKindInternal.Code, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.WhiteSpace),
@ -223,22 +278,28 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
Factory.Span(SpanKindInternal.Markup, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.AllWhiteSpace),
Factory.MetaCode("{").AutoCompleteWith("}", atEndOfSpan: true).Accepts(AcceptedCharactersInternal.None),
new MarkupBlock(
Factory.Markup(postStartBrace)))),
new RazorError(
LegacyResources.FormatParseError_Expected_EndOfBlock_Before_EOF("section", "}", "{"),
new SourceLocation(13, 0, 13),
length: 1));
Factory.Markup(postStartBrace)))));
}
[Fact]
public void ParseSectionBlockHandlesUnterminatedSection()
{
// Arrange
var chunkGenerator = new DirectiveChunkGenerator(SectionDirective.Directive);
chunkGenerator.Diagnostics.Add(
RazorDiagnostic.Create(
new RazorError(
LegacyResources.FormatParseError_Expected_EndOfBlock_Before_EOF("section", "}", "{"),
new SourceLocation(13, 0, 13),
length: 1)));
// Act & Assert
ParseDocumentTest(
"@section foo { <p>Foo{}</p>",
new[] { SectionDirective.Directive, },
new[] { SectionDirective.Directive },
new MarkupBlock(
Factory.EmptyHtml(),
new DirectiveBlock(new DirectiveChunkGenerator(SectionDirective.Directive),
new DirectiveBlock(chunkGenerator,
Factory.CodeTransition(),
Factory.MetaCode("section").Accepts(AcceptedCharactersInternal.None),
Factory.Span(SpanKindInternal.Code, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.WhiteSpace),
@ -252,27 +313,33 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
// Need to provide the markup span as fragments, since the parser will split the {} into separate symbols.
Factory.Markup("Foo", "{", "}"),
new MarkupTagBlock(
Factory.Markup("</p>"))))),
new RazorError(
LegacyResources.FormatParseError_Expected_EndOfBlock_Before_EOF("section", "}", "{"),
new SourceLocation(13, 0, 13),
length: 1));
Factory.Markup("</p>"))))));
}
[Fact]
public void ParseSectionBlockHandlesUnterminatedSectionWithNestedIf()
{
// Arrange
var newLine = Environment.NewLine;
var chunkGenerator = new DirectiveChunkGenerator(SectionDirective.Directive);
chunkGenerator.Diagnostics.Add(
RazorDiagnostic.Create(
new RazorError(
LegacyResources.FormatParseError_Expected_EndOfBlock_Before_EOF("section", "}", "{"),
new SourceLocation(13 + newLine.Length, 1, 0),
length: 1)));
var spaces = " ";
// Act & Assert
ParseDocumentTest(
string.Format(
"@section Test{0}{{{0}{1}@if(true){0}{1}{{{0}{1}{1}<p>Hello World</p>{0}{1}}}",
newLine,
spaces),
new[] { SectionDirective.Directive, },
new[] { SectionDirective.Directive },
new MarkupBlock(
Factory.EmptyHtml(),
new DirectiveBlock(new DirectiveChunkGenerator(SectionDirective.Directive),
new DirectiveBlock(chunkGenerator,
Factory.CodeTransition(),
Factory.MetaCode("section").Accepts(AcceptedCharactersInternal.None),
Factory.Span(SpanKindInternal.Code, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.WhiteSpace),
@ -291,47 +358,52 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
Factory.Markup("Hello World"),
BlockFactory.MarkupTagBlock("</p>", AcceptedCharactersInternal.None),
Factory.Markup(newLine).Accepts(AcceptedCharactersInternal.None)),
Factory.Code($"{spaces}}}").AsStatement())))),
new RazorError(
LegacyResources.FormatParseError_Expected_EndOfBlock_Before_EOF("section", "}", "{"),
new SourceLocation(13 + newLine.Length, 1, 0),
length: 1));
Factory.Code($"{spaces}}}").AsStatement())))));
}
[Fact]
public void ParseSectionBlockReportsErrorAndAcceptsWhitespaceToEndOfLineIfSectionNotFollowedByOpenBrace()
{
// Arrange
var chunkGenerator = new DirectiveChunkGenerator(SectionDirective.Directive);
chunkGenerator.Diagnostics.Add(
RazorDiagnostic.Create(
new RazorError(
LegacyResources.FormatUnexpectedEOFAfterDirective(SectionDirective.Directive.Directive, "{"),
new SourceLocation(18 + Environment.NewLine.Length, 0, 18 + Environment.NewLine.Length),
length: 1)));
// Act & Assert
ParseDocumentTest(
"@section foo " + Environment.NewLine,
new[] { SectionDirective.Directive, },
new[] { SectionDirective.Directive },
new MarkupBlock(
Factory.EmptyHtml(),
new DirectiveBlock(new DirectiveChunkGenerator(SectionDirective.Directive),
new DirectiveBlock(chunkGenerator,
Factory.CodeTransition(),
Factory.MetaCode("section").Accepts(AcceptedCharactersInternal.None),
Factory.Span(SpanKindInternal.Code, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.WhiteSpace),
Factory.Span(SpanKindInternal.Code, "foo", CSharpSymbolType.Identifier).AsDirectiveToken(SectionDirective.Directive.Tokens[0]),
Factory.Span(SpanKindInternal.Markup, " " + Environment.NewLine, markup: false).Accepts(AcceptedCharactersInternal.AllWhiteSpace)),
Factory.EmptyHtml()),
new RazorError(
LegacyResources.FormatUnexpectedEOFAfterDirective(SectionDirective.Directive.Directive, "{"),
new SourceLocation(18 + Environment.NewLine.Length, 0, 18 + Environment.NewLine.Length),
length: 1));
Factory.EmptyHtml()));
}
[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[] { SectionDirective.Directive, },
// Act & Assert
ParseDocumentTest(
"@section foo "
+ Environment.NewLine
+ Environment.NewLine
+ Environment.NewLine
+ Environment.NewLine
+ Environment.NewLine
+ Environment.NewLine
+ "{" + Environment.NewLine
+ "<p>Foo</p>" + Environment.NewLine
+ "}",
new[] { SectionDirective.Directive },
new MarkupBlock(
Factory.EmptyHtml(),
new DirectiveBlock(new DirectiveChunkGenerator(SectionDirective.Directive),
@ -356,9 +428,10 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
[Fact]
public void ParseSectionBlockParsesNamedSectionCorrectly()
{
// Act & Assert
ParseDocumentTest(
"@section foo { <p>Foo</p> }",
new[] { SectionDirective.Directive, },
new[] { SectionDirective.Directive },
new MarkupBlock(
Factory.EmptyHtml(),
new DirectiveBlock(new DirectiveChunkGenerator(SectionDirective.Directive),
@ -383,9 +456,10 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
[Fact]
public void ParseSectionBlockDoesNotRequireSpaceBetweenSectionNameAndOpenBrace()
{
// Act & Assert
ParseDocumentTest(
"@section foo{ <p>Foo</p> }",
new[] { SectionDirective.Directive, },
new[] { SectionDirective.Directive },
new MarkupBlock(
Factory.EmptyHtml(),
new DirectiveBlock(new DirectiveChunkGenerator(SectionDirective.Directive),
@ -409,9 +483,10 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
[Fact]
public void ParseSectionBlockBalancesBraces()
{
// Act & Assert
ParseDocumentTest(
"@section foo { <script>(function foo() { return 1; })();</script> }",
new[] { SectionDirective.Directive, },
new[] { SectionDirective.Directive },
new MarkupBlock(
Factory.EmptyHtml(),
new DirectiveBlock(new DirectiveChunkGenerator(SectionDirective.Directive),
@ -436,9 +511,10 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
[Fact]
public void ParseSectionBlockAllowsBracesInCSharpExpression()
{
// Act & Assert
ParseDocumentTest(
"@section foo { I really want to render a close brace, so here I go: @(\"}\") }",
new[] { SectionDirective.Directive, },
new[] { SectionDirective.Directive },
new MarkupBlock(
Factory.EmptyHtml(),
new DirectiveBlock(new DirectiveChunkGenerator(SectionDirective.Directive),
@ -463,11 +539,13 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
[Fact]
public void SectionIsCorrectlyTerminatedWhenCloseBraceImmediatelyFollowsCodeBlock()
{
ParseDocumentTest("@section Foo {" + Environment.NewLine
+ "@if(true) {" + Environment.NewLine
+ "}" + Environment.NewLine
+ "}",
new[] { SectionDirective.Directive, },
// Act & Assert
ParseDocumentTest(
"@section Foo {" + Environment.NewLine
+ "@if(true) {" + Environment.NewLine
+ "}" + Environment.NewLine
+ "}",
new[] { SectionDirective.Directive },
new MarkupBlock(
Factory.EmptyHtml(),
new DirectiveBlock(new DirectiveChunkGenerator(SectionDirective.Directive),
@ -490,10 +568,12 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
[Fact]
public void SectionIsCorrectlyTerminatedWhenCloseBraceImmediatelyFollowsCodeBlockNoWhitespace()
{
ParseDocumentTest("@section Foo {" + Environment.NewLine
+ "@if(true) {" + Environment.NewLine
+ "}}",
new[] { SectionDirective.Directive, },
// Act & Assert
ParseDocumentTest(
"@section Foo {" + Environment.NewLine
+ "@if(true) {" + Environment.NewLine
+ "}}",
new[] { SectionDirective.Directive },
new MarkupBlock(
Factory.EmptyHtml(),
new DirectiveBlock(new DirectiveChunkGenerator(SectionDirective.Directive),
@ -516,9 +596,10 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
[Fact]
public void ParseSectionBlockCorrectlyTerminatesWhenCloseBraceImmediatelyFollowsMarkup()
{
// Act & Assert
ParseDocumentTest(
"@section foo {something}",
new[] { SectionDirective.Directive, },
new[] { SectionDirective.Directive },
new MarkupBlock(
Factory.EmptyHtml(),
new DirectiveBlock(new DirectiveChunkGenerator(SectionDirective.Directive),
@ -537,9 +618,10 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
[Fact]
public void ParseSectionBlockParsesComment()
{
// Act & Assert
ParseDocumentTest(
"@section s {<!-- -->}",
new[] { SectionDirective.Directive, },
new[] { SectionDirective.Directive },
new MarkupBlock(
Factory.EmptyHtml(),
new DirectiveBlock(new DirectiveChunkGenerator(SectionDirective.Directive),
@ -560,9 +642,10 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
[Fact]
public void ParseSectionBlockParsesCommentWithDelimiters()
{
// Act & Assert
ParseDocumentTest(
"@section s {<!-- > \" '-->}",
new[] { SectionDirective.Directive, },
new[] { SectionDirective.Directive },
new MarkupBlock(
Factory.EmptyHtml(),
new DirectiveBlock(new DirectiveChunkGenerator(SectionDirective.Directive),
@ -581,9 +664,10 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
[Fact]
public void ParseSectionBlockCommentRecoversFromUnclosedTag()
{
// Act & Assert
ParseDocumentTest(
"@section s {" + Environment.NewLine + "<a" + Environment.NewLine + "<!-- > \" '-->}",
new[] { SectionDirective.Directive, },
new[] { SectionDirective.Directive },
new MarkupBlock(
Factory.EmptyHtml(),
new DirectiveBlock(new DirectiveChunkGenerator(SectionDirective.Directive),
@ -605,9 +689,10 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
[Fact]
public void ParseSectionBlockParsesXmlProcessingInstruction()
{
// Act & Assert
ParseDocumentTest(
"@section s { <? xml bleh ?>}",
new[] { SectionDirective.Directive, },
new[] { SectionDirective.Directive },
new MarkupBlock(
Factory.EmptyHtml(),
new DirectiveBlock(new DirectiveChunkGenerator(SectionDirective.Directive),
@ -698,7 +783,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
{
FixupSpans = true;
ParseDocumentTest(input, new[] { SectionDirective.Directive, }, (Block)expected);
ParseDocumentTest(input, new[] { SectionDirective.Directive }, (Block)expected);
}
}
}

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 System.Linq;
using Microsoft.AspNetCore.Razor.Language.Extensions;
using Xunit;
@ -12,14 +13,20 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
[Fact]
public void ParseInheritsStatementMarksInheritsSpanAsCanGrowIfMissingTrailingSpace()
{
// Arrange
var chunkGenerator = new DirectiveChunkGenerator(InheritsDirective.Directive);
chunkGenerator.Diagnostics.Add(
RazorDiagnostic.Create(
new RazorError(
LegacyResources.FormatUnexpectedEOFAfterDirective(InheritsDirective.Directive.Directive, "type"),
new SourceLocation(8, 0, 8), 1)));
// Act & Assert
ParseBlockTest(
"inherits",
new[] { InheritsDirective.Directive, },
new DirectiveBlock(new DirectiveChunkGenerator(InheritsDirective.Directive),
Factory.MetaCode("inherits").Accepts(AcceptedCharactersInternal.None)),
new RazorError(
LegacyResources.FormatUnexpectedEOFAfterDirective(InheritsDirective.Directive.Directive, "type"),
new SourceLocation(8, 0, 8), 1));
new[] { InheritsDirective.Directive },
new DirectiveBlock(chunkGenerator,
Factory.MetaCode("inherits").Accepts(AcceptedCharactersInternal.None)));
}
[Fact]
@ -27,7 +34,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
{
ParseBlockTest(
"inherits Foo.Bar<Biz<Qux>, string, int>.Baz",
new[] { InheritsDirective.Directive, },
new[] { InheritsDirective.Directive },
new DirectiveBlock(new DirectiveChunkGenerator(InheritsDirective.Directive),
Factory.MetaCode("inherits").Accepts(AcceptedCharactersInternal.None),
Factory.Span(SpanKindInternal.Code, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.WhiteSpace),
@ -37,13 +44,21 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
[Fact]
public void InheritsBlockOutputsErrorIfInheritsNotFollowedByTypeButAcceptsEntireLineAsCode()
{
// Arrange
var chunkGenerator = new DirectiveChunkGenerator(InheritsDirective.Directive);
chunkGenerator.Diagnostics.Add(
RazorDiagnostic.Create(
new RazorError(
LegacyResources.FormatDirectiveExpectsTypeName(InheritsDirective.Directive.Directive),
24, 0, 24, Environment.NewLine.Length)));
// Act & Assert
ParseBlockTest(
"inherits " + Environment.NewLine + "foo",
new[] { InheritsDirective.Directive, },
new DirectiveBlock(new DirectiveChunkGenerator(InheritsDirective.Directive),
new[] { InheritsDirective.Directive },
new DirectiveBlock(chunkGenerator,
Factory.MetaCode("inherits").Accepts(AcceptedCharactersInternal.None),
Factory.Span(SpanKindInternal.Code, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.WhiteSpace)),
new RazorError(LegacyResources.FormatDirectiveExpectsTypeName(InheritsDirective.Directive.Directive), 24, 0, 24, Environment.NewLine.Length));
Factory.Span(SpanKindInternal.Code, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.WhiteSpace)));
}
[Fact]
@ -146,7 +161,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
const string code = " foo(); \"bar}baz\" ";
ParseBlockTest(
"functions {" + code + "} zoop",
new[] { FunctionsDirective.Directive, },
new[] { FunctionsDirective.Directive },
new DirectiveBlock(new DirectiveChunkGenerator(FunctionsDirective.Directive),
Factory.MetaCode("functions").Accepts(AcceptedCharactersInternal.None),
Factory.Span(SpanKindInternal.Markup, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.AllWhiteSpace),
@ -158,18 +173,24 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
[Fact]
public void ParseBlockDoesNoErrorRecoveryForFunctionsBlock()
{
// Arrange
var chunkGenerator = new DirectiveChunkGenerator(FunctionsDirective.Directive);
chunkGenerator.Diagnostics.Add(
RazorDiagnostic.Create(
new RazorError(
LegacyResources.FormatParseError_Expected_EndOfBlock_Before_EOF("functions", "}", "{"),
new SourceLocation(10, 0, 10),
length: 1)));
// Act & Assert
ParseBlockTest(
"functions { { { { { } zoop",
new[] { FunctionsDirective.Directive, },
new DirectiveBlock(new DirectiveChunkGenerator(FunctionsDirective.Directive),
new[] { FunctionsDirective.Directive },
new DirectiveBlock(chunkGenerator,
Factory.MetaCode("functions").Accepts(AcceptedCharactersInternal.None),
Factory.Span(SpanKindInternal.Markup, " ", CSharpSymbolType.WhiteSpace).Accepts(AcceptedCharactersInternal.AllWhiteSpace),
Factory.MetaCode("{").AutoCompleteWith("}", atEndOfSpan: true).Accepts(AcceptedCharactersInternal.None),
Factory.Code(" { { { { } zoop").AsStatement()),
new RazorError(
LegacyResources.FormatParseError_Expected_EndOfBlock_Before_EOF("functions", "}", "{"),
new SourceLocation(10, 0, 10),
length: 1));
Factory.Code(" { { { { } zoop").AsStatement()));
}
[Fact]

View File

@ -334,24 +334,27 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
return _self.With(SpanChunkGenerator.Null);
}
public SpanConstructor AsAddTagHelper(string lookupText)
public SpanConstructor AsAddTagHelper(string lookupText, params RazorError[] legacyErrors)
{
var diagnostics = legacyErrors.Select(error => RazorDiagnostic.Create(error)).ToList();
return _self
.With(new AddTagHelperChunkGenerator(lookupText))
.With(new AddTagHelperChunkGenerator(lookupText, diagnostics))
.Accepts(AcceptedCharactersInternal.AnyExceptNewline);
}
public SpanConstructor AsRemoveTagHelper(string lookupText)
public SpanConstructor AsRemoveTagHelper(string lookupText, params RazorError[] legacyErrors)
{
var diagnostics = legacyErrors.Select(error => RazorDiagnostic.Create(error)).ToList();
return _self
.With(new RemoveTagHelperChunkGenerator(lookupText))
.With(new RemoveTagHelperChunkGenerator(lookupText, diagnostics))
.Accepts(AcceptedCharactersInternal.AnyExceptNewline);
}
public SpanConstructor AsTagHelperPrefixDirective(string prefix)
public SpanConstructor AsTagHelperPrefixDirective(string prefix, params RazorError[] legacyErrors)
{
var diagnostics = legacyErrors.Select(error => RazorDiagnostic.Create(error)).ToList();
return _self
.With(new TagHelperPrefixDirectiveChunkGenerator(prefix))
.With(new TagHelperPrefixDirectiveChunkGenerator(prefix, diagnostics))
.Accepts(AcceptedCharactersInternal.AnyExceptNewline);
}

View File

@ -47,12 +47,6 @@ global::System.Object __typeHelper = ";
#pragma warning disable 1998
public async System.Threading.Tasks.Task ExecuteAsync()
{
DefineSection("", async (__razor_section_writer) => {
});
DefineSection("", async (__razor_section_writer) => {
});
DefineSection("", async (__razor_section_writer) => {
});
}
#pragma warning restore 1998
}

View File

@ -16,43 +16,57 @@ Document -
MethodDeclaration - - public - async - System.Threading.Tasks.Task - ExecuteAsync
HtmlContent - (83:0,83 [4] IncompleteDirectives.cshtml)
RazorIRToken - (83:0,83 [4] IncompleteDirectives.cshtml) - Html - \n\n
MalformedDirective - (100:2,13 [0] IncompleteDirectives.cshtml)
DirectiveToken - (100:2,13 [0] IncompleteDirectives.cshtml) -
HtmlContent - (100:2,13 [2] IncompleteDirectives.cshtml)
RazorIRToken - (100:2,13 [2] IncompleteDirectives.cshtml) - Html - \n
MalformedDirective - (116:3,14 [0] IncompleteDirectives.cshtml)
DirectiveToken - (116:3,14 [0] IncompleteDirectives.cshtml) -
HtmlContent - (116:3,14 [2] IncompleteDirectives.cshtml)
RazorIRToken - (116:3,14 [2] IncompleteDirectives.cshtml) - Html - \n
MalformedDirective - (132:4,14 [1] IncompleteDirectives.cshtml)
DirectiveToken - (132:4,14 [1] IncompleteDirectives.cshtml) - "
HtmlContent - (133:4,15 [4] IncompleteDirectives.cshtml)
RazorIRToken - (133:4,15 [4] IncompleteDirectives.cshtml) - Html - \n\n
MalformedDirective - (153:6,16 [0] IncompleteDirectives.cshtml)
DirectiveToken - (153:6,16 [0] IncompleteDirectives.cshtml) -
HtmlContent - (153:6,16 [2] IncompleteDirectives.cshtml)
RazorIRToken - (153:6,16 [2] IncompleteDirectives.cshtml) - Html - \n
MalformedDirective - (172:7,17 [0] IncompleteDirectives.cshtml)
DirectiveToken - (172:7,17 [0] IncompleteDirectives.cshtml) -
HtmlContent - (172:7,17 [2] IncompleteDirectives.cshtml)
RazorIRToken - (172:7,17 [2] IncompleteDirectives.cshtml) - Html - \n
MalformedDirective - (191:8,17 [1] IncompleteDirectives.cshtml)
DirectiveToken - (191:8,17 [1] IncompleteDirectives.cshtml) - "
HtmlContent - (192:8,18 [4] IncompleteDirectives.cshtml)
RazorIRToken - (192:8,18 [4] IncompleteDirectives.cshtml) - Html - \n\n
MalformedDirective - (212:10,16 [0] IncompleteDirectives.cshtml)
DirectiveToken - (212:10,16 [0] IncompleteDirectives.cshtml) -
HtmlContent - (212:10,16 [2] IncompleteDirectives.cshtml)
RazorIRToken - (212:10,16 [2] IncompleteDirectives.cshtml) - Html - \n
MalformedDirective - (231:11,17 [0] IncompleteDirectives.cshtml)
DirectiveToken - (231:11,17 [0] IncompleteDirectives.cshtml) -
HtmlContent - (231:11,17 [2] IncompleteDirectives.cshtml)
RazorIRToken - (231:11,17 [2] IncompleteDirectives.cshtml) - Html - \n
MalformedDirective - (250:12,17 [1] IncompleteDirectives.cshtml)
DirectiveToken - (250:12,17 [1] IncompleteDirectives.cshtml) - "
HtmlContent - (251:12,18 [4] IncompleteDirectives.cshtml)
RazorIRToken - (251:12,18 [4] IncompleteDirectives.cshtml) - Html - \n\n
MalformedDirective - (255:14,0 [9] IncompleteDirectives.cshtml)
HtmlContent - (264:14,9 [2] IncompleteDirectives.cshtml)
RazorIRToken - (264:14,9 [2] IncompleteDirectives.cshtml) - Html - \n
MalformedDirective - (266:15,0 [10] IncompleteDirectives.cshtml)
HtmlContent - (276:15,10 [4] IncompleteDirectives.cshtml)
RazorIRToken - (276:15,10 [4] IncompleteDirectives.cshtml) - Html - \n\n
CSharpCode -
RazorIRToken - - CSharp - DefineSection("", async (__razor_section_writer) => {
CSharpCode -
RazorIRToken - - CSharp - });
MalformedDirective - (280:17,0 [12] IncompleteDirectives.cshtml)
MalformedDirective - (292:18,0 [15] IncompleteDirectives.cshtml)
MalformedDirective - (307:20,0 [8] IncompleteDirectives.cshtml)
HtmlContent - (315:20,8 [2] IncompleteDirectives.cshtml)
RazorIRToken - (315:20,8 [2] IncompleteDirectives.cshtml) - Html - \n
CSharpCode -
RazorIRToken - - CSharp - DefineSection("", async (__razor_section_writer) => {
CSharpCode -
RazorIRToken - - CSharp - });
MalformedDirective - (317:21,0 [9] IncompleteDirectives.cshtml)
HtmlContent - (326:21,9 [4] IncompleteDirectives.cshtml)
RazorIRToken - (326:21,9 [4] IncompleteDirectives.cshtml) - Html - \n\n
CSharpCode -
RazorIRToken - - CSharp - DefineSection("", async (__razor_section_writer) => {
CSharpCode -
RazorIRToken - - CSharp - });
MalformedDirective - (330:23,0 [9] IncompleteDirectives.cshtml)
HtmlContent - (339:23,9 [3] IncompleteDirectives.cshtml)
RazorIRToken - (339:23,9 [3] IncompleteDirectives.cshtml) - Html - {\n
MalformedDirective - (342:24,0 [12] IncompleteDirectives.cshtml)

View File

@ -13,14 +13,8 @@ namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests.TestFiles
WriteLiteral("\r\n");
WriteLiteral("\r\n");
WriteLiteral("\r\n\r\n");
DefineSection("", async () => {
});
WriteLiteral("\r\n");
DefineSection("", async () => {
});
WriteLiteral("\r\n\r\n");
DefineSection("", async () => {
});
WriteLiteral("{\r\n");
}
#pragma warning restore 1998

View File

@ -4,31 +4,45 @@ Document -
MethodDeclaration - - public - async - System.Threading.Tasks.Task - ExecuteAsync
HtmlContent - (83:0,83 [4] IncompleteDirectives.cshtml)
RazorIRToken - (83:0,83 [4] IncompleteDirectives.cshtml) - Html - \n\n
MalformedDirective - (100:2,13 [2] IncompleteDirectives.cshtml)
DirectiveToken - (100:2,13 [2] IncompleteDirectives.cshtml) -
MalformedDirective - (116:3,14 [2] IncompleteDirectives.cshtml)
DirectiveToken - (116:3,14 [2] IncompleteDirectives.cshtml) -
MalformedDirective - (132:4,14 [3] IncompleteDirectives.cshtml)
DirectiveToken - (132:4,14 [3] IncompleteDirectives.cshtml) - "
HtmlContent - (135:5,0 [2] IncompleteDirectives.cshtml)
RazorIRToken - (135:5,0 [2] IncompleteDirectives.cshtml) - Html - \n
MalformedDirective - (153:6,16 [2] IncompleteDirectives.cshtml)
DirectiveToken - (153:6,16 [2] IncompleteDirectives.cshtml) -
MalformedDirective - (172:7,17 [2] IncompleteDirectives.cshtml)
DirectiveToken - (172:7,17 [2] IncompleteDirectives.cshtml) -
MalformedDirective - (191:8,17 [3] IncompleteDirectives.cshtml)
DirectiveToken - (191:8,17 [3] IncompleteDirectives.cshtml) - "
HtmlContent - (194:9,0 [2] IncompleteDirectives.cshtml)
RazorIRToken - (194:9,0 [2] IncompleteDirectives.cshtml) - Html - \n
MalformedDirective - (212:10,16 [2] IncompleteDirectives.cshtml)
DirectiveToken - (212:10,16 [2] IncompleteDirectives.cshtml) -
MalformedDirective - (231:11,17 [2] IncompleteDirectives.cshtml)
DirectiveToken - (231:11,17 [2] IncompleteDirectives.cshtml) -
MalformedDirective - (250:12,17 [3] IncompleteDirectives.cshtml)
DirectiveToken - (250:12,17 [3] IncompleteDirectives.cshtml) - "
HtmlContent - (253:13,0 [2] IncompleteDirectives.cshtml)
RazorIRToken - (253:13,0 [2] IncompleteDirectives.cshtml) - Html - \n
MalformedDirective - (255:14,0 [9] IncompleteDirectives.cshtml)
HtmlContent - (264:14,9 [2] IncompleteDirectives.cshtml)
RazorIRToken - (264:14,9 [2] IncompleteDirectives.cshtml) - Html - \n
MalformedDirective - (266:15,0 [10] IncompleteDirectives.cshtml)
HtmlContent - (276:15,10 [4] IncompleteDirectives.cshtml)
RazorIRToken - (276:15,10 [4] IncompleteDirectives.cshtml) - Html - \n\n
CSharpCode -
RazorIRToken - - CSharp - DefineSection("", async () => {
CSharpCode -
RazorIRToken - - CSharp - });
MalformedDirective - (280:17,0 [12] IncompleteDirectives.cshtml)
MalformedDirective - (292:18,0 [15] IncompleteDirectives.cshtml)
MalformedDirective - (307:20,0 [8] IncompleteDirectives.cshtml)
HtmlContent - (315:20,8 [2] IncompleteDirectives.cshtml)
RazorIRToken - (315:20,8 [2] IncompleteDirectives.cshtml) - Html - \n
CSharpCode -
RazorIRToken - - CSharp - DefineSection("", async () => {
CSharpCode -
RazorIRToken - - CSharp - });
MalformedDirective - (317:21,0 [9] IncompleteDirectives.cshtml)
HtmlContent - (326:21,9 [4] IncompleteDirectives.cshtml)
RazorIRToken - (326:21,9 [4] IncompleteDirectives.cshtml) - Html - \n\n
CSharpCode -
RazorIRToken - - CSharp - DefineSection("", async () => {
CSharpCode -
RazorIRToken - - CSharp - });
MalformedDirective - (330:23,0 [9] IncompleteDirectives.cshtml)
HtmlContent - (339:23,9 [3] IncompleteDirectives.cshtml)
RazorIRToken - (339:23,9 [3] IncompleteDirectives.cshtml) - Html - {\n
MalformedDirective - (342:24,0 [12] IncompleteDirectives.cshtml)

View File

@ -15,8 +15,6 @@ global::System.Object Link = null;
#pragma warning disable 1998
public async System.Threading.Tasks.Task ExecuteAsync()
{
DefineSection("Link", async (__razor_section_writer) => {
});
#line 2 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/InlineBlocks.cshtml"
if(link != null) {

View File

@ -6,10 +6,8 @@ Document -
CSharpCode -
RazorIRToken - - CSharp - private static System.Object __o = null;
MethodDeclaration - - public - async - System.Threading.Tasks.Task - ExecuteAsync
CSharpCode -
RazorIRToken - - CSharp - DefineSection("Link", async (__razor_section_writer) => {
CSharpCode -
RazorIRToken - - CSharp - });
MalformedDirective - (0:0,0 [13] InlineBlocks.cshtml)
DirectiveToken - (9:0,9 [4] InlineBlocks.cshtml) - Link
HtmlContent - (13:0,13 [23] InlineBlocks.cshtml)
RazorIRToken - (13:0,13 [21] InlineBlocks.cshtml) - Html - (string link) {\n
RazorIRToken - (34:1,4 [2] InlineBlocks.cshtml) - Html - <a

View File

@ -5,21 +5,21 @@ Generated Location: (351:8,22 [4] )
Source Location: (44:1,14 [19] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/InlineBlocks.cshtml)
|if(link != null) { |
Generated Location: (793:20,14 [19] )
Generated Location: (705:18,14 [19] )
|if(link != null) { |
Source Location: (64:1,34 [4] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/InlineBlocks.cshtml)
|link|
Generated Location: (967:25,34 [4] )
Generated Location: (879:23,34 [4] )
|link|
Source Location: (68:1,38 [10] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/InlineBlocks.cshtml)
| } else { |
Generated Location: (1131:30,38 [10] )
Generated Location: (1043:28,38 [10] )
| } else { |
Source Location: (92:1,62 [2] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/InlineBlocks.cshtml)
| }|
Generated Location: (1324:35,62 [2] )
Generated Location: (1236:33,62 [2] )
| }|

View File

@ -7,8 +7,6 @@ namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests.TestFiles
#pragma warning disable 1998
public async System.Threading.Tasks.Task ExecuteAsync()
{
DefineSection("Link", async () => {
});
WriteLiteral("(string link) {\r\n <a");
BeginWriteAttribute("href", " href=\"", 36, "\"", 94, 1);
WriteAttributeValue("", 43, new Microsoft.AspNetCore.Mvc.Razor.HelperResult(async(__razor_attribute_value_writer) => {

View File

@ -2,10 +2,8 @@ Document -
NamespaceDeclaration - - Microsoft.AspNetCore.Razor.Language.IntegrationTests.TestFiles
ClassDeclaration - - public - TestFiles_IntegrationTests_CodeGenerationIntegrationTest_InlineBlocks_Runtime - -
MethodDeclaration - - public - async - System.Threading.Tasks.Task - ExecuteAsync
CSharpCode -
RazorIRToken - - CSharp - DefineSection("Link", async () => {
CSharpCode -
RazorIRToken - - CSharp - });
MalformedDirective - (0:0,0 [13] InlineBlocks.cshtml)
DirectiveToken - (9:0,9 [4] InlineBlocks.cshtml) - Link
HtmlContent - (13:0,13 [23] InlineBlocks.cshtml)
RazorIRToken - (13:0,13 [21] InlineBlocks.cshtml) - Html - (string link) {\n
RazorIRToken - (34:1,4 [2] InlineBlocks.cshtml) - Html - <a