protected virtual Func <bool> EndTerminatedDirective(string directive, BlockType blockType, SpanCodeGenerator codeGenerator, bool allowMarkup) { return(() => { SourceLocation blockStart = CurrentLocation; Context.CurrentBlock.Type = blockType; AssertDirective(directive); AcceptAndMoveNext(); Span.EditHandler.AcceptedCharacters = AcceptedCharacters.None; Span.CodeGenerator = SpanCodeGenerator.Null; Output(SpanKind.MetaCode); using (PushSpanConfig(StatementBlockSpanConfiguration(codeGenerator))) { AutoCompleteEditHandler editHandler = new AutoCompleteEditHandler(Language.TokenizeString); Span.EditHandler = editHandler; if (!EndTerminatedDirectiveBody(directive, blockStart, allowMarkup)) { editHandler.AutoCompleteString = String.Concat(SyntaxConstants.VB.EndKeyword, " ", directive); return false; } return true; } }); }
protected virtual void FunctionsDirective() { // Set the block type Context.CurrentBlock.Type = BlockType.Functions; // Verify we're on "functions" and accept AssertDirective(SyntaxConstants.CSharp.FunctionsKeyword); Block block = new Block(CurrentSymbol); AcceptAndMoveNext(); AcceptWhile(IsSpacingToken(includeNewLines: true, includeComments: false)); if (!At(CSharpSymbolType.LeftBrace)) { Context.OnError(CurrentLocation, RazorResources.ParseError_Expected_X, Language.GetSample(CSharpSymbolType.LeftBrace)); CompleteBlock(); Output(SpanKind.MetaCode); return; } else { Span.EditHandler.AcceptedCharacters = AcceptedCharacters.None; } // Capture start point and continue SourceLocation blockStart = CurrentLocation; AcceptAndMoveNext(); // Output what we've seen and continue Output(SpanKind.MetaCode); AutoCompleteEditHandler editHandler = new AutoCompleteEditHandler(Language.TokenizeString); Span.EditHandler = editHandler; Balance(BalancingModes.NoErrorOnFailure, CSharpSymbolType.LeftBrace, CSharpSymbolType.RightBrace, blockStart); Span.CodeGenerator = new TypeMemberCodeGenerator(); if (!At(CSharpSymbolType.RightBrace)) { editHandler.AutoCompleteString = "}"; Context.OnError(block.Start, RazorResources.ParseError_Expected_EndOfBlock_Before_EOF, block.Name, "}", "{"); CompleteBlock(); Output(SpanKind.Code); } else { Output(SpanKind.Code); Assert(CSharpSymbolType.RightBrace); Span.CodeGenerator = SpanCodeGenerator.Null; Span.EditHandler.AcceptedCharacters = AcceptedCharacters.None; AcceptAndMoveNext(); CompleteBlock(); Output(SpanKind.MetaCode); } }
public virtual string GetAutoCompleteString() { if (_lastAutoCompleteSpan != null) { AutoCompleteEditHandler editHandler = _lastAutoCompleteSpan.EditHandler as AutoCompleteEditHandler; if (editHandler != null) { return(editHandler.AutoCompleteString); } } return(null); }
private void ParseDirectiveBlock(RazorDirectiveDescriptor descriptor, Action <SourceLocation> parseChildren) { if (EndOfFile) { Context.OnError( CurrentLocation, $"Unexpected end of file following directive {descriptor.Name}. Expected '{{'", CurrentSymbol.Content.Length); } else if (!At(CSharpSymbolType.LeftBrace)) { Context.OnError( CurrentLocation, $"Unexpected literal '{CurrentSymbol.Content.Length}' following directive {descriptor.Name}. Expected '{{'", CurrentSymbol.Content.Length); } else { var editHandler = new AutoCompleteEditHandler(Language.TokenizeString, autoCompleteAtEndOfSpan: true); Span.EditHandler = editHandler; var startingBraceLocation = CurrentLocation; AcceptAndMoveNext(); Span.ChunkGenerator = SpanChunkGenerator.Null; Output(SpanKind.MetaCode, AcceptedCharacters.None); parseChildren(startingBraceLocation); Span.ChunkGenerator = SpanChunkGenerator.Null; if (!Optional(CSharpSymbolType.RightBrace)) { editHandler.AutoCompleteString = "}"; Context.OnError( startingBraceLocation, // TODO: This is RazorResources.FormatParseError_Expected_EndOfBlock_Before_EOF string.Format( "The {0} block is missing a closing \"{1}\" character. Make sure you have a matching \"{1}\" character for all the \"{2}\" characters within this block, and that none of the \"{1}\" characters are being interpreted as markup.", descriptor.Name, Language.GetSample(CSharpSymbolType.RightBrace), Language.GetSample(CSharpSymbolType.LeftBrace)), length: 1 /* } */); } else { Span.EditHandler.AcceptedCharacters = AcceptedCharacters.None; } CompleteBlock(insertMarkerIfNecessary: false, captureWhitespaceToEndOfLine: true); Span.ChunkGenerator = SpanChunkGenerator.Null; Output(SpanKind.MetaCode, AcceptedCharacters.None); } }
private void VerbatimBlock() { Assert(CSharpSymbolType.LeftBrace); var block = new Block(RazorResources.BlockName_Code, CurrentLocation); AcceptAndMoveNext(); // Set up the "{" span and output Span.EditHandler.AcceptedCharacters = AcceptedCharacters.None; Span.ChunkGenerator = SpanChunkGenerator.Null; Output(SpanKind.MetaCode); // Set up auto-complete and parse the code block var editHandler = new AutoCompleteEditHandler(Language.TokenizeString); Span.EditHandler = editHandler; CodeBlock(false, block); Span.ChunkGenerator = new StatementChunkGenerator(); AddMarkerSymbolIfNecessary(); if (!At(CSharpSymbolType.RightBrace)) { editHandler.AutoCompleteString = "}"; } Output(SpanKind.Code); if (Optional(CSharpSymbolType.RightBrace)) { // Set up the "}" span Span.EditHandler.AcceptedCharacters = AcceptedCharacters.None; Span.ChunkGenerator = SpanChunkGenerator.Null; } if (!IsNested) { EnsureCurrent(); if (At(CSharpSymbolType.NewLine) || (At(CSharpSymbolType.WhiteSpace) && NextIs(CSharpSymbolType.NewLine))) { Context.NullGenerateWhitespaceAndNewLine = true; } } Output(SpanKind.MetaCode); }
private void VerbatimBlock() { Assert(CSharpSymbolType.LeftBrace); Block block = new Block(RazorResources.BlockName_Code, CurrentLocation); AcceptAndMoveNext(); // Set up the "{" span and output Span.EditHandler.AcceptedCharacters = AcceptedCharacters.None; Span.CodeGenerator = SpanCodeGenerator.Null; Output(SpanKind.MetaCode); // Set up auto-complete and parse the code block AutoCompleteEditHandler editHandler = new AutoCompleteEditHandler( Language.TokenizeString ); Span.EditHandler = editHandler; CodeBlock(false, block); Span.CodeGenerator = new StatementCodeGenerator(); AddMarkerSymbolIfNecessary(); if (!At(CSharpSymbolType.RightBrace)) { editHandler.AutoCompleteString = "}"; } Output(SpanKind.Code); if (Optional(CSharpSymbolType.RightBrace)) { // Set up the "}" span Span.EditHandler.AcceptedCharacters = AcceptedCharacters.None; Span.CodeGenerator = SpanCodeGenerator.Null; } if (!At(CSharpSymbolType.WhiteSpace) && !At(CSharpSymbolType.NewLine)) { PutCurrentBack(); } CompleteBlock(insertMarkerIfNecessary: false); Output(SpanKind.MetaCode); }
protected virtual void SectionDirective() { bool nested = Context.IsWithin(BlockType.Section); bool errorReported = false; // Set the block and span type Context.CurrentBlock.Type = BlockType.Section; // Verify we're on "section" and accept AssertDirective(SyntaxConstants.CSharp.SectionKeyword); AcceptAndMoveNext(); if (nested) { Context.OnError(CurrentLocation, String.Format(CultureInfo.CurrentCulture, RazorResources.ParseError_Sections_Cannot_Be_Nested, RazorResources.SectionExample_CS)); errorReported = true; } IEnumerable <CSharpSymbol> ws = ReadWhile(IsSpacingToken(includeNewLines: true, includeComments: false)); // Get the section name string sectionName = String.Empty; if (!Required(CSharpSymbolType.Identifier, errorIfNotFound: true, errorBase: RazorResources.ParseError_Unexpected_Character_At_Section_Name_Start)) { if (!errorReported) { errorReported = true; } PutCurrentBack(); PutBack(ws); AcceptWhile(IsSpacingToken(includeNewLines: false, includeComments: false)); } else { Accept(ws); sectionName = CurrentSymbol.Content; AcceptAndMoveNext(); } Context.CurrentBlock.CodeGenerator = new SectionCodeGenerator(sectionName); SourceLocation errorLocation = CurrentLocation; ws = ReadWhile(IsSpacingToken(includeNewLines: true, includeComments: false)); // Get the starting brace bool sawStartingBrace = At(CSharpSymbolType.LeftBrace); if (!sawStartingBrace) { if (!errorReported) { errorReported = true; Context.OnError(errorLocation, RazorResources.ParseError_MissingOpenBraceAfterSection); } PutCurrentBack(); PutBack(ws); AcceptWhile(IsSpacingToken(includeNewLines: false, includeComments: false)); Optional(CSharpSymbolType.NewLine); Output(SpanKind.MetaCode); CompleteBlock(); return; } else { Accept(ws); } // Set up edit handler AutoCompleteEditHandler editHandler = new AutoCompleteEditHandler(Language.TokenizeString) { AutoCompleteAtEndOfSpan = true }; Span.EditHandler = editHandler; Span.Accept(CurrentSymbol); // Output Metacode then switch to section parser Output(SpanKind.MetaCode); SectionBlock("{", "}", caseSensitive: true); Span.CodeGenerator = SpanCodeGenerator.Null; // Check for the terminating "}" if (!Optional(CSharpSymbolType.RightBrace)) { editHandler.AutoCompleteString = "}"; Context.OnError(CurrentLocation, RazorResources.ParseError_Expected_X, Language.GetSample(CSharpSymbolType.RightBrace)); } else { Span.EditHandler.AcceptedCharacters = AcceptedCharacters.None; } CompleteBlock(insertMarkerIfNecessary: false, captureWhitespaceToEndOfLine: true); Output(SpanKind.MetaCode); return; }
protected virtual void HelperDirective() { bool nested = Context.IsWithin(BlockType.Helper); // Set the block and span type Context.CurrentBlock.Type = BlockType.Helper; // Verify we're on "helper" and accept AssertDirective(SyntaxConstants.CSharp.HelperKeyword); Block block = new Block(CurrentSymbol.Content.ToString().ToLowerInvariant(), CurrentLocation); AcceptAndMoveNext(); if (nested) { Context.OnError(CurrentLocation, RazorResources.ParseError_Helpers_Cannot_Be_Nested); } // Accept a single whitespace character if present, if not, we should stop now if (!At(CSharpSymbolType.WhiteSpace)) { string error; if (At(CSharpSymbolType.NewLine)) { error = RazorResources.ErrorComponent_Newline; } else if (EndOfFile) { error = RazorResources.ErrorComponent_EndOfFile; } else { error = String.Format(CultureInfo.CurrentCulture, RazorResources.ErrorComponent_Character, CurrentSymbol.Content); } Context.OnError( CurrentLocation, RazorResources.ParseError_Unexpected_Character_At_Helper_Name_Start, error); PutCurrentBack(); Output(SpanKind.MetaCode); return; } CSharpSymbol remainingWs = AcceptSingleWhiteSpaceCharacter(); // Output metacode and continue Output(SpanKind.MetaCode); if (remainingWs != null) { Accept(remainingWs); } AcceptWhile(IsSpacingToken(includeNewLines: false, includeComments: true)); // Don't accept newlines. // Expecting an identifier (helper name) bool errorReported = !Required(CSharpSymbolType.Identifier, errorIfNotFound: true, errorBase: RazorResources.ParseError_Unexpected_Character_At_Helper_Name_Start); if (!errorReported) { Assert(CSharpSymbolType.Identifier); AcceptAndMoveNext(); } AcceptWhile(IsSpacingToken(includeNewLines: false, includeComments: true)); // Expecting parameter list start: "(" SourceLocation bracketErrorPos = CurrentLocation; if (!Optional(CSharpSymbolType.LeftParenthesis)) { if (!errorReported) { errorReported = true; Context.OnError( CurrentLocation, RazorResources.ParseError_MissingCharAfterHelperName, "("); } } else { SourceLocation bracketStart = CurrentLocation; if (!Balance(BalancingModes.NoErrorOnFailure, CSharpSymbolType.LeftParenthesis, CSharpSymbolType.RightParenthesis, bracketStart)) { errorReported = true; Context.OnError( bracketErrorPos, RazorResources.ParseError_UnterminatedHelperParameterList); } Optional(CSharpSymbolType.RightParenthesis); } int bookmark = CurrentLocation.AbsoluteIndex; IEnumerable <CSharpSymbol> ws = ReadWhile(IsSpacingToken(includeNewLines: true, includeComments: true)); // Expecting a "{" SourceLocation errorLocation = CurrentLocation; bool headerComplete = At(CSharpSymbolType.LeftBrace); if (headerComplete) { Accept(ws); AcceptAndMoveNext(); } else { Context.Source.Position = bookmark; NextToken(); AcceptWhile(IsSpacingToken(includeNewLines: false, includeComments: true)); if (!errorReported) { Context.OnError( errorLocation, RazorResources.ParseError_MissingCharAfterHelperParameters, Language.GetSample(CSharpSymbolType.LeftBrace)); } } // Grab the signature and build the code generator AddMarkerSymbolIfNecessary(); LocationTagged <string> signature = Span.GetContent(); HelperCodeGenerator blockGen = new HelperCodeGenerator(signature, headerComplete); Context.CurrentBlock.CodeGenerator = blockGen; // The block will generate appropriate code, Span.CodeGenerator = SpanCodeGenerator.Null; if (!headerComplete) { CompleteBlock(); Output(SpanKind.Code); return; } else { Span.EditHandler.AcceptedCharacters = AcceptedCharacters.None; Output(SpanKind.Code); } // We're valid, so parse the nested block AutoCompleteEditHandler bodyEditHandler = new AutoCompleteEditHandler(Language.TokenizeString); using (PushSpanConfig(DefaultSpanConfig)) { using (Context.StartBlock(BlockType.Statement)) { Span.EditHandler = bodyEditHandler; CodeBlock(false, block); CompleteBlock(insertMarkerIfNecessary: true); Output(SpanKind.Code); } } Initialize(Span); EnsureCurrent(); Span.CodeGenerator = SpanCodeGenerator.Null; // The block will generate the footer code. if (!Optional(CSharpSymbolType.RightBrace)) { // The } is missing, so set the initial signature span to use it as an autocomplete string bodyEditHandler.AutoCompleteString = "}"; // Need to be able to accept anything to properly handle the autocomplete bodyEditHandler.AcceptedCharacters = AcceptedCharacters.Any; } else { blockGen.Footer = Span.GetContent(); Span.EditHandler.AcceptedCharacters = AcceptedCharacters.None; } CompleteBlock(); Output(SpanKind.Code); }
protected virtual bool HelperDirective() { if (Context.IsWithin(BlockType.Helper)) { Context.OnError(CurrentLocation, RazorResources.ParseError_Helpers_Cannot_Be_Nested); } Context.CurrentBlock.Type = BlockType.Helper; SourceLocation blockStart = CurrentLocation; AssertDirective(SyntaxConstants.VB.HelperKeyword); AcceptAndMoveNext(); VBSymbolType firstAfterKeyword = VBSymbolType.Unknown; if (CurrentSymbol != null) { firstAfterKeyword = CurrentSymbol.Type; } VBSymbol remainingWs = null; if (At(VBSymbolType.NewLine)) { // Accept a _single_ new line, we'll be aborting later. AcceptAndMoveNext(); } else { remainingWs = AcceptSingleWhiteSpaceCharacter(); } if (firstAfterKeyword == VBSymbolType.WhiteSpace || firstAfterKeyword == VBSymbolType.NewLine) { Span.EditHandler.AcceptedCharacters = AcceptedCharacters.None; } Output(SpanKind.MetaCode); if (firstAfterKeyword != VBSymbolType.WhiteSpace) { string error; if (At(VBSymbolType.NewLine)) { error = RazorResources.ErrorComponent_Newline; } else if (EndOfFile) { error = RazorResources.ErrorComponent_EndOfFile; } else { error = String.Format(CultureInfo.CurrentCulture, RazorResources.ErrorComponent_Character, CurrentSymbol.Content); } Context.OnError( CurrentLocation, RazorResources.ParseError_Unexpected_Character_At_Helper_Name_Start, error); // Bail out. PutCurrentBack(); Output(SpanKind.Code); return(false); } if (remainingWs != null) { Accept(remainingWs); } bool errorReported = !Required(VBSymbolType.Identifier, RazorResources.ParseError_Unexpected_Character_At_Helper_Name_Start); AcceptWhile(VBSymbolType.WhiteSpace); SourceLocation parensStart = CurrentLocation; bool headerComplete = false; if (!Optional(VBSymbolType.LeftParenthesis)) { if (!errorReported) { errorReported = true; Context.OnError(CurrentLocation, RazorResources.ParseError_MissingCharAfterHelperName, VBSymbol.GetSample(VBSymbolType.LeftParenthesis)); } } else if (!Balance(BalancingModes.NoErrorOnFailure, VBSymbolType.LeftParenthesis, VBSymbolType.RightParenthesis, parensStart)) { Context.OnError(parensStart, RazorResources.ParseError_UnterminatedHelperParameterList); } else { Expected(VBSymbolType.RightParenthesis); headerComplete = true; } AddMarkerSymbolIfNecessary(); Context.CurrentBlock.CodeGenerator = new HelperCodeGenerator( Span.GetContent(), headerComplete); AutoCompleteEditHandler editHandler = new AutoCompleteEditHandler(Language.TokenizeString); Span.EditHandler = editHandler; Output(SpanKind.Code); if (headerComplete) { bool old = IsNested; IsNested = true; using (Context.StartBlock(BlockType.Statement)) { using (PushSpanConfig(StatementBlockSpanConfiguration(new StatementCodeGenerator()))) { try { if (!EndTerminatedDirectiveBody(SyntaxConstants.VB.HelperKeyword, blockStart, allowAllTransitions: true)) { if (Context.LastAcceptedCharacters != AcceptedCharacters.Any) { AddMarkerSymbolIfNecessary(); } editHandler.AutoCompleteString = SyntaxConstants.VB.EndHelperKeyword; return(false); } else { return(true); } } finally { Output(SpanKind.Code); IsNested = old; } } } } else { Output(SpanKind.Code); } PutCurrentBack(); return(false); }
protected virtual bool SectionDirective() { SourceLocation start = CurrentLocation; AssertDirective(SyntaxConstants.VB.SectionKeyword); AcceptAndMoveNext(); if (Context.IsWithin(BlockType.Section)) { Context.OnError(CurrentLocation, RazorResources.ParseError_Sections_Cannot_Be_Nested, RazorResources.SectionExample_VB); } if (At(VBSymbolType.NewLine)) { AcceptAndMoveNext(); } else { AcceptVBSpaces(); } string sectionName = null; if (!At(VBSymbolType.Identifier)) { Context.OnError(CurrentLocation, RazorResources.ParseError_Unexpected_Character_At_Section_Name_Start, GetCurrentSymbolDisplay()); } else { sectionName = CurrentSymbol.Content; AcceptAndMoveNext(); } Context.CurrentBlock.Type = BlockType.Section; Context.CurrentBlock.CodeGenerator = new SectionCodeGenerator(sectionName ?? String.Empty); AutoCompleteEditHandler editHandler = new AutoCompleteEditHandler(Language.TokenizeString); Span.EditHandler = editHandler; PutCurrentBack(); Output(SpanKind.MetaCode); // Parse the section OtherParserBlock(null, SyntaxConstants.VB.EndSectionKeyword); Span.CodeGenerator = SpanCodeGenerator.Null; bool complete = false; if (!At(VBKeyword.End)) { Context.OnError(start, RazorResources.ParseError_BlockNotTerminated, SyntaxConstants.VB.SectionKeyword, SyntaxConstants.VB.EndSectionKeyword); editHandler.AutoCompleteString = SyntaxConstants.VB.EndSectionKeyword; } else { AcceptAndMoveNext(); AcceptWhile(VBSymbolType.WhiteSpace); if (!At(SyntaxConstants.VB.SectionKeyword)) { Context.OnError(start, RazorResources.ParseError_BlockNotTerminated, SyntaxConstants.VB.SectionKeyword, SyntaxConstants.VB.EndSectionKeyword); } else { AcceptAndMoveNext(); Span.EditHandler.AcceptedCharacters = AcceptedCharacters.None; complete = true; } } PutCurrentBack(); Output(SpanKind.MetaCode); return(complete); }
public void GetHashCode_ReturnsSameValue_WhenEqual( AutoCompleteEditHandler leftObject, AutoCompleteEditHandler rightObject) { // Arrange & Act var leftResult = leftObject.GetHashCode(); var rightResult = rightObject.GetHashCode(); // Assert Assert.Equal(leftResult, rightResult); }
public void Equals_False_WhenExpected(AutoCompleteEditHandler leftObject, object rightObject) { // Arrange & Act var result = leftObject.Equals(rightObject); // Assert Assert.False(result); }
protected virtual void FunctionsDirective() { // Set the block type Context.CurrentBlock.Type = BlockType.Functions; // Verify we're on "functions" and accept AssertDirective(SyntaxConstants.CSharp.FunctionsKeyword); var block = new Block(CurrentSymbol); AcceptAndMoveNext(); AcceptWhile(IsSpacingToken(includeNewLines: true, includeComments: false)); if (!At(CSharpSymbolType.LeftBrace)) { Context.OnError( CurrentLocation, RazorResources.FormatParseError_Expected_X(Language.GetSample(CSharpSymbolType.LeftBrace)), length: 1 /* { */); CompleteBlock(); Output(SpanKind.MetaCode); return; } else { Span.EditHandler.AcceptedCharacters = AcceptedCharacters.None; } // Capture start point and continue var blockStart = CurrentLocation; AcceptAndMoveNext(); // Output what we've seen and continue Output(SpanKind.MetaCode); var editHandler = new AutoCompleteEditHandler(Language.TokenizeString); Span.EditHandler = editHandler; Balance(BalancingModes.NoErrorOnFailure, CSharpSymbolType.LeftBrace, CSharpSymbolType.RightBrace, blockStart); Span.ChunkGenerator = new TypeMemberChunkGenerator(); if (!At(CSharpSymbolType.RightBrace)) { editHandler.AutoCompleteString = "}"; Context.OnError( blockStart, RazorResources.FormatParseError_Expected_EndOfBlock_Before_EOF(block.Name, "}", "{"), length: 1 /* } */); CompleteBlock(); Output(SpanKind.Code); } else { Output(SpanKind.Code); Assert(CSharpSymbolType.RightBrace); Span.ChunkGenerator = SpanChunkGenerator.Null; Span.EditHandler.AcceptedCharacters = AcceptedCharacters.None; AcceptAndMoveNext(); CompleteBlock(); Output(SpanKind.MetaCode); } }
protected virtual void SectionDirective() { var nested = Context.IsWithin(BlockType.Section); var errorReported = false; // Set the block and span type Context.CurrentBlock.Type = BlockType.Section; // Verify we're on "section" and accept AssertDirective(SyntaxConstants.CSharp.SectionKeyword); var startLocation = CurrentLocation; AcceptAndMoveNext(); if (nested) { Context.OnError( startLocation, RazorResources.FormatParseError_Sections_Cannot_Be_Nested(RazorResources.SectionExample_CS), Span.GetContent().Value.Length); errorReported = true; } var whitespace = ReadWhile(IsSpacingToken(includeNewLines: true, includeComments: false)); // Get the section name var sectionName = string.Empty; if (!Required(CSharpSymbolType.Identifier, errorIfNotFound: true, errorBase: RazorResources.FormatParseError_Unexpected_Character_At_Section_Name_Start)) { if (!errorReported) { errorReported = true; } PutCurrentBack(); PutBack(whitespace); AcceptWhile(IsSpacingToken(includeNewLines: false, includeComments: false)); } else { Accept(whitespace); sectionName = CurrentSymbol.Content; AcceptAndMoveNext(); } Context.CurrentBlock.ChunkGenerator = new SectionChunkGenerator(sectionName); var errorLocation = CurrentLocation; whitespace = ReadWhile(IsSpacingToken(includeNewLines: true, includeComments: false)); // Get the starting brace var sawStartingBrace = At(CSharpSymbolType.LeftBrace); if (!sawStartingBrace) { if (!errorReported) { errorReported = true; Context.OnError( errorLocation, RazorResources.ParseError_MissingOpenBraceAfterSection, length: 1 /* { */); } PutCurrentBack(); PutBack(whitespace); AcceptWhile(IsSpacingToken(includeNewLines: false, includeComments: false)); Optional(CSharpSymbolType.NewLine); Output(SpanKind.MetaCode); CompleteBlock(); return; } else { Accept(whitespace); } var startingBraceLocation = CurrentLocation; // Set up edit handler var editHandler = new AutoCompleteEditHandler(Language.TokenizeString, autoCompleteAtEndOfSpan: true); Span.EditHandler = editHandler; Span.Accept(CurrentSymbol); // Output Metacode then switch to section parser Output(SpanKind.MetaCode); SectionBlock("{", "}", caseSensitive: true); Span.ChunkGenerator = SpanChunkGenerator.Null; // Check for the terminating "}" if (!Optional(CSharpSymbolType.RightBrace)) { editHandler.AutoCompleteString = "}"; Context.OnError( startingBraceLocation, RazorResources.FormatParseError_Expected_EndOfBlock_Before_EOF( SyntaxConstants.CSharp.SectionKeyword, Language.GetSample(CSharpSymbolType.RightBrace), Language.GetSample(CSharpSymbolType.LeftBrace)), length: 1 /* } */); } else { Span.EditHandler.AcceptedCharacters = AcceptedCharacters.None; } CompleteBlock(insertMarkerIfNecessary: false, captureWhitespaceToEndOfLine: true); Output(SpanKind.MetaCode); return; }