' Licensed to the .NET Foundation under one or more agreements. ' The .NET Foundation licenses this file to you under the MIT license. ' See the LICENSE file in the project root for more information. Imports System.Globalization Imports System.Text Imports Microsoft.CodeAnalysis.Simplification Imports Microsoft.CodeAnalysis.VisualBasic.Syntax Namespace Microsoft.CodeAnalysis.VisualBasic.CodeGeneration Partial Friend Module ExpressionGenerator Private Structure StringPiece Public ReadOnly Value As String Public ReadOnly Kind As StringPieceKind Public Sub New(value As String, kind As StringPieceKind) Me.Value = value Me.Kind = kind End Sub Private Shared Function IsPrintable(c As Char) As Boolean Dim category = CharUnicodeInfo.GetUnicodeCategory(c) Return IsPrintable(category) AndAlso Not IsQuoteCharacter(c) End Function Private Shared Function IsPrintable(c As UnicodeCategory) As Boolean Return c <> UnicodeCategory.OtherNotAssigned AndAlso c <> UnicodeCategory.ParagraphSeparator AndAlso c <> UnicodeCategory.Control AndAlso c <> UnicodeCategory.Surrogate End Function Private Shared Function IsQuoteCharacter(c As Char) As Boolean Const DWCH_LSMART_DQ As Char = ChrW(&H201CS) '// DW left single Const DWCH_RSMART_DQ As Char = ChrW(&H201DS) '// DW right single smart quote Const DWCH_DQ As Char = ChrW(AscW(""""c) + (&HFF00US - &H20US)) '// DW dual quote Return c = DWCH_LSMART_DQ OrElse c = DWCH_RSMART_DQ OrElse c = DWCH_DQ End Function Public Function GenerateExpression() As ExpressionSyntax Select Case Me.Kind Case StringPieceKind.Normal Dim literal = VisualBasic.SymbolDisplay.FormatPrimitive(Me.Value, quoteStrings:=True, useHexadecimalNumbers:=False) Return SyntaxFactory.StringLiteralExpression( SyntaxFactory.StringLiteralToken(literal, Me.Value)) Case StringPieceKind.NonPrintable Return GenerateChrWExpression(Me.Value(0)) Case StringPieceKind.Cr Return GenerateStringConstantExpression("vbCr") Case StringPieceKind.Lf Return GenerateStringConstantExpression("vbLf") Case StringPieceKind.CrLf Return GenerateStringConstantExpression("vbCrLf") Case StringPieceKind.NullChar Return GenerateStringConstantExpression("vbNullChar") Case StringPieceKind.Back Return GenerateStringConstantExpression("vbBack") Case StringPieceKind.FormFeed Return GenerateStringConstantExpression("vbFormFeed") Case StringPieceKind.Tab Return GenerateStringConstantExpression("vbTab") Case StringPieceKind.VerticalTab Return GenerateStringConstantExpression("vbVerticalTab") Case Else Throw ExceptionUtilities.UnexpectedValue(Me.Kind) End Select End Function Private Shared Function GenerateStringConstantExpression(name As String) As MemberAccessExpressionSyntax Dim result = GenerateMemberAccessExpression("Microsoft", "VisualBasic", "Constants", name) Return result.WithAdditionalAnnotations(Simplifier.Annotation) End Function Public Shared Function Split(value As String) As IList(Of StringPiece) Dim result = New List(Of StringPiece) Dim sb = New StringBuilder() Dim i = 0 While i < value.Length Dim c = value(i) i += 1 ' Handle unicode surrogates. If this character is a surrogate, but we get a ' viable surrogate pair, then just add the pair to the resultant string piece. Dim category = CharUnicodeInfo.GetUnicodeCategory(c) If category = UnicodeCategory.Surrogate Then Dim fullCategory = CharUnicodeInfo.GetUnicodeCategory(value, i - 1) If IsPrintable(fullCategory) Then sb.Append(c) sb.Append(value(i)) i += 1 Continue While End If End If If IsPrintable(c) Then sb.Append(c) Else If sb.Length > 0 Then result.Add(New StringPiece(sb.ToString(), StringPieceKind.Normal)) sb.Clear() End If If c = vbNullChar Then result.Add(New StringPiece(Nothing, StringPieceKind.NullChar)) ElseIf c = vbBack Then result.Add(New StringPiece(Nothing, StringPieceKind.Back)) ElseIf c = vbFormFeed Then result.Add(New StringPiece(Nothing, StringPieceKind.FormFeed)) ElseIf c = vbTab Then result.Add(New StringPiece(Nothing, StringPieceKind.Tab)) ElseIf c = vbVerticalTab Then result.Add(New StringPiece(Nothing, StringPieceKind.VerticalTab)) ElseIf c = vbCr Then If i < value.Length AndAlso value(i) = vbLf Then result.Add(New StringPiece(Nothing, StringPieceKind.CrLf)) i = i + 1 Else result.Add(New StringPiece(Nothing, StringPieceKind.Cr)) End If ElseIf c = vbLf Then result.Add(New StringPiece(Nothing, StringPieceKind.Lf)) Else result.Add(New StringPiece(c, StringPieceKind.NonPrintable)) End If End If End While If sb.Length > 0 Then result.Add(New StringPiece(sb.ToString(), StringPieceKind.Normal)) sb.Clear() End If Return result End Function End Structure End Module End Namespace |