From c7dcfd9167eb68df4f79e53550d3bfdb949ac197 Mon Sep 17 00:00:00 2001 From: Timur Kelman Date: Mon, 22 Jul 2024 18:40:44 +0200 Subject: [PATCH] take parameter attributes into account in CreateOptionalRefArg --- CodeConverter/CSharp/ExpressionNodeVisitor.cs | 48 ++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) diff --git a/CodeConverter/CSharp/ExpressionNodeVisitor.cs b/CodeConverter/CSharp/ExpressionNodeVisitor.cs index 1084ed19..321c3509 100644 --- a/CodeConverter/CSharp/ExpressionNodeVisitor.cs +++ b/CodeConverter/CSharp/ExpressionNodeVisitor.cs @@ -1818,8 +1818,54 @@ private ArgumentSyntax CreateExtraArgOrNull(IParameterSymbol p, bool requiresCom private ArgumentSyntax CreateOptionalRefArg(IParameterSymbol p, RefKind refKind) { string prefix = $"arg{p.Name}"; - var local = _typeContext.PerScopeState.Hoist(new AdditionalDeclaration(prefix, CommonConversions.Literal(p.ExplicitDefaultValue), CommonConversions.GetTypeSyntax(p.Type))); + var type = CommonConversions.GetTypeSyntax(p.Type); + ExpressionSyntax initializer; + if (p.HasExplicitDefaultValue) { + initializer = CommonConversions.Literal(p.ExplicitDefaultValue); + } else if (HasOptionalAttribute(p)) { + if (TryGetDefaultParameterValueAttributeValue(p, out var defaultValue)){ + initializer = CommonConversions.Literal(defaultValue); + } else { + initializer = SyntaxFactory.DefaultExpression(type); + } + } else { + //invalid VB.NET code + return null; + } + var local = _typeContext.PerScopeState.Hoist(new AdditionalDeclaration(prefix, initializer, type)); return (ArgumentSyntax)CommonConversions.CsSyntaxGenerator.Argument(p.Name, refKind, local.IdentifierName); + + bool HasOptionalAttribute(IParameterSymbol p) + { + var optionalAttribute = _semanticModel.Compilation.GetTypeByMetadataName("System.Runtime.InteropServices.OptionalAttribute"); + if (optionalAttribute == null) { + return false; + } + + return p.GetAttributes().Any(a => SymbolEqualityComparer.IncludeNullability.Equals(a.AttributeClass, optionalAttribute)); + } + + bool TryGetDefaultParameterValueAttributeValue(IParameterSymbol p, out object defaultValue) + { + defaultValue = null; + + var defaultParameterValueAttribute = _semanticModel.Compilation.GetTypeByMetadataName("System.Runtime.InteropServices.DefaultParameterValueAttribute"); + if (defaultParameterValueAttribute == null) { + return false; + } + + var attributeData = p.GetAttributes().FirstOrDefault(a => SymbolEqualityComparer.IncludeNullability.Equals(a.AttributeClass, defaultParameterValueAttribute)); + if (attributeData == null) { + return false; + } + + if (attributeData.ConstructorArguments.Length == 0) { + return false; + } + + defaultValue = attributeData.ConstructorArguments.First().Value; + return true; + } } private RefConversion NeedsVariableForArgument(VBasic.Syntax.ArgumentSyntax node, RefKind refKind)