提交 20b75912 编写于 作者: A AlekseyTs 提交者: GitHub

Ensure proper handling of a line-break following an incomplete string interpolation. (#18619)

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.
上级 3dff8b3c
......@@ -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 ".
If Not IsValidStatementTerminator(CurrentToken) Then
ResetCurrentToken(ScannerState.InterpolatedStringFormatString)
Dim skippedToken As SyntaxToken = Nothing
If CurrentToken.Kind = SyntaxKind.InterpolatedStringText Then
skippedToken = CurrentToken
GetNextToken(ScannerState.InterpolatedStringPunctuation)
End If
If CurrentToken.Kind = SyntaxKind.CloseBraceToken Then
closeBraceToken = DirectCast(CurrentToken, PunctuationSyntax)
GetNextToken(ScannerState.InterpolatedStringContent)
Else
Debug.Assert(CurrentToken.Kind <> SyntaxKind.CloseBraceToken)
closeBraceToken = DirectCast(HandleUnexpectedToken(SyntaxKind.CloseBraceToken), PunctuationSyntax)
End If
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)
......
......@@ -772,6 +772,31 @@ End Module
Assert.Equal(False, incrementalTree.GetRoot().ContainsDiagnostics)
VerifyEquivalent(incrementalTree, expectedTree)
End Sub
<Fact>
<WorkItem(405887, "https://devdiv.visualstudio.com/DevDiv/_workitems?id=405887")>
Public Sub IncrementalParseInterpolationInSingleLineIf()
Dim code As String = (<![CDATA[
Module Module1
Sub Test1(val1 As Integer)
If val1 = 1 Then System.Console.WriteLine($"abc '" & sServiceName & "'")
End Sub
End Module
]]>).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
<WorkItem(543489, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543489")>
......
......@@ -9122,4 +9122,158 @@ BC42105: Function 'Test2' doesn't return a value on all code paths. A null refer
~~~~~~~~~~~~
</expected>)
End Sub
<Fact>
<WorkItem(405887, "https://devdiv.visualstudio.com/DevDiv/_workitems?id=405887")>
Public Sub ParseLineIfWithIncompleteInterpolatedString_01()
Dim compilationDef =
<compilation>
<file name="a.vb"><![CDATA[
Module Module1
Sub Test1(val1 As Integer)
If val1 = 1 Then System.Console.WriteLine($"abc '{ sServiceName & "'")
End Sub
End Module
]]></file>
</compilation>
Dim compilation = CreateCompilationWithMscorlibAndVBRuntime(compilationDef, TestOptions.ReleaseDll)
CompilationUtils.AssertTheseDiagnostics(compilation,
<expected><![CDATA[
BC30625: 'Module' statement must end with a matching 'End Module'.
Module Module1
~~~~~~~~~~~~~~
BC30026: 'End Sub' expected.
Sub Test1(val1 As Integer)
~~~~~~~~~~~~~~~~~~~~~~~~~~
BC30451: 'sServiceName' is not declared. It may be inaccessible due to its protection level.
If val1 = 1 Then System.Console.WriteLine($"abc '{ sServiceName & "'")
~~~~~~~~~~~~
BC30370: '}' expected.
If val1 = 1 Then System.Console.WriteLine($"abc '{ sServiceName & "'")
~
BC30198: ')' expected.
End Module
~
]]></expected>)
End Sub
<Fact>
<WorkItem(405887, "https://devdiv.visualstudio.com/DevDiv/_workitems?id=405887")>
Public Sub ParseLineIfWithIncompleteInterpolatedString_02()
Dim compilationDef =
<compilation>
<file name="a.vb"><![CDATA[
Module Module1
Sub Test1(val1 As Integer)
If val1 = 1 Then System.Console.WriteLine($"abc '{ sServiceName & "'"})
End Sub
End Module
]]></file>
</compilation>
Dim compilation = CreateCompilationWithMscorlibAndVBRuntime(compilationDef, TestOptions.ReleaseDll)
CompilationUtils.AssertTheseDiagnostics(compilation,
<expected><![CDATA[
BC30625: 'Module' statement must end with a matching 'End Module'.
Module Module1
~~~~~~~~~~~~~~
BC30026: 'End Sub' expected.
Sub Test1(val1 As Integer)
~~~~~~~~~~~~~~~~~~~~~~~~~~
BC30451: 'sServiceName' is not declared. It may be inaccessible due to its protection level.
If val1 = 1 Then System.Console.WriteLine($"abc '{ sServiceName & "'"})
~~~~~~~~~~~~
BC30198: ')' expected.
End Module
~
]]></expected>)
End Sub
<Fact>
<WorkItem(405887, "https://devdiv.visualstudio.com/DevDiv/_workitems?id=405887")>
Public Sub ParseLineIfWithIncompleteInterpolatedString_03()
Dim compilationDef =
<compilation>
<file name="a.vb"><![CDATA[
Module Module1
Sub Test1(val1 As Integer)
If val1 = 1 Then System.Console.WriteLine($"abc '{ sServiceName & "'"}")
End Sub
End Module
]]></file>
</compilation>
Dim compilation = CreateCompilationWithMscorlibAndVBRuntime(compilationDef, TestOptions.ReleaseDll)
CompilationUtils.AssertTheseDiagnostics(compilation,
<expected><![CDATA[
BC30451: 'sServiceName' is not declared. It may be inaccessible due to its protection level.
If val1 = 1 Then System.Console.WriteLine($"abc '{ sServiceName & "'"}")
~~~~~~~~~~~~
]]></expected>)
End Sub
<Fact>
<WorkItem(405887, "https://devdiv.visualstudio.com/DevDiv/_workitems?id=405887")>
Public Sub ParseLineIfWithIncompleteInterpolatedString_04()
Dim compilationDef =
<compilation>
<file name="a.vb"><![CDATA[
Module Module1
Sub Test1(val1 As Integer)
If val1 = 1 Then System.Console.WriteLine($"abc '{ sServiceName & "'" ")
End Sub
End Module
]]></file>
</compilation>
Dim compilation = CreateCompilationWithMscorlibAndVBRuntime(compilationDef, TestOptions.ReleaseDll)
CompilationUtils.AssertTheseDiagnostics(compilation,
<expected><![CDATA[
BC30451: 'sServiceName' is not declared. It may be inaccessible due to its protection level.
If val1 = 1 Then System.Console.WriteLine($"abc '{ sServiceName & "'" ")
~~~~~~~~~~~~
BC30370: '}' expected.
If val1 = 1 Then System.Console.WriteLine($"abc '{ sServiceName & "'" ")
~
]]></expected>)
End Sub
<Fact>
<WorkItem(405887, "https://devdiv.visualstudio.com/DevDiv/_workitems?id=405887")>
Public Sub ParseLineIfWithIncompleteInterpolatedString_05()
Dim compilationDef =
<compilation>
<file name="a.vb"><![CDATA[
Module Module1
Sub Test1(val1 As Integer)
If val1 = 1 Then System.Console.WriteLine($"abc '{ sServiceName & "'"")
End Sub
End Module
]]></file>
</compilation>
Dim compilation = CreateCompilationWithMscorlibAndVBRuntime(compilationDef, TestOptions.ReleaseDll)
CompilationUtils.AssertTheseDiagnostics(compilation,
<expected><![CDATA[
BC30625: 'Module' statement must end with a matching 'End Module'.
Module Module1
~~~~~~~~~~~~~~
BC30026: 'End Sub' expected.
Sub Test1(val1 As Integer)
~~~~~~~~~~~~~~~~~~~~~~~~~~
BC30451: 'sServiceName' is not declared. It may be inaccessible due to its protection level.
If val1 = 1 Then System.Console.WriteLine($"abc '{ sServiceName & "'"")
~~~~~~~~~~~~
BC30648: String constants must end with a double quote.
If val1 = 1 Then System.Console.WriteLine($"abc '{ sServiceName & "'"")
~~~~~~
BC30198: ')' expected.
End Module
~
BC30370: '}' expected.
End Module
~
]]></expected>)
End Sub
End Class
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册