From 2fe78d70dbb6d9ff29add8745c176b688b2dc21b Mon Sep 17 00:00:00 2001 From: Ajay Bhargav Baaskaran Date: Wed, 13 May 2015 17:21:41 -0700 Subject: [PATCH] [Fixes #217] Applying error squiggly to full directive --- src/Microsoft.AspNet.Razor/ErrorSink.cs | 2 +- .../Parser/CSharpCodeParser.Directives.cs | 52 +++++++++++++------ .../Parser/ParserContext.cs | 8 +++ src/Microsoft.AspNet.Razor/RazorError.cs | 7 ++- .../Parser/CSharp/CSharpAutoCompleteTest.cs | 4 +- .../Parser/CSharp/CSharpDirectivesTest.cs | 24 ++++----- .../Parser/CSharp/CSharpErrorTest.cs | 2 +- .../Parser/CSharp/CSharpSectionTest.cs | 5 +- .../Parser/CSharp/CSharpSpecialBlockTest.cs | 6 +-- 9 files changed, 70 insertions(+), 40 deletions(-) diff --git a/src/Microsoft.AspNet.Razor/ErrorSink.cs b/src/Microsoft.AspNet.Razor/ErrorSink.cs index 86b193d3cc..c2295dc80a 100644 --- a/src/Microsoft.AspNet.Razor/ErrorSink.cs +++ b/src/Microsoft.AspNet.Razor/ErrorSink.cs @@ -47,7 +47,7 @@ namespace Microsoft.AspNet.Razor /// A message describing the error. public void OnError(SourceLocation location, string message) { - _errors.Add(new RazorError(message, location)); + OnError(location, message, RazorError.DefaultErrorLength); } /// diff --git a/src/Microsoft.AspNet.Razor/Parser/CSharpCodeParser.Directives.cs b/src/Microsoft.AspNet.Razor/Parser/CSharpCodeParser.Directives.cs index 5b9bf13b1c..1f7685a1aa 100644 --- a/src/Microsoft.AspNet.Razor/Parser/CSharpCodeParser.Directives.cs +++ b/src/Microsoft.AspNet.Razor/Parser/CSharpCodeParser.Directives.cs @@ -2,10 +2,8 @@ // 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.Diagnostics; using System.Diagnostics.CodeAnalysis; -using Microsoft.AspNet.Razor.Editor; using Microsoft.AspNet.Razor.Generator; using Microsoft.AspNet.Razor.Parser.SyntaxTree; using Microsoft.AspNet.Razor.Tokenizer.Symbols; @@ -57,15 +55,19 @@ namespace Microsoft.AspNet.Razor.Parser // Verify we're on "section" and accept AssertDirective(SyntaxConstants.CSharp.SectionKeyword); + var startLocation = CurrentLocation; AcceptAndMoveNext(); if (nested) { - Context.OnError(CurrentLocation, RazorResources.FormatParseError_Sections_Cannot_Be_Nested(RazorResources.SectionExample_CS)); + Context.OnError( + startLocation, + RazorResources.FormatParseError_Sections_Cannot_Be_Nested(RazorResources.SectionExample_CS), + Span.GetContent().Value.Length); errorReported = true; } - IEnumerable ws = ReadWhile(IsSpacingToken(includeNewLines: true, includeComments: false)); + var whitespace = ReadWhile(IsSpacingToken(includeNewLines: true, includeComments: false)); // Get the section name var sectionName = string.Empty; @@ -79,19 +81,19 @@ namespace Microsoft.AspNet.Razor.Parser } PutCurrentBack(); - PutBack(ws); + PutBack(whitespace); AcceptWhile(IsSpacingToken(includeNewLines: false, includeComments: false)); } else { - Accept(ws); + Accept(whitespace); sectionName = CurrentSymbol.Content; AcceptAndMoveNext(); } Context.CurrentBlock.CodeGenerator = new SectionCodeGenerator(sectionName); var errorLocation = CurrentLocation; - ws = ReadWhile(IsSpacingToken(includeNewLines: true, includeComments: false)); + whitespace = ReadWhile(IsSpacingToken(includeNewLines: true, includeComments: false)); // Get the starting brace var sawStartingBrace = At(CSharpSymbolType.LeftBrace); @@ -104,7 +106,7 @@ namespace Microsoft.AspNet.Razor.Parser } PutCurrentBack(); - PutBack(ws); + PutBack(whitespace); AcceptWhile(IsSpacingToken(includeNewLines: false, includeComments: false)); Optional(CSharpSymbolType.NewLine); Output(SpanKind.MetaCode); @@ -113,7 +115,7 @@ namespace Microsoft.AspNet.Razor.Parser } else { - Accept(ws); + Accept(whitespace); } // Set up edit handler @@ -184,7 +186,7 @@ namespace Microsoft.AspNet.Razor.Parser if (!At(CSharpSymbolType.RightBrace)) { editHandler.AutoCompleteString = "}"; - Context.OnError(block.Start, RazorResources.FormatParseError_Expected_EndOfBlock_Before_EOF(block.Name, "}", "{")); + Context.OnError(blockStart, RazorResources.FormatParseError_Expected_EndOfBlock_Before_EOF(block.Name, "}", "{")); CompleteBlock(); Output(SpanKind.Code); } @@ -225,11 +227,15 @@ namespace Microsoft.AspNet.Razor.Parser protected void BaseTypeDirective(string noTypeNameError, Func createCodeGenerator) { + var keywordStartLocation = Span.Start; + // Set the block type Context.CurrentBlock.Type = BlockType.Directive; + var keywordLength = Span.GetContent().Value.Length; + // Accept whitespace - var remainingWs = AcceptSingleWhiteSpaceCharacter(); + var remainingWhitespace = AcceptSingleWhiteSpaceCharacter(); if (Span.Symbols.Count > 1) { @@ -238,15 +244,19 @@ namespace Microsoft.AspNet.Razor.Parser Output(SpanKind.MetaCode); - if (remainingWs != null) + if (remainingWhitespace != null) { - Accept(remainingWs); + Accept(remainingWhitespace); } + AcceptWhile(IsSpacingToken(includeNewLines: false, includeComments: true)); if (EndOfFile || At(CSharpSymbolType.WhiteSpace) || At(CSharpSymbolType.NewLine)) { - Context.OnError(CurrentLocation, noTypeNameError); + Context.OnError( + keywordStartLocation, + noTypeNameError, + keywordLength); } // Parse to the end of the line @@ -271,6 +281,7 @@ namespace Microsoft.AspNet.Razor.Parser private void TagHelperDirective(string keyword, Func buildCodeGenerator) { AssertDirective(keyword); + var keywordStartLocation = CurrentLocation; // Accept the directive name AcceptAndMoveNext(); @@ -278,6 +289,8 @@ namespace Microsoft.AspNet.Razor.Parser // Set the block type Context.CurrentBlock.Type = BlockType.Directive; + var keywordLength = Span.GetContent().Value.Length; + var foundWhitespace = At(CSharpSymbolType.WhiteSpace); AcceptWhile(CSharpSymbolType.WhiteSpace); @@ -287,7 +300,10 @@ namespace Microsoft.AspNet.Razor.Parser if (EndOfFile || At(CSharpSymbolType.NewLine)) { - Context.OnError(CurrentLocation, RazorResources.FormatParseError_DirectiveMustHaveValue(keyword)); + Context.OnError( + keywordStartLocation, + RazorResources.FormatParseError_DirectiveMustHaveValue(keyword), + keywordLength); } else { @@ -318,8 +334,10 @@ namespace Microsoft.AspNet.Razor.Parser if (!startsWithQuote || !rawValue.EndsWith("\"", StringComparison.OrdinalIgnoreCase)) { - Context.OnError(startLocation, - RazorResources.FormatParseError_DirectiveMustBeSurroundedByQuotes(keyword)); + Context.OnError( + startLocation, + RazorResources.FormatParseError_DirectiveMustBeSurroundedByQuotes(keyword), + rawValue.Length); } } diff --git a/src/Microsoft.AspNet.Razor/Parser/ParserContext.cs b/src/Microsoft.AspNet.Razor/Parser/ParserContext.cs index 64eba5bf4a..3d3b7c1f9e 100644 --- a/src/Microsoft.AspNet.Razor/Parser/ParserContext.cs +++ b/src/Microsoft.AspNet.Razor/Parser/ParserContext.cs @@ -208,6 +208,14 @@ namespace Microsoft.AspNet.Razor.Parser _errorSink.OnError(location, message); } + public void OnError(SourceLocation location, string message, int length) + { + EnusreNotTerminated(); + AssertOnOwnerTask(); + + _errorSink.OnError(location, message, length); + } + public void OnError(SourceLocation location, string message, params object[] args) { EnusreNotTerminated(); diff --git a/src/Microsoft.AspNet.Razor/RazorError.cs b/src/Microsoft.AspNet.Razor/RazorError.cs index 84657f0a0d..6f5118e4d6 100644 --- a/src/Microsoft.AspNet.Razor/RazorError.cs +++ b/src/Microsoft.AspNet.Razor/RazorError.cs @@ -9,13 +9,15 @@ namespace Microsoft.AspNet.Razor { public class RazorError : IEquatable { + internal const int DefaultErrorLength = 1; + public RazorError() : this(message: string.Empty, location: SourceLocation.Undefined) { } public RazorError(string message, SourceLocation location) - : this(message, location, 1) + : this(message, location, DefaultErrorLength) { } @@ -77,7 +79,8 @@ namespace Microsoft.AspNet.Razor { return other != null && string.Equals(other.Message, Message, StringComparison.Ordinal) && - Location.Equals(other.Location); + Location.Equals(other.Location) && + Length.Equals(other.Length); } } } diff --git a/test/Microsoft.AspNet.Razor.Test/Parser/CSharp/CSharpAutoCompleteTest.cs b/test/Microsoft.AspNet.Razor.Test/Parser/CSharp/CSharpAutoCompleteTest.cs index 4491ff55fd..c579a2ce6a 100644 --- a/test/Microsoft.AspNet.Razor.Test/Parser/CSharp/CSharpAutoCompleteTest.cs +++ b/test/Microsoft.AspNet.Razor.Test/Parser/CSharp/CSharpAutoCompleteTest.cs @@ -29,7 +29,7 @@ namespace Microsoft.AspNet.Razor.Test.Parser.CSharp AutoCompleteString = "}" })), new RazorError(RazorResources.FormatParseError_Expected_EndOfBlock_Before_EOF("functions", "}", "{"), - 1, 0, 1)); + 10, 0, 10)); } [Fact] @@ -79,7 +79,7 @@ namespace Microsoft.AspNet.Razor.Test.Parser.CSharp AutoCompleteString = "}" })), new RazorError(RazorResources.FormatParseError_Expected_EndOfBlock_Before_EOF("functions", "}", "{"), - 1, 0, 1)); + 10, 0, 10)); } [Fact] diff --git a/test/Microsoft.AspNet.Razor.Test/Parser/CSharp/CSharpDirectivesTest.cs b/test/Microsoft.AspNet.Razor.Test/Parser/CSharp/CSharpDirectivesTest.cs index a7f0e2411a..f323c36f27 100644 --- a/test/Microsoft.AspNet.Razor.Test/Parser/CSharp/CSharpDirectivesTest.cs +++ b/test/Microsoft.AspNet.Razor.Test/Parser/CSharp/CSharpDirectivesTest.cs @@ -52,7 +52,7 @@ namespace Microsoft.AspNet.Razor.Test.Parser.CSharp new RazorError( RazorResources.FormatParseError_DirectiveMustHaveValue( SyntaxConstants.CSharp.TagHelperPrefixKeyword), - absoluteIndex: 17, lineIndex: 0, columnIndex: 17)); + absoluteIndex: 1, lineIndex: 0, columnIndex: 1, length: 15)); } [Fact] @@ -72,7 +72,7 @@ namespace Microsoft.AspNet.Razor.Test.Parser.CSharp new RazorError( RazorResources.FormatParseError_DirectiveMustBeSurroundedByQuotes( SyntaxConstants.CSharp.TagHelperPrefixKeyword), - absoluteIndex: 17, lineIndex: 0, columnIndex: 17)); + absoluteIndex: 17, lineIndex: 0, columnIndex: 17, length: 4)); } [Fact] @@ -93,7 +93,7 @@ namespace Microsoft.AspNet.Razor.Test.Parser.CSharp new RazorError( RazorResources.FormatParseError_DirectiveMustBeSurroundedByQuotes( SyntaxConstants.CSharp.TagHelperPrefixKeyword), - absoluteIndex: 17, lineIndex: 0, columnIndex: 17)); + absoluteIndex: 17, lineIndex: 0, columnIndex: 17, length: 4)); } [Fact] @@ -111,7 +111,7 @@ namespace Microsoft.AspNet.Razor.Test.Parser.CSharp new RazorError( RazorResources.FormatParseError_DirectiveMustBeSurroundedByQuotes( SyntaxConstants.CSharp.TagHelperPrefixKeyword), - absoluteIndex: 17, lineIndex: 0, columnIndex: 17)); + absoluteIndex: 17, lineIndex: 0, columnIndex: 17, length: 3)); } [Fact] @@ -153,7 +153,7 @@ namespace Microsoft.AspNet.Razor.Test.Parser.CSharp new RazorError( RazorResources.FormatParseError_DirectiveMustHaveValue( SyntaxConstants.CSharp.RemoveTagHelperKeyword), - absoluteIndex: 17, lineIndex: 0, columnIndex: 17)); + absoluteIndex: 1, lineIndex: 0, columnIndex: 1, length: 15)); } [Fact] @@ -172,7 +172,7 @@ namespace Microsoft.AspNet.Razor.Test.Parser.CSharp new RazorError( RazorResources.FormatParseError_DirectiveMustBeSurroundedByQuotes( SyntaxConstants.CSharp.RemoveTagHelperKeyword), - absoluteIndex: 17, lineIndex: 0, columnIndex: 17)); + absoluteIndex: 17, lineIndex: 0, columnIndex: 17, length: 4)); } [Fact] @@ -192,7 +192,7 @@ namespace Microsoft.AspNet.Razor.Test.Parser.CSharp new RazorError( RazorResources.FormatParseError_DirectiveMustBeSurroundedByQuotes( SyntaxConstants.CSharp.RemoveTagHelperKeyword), - absoluteIndex: 17, lineIndex: 0, columnIndex: 17)); + absoluteIndex: 17, lineIndex: 0, columnIndex: 17, length: 4)); } [Fact] @@ -209,7 +209,7 @@ namespace Microsoft.AspNet.Razor.Test.Parser.CSharp new RazorError( RazorResources.FormatParseError_DirectiveMustBeSurroundedByQuotes( SyntaxConstants.CSharp.RemoveTagHelperKeyword), - absoluteIndex: 17, lineIndex: 0, columnIndex: 17)); + absoluteIndex: 17, lineIndex: 0, columnIndex: 17, length: 3)); } [Fact] @@ -249,7 +249,7 @@ namespace Microsoft.AspNet.Razor.Test.Parser.CSharp .Accepts(AcceptedCharacters.AnyExceptNewline)), new RazorError( RazorResources.FormatParseError_DirectiveMustHaveValue(SyntaxConstants.CSharp.AddTagHelperKeyword), - absoluteIndex: 14, lineIndex: 0, columnIndex: 14)); + absoluteIndex: 1, lineIndex: 0, columnIndex: 1, length: 12)); } [Fact] @@ -268,7 +268,7 @@ namespace Microsoft.AspNet.Razor.Test.Parser.CSharp new RazorError( RazorResources.FormatParseError_DirectiveMustBeSurroundedByQuotes( SyntaxConstants.CSharp.AddTagHelperKeyword), - absoluteIndex: 14, lineIndex: 0, columnIndex: 14)); + absoluteIndex: 14, lineIndex: 0, columnIndex: 14, length: 4)); } [Fact] @@ -288,7 +288,7 @@ namespace Microsoft.AspNet.Razor.Test.Parser.CSharp new RazorError( RazorResources.FormatParseError_DirectiveMustBeSurroundedByQuotes( SyntaxConstants.CSharp.AddTagHelperKeyword), - absoluteIndex: 14, lineIndex: 0, columnIndex: 14)); + absoluteIndex: 14, lineIndex: 0, columnIndex: 14, length: 4)); } [Fact] @@ -305,7 +305,7 @@ namespace Microsoft.AspNet.Razor.Test.Parser.CSharp new RazorError( RazorResources.FormatParseError_DirectiveMustBeSurroundedByQuotes( SyntaxConstants.CSharp.AddTagHelperKeyword), - absoluteIndex: 14, lineIndex: 0, columnIndex: 14)); + absoluteIndex: 14, lineIndex: 0, columnIndex: 14, length: 3)); } [Fact] diff --git a/test/Microsoft.AspNet.Razor.Test/Parser/CSharp/CSharpErrorTest.cs b/test/Microsoft.AspNet.Razor.Test/Parser/CSharp/CSharpErrorTest.cs index 518a8a8314..5035994bc9 100644 --- a/test/Microsoft.AspNet.Razor.Test/Parser/CSharp/CSharpErrorTest.cs +++ b/test/Microsoft.AspNet.Razor.Test/Parser/CSharp/CSharpErrorTest.cs @@ -272,7 +272,7 @@ namespace Microsoft.AspNet.Razor.Test.Parser.CSharp .AutoCompleteWith("}")), new RazorError( RazorResources.FormatParseError_Expected_EndOfBlock_Before_EOF("functions", '}', '{'), - SourceLocation.Zero)); + new SourceLocation(10, 0, 10))); } [Fact] diff --git a/test/Microsoft.AspNet.Razor.Test/Parser/CSharp/CSharpSectionTest.cs b/test/Microsoft.AspNet.Razor.Test/Parser/CSharp/CSharpSectionTest.cs index 3adb784f5f..2c8f9754dc 100644 --- a/test/Microsoft.AspNet.Razor.Test/Parser/CSharp/CSharpSectionTest.cs +++ b/test/Microsoft.AspNet.Razor.Test/Parser/CSharp/CSharpSectionTest.cs @@ -141,8 +141,9 @@ namespace Microsoft.AspNet.Razor.Test.Parser.CSharp Factory.MetaCode("}").Accepts(AcceptedCharacters.None)), Factory.EmptyHtml()), new RazorError( - RazorResources.FormatParseError_Sections_Cannot_Be_Nested(RazorResources.SectionExample_CS), - 23, 0, 23)); + RazorResources.FormatParseError_Sections_Cannot_Be_Nested(RazorResources.SectionExample_CS), + new SourceLocation(16, 0, 16), + 7)); } [Fact] diff --git a/test/Microsoft.AspNet.Razor.Test/Parser/CSharp/CSharpSpecialBlockTest.cs b/test/Microsoft.AspNet.Razor.Test/Parser/CSharp/CSharpSpecialBlockTest.cs index 031c71c3b4..0ec64357ed 100644 --- a/test/Microsoft.AspNet.Razor.Test/Parser/CSharp/CSharpSpecialBlockTest.cs +++ b/test/Microsoft.AspNet.Razor.Test/Parser/CSharp/CSharpSpecialBlockTest.cs @@ -20,7 +20,7 @@ namespace Microsoft.AspNet.Razor.Test.Parser.CSharp ), new RazorError( RazorResources.ParseError_InheritsKeyword_Must_Be_Followed_By_TypeName, - new SourceLocation(8, 0, 8))); + new SourceLocation(0, 0, 0), 8)); } [Fact] @@ -44,7 +44,7 @@ namespace Microsoft.AspNet.Razor.Test.Parser.CSharp Factory.Code(" " + Environment.NewLine) .AsBaseType(string.Empty) ), - new RazorError(RazorResources.ParseError_InheritsKeyword_Must_Be_Followed_By_TypeName, 24, 0, 24)); + new RazorError(RazorResources.ParseError_InheritsKeyword_Must_Be_Followed_By_TypeName, 0, 0, 0, 8)); } [Fact] @@ -165,7 +165,7 @@ namespace Microsoft.AspNet.Razor.Test.Parser.CSharp ), new RazorError( RazorResources.FormatParseError_Expected_EndOfBlock_Before_EOF("functions", "}", "{"), - SourceLocation.Zero)); + new SourceLocation(10, 0, 10))); } [Fact]