Skip to content

Commit 0294eaf

Browse files
Timur KelmanTimur Kelman
authored andcommitted
use ref arguments if ByRef parameter was involved
1 parent f0eb3f7 commit 0294eaf

5 files changed

Lines changed: 52 additions & 11 deletions

File tree

CodeConverter/CSharp/CommonConversions.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ public bool ShouldPreferExplicitType(VBSyntax.ExpressionSyntax exp,
145145
equalsValueClauseSyntax = null;
146146
} else {
147147
var returnBlock = SyntaxFactory.Block(SyntaxFactory.ReturnStatement(adjustedInitializerExpr));
148-
_typeContext.PerScopeState.Hoist(new HoistedParameterlessFunction(GetInitialValueFunctionName(vbName), csTypeSyntax, returnBlock));
148+
_typeContext.PerScopeState.Hoist(new HoistedFunction(GetInitialValueFunctionName(vbName), csTypeSyntax, returnBlock, null));
149149
equalsValueClauseSyntax = null;
150150
}
151151
} else {

CodeConverter/CSharp/ExpressionNodeVisitor.cs

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1174,9 +1174,41 @@ private async Task<InvocationExpressionSyntax> HoistAndCallLocalFunctionAsync(VB
11741174
statements.Concat(SyntaxFactory.ReturnStatement(ValidSyntaxFactory.IdentifierName(retVariableName)).Yield())
11751175
);
11761176
var returnType = CommonConversions.GetTypeSyntax(invocationSymbol.ReturnType);
1177-
1178-
var localFunc = _typeContext.PerScopeState.Hoist(new HoistedParameterlessFunction(localFuncName, returnType, block));
1179-
return SyntaxFactory.InvocationExpression(localFunc.TempIdentifier, SyntaxFactory.ArgumentList());
1177+
1178+
//any argument that's a ByRef parameter of the parent method needs to be passed as a ref parameter to the local function (to avoid error CS1628)
1179+
var refParametersOfParent = GetRefParameters(invocation.ArgumentList);
1180+
var (args, @params) = CreateArgumentsAndParametersLists(refParametersOfParent);
1181+
1182+
var localFunc = _typeContext.PerScopeState.Hoist(new HoistedFunction(localFuncName, returnType, block, SyntaxFactory.ParameterList(@params)));
1183+
return SyntaxFactory.InvocationExpression(localFunc.TempIdentifier, SyntaxFactory.ArgumentList(args));
1184+
1185+
List<IParameterSymbol> GetRefParameters(VBSyntax.ArgumentListSyntax argumentList)
1186+
{
1187+
var result = new List<IParameterSymbol>();
1188+
if (argumentList is null) return result;
1189+
1190+
foreach (var arg in argumentList.Arguments) {
1191+
if (_semanticModel.GetSymbolInfo(arg.GetExpression()).Symbol is not IParameterSymbol p) continue;
1192+
if (p.RefKind != RefKind.None) {
1193+
result.Add(p);
1194+
}
1195+
}
1196+
1197+
return result;
1198+
}
1199+
1200+
(SeparatedSyntaxList<ArgumentSyntax>, SeparatedSyntaxList<ParameterSyntax>) CreateArgumentsAndParametersLists(List<IParameterSymbol> parameterSymbols)
1201+
{
1202+
var arguments = new List<ArgumentSyntax>();
1203+
var parameters = new List<ParameterSyntax>();
1204+
foreach (var p in parameterSymbols) {
1205+
var arg = (ArgumentSyntax)CommonConversions.CsSyntaxGenerator.Argument(p.RefKind, SyntaxFactory.IdentifierName(p.Name));
1206+
arguments.Add(arg);
1207+
var par = (ParameterSyntax)CommonConversions.CsSyntaxGenerator.ParameterDeclaration(p);
1208+
parameters.Add(par);
1209+
}
1210+
return (SyntaxFactory.SeparatedList(arguments), SyntaxFactory.SeparatedList(parameters));
1211+
}
11801212
}
11811213

11821214
private bool RequiresLocalFunction(VBSyntax.InvocationExpressionSyntax invocation, IMethodSymbol invocationSymbol)

CodeConverter/CSharp/HoistedParameterlessFunction.cs renamed to CodeConverter/CSharp/HoistedFunction.cs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,25 @@
33

44
namespace ICSharpCode.CodeConverter.CSharp;
55

6-
internal class HoistedParameterlessFunction : IHoistedNode
6+
internal class HoistedFunction : IHoistedNode
77
{
88
private readonly TypeSyntax _returnType;
99
private readonly BlockSyntax _block;
10+
private readonly ParameterListSyntax _parameters;
1011

1112
public string Id { get; }
1213
public string Prefix { get; }
1314

14-
public HoistedParameterlessFunction(string localFuncName, TypeSyntax returnType, BlockSyntax block)
15+
public HoistedFunction(string localFuncName, TypeSyntax returnType, BlockSyntax block, ParameterListSyntax parameters)
1516
{
1617
Id = $"hs{Guid.NewGuid().ToString("N")}";
1718
Prefix = localFuncName;
1819
_returnType = returnType;
1920
_block = block;
21+
_parameters = parameters;
2022
}
2123

2224
public IdentifierNameSyntax TempIdentifier => ValidSyntaxFactory.IdentifierName(Id).WithAdditionalAnnotations(PerScopeState.AdditionalLocalAnnotation);
23-
public LocalFunctionStatementSyntax AsLocalFunction(string functionName) => SyntaxFactory.LocalFunctionStatement(_returnType, SyntaxFactory.Identifier(functionName)).WithBody(_block);
24-
public MethodDeclarationSyntax AsInstanceMethod(string functionName) => ValidSyntaxFactory.CreateParameterlessMethod(functionName, _returnType, _block);
25+
public LocalFunctionStatementSyntax AsLocalFunction(string functionName) => SyntaxFactory.LocalFunctionStatement(_returnType, SyntaxFactory.Identifier(functionName)).WithParameterList(_parameters).WithBody(_block);
26+
public MethodDeclarationSyntax AsInstanceMethod(string functionName) => ValidSyntaxFactory.CreateMethod(functionName, _returnType, _parameters, _block);
2527
}

CodeConverter/CSharp/PerScopeState.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,9 +86,9 @@ private StatementSyntax[] GetPostStatements()
8686
.ToArray();
8787
}
8888

89-
public IReadOnlyCollection<HoistedParameterlessFunction> GetParameterlessFunctions()
89+
public IReadOnlyCollection<HoistedFunction> GetParameterlessFunctions()
9090
{
91-
return _hoistedNodesPerScope.Peek().OfType<HoistedParameterlessFunction>().ToArray();
91+
return _hoistedNodesPerScope.Peek().OfType<HoistedFunction>().ToArray();
9292
}
9393

9494
public IReadOnlyCollection<HoistedFieldFromVbStaticVariable> GetFields()

CodeConverter/CSharp/ValidSyntaxFactory.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,10 +74,17 @@ expressionSyntax is IdentifierNameSyntax ||
7474
}
7575

7676
public static MethodDeclarationSyntax CreateParameterlessMethod(string newMethodName, TypeSyntax type, BlockSyntax body)
77+
{
78+
var parameterList = SyntaxFactory.ParameterList();
79+
return CreateMethod(newMethodName, type, parameterList, body);
80+
}
81+
82+
public static MethodDeclarationSyntax CreateMethod(string newMethodName, TypeSyntax type, ParameterListSyntax parameterList, BlockSyntax body)
7783
{
7884
var modifiers = SyntaxFactory.TokenList(SyntaxFactory.Token(SyntaxKind.StaticKeyword));
7985
var typeConstraints = SyntaxFactory.List<TypeParameterConstraintClauseSyntax>();
80-
var parameterList = SyntaxFactory.ParameterList();
86+
parameterList ??= SyntaxFactory.ParameterList();
87+
8188
var methodAttrs = SyntaxFactory.List<AttributeListSyntax>();
8289

8390
ArrowExpressionClauseSyntax arrowExpression = null;

0 commit comments

Comments
 (0)