Skip to content

Commit ab34487

Browse files
Rename after
1 parent c942216 commit ab34487

9 files changed

Lines changed: 75 additions & 52 deletions

File tree

CodeConverter/CSharp/AdditionalDeclaration.cs

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -23,23 +23,5 @@ public AdditionalDeclaration(string prefix, ExpressionSyntax initializer, TypeSy
2323
}
2424

2525
public IdentifierNameSyntax IdentifierName => SyntaxFactory.IdentifierName(Id).WithAdditionalAnnotations(HoistedNodeState.Annotation);
26-
27-
28-
public static IEnumerable<StatementSyntax> ReplaceNames(IEnumerable<StatementSyntax> csNodes, Dictionary<string, string> newNames)
29-
{
30-
csNodes = csNodes.Select(csNode => ReplaceNames(csNode, newNames)).ToList();
31-
return csNodes;
32-
}
33-
34-
public static T ReplaceNames<T>(T csNode, Dictionary<string, string> newNames) where T: SyntaxNode
35-
{
36-
return csNode.ReplaceNodes(csNode.GetAnnotatedNodes(HoistedNodeState.Annotation), (_, withReplaced) => {
37-
var idns = (IdentifierNameSyntax)withReplaced;
38-
if (newNames.TryGetValue(idns.Identifier.ValueText, out var newName)) {
39-
return idns.WithoutAnnotations(HoistedNodeState.Annotation).WithIdentifier(SyntaxFactory.Identifier(newName));
40-
}
41-
return idns;
42-
});
43-
}
4426
}
4527
}

CodeConverter/CSharp/DeclarationNodeVisitor.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -555,7 +555,7 @@ private IEnumerable<MemberDeclarationSyntax> CreateAdditionalLocalMembers(Syntax
555555

556556
// This should probably use a unique name like in MethodBodyVisitor - a collision is far less likely here
557557
var newNames = declarationInfo.ToDictionary(l => l.Id, l => l.Prefix);
558-
var newInitializer = AdditionalDeclaration.ReplaceNames(v.Initializer.Value, newNames);
558+
var newInitializer = HoistedNodeState.ReplaceNames(v.Initializer.Value, newNames);
559559

560560
var body = SyntaxFactory.Block(localVars.Concat(SyntaxFactory.ReturnStatement(newInitializer).Yield()));
561561
// Method calls in initializers must be static in C# - Supporting this is #281

CodeConverter/CSharp/ExpressionNodeVisitor.cs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -930,15 +930,13 @@ private async Task<InvocationExpressionSyntax> HoistAndCallLocalFunction(VBSynta
930930

931931
var statements = await _additionalLocals.CreateLocals(invocation, new[] { callAndStoreResult }, generatedNames, _semanticModel);
932932

933-
var localFuncId = SyntaxFactory.IdentifierName(localFuncName);
934-
935933
var block = SyntaxFactory.Block(
936934
statements.Concat(SyntaxFactory.ReturnStatement(SyntaxFactory.IdentifierName(retVariableName)).Yield())
937935
);
938-
var localFunction = SyntaxFactory.LocalFunctionStatement(CommonConversions.GetTypeSyntax(invocationSymbol.ReturnType),
939-
localFuncId.Identifier).WithBody(block);
940-
_additionalLocals.Hoist(new HoistedStatement(localFunction));
941-
return SyntaxFactory.InvocationExpression(localFuncId, SyntaxFactory.ArgumentList());
936+
var returnType = CommonConversions.GetTypeSyntax(invocationSymbol.ReturnType);
937+
938+
var localFunc = _additionalLocals.Hoist(new HoistedLocalFunction(localFuncName, returnType, block));
939+
return SyntaxFactory.InvocationExpression(localFunc.TempIdentifier, SyntaxFactory.ArgumentList());
942940
}
943941

944942
private bool RequiresLocalFunction(VBSyntax.InvocationExpressionSyntax invocation, IMethodSymbol invocationSymbol)
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
using System;
2+
using Microsoft.CodeAnalysis;
3+
using Microsoft.CodeAnalysis.CSharp;
4+
using Microsoft.CodeAnalysis.CSharp.Syntax;
5+
6+
namespace ICSharpCode.CodeConverter.CSharp
7+
{
8+
internal class HoistedLocalFunction : IHoistedNode
9+
{
10+
private readonly TypeSyntax _returnType;
11+
private readonly BlockSyntax _block;
12+
13+
public string Id { get; }
14+
public string Prefix { get; }
15+
16+
public HoistedLocalFunction(string localFuncName, TypeSyntax returnType, BlockSyntax block)
17+
{
18+
Id = $"hs{Guid.NewGuid().ToString("N")}";
19+
Prefix = localFuncName;
20+
_returnType = returnType;
21+
_block = block;
22+
}
23+
24+
public IdentifierNameSyntax TempIdentifier => SyntaxFactory.IdentifierName(Id).WithAdditionalAnnotations(HoistedNodeState.Annotation);
25+
public LocalFunctionStatementSyntax LocalFunction(string functionName) => SyntaxFactory.LocalFunctionStatement(_returnType, SyntaxFactory.Identifier(functionName)).WithBody(_block);
26+
}
27+
}

CodeConverter/CSharp/HoistedNodeState.cs

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
using CS = Microsoft.CodeAnalysis.CSharp;
99
using ICSharpCode.CodeConverter.Shared;
1010
using System;
11+
using Microsoft.CodeAnalysis.CSharp.Syntax;
12+
using Microsoft.CodeAnalysis.CSharp;
1113

1214
namespace ICSharpCode.CodeConverter.CSharp
1315
{
@@ -57,15 +59,26 @@ public IReadOnlyCollection<AdditionalAssignment> GetPostAssignments()
5759
return _hoistedNodesPerScope.Peek().OfType<AdditionalAssignment>().ToArray();
5860
}
5961

60-
public IReadOnlyCollection<HoistedStatement> GetStatements()
62+
public IReadOnlyCollection<HoistedLocalFunction> GetStatements()
6163
{
62-
return _hoistedNodesPerScope.Peek().OfType<HoistedStatement>().ToArray();
64+
return _hoistedNodesPerScope.Peek().OfType<HoistedLocalFunction>().ToArray();
6365
}
6466

65-
public async Task<SyntaxList<CS.Syntax.StatementSyntax>> CreateLocals(VBasic.VisualBasicSyntaxNode vbNode, IEnumerable<CS.Syntax.StatementSyntax> csNodes, HashSet<string> generatedNames, SemanticModel semanticModel)
67+
public SyntaxList<StatementSyntax> CreateStatements(VBasic.VisualBasicSyntaxNode vbNode, IEnumerable<StatementSyntax> statements, HashSet<string> generatedNames, SemanticModel semanticModel)
6668
{
67-
var preDeclarations = new List<CS.Syntax.StatementSyntax>();
68-
var postAssignments = new List<CS.Syntax.StatementSyntax>();
69+
var localFunctions = GetStatements();
70+
var newNames = localFunctions.ToDictionary(f => f.Id, f =>
71+
NameGenerator.GetUniqueVariableNameInScope(semanticModel, generatedNames, vbNode, f.Prefix)
72+
);
73+
statements = ReplaceNames(statements, newNames);
74+
var functions = localFunctions.Select(f => f.LocalFunction(newNames[f.Id]));
75+
return SyntaxFactory.List(functions.Concat(statements));
76+
}
77+
78+
public async Task<SyntaxList<StatementSyntax>> CreateLocals(VBasic.VisualBasicSyntaxNode vbNode, IEnumerable<StatementSyntax> csNodes, HashSet<string> generatedNames, SemanticModel semanticModel)
79+
{
80+
var preDeclarations = new List<StatementSyntax>();
81+
var postAssignments = new List<StatementSyntax>();
6982

7083
var additionalDeclarationInfo = GetDeclarations();
7184
var newNames = additionalDeclarationInfo.ToDictionary(l => l.Id, l =>
@@ -82,9 +95,26 @@ public IReadOnlyCollection<HoistedStatement> GetStatements()
8295
postAssignments.Add(CS.SyntaxFactory.ExpressionStatement(assign));
8396
}
8497

85-
var statementsWithUpdatedIds = AdditionalDeclaration.ReplaceNames(preDeclarations.Concat(csNodes).Concat(postAssignments), newNames);
98+
var statementsWithUpdatedIds = ReplaceNames(preDeclarations.Concat(csNodes).Concat(postAssignments), newNames);
8699

87100
return CS.SyntaxFactory.List(statementsWithUpdatedIds);
88101
}
102+
103+
public static IEnumerable<StatementSyntax> ReplaceNames(IEnumerable<StatementSyntax> csNodes, Dictionary<string, string> newNames)
104+
{
105+
csNodes = csNodes.Select(csNode => ReplaceNames(csNode, newNames)).ToList();
106+
return csNodes;
107+
}
108+
109+
public static T ReplaceNames<T>(T csNode, Dictionary<string, string> newNames) where T : SyntaxNode
110+
{
111+
return csNode.ReplaceNodes(csNode.GetAnnotatedNodes(Annotation), (_, withReplaced) => {
112+
var idns = (IdentifierNameSyntax)withReplaced;
113+
if (newNames.TryGetValue(idns.Identifier.ValueText, out var newName)) {
114+
return idns.WithoutAnnotations(Annotation).WithIdentifier(CS.SyntaxFactory.Identifier(newName));
115+
}
116+
return idns;
117+
});
118+
}
89119
}
90120
}

CodeConverter/CSharp/HoistedNodeStateVisitor.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ private async Task<SyntaxList<StatementSyntax>> AddLocalVariables(VBasic.VisualB
4646
try {
4747
var csNodes = await _wrappedVisitor.Visit(node);
4848
var statements = await _additionalLocals.CreateLocals(node, csNodes, _generatedNames, _semanticModel);
49-
return statements.InsertRange(0, _additionalLocals.GetStatements().Select(s => s.Statement));
49+
return _additionalLocals.CreateStatements(node, statements, _generatedNames, _semanticModel);
5050
} finally {
5151
_additionalLocals.PopScope();
5252
}

CodeConverter/CSharp/HoistedStatement.cs

Lines changed: 0 additions & 14 deletions
This file was deleted.

CodeConverter/VB/CommonConversions.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -322,9 +322,9 @@ public LambdaExpressionSyntax ConvertLambdaExpression(CSS.AnonymousFunctionExpre
322322
return CreateLambdaExpression(singleLineExpressionKind, multiLineExpressionKind, header, statements, endBlock);
323323

324324
}
325-
StatementSyntax GetStatementSyntax(VisualBasicSyntaxNode node, Func<ExpressionSyntax, StatementSyntax> create) {
326-
if (node is StatementSyntax)
327-
return (StatementSyntax)node;
325+
326+
private StatementSyntax GetStatementSyntax(VisualBasicSyntaxNode node, Func<ExpressionSyntax, StatementSyntax> create) {
327+
if (node is StatementSyntax syntax) return syntax;
328328
return create(node as ExpressionSyntax);
329329
}
330330

Tests/CSharp/ExpressionTests/ByRefTests.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -398,9 +398,9 @@ public void UsesRef(bool someBool, int someInt)
398398
int argvrbTst3 = Prop;
399399
bool c = TakesRef(ref argvrbTst3);
400400
Prop = argvrbTst3; // Requires variable before, and to assign back after
401-
bool localTakesRef1() { int argvrbTst = Prop; var ret = TakesRef(ref argvrbTst); Prop = argvrbTst; return ret; }
401+
bool localTakesRef() { int argvrbTst = Prop; var ret = TakesRef(ref argvrbTst); Prop = argvrbTst; return ret; }
402402
403-
bool localTakesRef2() { int argvrbTst = 3; var ret = TakesRef(ref argvrbTst); return ret; }
403+
bool localTakesRef1() { int argvrbTst = 3; var ret = TakesRef(ref argvrbTst); return ret; }
404404
405405
if (16 > someInt || TakesRef(ref someInt)) // Convert directly
406406
{
@@ -410,7 +410,7 @@ public void UsesRef(bool someBool, int someInt)
410410
{
411411
someInt += 1;
412412
}
413-
else if (localTakesRef2()) // Requires variable before, and to assign back after (in local function)
413+
else if (localTakesRef()) // Requires variable before, and to assign back after (in local function)
414414
{
415415
someInt -= 2;
416416
}

0 commit comments

Comments
 (0)