From 20b75912b87ef3531a0b37c61e94e2fbf91f1321 Mon Sep 17 00:00:00 2001 From: AlekseyTs Date: Fri, 14 Apr 2017 13:20:08 -0700 Subject: [PATCH] Ensure proper handling of a line-break following an incomplete string interpolation. (#18619) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ensure proper handling of a line-break following an incomplete string interpolation. Fixes https://devdiv.visualstudio.com/DevDiv/_workitems?id=405887. The error recovery wasn’t including the line-break into interpolated string, yet wasn’t creating proper statement terminator token for it. The change ensures that the line-break is treated as part of the string for the purpose of the error recovery, this is what would happen if the interpolation was properly terminated with ‘}’ before the end of the line. --- .../Parser/ParseInterpolatedString.vb | 25 +-- .../IncrementalParser/IncrementalParser.vb | 25 +++ .../Test/Syntax/Parser/ParseStatements.vb | 154 ++++++++++++++++++ 3 files changed, 187 insertions(+), 17 deletions(-) diff --git a/src/Compilers/VisualBasic/Portable/Parser/ParseInterpolatedString.vb b/src/Compilers/VisualBasic/Portable/Parser/ParseInterpolatedString.vb index bc5f44e0342..d5a62c7f8d1 100644 --- a/src/Compilers/VisualBasic/Portable/Parser/ParseInterpolatedString.vb +++ b/src/Compilers/VisualBasic/Portable/Parser/ParseInterpolatedString.vb @@ -235,32 +235,23 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Syntax.InternalSyntax closeBraceToken = DirectCast(CurrentToken, PunctuationSyntax) GetNextToken(ScannerState.InterpolatedStringContent) - ElseIf CurrentToken.Kind = SyntaxKind.EndOfInterpolatedStringToken + ElseIf CurrentToken.Kind = SyntaxKind.EndOfInterpolatedStringToken Then GetNextToken(ScannerState.VB) closeBraceToken = DirectCast(HandleUnexpectedToken(SyntaxKind.CloseBraceToken), PunctuationSyntax) Else ' Content rules will either resync at a } or at the closing ". - ResetCurrentToken(ScannerState.InterpolatedStringFormatString) - - Dim skippedToken As SyntaxToken = Nothing - - If CurrentToken.Kind = SyntaxKind.InterpolatedStringText Then - skippedToken = CurrentToken - GetNextToken(ScannerState.InterpolatedStringPunctuation) + If Not IsValidStatementTerminator(CurrentToken) Then + ResetCurrentToken(ScannerState.InterpolatedStringFormatString) End If - If CurrentToken.Kind = SyntaxKind.CloseBraceToken Then - closeBraceToken = DirectCast(CurrentToken, PunctuationSyntax) - GetNextToken(ScannerState.InterpolatedStringContent) - Else - closeBraceToken = DirectCast(HandleUnexpectedToken(SyntaxKind.CloseBraceToken), PunctuationSyntax) - End If + Debug.Assert(CurrentToken.Kind <> SyntaxKind.CloseBraceToken) + closeBraceToken = DirectCast(HandleUnexpectedToken(SyntaxKind.CloseBraceToken), PunctuationSyntax) - If skippedToken IsNot Nothing Then - closeBraceToken = AddLeadingSyntax(closeBraceToken, skippedToken, ERRID.ERR_Syntax) + If CurrentToken.Kind = SyntaxKind.InterpolatedStringTextToken Then + ResetCurrentToken(ScannerState.InterpolatedStringContent) + GetNextToken(ScannerState.InterpolatedStringContent) End If - End If Return SyntaxFactory.Interpolation(openBraceToken, expression, alignmentClauseOpt, formatStringClauseOpt, closeBraceToken) diff --git a/src/Compilers/VisualBasic/Test/Syntax/IncrementalParser/IncrementalParser.vb b/src/Compilers/VisualBasic/Test/Syntax/IncrementalParser/IncrementalParser.vb index b9fd3f3c7a0..0894d57539b 100644 --- a/src/Compilers/VisualBasic/Test/Syntax/IncrementalParser/IncrementalParser.vb +++ b/src/Compilers/VisualBasic/Test/Syntax/IncrementalParser/IncrementalParser.vb @@ -772,6 +772,31 @@ End Module Assert.Equal(False, incrementalTree.GetRoot().ContainsDiagnostics) VerifyEquivalent(incrementalTree, expectedTree) End Sub + + + + Public Sub IncrementalParseInterpolationInSingleLineIf() + Dim code As String = ().Value + + Dim oldText = SourceText.From(code) + Dim oldTree = VisualBasicSyntaxTree.ParseText(oldText) + + Const replace = """ &" + Dim insertionPoint = code.IndexOf(replace, StringComparison.Ordinal) + Dim newText = oldText.WithChanges(New TextChange(New TextSpan(insertionPoint, replace.Length), "{")) + Dim expectedTree = VisualBasicSyntaxTree.ParseText(newText) + Dim incrementalTree = oldTree.WithChangedText(newText) + + Assert.Equal(True, expectedTree.GetRoot().ContainsDiagnostics) + Assert.Equal(True, incrementalTree.GetRoot().ContainsDiagnostics) + VerifyEquivalent(incrementalTree, expectedTree) + End Sub #End Region diff --git a/src/Compilers/VisualBasic/Test/Syntax/Parser/ParseStatements.vb b/src/Compilers/VisualBasic/Test/Syntax/Parser/ParseStatements.vb index 608413dc31d..9d11e7a69c1 100644 --- a/src/Compilers/VisualBasic/Test/Syntax/Parser/ParseStatements.vb +++ b/src/Compilers/VisualBasic/Test/Syntax/Parser/ParseStatements.vb @@ -9122,4 +9122,158 @@ BC42105: Function 'Test2' doesn't return a value on all code paths. A null refer ~~~~~~~~~~~~ ) End Sub + + + + Public Sub ParseLineIfWithIncompleteInterpolatedString_01() + Dim compilationDef = + + + + + Dim compilation = CreateCompilationWithMscorlibAndVBRuntime(compilationDef, TestOptions.ReleaseDll) + CompilationUtils.AssertTheseDiagnostics(compilation, +) + End Sub + + + + Public Sub ParseLineIfWithIncompleteInterpolatedString_02() + Dim compilationDef = + + + + + Dim compilation = CreateCompilationWithMscorlibAndVBRuntime(compilationDef, TestOptions.ReleaseDll) + CompilationUtils.AssertTheseDiagnostics(compilation, +) + End Sub + + + + Public Sub ParseLineIfWithIncompleteInterpolatedString_03() + Dim compilationDef = + + + + + Dim compilation = CreateCompilationWithMscorlibAndVBRuntime(compilationDef, TestOptions.ReleaseDll) + CompilationUtils.AssertTheseDiagnostics(compilation, +) + End Sub + + + + Public Sub ParseLineIfWithIncompleteInterpolatedString_04() + Dim compilationDef = + + + + + Dim compilation = CreateCompilationWithMscorlibAndVBRuntime(compilationDef, TestOptions.ReleaseDll) + CompilationUtils.AssertTheseDiagnostics(compilation, +) + End Sub + + + + Public Sub ParseLineIfWithIncompleteInterpolatedString_05() + Dim compilationDef = + + + + + Dim compilation = CreateCompilationWithMscorlibAndVBRuntime(compilationDef, TestOptions.ReleaseDll) + CompilationUtils.AssertTheseDiagnostics(compilation, +) + End Sub End Class -- GitLab