diff --git a/src/Compilers/VisualBasic/Portable/Binding/Binder_Conversions.vb b/src/Compilers/VisualBasic/Portable/Binding/Binder_Conversions.vb
index 75d4e36989ad4..ea0d099de5abd 100644
--- a/src/Compilers/VisualBasic/Portable/Binding/Binder_Conversions.vb
+++ b/src/Compilers/VisualBasic/Portable/Binding/Binder_Conversions.vb
@@ -1618,7 +1618,9 @@ DoneWithDiagnostics:
If (convKind And ConversionKind.InterpolatedString) = ConversionKind.InterpolatedString Then
Debug.Assert(targetType.Equals(Compilation.GetWellKnownType(WellKnownType.System_IFormattable)) OrElse targetType.Equals(Compilation.GetWellKnownType(WellKnownType.System_FormattableString)))
- Return New BoundConversion(tree, node, ConversionKind.InterpolatedString, False, isExplicit, targetType)
+ Return New BoundConversion(tree,
+ BindUnconvertedInterpolatedStringToFormattable(tree, node, targetType, diagnostics),
+ ConversionKind.InterpolatedString, False, isExplicit, targetType)
End If
Return node
diff --git a/src/Compilers/VisualBasic/Portable/Binding/Binder_Expressions.vb b/src/Compilers/VisualBasic/Portable/Binding/Binder_Expressions.vb
index 3d93cd5b469d9..b95a41d77aa3c 100644
--- a/src/Compilers/VisualBasic/Portable/Binding/Binder_Expressions.vb
+++ b/src/Compilers/VisualBasic/Portable/Binding/Binder_Expressions.vb
@@ -1400,6 +1400,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Throw ExceptionUtilities.UnexpectedValue(propertyAccess.AccessKind)
End Select
+ ElseIf expr.Kind = BoundKind.InterpolatedStringExpression Then
+
+ expr = BindUnconvertedInterpolatedStringToString(DirectCast(expr, BoundInterpolatedStringExpression), diagnostics)
+
ElseIf expr.IsLateBound() Then
Select Case expr.GetLateBoundAccessKind()
diff --git a/src/Compilers/VisualBasic/Portable/Binding/Binder_InterpolatedString.vb b/src/Compilers/VisualBasic/Portable/Binding/Binder_InterpolatedString.vb
index d9cd0d0c3730d..7aab533abbe43 100644
--- a/src/Compilers/VisualBasic/Portable/Binding/Binder_InterpolatedString.vb
+++ b/src/Compilers/VisualBasic/Portable/Binding/Binder_InterpolatedString.vb
@@ -29,7 +29,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
End Select
Next
- Return New BoundInterpolatedStringExpression(syntax, contentBuilder.ToImmutableAndFree(), binder:=Me, type:=GetSpecialType(SpecialType.System_String, syntax, diagnostics))
+ Return New BoundInterpolatedStringExpression(syntax, contentBuilder.ToImmutableAndFree(), constructionOpt:=Nothing, type:=GetSpecialType(SpecialType.System_String, syntax, diagnostics))
End Function
@@ -72,5 +72,174 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
End Function
+ Private Function BindUnconvertedInterpolatedStringToString(node As BoundInterpolatedStringExpression, diagnostics As BindingDiagnosticBag) As BoundExpression
+
+ Debug.Assert(node.Type.SpecialType = SpecialType.System_String)
+
+ ' We lower an interpolated string into an invocation of String.Format or System.Runtime.CompilerServices.FormattableStringFactory.Create.
+ ' For example, we translate the expression:
+ '
+ ' $"Jenny, don't change your number: {phoneNumber:###-####}."
+ '
+ ' into
+ '
+ ' String.Format("Jenny, don't change your number: {0:###-####}.", phoneNumber)
+ '
+ ' TODO: A number of optimizations would be beneficial in the generated code.
+ '
+ ' (1) If there is no width or format, and the argument is a value type, call .ToString()
+ ' on it directly so that we avoid the boxing overhead.
+ '
+ ' (2) For the built-in types, we can use .ToString(string format) for some format strings.
+ ' Detect those cases that can be handled that way and take advantage of them.
+ If node.IsEmpty OrElse Not node.HasInterpolations Then
+ Return node
+ End If
+
+ Return node.Update(node.Contents,
+ constructionOpt:=TryInvokeInterpolatedStringFactory(node,
+ factoryType:=node.Type,
+ factoryMethodName:="Format",
+ targetType:=node.Type,
+ diagnostics),
+ node.Type)
+ End Function
+
+ Private Function BindUnconvertedInterpolatedStringToFormattable(syntax As SyntaxNode, node As BoundInterpolatedStringExpression, targetType As TypeSymbol, diagnostics As BindingDiagnosticBag) As BoundExpression
+
+ Debug.Assert(targetType.Equals(Compilation.GetWellKnownType(WellKnownType.System_FormattableString)) OrElse
+ targetType.Equals(Compilation.GetWellKnownType(WellKnownType.System_IFormattable)))
+
+ ' We lower an interpolated string into an invocation of System.Runtime.CompilerServices.FormattableStringFactory.Create.
+ ' For example, we translate the expression:
+ '
+ ' $"Jenny, don't change your number: {phoneNumber:###-####}."
+ '
+ ' into
+ '
+ ' FormattableStringFactory.Create("Jenny, don't change your number: {0:###-####}.", phoneNumber)
+ '
+ ' TODO: A number of optimizations would be beneficial in the generated code.
+ '
+ ' (1) If there is no width or format, and the argument is a value type, call .ToString()
+ ' on it directly so that we avoid the boxing overhead.
+ '
+ ' (2) For the built-in types, we can use .ToString(string format) for some format strings.
+ ' Detect those cases that can be handled that way and take advantage of them.
+
+ Return node.Update(node.Contents,
+ constructionOpt:=TryInvokeInterpolatedStringFactory(node,
+ factoryType:=GetWellKnownType(WellKnownType.System_Runtime_CompilerServices_FormattableStringFactory, syntax, diagnostics),
+ factoryMethodName:="Create",
+ targetType,
+ diagnostics),
+ node.Type)
+ End Function
+
+ Private Function TryInvokeInterpolatedStringFactory(node As BoundInterpolatedStringExpression, factoryType As TypeSymbol, factoryMethodName As String, targetType As TypeSymbol, diagnostics As BindingDiagnosticBag) As BoundExpression
+
+ Dim hasErrors As Boolean = False
+
+ If factoryType.IsErrorType() OrElse
+ node.HasErrors OrElse
+ node.Contents.OfType(Of BoundInterpolation)().Any(
+ Function(interpolation) interpolation.Expression.HasErrors OrElse
+ (interpolation.AlignmentOpt IsNot Nothing AndAlso
+ Not (interpolation.AlignmentOpt.IsConstant AndAlso interpolation.AlignmentOpt.ConstantValueOpt.IsIntegral))) Then
+ Return Nothing
+ End If
+
+ Dim lookup = LookupResult.GetInstance()
+ Dim useSiteInfo = GetNewCompoundUseSiteInfo(diagnostics)
+
+ LookupMember(lookup, factoryType, factoryMethodName, 0, LookupOptions.MustNotBeInstance Or LookupOptions.MethodsOnly Or LookupOptions.AllMethodsOfAnyArity, useSiteInfo)
+
+ diagnostics.Add(node, useSiteInfo)
+
+ If lookup.Kind = LookupResultKind.Inaccessible Then
+ hasErrors = True
+ ElseIf Not lookup.IsGood Then
+ lookup.Free()
+ GoTo Report_ERR_InterpolatedStringFactoryError
+ End If
+
+ Dim methodGroup = New BoundMethodGroup(node.Syntax, Nothing, lookup.Symbols.ToDowncastedImmutable(Of MethodSymbol), lookup.Kind, Nothing, QualificationKind.QualifiedViaTypeName).MakeCompilerGenerated()
+ lookup.Free()
+
+ Dim formatStringBuilderHandle = PooledStringBuilder.GetInstance()
+ Dim arguments = ArrayBuilder(Of BoundExpression).GetInstance()
+ Dim interpolationOrdinal = -1
+
+ arguments.Add(Nothing) ' Placeholder for format string.
+
+ For Each item In node.Contents
+
+ Select Case item.Kind
+
+ Case BoundKind.Literal
+
+ formatStringBuilderHandle.Builder.Append(DirectCast(item, BoundLiteral).Value.StringValue)
+
+ Case BoundKind.Interpolation
+
+ interpolationOrdinal += 1
+
+ Dim interpolation = DirectCast(item, BoundInterpolation)
+
+ With formatStringBuilderHandle.Builder
+
+ .Append("{"c)
+
+ .Append(interpolationOrdinal.ToString(Globalization.CultureInfo.InvariantCulture))
+
+ If interpolation.AlignmentOpt IsNot Nothing Then
+ Debug.Assert(interpolation.AlignmentOpt.IsConstant AndAlso interpolation.AlignmentOpt.ConstantValueOpt.IsIntegral)
+ .Append(","c)
+ .Append(interpolation.AlignmentOpt.ConstantValueOpt.Int64Value.ToString(Globalization.CultureInfo.InvariantCulture))
+ End If
+
+ If interpolation.FormatStringOpt IsNot Nothing Then
+ .Append(":")
+ .Append(interpolation.FormatStringOpt.Value.StringValue)
+ End If
+
+ .Append("}"c)
+ End With
+
+ arguments.Add(interpolation.Expression)
+
+ Case Else
+ Throw ExceptionUtilities.Unreachable()
+ End Select
+
+ Next
+
+ arguments(0) = CreateStringLiteral(node.Syntax, formatStringBuilderHandle.ToStringAndFree(), compilerGenerated:=True, diagnostics)
+
+ Dim result As BoundExpression = MakeRValue(BindInvocationExpression(node.Syntax,
+ node.Syntax,
+ TypeCharacter.None,
+ methodGroup,
+ arguments.ToImmutableAndFree(),
+ Nothing,
+ diagnostics,
+ callerInfoOpt:=Nothing,
+ forceExpandedForm:=True), diagnostics).MakeCompilerGenerated()
+
+ If Not result.Type.Equals(targetType) Then
+ result = ApplyImplicitConversion(node.Syntax, targetType, result, diagnostics).MakeCompilerGenerated()
+ End If
+
+ If hasErrors OrElse result.HasErrors Then
+ GoTo Report_ERR_InterpolatedStringFactoryError
+ End If
+
+ Return result
+
+Report_ERR_InterpolatedStringFactoryError:
+ ReportDiagnostic(diagnostics, node.Syntax, ErrorFactory.ErrorInfo(ERRID.ERR_InterpolatedStringFactoryError, factoryType.Name, factoryMethodName))
+ Return Nothing
+ End Function
+
End Class
End Namespace
diff --git a/src/Compilers/VisualBasic/Portable/Binding/Binder_XmlLiterals.vb b/src/Compilers/VisualBasic/Portable/Binding/Binder_XmlLiterals.vb
index d7bbfeb39bdfb..02b4d1fb55803 100644
--- a/src/Compilers/VisualBasic/Portable/Binding/Binder_XmlLiterals.vb
+++ b/src/Compilers/VisualBasic/Portable/Binding/Binder_XmlLiterals.vb
@@ -1048,7 +1048,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
End Function
Private Function CreateStringLiteral(
- syntax As VisualBasicSyntaxNode,
+ syntax As SyntaxNode,
str As String,
compilerGenerated As Boolean,
diagnostics As BindingDiagnosticBag,
diff --git a/src/Compilers/VisualBasic/Portable/BoundTree/BoundNodes.xml b/src/Compilers/VisualBasic/Portable/BoundTree/BoundNodes.xml
index 20716accb919f..6087a847a95d2 100644
--- a/src/Compilers/VisualBasic/Portable/BoundTree/BoundNodes.xml
+++ b/src/Compilers/VisualBasic/Portable/BoundTree/BoundNodes.xml
@@ -1927,7 +1927,7 @@
-
+
diff --git a/src/Compilers/VisualBasic/Portable/Generated/BoundNodes.xml.Generated.vb b/src/Compilers/VisualBasic/Portable/Generated/BoundNodes.xml.Generated.vb
index 0a39a76c105d9..75908f54fc387 100644
--- a/src/Compilers/VisualBasic/Portable/Generated/BoundNodes.xml.Generated.vb
+++ b/src/Compilers/VisualBasic/Portable/Generated/BoundNodes.xml.Generated.vb
@@ -9239,15 +9239,14 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Partial Friend NotInheritable Class BoundInterpolatedStringExpression
Inherits BoundExpression
- Public Sub New(syntax As SyntaxNode, contents As ImmutableArray(Of BoundNode), binder As Binder, type As TypeSymbol, Optional hasErrors As Boolean = False)
- MyBase.New(BoundKind.InterpolatedStringExpression, syntax, type, hasErrors OrElse contents.NonNullAndHasErrors())
+ Public Sub New(syntax As SyntaxNode, contents As ImmutableArray(Of BoundNode), constructionOpt As BoundExpression, type As TypeSymbol, Optional hasErrors As Boolean = False)
+ MyBase.New(BoundKind.InterpolatedStringExpression, syntax, type, hasErrors OrElse contents.NonNullAndHasErrors() OrElse constructionOpt.NonNullAndHasErrors())
Debug.Assert(Not (contents.IsDefault), "Field 'contents' cannot be null (use Null=""allow"" in BoundNodes.xml to remove this check)")
- Debug.Assert(binder IsNot Nothing, "Field 'binder' cannot be null (use Null=""allow"" in BoundNodes.xml to remove this check)")
Debug.Assert(type IsNot Nothing, "Field 'type' cannot be null (use Null=""allow"" in BoundNodes.xml to remove this check)")
Me._Contents = contents
- Me._Binder = binder
+ Me._ConstructionOpt = constructionOpt
Validate()
End Sub
@@ -9263,10 +9262,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
End Get
End Property
- Private ReadOnly _Binder As Binder
- Public ReadOnly Property Binder As Binder
+ Private ReadOnly _ConstructionOpt As BoundExpression
+ Public ReadOnly Property ConstructionOpt As BoundExpression
Get
- Return _Binder
+ Return _ConstructionOpt
End Get
End Property
@@ -9275,9 +9274,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Return visitor.VisitInterpolatedStringExpression(Me)
End Function
- Public Function Update(contents As ImmutableArray(Of BoundNode), binder As Binder, type As TypeSymbol) As BoundInterpolatedStringExpression
- If contents <> Me.Contents OrElse binder IsNot Me.Binder OrElse type IsNot Me.Type Then
- Dim result = New BoundInterpolatedStringExpression(Me.Syntax, contents, binder, type, Me.HasErrors)
+ Public Function Update(contents As ImmutableArray(Of BoundNode), constructionOpt As BoundExpression, type As TypeSymbol) As BoundInterpolatedStringExpression
+ If contents <> Me.Contents OrElse constructionOpt IsNot Me.ConstructionOpt OrElse type IsNot Me.Type Then
+ Dim result = New BoundInterpolatedStringExpression(Me.Syntax, contents, constructionOpt, type, Me.HasErrors)
result.CopyAttributes(Me)
Return result
End If
@@ -13126,8 +13125,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Public Overrides Function VisitInterpolatedStringExpression(node As BoundInterpolatedStringExpression) As BoundNode
Dim contents As ImmutableArray(Of BoundNode) = Me.VisitList(node.Contents)
+ Dim constructionOpt As BoundExpression = node.ConstructionOpt
Dim type as TypeSymbol = Me.VisitType(node.Type)
- Return node.Update(contents, node.Binder, type)
+ Return node.Update(contents, constructionOpt, type)
End Function
Public Overrides Function VisitInterpolation(node As BoundInterpolation) As BoundNode
@@ -14589,7 +14589,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Public Overrides Function VisitInterpolatedStringExpression(node As BoundInterpolatedStringExpression, arg As Object) As TreeDumperNode
Return New TreeDumperNode("interpolatedStringExpression", Nothing, New TreeDumperNode() {
New TreeDumperNode("contents", Nothing, From x In node.Contents Select Visit(x, Nothing)),
- New TreeDumperNode("binder", node.Binder, Nothing),
+ New TreeDumperNode("constructionOpt", Nothing, new TreeDumperNode() {Visit(node.ConstructionOpt, Nothing)}),
New TreeDumperNode("type", node.Type, Nothing)
})
End Function
diff --git a/src/Compilers/VisualBasic/Portable/Lowering/Diagnostics/DiagnosticsPass_ExpressionLambdas.vb b/src/Compilers/VisualBasic/Portable/Lowering/Diagnostics/DiagnosticsPass_ExpressionLambdas.vb
index cc44e74774a88..786b7d35f6080 100644
--- a/src/Compilers/VisualBasic/Portable/Lowering/Diagnostics/DiagnosticsPass_ExpressionLambdas.vb
+++ b/src/Compilers/VisualBasic/Portable/Lowering/Diagnostics/DiagnosticsPass_ExpressionLambdas.vb
@@ -405,6 +405,10 @@ lSelect:
Me._diagnostics.Add(New VBDiagnostic(ErrorFactory.ErrorInfo(code), node.Syntax.GetLocation()))
End Sub
+ Public Overrides Function VisitInterpolatedStringExpression(node As BoundInterpolatedStringExpression) As BoundNode
+ Visit(node.ConstructionOpt)
+ Return MyBase.VisitInterpolatedStringExpression(node)
+ End Function
End Class
End Namespace
diff --git a/src/Compilers/VisualBasic/Portable/Lowering/LocalRewriter/LocalRewriter_Conversion.vb b/src/Compilers/VisualBasic/Portable/Lowering/LocalRewriter/LocalRewriter_Conversion.vb
index e727785341c65..7b7cae1b91a71 100644
--- a/src/Compilers/VisualBasic/Portable/Lowering/LocalRewriter/LocalRewriter_Conversion.vb
+++ b/src/Compilers/VisualBasic/Portable/Lowering/LocalRewriter/LocalRewriter_Conversion.vb
@@ -591,92 +591,6 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Return operand
End Function
- Private Function RewriteNullableReferenceConversion(node As BoundConversion,
- rewrittenOperand As BoundExpression) As BoundExpression
-
- Dim resultType = node.Type
- Dim operandType = rewrittenOperand.Type
-
- If operandType.IsStringType Then
- ' CType(string, T?) ---> new T?(CType(string, T))
- Dim innerTargetType = resultType.GetNullableUnderlyingType
- Dim useSiteInfo = GetNewCompoundUseSiteInfo()
- Dim convKind = Conversions.ClassifyConversion(operandType, innerTargetType, useSiteInfo).Key
- Debug.Assert(Conversions.ConversionExists(convKind))
- _diagnostics.Add(node, useSiteInfo)
- Return WrapInNullable(
- TransformRewrittenConversion(
- node.Update(rewrittenOperand,
- convKind,
- node.Checked,
- node.ExplicitCastInCode,
- node.ConstantValueOpt,
- node.ExtendedInfoOpt,
- resultType.GetNullableUnderlyingType)),
- resultType)
- End If
-
- If resultType.IsStringType Then
- ' conversion to string is an intrinsic conversion and can be lifted.
- ' T? --> string ==> T.Value -- string
- ' note that nullable null does not convert to string null, i.e. this conversion
- ' is not null-propagating
-
- rewrittenOperand = NullableValue(rewrittenOperand)
- Dim useSiteInfo = GetNewCompoundUseSiteInfo()
- Dim convKind = Conversions.ClassifyDirectCastConversion(rewrittenOperand.Type, resultType, useSiteInfo)
- Debug.Assert(Conversions.ConversionExists(convKind))
- _diagnostics.Add(node, useSiteInfo)
- Return TransformRewrittenConversion(
- node.Update(rewrittenOperand,
- node.ConversionKind And (Not ConversionKind.Nullable),
- node.Checked,
- node.ExplicitCastInCode,
- node.ConstantValueOpt,
- node.ExtendedInfoOpt,
- resultType))
- End If
-
- If operandType.IsNullableType Then
- ' T? --> RefType, this is a boxing conversion (DirectCast)
- If HasNoValue(rewrittenOperand) Then
- ' DirectCast(Nothing, operatorType)
- Return New BoundDirectCast(node.Syntax,
- MakeNullLiteral(rewrittenOperand.Syntax, resultType),
- ConversionKind.WideningNothingLiteral,
- resultType)
- End If
-
- If HasValue(rewrittenOperand) Then
- ' DirectCast(operand.GetValueOrDefault, operatorType)
- Dim unwrappedOperand = NullableValueOrDefault(rewrittenOperand)
- Dim useSiteInfo = GetNewCompoundUseSiteInfo()
- Dim convKind = Conversions.ClassifyDirectCastConversion(unwrappedOperand.Type, resultType, useSiteInfo)
- Debug.Assert(Conversions.ConversionExists(convKind))
- _diagnostics.Add(node, useSiteInfo)
- Return New BoundDirectCast(node.Syntax,
- unwrappedOperand,
- convKind,
- resultType)
- End If
- End If
-
- If resultType.IsNullableType Then
- ' RefType --> T? , this is just an unboxing conversion.
- Dim useSiteInfo = GetNewCompoundUseSiteInfo()
- Dim convKind = Conversions.ClassifyDirectCastConversion(rewrittenOperand.Type, resultType, useSiteInfo)
- Debug.Assert(Conversions.ConversionExists(convKind))
- _diagnostics.Add(node, useSiteInfo)
- Return New BoundDirectCast(node.Syntax,
- rewrittenOperand,
- convKind,
- resultType)
-
- End If
-
- Throw ExceptionUtilities.Unreachable
- End Function
-
Private Function RewriteNullableUserDefinedConversion(node As BoundUserDefinedConversion) As BoundNode
' User defined conversions rewrite as:
' Sequence(operandCapture, If(operandCapture.HasValue, Conversion(operandCapture), Null)
diff --git a/src/Compilers/VisualBasic/Portable/Lowering/LocalRewriter/LocalRewriter_InterpolatedString.vb b/src/Compilers/VisualBasic/Portable/Lowering/LocalRewriter/LocalRewriter_InterpolatedString.vb
index 8002dbc4b5c63..3570e6a0a55c2 100644
--- a/src/Compilers/VisualBasic/Portable/Lowering/LocalRewriter/LocalRewriter_InterpolatedString.vb
+++ b/src/Compilers/VisualBasic/Portable/Lowering/LocalRewriter/LocalRewriter_InterpolatedString.vb
@@ -46,7 +46,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Return factory.StringLiteral(ConstantValue.Create(valueWithEscapes.Replace("{{", "{").Replace("}}", "}")))
Else
- Return InvokeInterpolatedStringFactory(node, node.Type, "Format", node.Type, factory)
+ Debug.Assert(node.ConstructionOpt IsNot Nothing)
+ Return VisitExpression(node.ConstructionOpt)
End If
End Function
@@ -57,10 +58,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Dim targetType = conversion.Type
Dim node = DirectCast(conversion.Operand, BoundInterpolatedStringExpression)
- Dim binder = node.Binder
+ Debug.Assert(node.ConstructionOpt IsNot Nothing)
- Debug.Assert(targetType.Equals(binder.Compilation.GetWellKnownType(WellKnownType.System_FormattableString)) OrElse
- targetType.Equals(binder.Compilation.GetWellKnownType(WellKnownType.System_IFormattable)))
+ Debug.Assert(targetType.Equals(Compilation.GetWellKnownType(WellKnownType.System_FormattableString)) OrElse
+ targetType.Equals(Compilation.GetWellKnownType(WellKnownType.System_IFormattable)))
' We lower an interpolated string into an invocation of System.Runtime.CompilerServices.FormattableStringFactory.Create.
' For example, we translate the expression:
@@ -78,117 +79,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
'
' (2) For the built-in types, we can use .ToString(string format) for some format strings.
' Detect those cases that can be handled that way and take advantage of them.
- Return InvokeInterpolatedStringFactory(node,
- binder.GetWellKnownType(WellKnownType.System_Runtime_CompilerServices_FormattableStringFactory, conversion.Syntax, _diagnostics),
- "Create",
- conversion.Type,
- New SyntheticBoundNodeFactory(_topMethod, _currentMethodOrLambda, node.Syntax, _compilationState, _diagnostics))
-
- End Function
-
- Private Function InvokeInterpolatedStringFactory(node As BoundInterpolatedStringExpression, factoryType As TypeSymbol, factoryMethodName As String, targetType As TypeSymbol, factory As SyntheticBoundNodeFactory) As BoundExpression
-
- Dim hasErrors As Boolean = False
-
- If factoryType.IsErrorType() Then
- GoTo ReturnBadExpression
- End If
-
- Dim binder = node.Binder
-
- Dim lookup = LookupResult.GetInstance()
- Dim useSiteInfo = GetNewCompoundUseSiteInfo()
-
- binder.LookupMember(lookup, factoryType, factoryMethodName, 0, LookupOptions.MustNotBeInstance Or LookupOptions.MethodsOnly Or LookupOptions.AllMethodsOfAnyArity, useSiteInfo)
-
- _diagnostics.Add(node, useSiteInfo)
-
- If lookup.Kind = LookupResultKind.Inaccessible Then
- hasErrors = True
- ElseIf Not lookup.IsGood Then
- lookup.Free()
- GoTo ReturnBadExpression
- End If
-
- Dim methodGroup = New BoundMethodGroup(node.Syntax, Nothing, lookup.Symbols.ToDowncastedImmutable(Of MethodSymbol), lookup.Kind, Nothing, QualificationKind.QualifiedViaTypeName).MakeCompilerGenerated()
- lookup.Free()
-
- Dim formatStringBuilderHandle = PooledStringBuilder.GetInstance()
- Dim arguments = ArrayBuilder(Of BoundExpression).GetInstance()
- Dim interpolationOrdinal = -1
-
- arguments.Add(Nothing) ' Placeholder for format string.
-
- For Each item In node.Contents
-
- Select Case item.Kind
-
- Case BoundKind.Literal
-
- formatStringBuilderHandle.Builder.Append(DirectCast(item, BoundLiteral).Value.StringValue)
-
- Case BoundKind.Interpolation
-
- interpolationOrdinal += 1
-
- Dim interpolation = DirectCast(item, BoundInterpolation)
-
- With formatStringBuilderHandle.Builder
-
- .Append("{"c)
-
- .Append(interpolationOrdinal.ToString(Globalization.CultureInfo.InvariantCulture))
-
- If interpolation.AlignmentOpt IsNot Nothing Then
- Debug.Assert(interpolation.AlignmentOpt.IsConstant AndAlso interpolation.AlignmentOpt.ConstantValueOpt.IsIntegral)
- .Append(","c)
- .Append(interpolation.AlignmentOpt.ConstantValueOpt.Int64Value.ToString(Globalization.CultureInfo.InvariantCulture))
- End If
-
- If interpolation.FormatStringOpt IsNot Nothing Then
- .Append(":")
- .Append(interpolation.FormatStringOpt.Value.StringValue)
- End If
-
- .Append("}"c)
- End With
-
- arguments.Add(interpolation.Expression)
-
- Case Else
- Throw ExceptionUtilities.Unreachable()
- End Select
-
- Next
-
- arguments(0) = factory.StringLiteral(ConstantValue.Create(formatStringBuilderHandle.ToStringAndFree())).MakeCompilerGenerated()
-
- Dim result As BoundExpression = binder.MakeRValue(binder.BindInvocationExpression(node.Syntax,
- node.Syntax,
- TypeCharacter.None,
- methodGroup,
- arguments.ToImmutableAndFree(),
- Nothing,
- _diagnostics,
- callerInfoOpt:=Nothing,
- forceExpandedForm:=True), _diagnostics).MakeCompilerGenerated()
-
- If Not result.Type.Equals(targetType) Then
- result = binder.ApplyImplicitConversion(node.Syntax, targetType, result, _diagnostics).MakeCompilerGenerated()
- End If
-
- If hasErrors OrElse result.HasErrors Then
- GoTo ReturnBadExpression
- End If
-
- result = VisitExpression(result)
-
- Return result
-
-ReturnBadExpression:
- ReportDiagnostic(node, ErrorFactory.ErrorInfo(ERRID.ERR_InterpolatedStringFactoryError, factoryType.Name, factoryMethodName), _diagnostics)
- Return factory.Convert(targetType, factory.BadExpression(DirectCast(MyBase.VisitInterpolatedStringExpression(node), BoundExpression)))
-
+ Return VisitExpression(node.ConstructionOpt)
End Function
End Class