@@ -35,7 +35,6 @@ internal class ExpressionNodeVisitor : VBasic.VisualBasicSyntaxVisitor<Task<CSha
3535 private readonly QueryConverter _queryConverter ;
3636 private readonly Lazy < IReadOnlyDictionary < ITypeSymbol , string > > _convertMethodsLookupByReturnType ;
3737 private readonly LambdaConverter _lambdaConverter ;
38- private readonly INamedTypeSymbol _vbBooleanTypeSymbol ;
3938 private readonly VisualBasicNullableExpressionsConverter _visualBasicNullableTypesConverter ;
4039 private readonly Dictionary < string , Stack < ( SyntaxNode Scope , string TempName ) > > _tempNameForAnonymousScope = new ( ) ;
4140 private readonly HashSet < string > _generatedNames = new ( StringComparer . OrdinalIgnoreCase ) ;
@@ -58,7 +57,6 @@ public ExpressionNodeVisitor(SemanticModel semanticModel,
5857 // If this isn't needed, the assembly with Conversions may not be referenced, so this must be done lazily
5958 _convertMethodsLookupByReturnType =
6059 new Lazy < IReadOnlyDictionary < ITypeSymbol , string > > ( ( ) => CreateConvertMethodsLookupByReturnType ( semanticModel ) ) ;
61- _vbBooleanTypeSymbol = _semanticModel . Compilation . GetTypeByMetadataName ( "System.Boolean" ) ;
6260 }
6361
6462 private static IReadOnlyDictionary < ITypeSymbol , string > CreateConvertMethodsLookupByReturnType (
@@ -775,7 +773,7 @@ public override async Task<CSharpSyntaxNode> VisitBinaryConditionalExpression(VB
775773 public override async Task < CSharpSyntaxNode > VisitTernaryConditionalExpression ( VBasic . Syntax . TernaryConditionalExpressionSyntax node )
776774 {
777775 var condition = await node . Condition . AcceptAsync < ExpressionSyntax > ( TriviaConvertingExpressionVisitor ) ;
778- condition = CommonConversions . TypeConversionAnalyzer . AddExplicitConversion ( node . Condition , condition , forceTargetType : _vbBooleanTypeSymbol ) ;
776+ condition = CommonConversions . TypeConversionAnalyzer . AddExplicitConversion ( node . Condition , condition , forceTargetType : CommonConversions . KnownTypes . Boolean ) ;
779777
780778 var whenTrue = await node . WhenTrue . AcceptAsync < ExpressionSyntax > ( TriviaConvertingExpressionVisitor ) ;
781779 whenTrue = CommonConversions . TypeConversionAnalyzer . AddExplicitConversion ( node . WhenTrue , whenTrue ) ;
@@ -900,7 +898,7 @@ private async Task<CSharpSyntaxNode> ConvertBinaryExpressionAsync(VBasic.Syntax.
900898 omitConversion = lhsTypeInfo . Type . SpecialType == SpecialType . System_String ||
901899 rhsTypeInfo . Type . SpecialType == SpecialType . System_String ;
902900 if ( lhsTypeInfo . ConvertedType . SpecialType != SpecialType . System_String ) {
903- forceLhsTargetType = _semanticModel . Compilation . GetTypeByMetadataName ( "System. String" ) ;
901+ forceLhsTargetType = CommonConversions . KnownTypes . String ;
904902 }
905903 }
906904 }
@@ -938,6 +936,8 @@ private async Task<CSharpSyntaxNode> ConvertBinaryExpressionAsync(VBasic.Syntax.
938936 return node . Parent . IsKind ( VBasic . SyntaxKind . SimpleArgument ) ? exp : exp . AddParens ( ) ;
939937 }
940938
939+
940+
941941 private async Task < ExpressionSyntax > RewriteBinaryOperatorOrNullAsync ( VBSyntax . BinaryExpressionSyntax node ) =>
942942 await _operatorConverter . ConvertRewrittenBinaryOperatorOrNullAsync ( node , TriviaConvertingExpressionVisitor . IsWithinQuery ) ;
943943
@@ -1818,8 +1818,54 @@ private ArgumentSyntax CreateExtraArgOrNull(IParameterSymbol p, bool requiresCom
18181818 private ArgumentSyntax CreateOptionalRefArg ( IParameterSymbol p , RefKind refKind )
18191819 {
18201820 string prefix = $ "arg{ p . Name } ";
1821- var local = _typeContext . PerScopeState . Hoist ( new AdditionalDeclaration ( prefix , CommonConversions . Literal ( p . ExplicitDefaultValue ) , CommonConversions . GetTypeSyntax ( p . Type ) ) ) ;
1821+ var type = CommonConversions . GetTypeSyntax ( p . Type ) ;
1822+ ExpressionSyntax initializer ;
1823+ if ( p . HasExplicitDefaultValue ) {
1824+ initializer = CommonConversions . Literal ( p . ExplicitDefaultValue ) ;
1825+ } else if ( HasOptionalAttribute ( p ) ) {
1826+ if ( TryGetDefaultParameterValueAttributeValue ( p , out var defaultValue ) ) {
1827+ initializer = CommonConversions . Literal ( defaultValue ) ;
1828+ } else {
1829+ initializer = SyntaxFactory . DefaultExpression ( type ) ;
1830+ }
1831+ } else {
1832+ //invalid VB.NET code
1833+ return null ;
1834+ }
1835+ var local = _typeContext . PerScopeState . Hoist ( new AdditionalDeclaration ( prefix , initializer , type ) ) ;
18221836 return ( ArgumentSyntax ) CommonConversions . CsSyntaxGenerator . Argument ( p . Name , refKind , local . IdentifierName ) ;
1837+
1838+ bool HasOptionalAttribute ( IParameterSymbol p )
1839+ {
1840+ var optionalAttribute = CommonConversions . KnownTypes . OptionalAttribute ;
1841+ if ( optionalAttribute == null ) {
1842+ return false ;
1843+ }
1844+
1845+ return p . GetAttributes ( ) . Any ( a => SymbolEqualityComparer . IncludeNullability . Equals ( a . AttributeClass , optionalAttribute ) ) ;
1846+ }
1847+
1848+ bool TryGetDefaultParameterValueAttributeValue ( IParameterSymbol p , out object defaultValue )
1849+ {
1850+ defaultValue = null ;
1851+
1852+ var defaultParameterValueAttribute = CommonConversions . KnownTypes . DefaultParameterValueAttribute ;
1853+ if ( defaultParameterValueAttribute == null ) {
1854+ return false ;
1855+ }
1856+
1857+ var attributeData = p . GetAttributes ( ) . FirstOrDefault ( a => SymbolEqualityComparer . IncludeNullability . Equals ( a . AttributeClass , defaultParameterValueAttribute ) ) ;
1858+ if ( attributeData == null ) {
1859+ return false ;
1860+ }
1861+
1862+ if ( attributeData . ConstructorArguments . Length == 0 ) {
1863+ return false ;
1864+ }
1865+
1866+ defaultValue = attributeData . ConstructorArguments . First ( ) . Value ;
1867+ return true ;
1868+ }
18231869 }
18241870
18251871 private RefConversion NeedsVariableForArgument ( VBasic . Syntax . ArgumentSyntax node , RefKind refKind )
@@ -1898,7 +1944,7 @@ private ISymbol GetInvocationSymbol(SyntaxNode invocation)
18981944 ( VBSyntax . InvocationExpressionSyntax e ) => _semanticModel . GetSymbolInfo ( e ) . ExtractBestMatch < ISymbol > ( ) ,
18991945 ( VBSyntax . ObjectCreationExpressionSyntax e ) => _semanticModel . GetSymbolInfo ( e ) . ExtractBestMatch < ISymbol > ( ) ,
19001946 ( VBSyntax . RaiseEventStatementSyntax e ) => _semanticModel . GetSymbolInfo ( e . Name ) . ExtractBestMatch < ISymbol > ( ) ,
1901- ( VBSyntax . MidExpressionSyntax _ ) => _semanticModel . Compilation . GetTypeByMetadataName ( "Microsoft.VisualBasic.CompilerServices.StringType" ) ? . GetMembers ( "MidStmtStr" ) . FirstOrDefault ( ) ,
1947+ ( VBSyntax . MidExpressionSyntax _ ) => CommonConversions . KnownTypes . VbCompilerStringType ? . GetMembers ( "MidStmtStr" ) . FirstOrDefault ( ) ,
19021948 _ => throw new NotSupportedException ( ) ) ;
19031949 return symbol ;
19041950 }
0 commit comments