diff --git a/src/Microsoft.AspNetCore.Razor.Language/DefaultDirectiveSyntaxTreePass.cs b/src/Microsoft.AspNetCore.Razor.Language/DefaultDirectiveSyntaxTreePass.cs index d05949477c..d41b998ca9 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/DefaultDirectiveSyntaxTreePass.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/DefaultDirectiveSyntaxTreePass.cs @@ -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++; diff --git a/src/Microsoft.AspNetCore.Razor.Language/DefaultRazorIRLoweringPhase.cs b/src/Microsoft.AspNetCore.Razor.Language/DefaultRazorIRLoweringPhase.cs index e43c086924..11d9b24ce6 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/DefaultRazorIRLoweringPhase.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/DefaultRazorIRLoweringPhase.cs @@ -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 diagnostics) + => diagnostics.Count > 0 && diagnostics.Any(diagnostic => diagnostic.Severity == RazorDiagnosticSeverity.Error); } } diff --git a/src/Microsoft.AspNetCore.Razor.Language/DefaultRazorTagHelperBinderPhase.cs b/src/Microsoft.AspNetCore.Razor.Language/DefaultRazorTagHelperBinderPhase.cs index 4970a761fe..f3892516ee 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/DefaultRazorTagHelperBinderPhase.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/DefaultRazorTagHelperBinderPhase.cs @@ -47,11 +47,10 @@ namespace Microsoft.AspNetCore.Razor.Language var errorList = new List(); 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 directives, RazorCodeDocument codeDocument, ErrorSink errorSink) + internal string ProcessTagHelperPrefix(List 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 ProcessDirectives( IReadOnlyList directives, - IReadOnlyList tagHelpers, - ErrorSink errorSink) + IReadOnlyList tagHelpers) { var matches = new HashSet(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 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 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; diff --git a/src/Microsoft.AspNetCore.Razor.Language/DirectiveRemovalIROptimizationPass.cs b/src/Microsoft.AspNetCore.Razor.Language/DirectiveRemovalIROptimizationPass.cs index 00a0935767..9902e01e78 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/DirectiveRemovalIROptimizationPass.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/DirectiveRemovalIROptimizationPass.cs @@ -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 DirectiveNodes { get; } = new List(); public override void VisitDirective(DirectiveIRNode node) { - DirectiveNodes.Add((node, Parent)); + DirectiveNodes.Add(new RazorIRNodeReference(Parent, node)); } } } diff --git a/src/Microsoft.AspNetCore.Razor.Language/Intermediate/MalformedDirectiveIRNode.cs b/src/Microsoft.AspNetCore.Razor.Language/Intermediate/MalformedDirectiveIRNode.cs new file mode 100644 index 0000000000..4d21e4dcad --- /dev/null +++ b/src/Microsoft.AspNetCore.Razor.Language/Intermediate/MalformedDirectiveIRNode.cs @@ -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 Tokens => Children.OfType(); + + public DirectiveDescriptor Descriptor { get; set; } + + public override void Accept(RazorIRNodeVisitor visitor) + { + visitor.VisitMalformedDirective(this); + } + } +} \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Razor.Language/Intermediate/RazorIRNodeVisitor.cs b/src/Microsoft.AspNetCore.Razor.Language/Intermediate/RazorIRNodeVisitor.cs index ddb1e4d15b..8e9736370c 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/Intermediate/RazorIRNodeVisitor.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/Intermediate/RazorIRNodeVisitor.cs @@ -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); diff --git a/src/Microsoft.AspNetCore.Razor.Language/Legacy/AddTagHelperChunkGenerator.cs b/src/Microsoft.AspNetCore.Razor.Language/Legacy/AddTagHelperChunkGenerator.cs index f682f87c87..92a43c2d50 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/Legacy/AddTagHelperChunkGenerator.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/Legacy/AddTagHelperChunkGenerator.cs @@ -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 diagnostics) { LookupText = lookupText; + Diagnostics = diagnostics; } public string LookupText { get; } + public List 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); } diff --git a/src/Microsoft.AspNetCore.Razor.Language/Legacy/CSharpCodeParser.cs b/src/Microsoft.AspNetCore.Razor.Language/Legacy/CSharpCodeParser.cs index 6d4d957b73..f85d6b2d46 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/Legacy/CSharpCodeParser.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/Legacy/CSharpCodeParser.cs @@ -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
@hello.
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
@hello.
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 chunkGeneratorFactory) + private void TagHelperDirective(string keyword, Func, 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 directiveErrors; + if (directiveErrorSink.Errors.Count > 0) + { + directiveErrors = directiveErrorSink.Errors.Select(RazorDiagnostic.Create).ToList(); + } + else + { + directiveErrors = new List(); } - 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); diff --git a/src/Microsoft.AspNetCore.Razor.Language/Legacy/DirectiveChunkGenerator.cs b/src/Microsoft.AspNetCore.Razor.Language/Legacy/DirectiveChunkGenerator.cs index 4ed071400e..c584de9cc8 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/Legacy/DirectiveChunkGenerator.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/Legacy/DirectiveChunkGenerator.cs @@ -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 _diagnostics; public DirectiveChunkGenerator(DirectiveDescriptor descriptor) { @@ -17,6 +21,19 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy public DirectiveDescriptor Descriptor { get; } + public List Diagnostics + { + get + { + if (_diagnostics == null) + { + _diagnostics = new List(); + } + + 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(); + } } } diff --git a/src/Microsoft.AspNetCore.Razor.Language/Legacy/ParserContext.cs b/src/Microsoft.AspNetCore.Razor.Language/Legacy/ParserContext.cs index f12264df83..897504a300 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/Legacy/ParserContext.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/Legacy/ParserContext.cs @@ -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; } diff --git a/src/Microsoft.AspNetCore.Razor.Language/Legacy/RemoveTagHelperChunkGenerator.cs b/src/Microsoft.AspNetCore.Razor.Language/Legacy/RemoveTagHelperChunkGenerator.cs index ac8df6da50..21bc2978e9 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/Legacy/RemoveTagHelperChunkGenerator.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/Legacy/RemoveTagHelperChunkGenerator.cs @@ -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 diagnostics) { LookupText = lookupText; + Diagnostics = diagnostics; } public string LookupText { get; } + public List 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); } diff --git a/src/Microsoft.AspNetCore.Razor.Language/Legacy/TagHelperDirectiveDescriptor.cs b/src/Microsoft.AspNetCore.Razor.Language/Legacy/TagHelperDirectiveDescriptor.cs index b1fa4feeca..d5cb428fe3 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/Legacy/TagHelperDirectiveDescriptor.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/Legacy/TagHelperDirectiveDescriptor.cs @@ -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 of this directive. /// public TagHelperDirectiveType DirectiveType { get; set; } + + public List Diagnostics { get; set; } } } \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Razor.Language/Legacy/TagHelperPrefixDirectiveChunkGenerator.cs b/src/Microsoft.AspNetCore.Razor.Language/Legacy/TagHelperPrefixDirectiveChunkGenerator.cs index 1290988c8e..fae8d93ed8 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/Legacy/TagHelperPrefixDirectiveChunkGenerator.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/Legacy/TagHelperPrefixDirectiveChunkGenerator.cs @@ -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 diagnostics) { Prefix = prefix; + Diagnostics = diagnostics; } public string Prefix { get; } + public List 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); } diff --git a/src/Microsoft.AspNetCore.Razor.Language/Properties/Resources.Designer.cs b/src/Microsoft.AspNetCore.Razor.Language/Properties/Resources.Designer.cs index 907fec1eeb..a041563555 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/Properties/Resources.Designer.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/Properties/Resources.Designer.cs @@ -444,6 +444,20 @@ namespace Microsoft.AspNetCore.Razor.Language internal static string FormatDirectiveMustAppearAtStartOfLine(object p0) => string.Format(CultureInfo.CurrentCulture, GetString("DirectiveMustAppearAtStartOfLine"), p0); + /// + /// The '{0}' directives value(s) must be separated by whitespace. + /// + internal static string DirectiveTokensMustBeSeparatedByWhitespace + { + get => GetString("DirectiveTokensMustBeSeparatedByWhitespace"); + } + + /// + /// The '{0}' directives value(s) must be separated by whitespace. + /// + internal static string FormatDirectiveTokensMustBeSeparatedByWhitespace(object p0) + => string.Format(CultureInfo.CurrentCulture, GetString("DirectiveTokensMustBeSeparatedByWhitespace"), p0); + /// /// The key must not be null. /// diff --git a/src/Microsoft.AspNetCore.Razor.Language/Resources.resx b/src/Microsoft.AspNetCore.Razor.Language/Resources.resx index 3f490ae2f9..5f1f9562d4 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/Resources.resx +++ b/src/Microsoft.AspNetCore.Razor.Language/Resources.resx @@ -210,6 +210,9 @@ The '{0}` directive must appear at the start of the line. + + The '{0}' directives value(s) must be separated by whitespace. + The key must not be null. diff --git a/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/IntegrationTests/CodeGenerationIntegrationTest.cs b/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/IntegrationTests/CodeGenerationIntegrationTest.cs index c344a4f1f1..d8a93ef060 100644 --- a/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/IntegrationTests/CodeGenerationIntegrationTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/IntegrationTests/CodeGenerationIntegrationTest.cs @@ -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 }"; 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 "; var references = CreateCompilationReferences(CurrentMvcShim, appCode); - RunDesignTimeTest( - references, - expectedErrors: new[] - { - "Identifier expected" - }); + RunDesignTimeTest(references); } [Fact] diff --git a/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/PageDirectiveTest.cs b/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/PageDirectiveTest.cs index 428dd51f71..8380727b3c 100644 --- a/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/PageDirectiveTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/PageDirectiveTest.cs @@ -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() { diff --git a/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives_DesignTime.codegen.cs b/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives_DesignTime.codegen.cs index c5ce5a2371..aeeda90034 100644 --- a/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives_DesignTime.codegen.cs +++ b/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives_DesignTime.codegen.cs @@ -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; diff --git a/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives_DesignTime.ir.txt b/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives_DesignTime.ir.txt index a4e629b53d..968878a06f 100644 --- a/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives_DesignTime.ir.txt +++ b/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives_DesignTime.ir.txt @@ -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 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 - diff --git a/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives_DesignTime.mappings.txt b/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives_DesignTime.mappings.txt index da2d5f1fc3..23f8a7d6f5 100644 --- a/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives_DesignTime.mappings.txt +++ b/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives_DesignTime.mappings.txt @@ -1,5 +1,5 @@ Source Location: (159:11,8 [17] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml) |MyService| -Generated Location: (616:16,0 [17] ) +Generated Location: (833:17,0 [17] ) |MyService| diff --git a/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives_Runtime.codegen.cs b/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives_Runtime.codegen.cs index 99292e76b0..5488bac509 100644 --- a/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives_Runtime.codegen.cs +++ b/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives_Runtime.codegen.cs @@ -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; diff --git a/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives_Runtime.ir.txt b/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives_Runtime.ir.txt index 3727695b5e..8256aa1e47 100644 --- a/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives_Runtime.ir.txt +++ b/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives_Runtime.ir.txt @@ -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 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) diff --git a/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/InvalidNamespaceAtEOF_DesignTime.codegen.cs b/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/InvalidNamespaceAtEOF_DesignTime.codegen.cs index 0dd729a78d..e8fd02493b 100644 --- a/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/InvalidNamespaceAtEOF_DesignTime.codegen.cs +++ b/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/InvalidNamespaceAtEOF_DesignTime.codegen.cs @@ -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; diff --git a/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/InvalidNamespaceAtEOF_DesignTime.ir.txt b/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/InvalidNamespaceAtEOF_DesignTime.ir.txt index 018ac0cb2c..4bd04cdb6d 100644 --- a/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/InvalidNamespaceAtEOF_DesignTime.ir.txt +++ b/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/InvalidNamespaceAtEOF_DesignTime.ir.txt @@ -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 - diff --git a/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/InvalidNamespaceAtEOF_Runtime.codegen.cs b/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/InvalidNamespaceAtEOF_Runtime.codegen.cs index 0e8e0f2afd..8f1f15dd85 100644 --- a/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/InvalidNamespaceAtEOF_Runtime.codegen.cs +++ b/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/InvalidNamespaceAtEOF_Runtime.codegen.cs @@ -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; diff --git a/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/InvalidNamespaceAtEOF_Runtime.ir.txt b/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/InvalidNamespaceAtEOF_Runtime.ir.txt index 28ffcc6237..9b586b65a0 100644 --- a/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/InvalidNamespaceAtEOF_Runtime.ir.txt +++ b/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/InvalidNamespaceAtEOF_Runtime.ir.txt @@ -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 - 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) diff --git a/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/MalformedPageDirective_DesignTime.codegen.cs b/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/MalformedPageDirective_DesignTime.codegen.cs index 1cff6891cd..8f021837e1 100644 --- a/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/MalformedPageDirective_DesignTime.codegen.cs +++ b/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/MalformedPageDirective_DesignTime.codegen.cs @@ -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 { #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 Html { get; private set; } - public global::Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionary ViewData => (global::Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionary)PageContext?.ViewData; - public TestFiles_IntegrationTests_CodeGenerationIntegrationTest_MalformedPageDirective_cshtml Model => ViewData.Model; + public global::Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper Html { get; private set; } } } diff --git a/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/MalformedPageDirective_DesignTime.ir.txt b/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/MalformedPageDirective_DesignTime.ir.txt index 9ae80d1571..838720effa 100644 --- a/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/MalformedPageDirective_DesignTime.ir.txt +++ b/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/MalformedPageDirective_DesignTime.ir.txt @@ -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 - DesignTimeDirective - DirectiveToken - (231:7,8 [62] ) - global::Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper 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 -

@@ -42,7 +43,3 @@ Document - InjectDirective - InjectDirective - InjectDirective - - CSharpCode - - RazorIRToken - - CSharp - public global::Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionary ViewData => (global::Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionary)PageContext?.ViewData; - CSharpCode - - RazorIRToken - - CSharp - public TestFiles_IntegrationTests_CodeGenerationIntegrationTest_MalformedPageDirective_cshtml Model => ViewData.Model; diff --git a/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/MalformedPageDirective_Runtime.codegen.cs b/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/MalformedPageDirective_Runtime.codegen.cs index ed46639a5d..faf92d5caf 100644 --- a/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/MalformedPageDirective_Runtime.codegen.cs +++ b/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/MalformedPageDirective_Runtime.codegen.cs @@ -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 { #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 Html { get; private set; } - public global::Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionary ViewData => (global::Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionary)PageContext?.ViewData; - public TestFiles_IntegrationTests_CodeGenerationIntegrationTest_MalformedPageDirective_cshtml Model => ViewData.Model; + public global::Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper Html { get; private set; } } } diff --git a/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/MalformedPageDirective_Runtime.ir.txt b/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/MalformedPageDirective_Runtime.ir.txt index 9d5a94fd61..fecda65a8c 100644 --- a/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/MalformedPageDirective_Runtime.ir.txt +++ b/test/Microsoft.AspNetCore.Mvc.Razor.Extensions.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/MalformedPageDirective_Runtime.ir.txt @@ -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 - 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 ViewData => (global::Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionary)PageContext?.ViewData; - CSharpCode - - RazorIRToken - - CSharp - public TestFiles_IntegrationTests_CodeGenerationIntegrationTest_MalformedPageDirective_cshtml Model => ViewData.Model; diff --git a/test/Microsoft.AspNetCore.Razor.Language.Test/DefaultRazorTagHelperBinderPhaseTest.cs b/test/Microsoft.AspNetCore.Razor.Language.Test/DefaultRazorTagHelperBinderPhaseTest.cs index 8d1fa6f084..c264bbf92b 100644 --- a/test/Microsoft.AspNetCore.Razor.Language.Test/DefaultRazorTagHelperBinderPhaseTest.cs +++ b/test/Microsoft.AspNetCore.Razor.Language.Test/DefaultRazorTagHelperBinderPhaseTest.cs @@ -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().First().Children.Last() as Span; + var chunkGenerator = Assert.IsType(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().First().Children.Last() as Span; + var chunkGenerator = Assert.IsType(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().First().Children.Last() as Span; + var chunkGenerator = Assert.IsType(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(), }; 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(), }, }, new[] @@ -527,7 +533,8 @@ namespace Microsoft.AspNetCore.Razor.Language { DirectiveText = "th\t", Location = directiveLocation1, - DirectiveType = TagHelperDirectiveType.TagHelperPrefix + DirectiveType = TagHelperDirectiveType.TagHelperPrefix, + Diagnostics = new List(), } }, 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(), } }, new[] @@ -571,7 +579,8 @@ namespace Microsoft.AspNetCore.Razor.Language { DirectiveText = " th ", Location = directiveLocation1, - DirectiveType = TagHelperDirectiveType.TagHelperPrefix + DirectiveType = TagHelperDirectiveType.TagHelperPrefix, + Diagnostics = new List(), } }, new[] @@ -593,7 +602,8 @@ namespace Microsoft.AspNetCore.Razor.Language { DirectiveText = "@", Location = directiveLocation1, - DirectiveType = TagHelperDirectiveType.TagHelperPrefix + DirectiveType = TagHelperDirectiveType.TagHelperPrefix, + Diagnostics = new List(), } }, new[] @@ -615,7 +625,8 @@ namespace Microsoft.AspNetCore.Razor.Language { DirectiveText = "t@h", Location = directiveLocation1, - DirectiveType = TagHelperDirectiveType.TagHelperPrefix + DirectiveType = TagHelperDirectiveType.TagHelperPrefix, + Diagnostics = new List(), } }, new[] @@ -637,7 +648,8 @@ namespace Microsoft.AspNetCore.Razor.Language { DirectiveText = "!", Location = directiveLocation1, - DirectiveType = TagHelperDirectiveType.TagHelperPrefix + DirectiveType = TagHelperDirectiveType.TagHelperPrefix, + Diagnostics = new List(), } }, new[] @@ -659,7 +671,8 @@ namespace Microsoft.AspNetCore.Razor.Language { DirectiveText = "!th", Location = directiveLocation1, - DirectiveType = TagHelperDirectiveType.TagHelperPrefix + DirectiveType = TagHelperDirectiveType.TagHelperPrefix, + Diagnostics = new List(), } }, new[] @@ -685,18 +698,18 @@ namespace Microsoft.AspNetCore.Razor.Language object expectedErrors) { // Arrange - var errorSink = new ErrorSink(); - + var expectedDiagnostics = ((IEnumerable)expectedErrors).Select(RazorDiagnostic.Create); + var tagHelperDirectives = (IEnumerable)directives; var phase = new DefaultRazorTagHelperBinderPhase(); // Act - foreach (var directive in ((IEnumerable)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)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)directiveDescriptors; // Act - var prefix = phase.ProcessTagHelperPrefix(((IEnumerable)directiveDescriptors).ToList(), document, errorSink); + var prefix = phase.ProcessTagHelperPrefix(((IEnumerable)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)directiveDescriptors; var expected = (IEnumerable)expectedDescriptors; // Act var results = phase.ProcessDirectives( - new List((IEnumerable)directiveDescriptors), - new List((IEnumerable)tagHelpers), - errorSink); + new List(tagHelperDirectives), + new List((IEnumerable)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)directiveDescriptors; var phase = new DefaultRazorTagHelperBinderPhase(); // Act var results = phase.ProcessDirectives( - new List((IEnumerable)directiveDescriptors), - new List((IEnumerable)tagHelpers), - errorSink); + new List(tagHelperDirectives), + new List((IEnumerable)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(), + } + }; // 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(), }; 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(), }; } @@ -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); }); diff --git a/test/Microsoft.AspNetCore.Razor.Language.Test/Legacy/CSharpAutoCompleteTest.cs b/test/Microsoft.AspNetCore.Razor.Language.Test/Legacy/CSharpAutoCompleteTest.cs index c5cd5ec692..9f0e9f1fba 100644 --- a/test/Microsoft.AspNetCore.Razor.Language.Test/Legacy/CSharpAutoCompleteTest.cs +++ b/test/Microsoft.AspNetCore.Razor.Language.Test/Legacy/CSharpAutoCompleteTest.cs @@ -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 - + "

Foo

", - 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 + "

Foo

", + 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("

")), Factory.Markup("Foo"), new MarkupTagBlock( - Factory.Markup("

")))), - new RazorError( - LegacyResources.FormatParseError_Expected_EndOfBlock_Before_EOF("section", "}", "{"), - new SourceLocation(16, 0, 16), - length: 1)); + Factory.Markup("

"))))); } [Fact] public void VerbatimBlockAutoCompleteAtStartOfFile() { - ParseBlockTest("@{" + Environment.NewLine - + "

", - 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("

").Accepts(AcceptedCharactersInternal.None)), - new MarkupTagBlock( - Factory.Markup("

").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 + "

", + 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("

").Accepts(AcceptedCharactersInternal.None)), + new MarkupTagBlock( + Factory.Markup("

").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)); } } } diff --git a/test/Microsoft.AspNetCore.Razor.Language.Test/Legacy/CSharpDirectivesTest.cs b/test/Microsoft.AspNetCore.Razor.Language.Test/Legacy/CSharpDirectivesTest.cs index 903ecd7033..4c48b7a8de 100644 --- a/test/Microsoft.AspNetCore.Razor.Language.Test/Legacy/CSharpDirectivesTest.cs +++ b/test/Microsoft.AspNetCore.Razor.Language.Test/Legacy/CSharpDirectivesTest.cs @@ -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] diff --git a/test/Microsoft.AspNetCore.Razor.Language.Test/Legacy/CSharpErrorTest.cs b/test/Microsoft.AspNetCore.Razor.Language.Test/Legacy/CSharpErrorTest.cs index e131008c6b..d9be2f5e7b 100644 --- a/test/Microsoft.AspNetCore.Razor.Language.Test/Legacy/CSharpErrorTest.cs +++ b/test/Microsoft.AspNetCore.Razor.Language.Test/Legacy/CSharpErrorTest.cs @@ -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] diff --git a/test/Microsoft.AspNetCore.Razor.Language.Test/Legacy/CSharpSectionTest.cs b/test/Microsoft.AspNetCore.Razor.Language.Test/Legacy/CSharpSectionTest.cs index e4ccd83029..4681038d84 100644 --- a/test/Microsoft.AspNetCore.Razor.Language.Test/Legacy/CSharpSectionTest.cs +++ b/test/Microsoft.AspNetCore.Razor.Language.Test/Legacy/CSharpSectionTest.cs @@ -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 {

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)), @@ -101,22 +130,28 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy Factory.Markup("Foo"), new MarkupTagBlock( Factory.Markup("

")), - 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 {

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), @@ -127,19 +162,31 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy Factory.Markup("Foo"), new MarkupTagBlock( Factory.Markup("

")), - 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 {

Foo

} }", - 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 {

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), @@ -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("

"))))), - new RazorError( - LegacyResources.FormatParseError_Expected_EndOfBlock_Before_EOF("section", "}", "{"), - new SourceLocation(13, 0, 13), - length: 1)); + Factory.Markup("

")))))); } [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}

Hello World

{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("

", 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 - + "

Foo

" + Environment.NewLine - + "}", - new[] { SectionDirective.Directive, }, + // Act & Assert + ParseDocumentTest( + "@section foo " + + Environment.NewLine + + Environment.NewLine + + Environment.NewLine + + Environment.NewLine + + Environment.NewLine + + Environment.NewLine + + "{" + Environment.NewLine + + "

Foo

" + 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 {

Foo

}", - 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{

Foo

}", - 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 { }", - 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 + " \" '-->}", - 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 { }", - 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); } } } diff --git a/test/Microsoft.AspNetCore.Razor.Language.Test/Legacy/CSharpSpecialBlockTest.cs b/test/Microsoft.AspNetCore.Razor.Language.Test/Legacy/CSharpSpecialBlockTest.cs index fbbfa9e2fc..650c12d506 100644 --- a/test/Microsoft.AspNetCore.Razor.Language.Test/Legacy/CSharpSpecialBlockTest.cs +++ b/test/Microsoft.AspNetCore.Razor.Language.Test/Legacy/CSharpSpecialBlockTest.cs @@ -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, 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] diff --git a/test/Microsoft.AspNetCore.Razor.Language.Test/Legacy/TestSpanBuilder.cs b/test/Microsoft.AspNetCore.Razor.Language.Test/Legacy/TestSpanBuilder.cs index 213883c0ff..dc0e19f801 100644 --- a/test/Microsoft.AspNetCore.Razor.Language.Test/Legacy/TestSpanBuilder.cs +++ b/test/Microsoft.AspNetCore.Razor.Language.Test/Legacy/TestSpanBuilder.cs @@ -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); } diff --git a/test/Microsoft.AspNetCore.Razor.Language.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives_DesignTime.codegen.cs b/test/Microsoft.AspNetCore.Razor.Language.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives_DesignTime.codegen.cs index b605e8dbdc..f47b579ee3 100644 --- a/test/Microsoft.AspNetCore.Razor.Language.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives_DesignTime.codegen.cs +++ b/test/Microsoft.AspNetCore.Razor.Language.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives_DesignTime.codegen.cs @@ -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 } diff --git a/test/Microsoft.AspNetCore.Razor.Language.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives_DesignTime.ir.txt b/test/Microsoft.AspNetCore.Razor.Language.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives_DesignTime.ir.txt index 0563488222..e2b03c6e98 100644 --- a/test/Microsoft.AspNetCore.Razor.Language.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives_DesignTime.ir.txt +++ b/test/Microsoft.AspNetCore.Razor.Language.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives_DesignTime.ir.txt @@ -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) diff --git a/test/Microsoft.AspNetCore.Razor.Language.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives_Runtime.codegen.cs b/test/Microsoft.AspNetCore.Razor.Language.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives_Runtime.codegen.cs index 4da141abdd..4dd2fdebf7 100644 --- a/test/Microsoft.AspNetCore.Razor.Language.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives_Runtime.codegen.cs +++ b/test/Microsoft.AspNetCore.Razor.Language.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives_Runtime.codegen.cs @@ -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 diff --git a/test/Microsoft.AspNetCore.Razor.Language.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives_Runtime.ir.txt b/test/Microsoft.AspNetCore.Razor.Language.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives_Runtime.ir.txt index cc812008b8..48b9d2d802 100644 --- a/test/Microsoft.AspNetCore.Razor.Language.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives_Runtime.ir.txt +++ b/test/Microsoft.AspNetCore.Razor.Language.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives_Runtime.ir.txt @@ -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) diff --git a/test/Microsoft.AspNetCore.Razor.Language.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/InlineBlocks_DesignTime.codegen.cs b/test/Microsoft.AspNetCore.Razor.Language.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/InlineBlocks_DesignTime.codegen.cs index fc786858d9..5b223d7551 100644 --- a/test/Microsoft.AspNetCore.Razor.Language.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/InlineBlocks_DesignTime.codegen.cs +++ b/test/Microsoft.AspNetCore.Razor.Language.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/InlineBlocks_DesignTime.codegen.cs @@ -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) { diff --git a/test/Microsoft.AspNetCore.Razor.Language.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/InlineBlocks_DesignTime.ir.txt b/test/Microsoft.AspNetCore.Razor.Language.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/InlineBlocks_DesignTime.ir.txt index 51b2e8e318..b892f5ff97 100644 --- a/test/Microsoft.AspNetCore.Razor.Language.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/InlineBlocks_DesignTime.ir.txt +++ b/test/Microsoft.AspNetCore.Razor.Language.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/InlineBlocks_DesignTime.ir.txt @@ -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 - { - }); WriteLiteral("(string link) {\r\n { diff --git a/test/Microsoft.AspNetCore.Razor.Language.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/InlineBlocks_Runtime.ir.txt b/test/Microsoft.AspNetCore.Razor.Language.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/InlineBlocks_Runtime.ir.txt index ce46ba6278..e0b73fa873 100644 --- a/test/Microsoft.AspNetCore.Razor.Language.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/InlineBlocks_Runtime.ir.txt +++ b/test/Microsoft.AspNetCore.Razor.Language.Test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/InlineBlocks_Runtime.ir.txt @@ -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 -