Skip to content

Commit dffec18

Browse files
Assign names back to their originals - fixes #569
1 parent 5ec5b5f commit dffec18

File tree

9 files changed

+133
-26
lines changed

9 files changed

+133
-26
lines changed

CodeConverter/CSharp/AdditionalInitializers.cs

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,18 @@
55
using Microsoft.CodeAnalysis;
66
using Microsoft.CodeAnalysis.CSharp;
77
using Microsoft.CodeAnalysis.CSharp.Syntax;
8-
using ExpressionSyntax = Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionSyntax;
98

109
namespace ICSharpCode.CodeConverter.CSharp
1110
{
12-
public class AdditionalInitializers
11+
internal class AdditionalInitializers
1312
{
1413
public AdditionalInitializers(bool shouldAddTypeWideInitToThisPart)
1514
{
1615
ShouldAddTypeWideInitToThisPart = shouldAddTypeWideInitToThisPart;
1716
}
1817

19-
public List<(ExpressionSyntax Field, SyntaxKind AssignmentKind, ExpressionSyntax Initializer)> AdditionalStaticInitializers { get; } = new List<(ExpressionSyntax, SyntaxKind, ExpressionSyntax)>();
20-
public List<(ExpressionSyntax Field, SyntaxKind AssignmentKind, ExpressionSyntax Initializer)> AdditionalInstanceInitializers { get; } = new List<(ExpressionSyntax, SyntaxKind, ExpressionSyntax)>();
18+
public List<Assignment> AdditionalStaticInitializers { get; } = new List<Assignment>();
19+
public List<Assignment> AdditionalInstanceInitializers { get; } = new List<Assignment>();
2120
public bool ShouldAddTypeWideInitToThisPart { get; }
2221

2322
public IReadOnlyCollection<MemberDeclarationSyntax> WithAdditionalInitializers(ITypeSymbol parentType,
@@ -40,7 +39,7 @@ public IReadOnlyCollection<MemberDeclarationSyntax> WithAdditionalInitializers(I
4039
}
4140

4241
private List<MemberDeclarationSyntax> WithAdditionalInitializers(List<MemberDeclarationSyntax> convertedMembers,
43-
SyntaxToken convertIdentifier, IReadOnlyCollection<(ExpressionSyntax Field, SyntaxKind AssignmentKind, ExpressionSyntax Initializer)> additionalInitializers,
42+
SyntaxToken convertIdentifier, IReadOnlyCollection<Assignment> additionalInitializers,
4443
SyntaxTokenList modifiers, IEnumerable<ConstructorDeclarationSyntax> constructorsEnumerable, bool addConstructor, bool addedConstructorRequiresInitializeComponent)
4544
{
4645
if (!additionalInitializers.Any() && (!addConstructor || !addedConstructorRequiresInitializeComponent)) return convertedMembers;
@@ -64,17 +63,23 @@ private List<MemberDeclarationSyntax> WithAdditionalInitializers(List<MemberDecl
6463
}
6564

6665
private ConstructorDeclarationSyntax WithAdditionalInitializers(ConstructorDeclarationSyntax oldConstructor,
67-
IReadOnlyCollection<(ExpressionSyntax Field, SyntaxKind AssignmentKind, ExpressionSyntax Initializer)> additionalConstructorAssignments)
66+
IReadOnlyCollection<Assignment> additionalConstructorAssignments)
6867
{
69-
var initializerStatements = additionalConstructorAssignments.Select(assignment =>
70-
SyntaxFactory.ExpressionStatement(SyntaxFactory.AssignmentExpression(
71-
assignment.AssignmentKind, assignment.Field, assignment.Initializer))
72-
).ToList();
68+
var preInitializerStatements = CreateAssignmentStatement(additionalConstructorAssignments.Where(x => !x.PostAssignment));
69+
var postInitializerStatements = CreateAssignmentStatement(additionalConstructorAssignments.Where(x => x.PostAssignment));
7370
var oldConstructorBody = oldConstructor.Body ?? SyntaxFactory.Block(SyntaxFactory.ExpressionStatement(oldConstructor.ExpressionBody.Expression));
7471
var newConstructor = oldConstructor.WithBody(oldConstructorBody.WithStatements(
75-
oldConstructorBody.Statements.InsertRange(0, initializerStatements)));
72+
oldConstructorBody.Statements.InsertRange(0, preInitializerStatements).AddRange(postInitializerStatements)));
7673

7774
return newConstructor;
7875
}
76+
77+
private static List<ExpressionStatementSyntax> CreateAssignmentStatement(IEnumerable<Assignment> additionalConstructorAssignments)
78+
{
79+
return additionalConstructorAssignments.Select(assignment =>
80+
SyntaxFactory.ExpressionStatement(SyntaxFactory.AssignmentExpression(
81+
assignment.AssignmentKind, assignment.Field, assignment.Initializer))
82+
).ToList();
83+
}
7984
}
8085
}

CodeConverter/CSharp/Assignment.cs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
using System.Collections.Generic;
2+
using Microsoft.CodeAnalysis.CSharp;
3+
using Microsoft.CodeAnalysis.CSharp.Syntax;
4+
5+
namespace ICSharpCode.CodeConverter.CSharp
6+
{
7+
internal struct Assignment
8+
{
9+
public ExpressionSyntax Field;
10+
public SyntaxKind AssignmentKind;
11+
public ExpressionSyntax Initializer;
12+
public bool PostAssignment;
13+
14+
public Assignment(ExpressionSyntax field, SyntaxKind assignmentKind, ExpressionSyntax initializer, bool postAssignment = false)
15+
{
16+
Field = field;
17+
AssignmentKind = assignmentKind;
18+
Initializer = initializer;
19+
PostAssignment = postAssignment;
20+
}
21+
22+
public override bool Equals(object obj) => obj is Assignment other &&
23+
(other.Field, other.AssignmentKind, other.Initializer, other.PostAssignment).Equals((Field, AssignmentKind, Initializer, PostAssignment));
24+
25+
26+
public override int GetHashCode() => (Field, AssignmentKind, Initializer, PostAssignment).GetHashCode();
27+
28+
public void Deconstruct(out ExpressionSyntax field, out SyntaxKind assignmentKind, out ExpressionSyntax initializer)
29+
{
30+
field = Field;
31+
assignmentKind = AssignmentKind;
32+
initializer = Initializer;
33+
}
34+
35+
public static implicit operator Assignment((ExpressionSyntax Field, SyntaxKind AssignmentKind, ExpressionSyntax Initializer) value)
36+
{
37+
return new Assignment(value.Field, value.AssignmentKind, value.Initializer);
38+
}
39+
}
40+
}

CodeConverter/CSharp/DeclarationNodeVisitor.cs

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -206,11 +206,17 @@ private async Task<IEnumerable<MemberDeclarationSyntax>> ConvertMembersAsync(VBS
206206
var requiresInitializeComponent = namedTypeSymbol.IsDesignerGeneratedTypeWithInitializeComponent(_vbCompilation);
207207

208208
if (shouldAddTypeWideInitToThisPart) {
209-
var constructorFieldInitializersFromOtherParts = GetConstructorFieldInitializersFromOtherParts(namedTypeSymbol);
209+
var otherPartsOfType = GetAllPartsOfType(parentType, namedTypeSymbol).ToArray();
210+
var constructorFieldInitializersFromOtherParts = otherPartsOfType
211+
.Where(t => (!Equals(t.Type.SyntaxTree.FilePath, _semanticModel.SyntaxTree.FilePath) || !t.Type.Span.Equals(parentType.Span)))
212+
.SelectMany(r => GetFieldsIdentifiersWithInitializer(r.Type, r.SemanticModel));
210213
additionalInitializers.AdditionalInstanceInitializers.AddRange(constructorFieldInitializersFromOtherParts);
211214
if (requiresInitializeComponent) {
212215
// Constructor event handlers not required since they'll be inside InitializeComponent - see other use of IsDesignerGeneratedTypeWithInitializeComponent
213-
directlyConvertedMembers = directlyConvertedMembers.Concat(methodsWithHandles.CreateDelegatingMethodsRequiredByInitializeComponent());
216+
directlyConvertedMembers = directlyConvertedMembers
217+
.Concat(methodsWithHandles.CreateDelegatingMethodsRequiredByInitializeComponent());
218+
additionalInitializers.AdditionalInstanceInitializers
219+
.AddRange(WinformsConversions.GetNameAssignments(otherPartsOfType));
214220
} else {
215221
additionalInitializers.AdditionalInstanceInitializers.AddRange(methodsWithHandles.GetConstructorEventHandlers());
216222
}
@@ -231,24 +237,23 @@ async Task<MemberDeclarationSyntax[]> GetDirectlyConvertedMembers(AdditionalInit
231237
}
232238
}
233239

234-
private IEnumerable<(ExpressionSyntax, CSSyntaxKind SimpleAssignmentExpression, ExpressionSyntax)> GetConstructorFieldInitializersFromOtherParts(ITypeSymbol parentType)
240+
private IEnumerable<(VBSyntax.TypeBlockSyntax Type, SemanticModel SemanticModel)> GetAllPartsOfType(VBSyntax.TypeBlockSyntax parentTypeBlock, ITypeSymbol parentType)
235241
{
236242
return parentType.DeclaringSyntaxReferences
237-
.Where(r => !Equals(r.SyntaxTree.FilePath, _semanticModel.SyntaxTree.FilePath))
238-
.Select(t => (Type: t.GetSyntax().Parent as VBSyntax.TypeBlockSyntax, SemanticModel: _vbCompilation.GetSemanticModel(t.SyntaxTree)))
239-
.Where(t => t.Type != null)
240-
.SelectMany(r => GetFieldsIdentifiersWithInitializer(r.Type, r.SemanticModel));
243+
.Select(t => t.GetSyntax().Parent as VBSyntax.TypeBlockSyntax)
244+
.Where(t => t != null)
245+
.Select(t => (Type: t, SemanticModel: _vbCompilation.GetSemanticModel(t.SyntaxTree)));
241246
}
242247

243-
private IEnumerable<(ExpressionSyntax, CSSyntaxKind SimpleAssignmentExpression, ExpressionSyntax)> GetFieldsIdentifiersWithInitializer(VBSyntax.TypeBlockSyntax tbs, SemanticModel semanticModel)
248+
private IEnumerable<Assignment> GetFieldsIdentifiersWithInitializer(VBSyntax.TypeBlockSyntax tbs, SemanticModel semanticModel)
244249
{
245250
return tbs.Members.OfType<VBSyntax.FieldDeclarationSyntax>()
246251
.SelectMany(f => f.Declarators.SelectMany(d => d.Names.Select(n => (n, d.Initializer))))
247252
.Where(f => !semanticModel.IsDefinitelyStatic(f.n, f.Initializer?.Value))
248253
.Select(f => CreateInitializer(f));
249254
}
250255

251-
private (ExpressionSyntax, CSSyntaxKind SimpleAssignmentExpression, ExpressionSyntax) CreateInitializer((VBSyntax.ModifiedIdentifierSyntax n, VBSyntax.EqualsValueSyntax Initializer) f)
256+
private Assignment CreateInitializer((VBSyntax.ModifiedIdentifierSyntax n, VBSyntax.EqualsValueSyntax Initializer) f)
252257
{
253258
var csId = CommonConversions.ConvertIdentifier(f.n.Identifier);
254259
string initializerFunctionName = CommonConversions.GetInitialValueFunctionName(f.n);

CodeConverter/CSharp/MethodWithHandles.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
namespace ICSharpCode.CodeConverter.CSharp
1313
{
14-
public class MethodWithHandles
14+
internal class MethodWithHandles
1515
{
1616
private IdentifierNameSyntax _methodId;
1717
private readonly SyntaxGenerator _csSyntaxGenerator;
@@ -173,10 +173,10 @@ private static ExpressionSyntax MemberAccess(ExpressionSyntax eventSource, (Synt
173173
eventSource, SyntaxFactory.IdentifierName(e.EventSymbolName));
174174
}
175175

176-
public IEnumerable<(ExpressionSyntax EventField, SyntaxKind AssignmentKind, ExpressionSyntax HandlerId)> GetConstructorEventHandlers()
176+
public IEnumerable<Assignment> GetConstructorEventHandlers()
177177
{
178178
return HandledClassEventCSharpIds.Select(e =>
179-
(MemberAccess(SyntaxFactory.IdentifierName(e.EventContainerName), e), SyntaxKind.AddAssignmentExpression, Invocable(_methodId, e.ParametersToDiscard))
179+
new Assignment(MemberAccess(SyntaxFactory.IdentifierName(e.EventContainerName), e), SyntaxKind.AddAssignmentExpression, Invocable(_methodId, e.ParametersToDiscard))
180180
);
181181
}
182182

CodeConverter/CSharp/MethodsWithHandles.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ public IEnumerable<StatementSyntax> GetInitializeComponentClassEventHandlers()
6767
return _methodWithHandleses.SelectMany(m => m.GetInitializeComponentClassEventHandlers()).ToArray();
6868
}
6969

70-
public (ExpressionSyntax EventField, SyntaxKind AssignmentKind, ExpressionSyntax HandlerId)[] GetConstructorEventHandlers()
70+
public Assignment[] GetConstructorEventHandlers()
7171
{
7272
return _methodWithHandleses.SelectMany(m => m.GetConstructorEventHandlers()).ToArray();
7373
}

CodeConverter/CSharp/WinformsConversions.cs

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
1-
using System.Linq;
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
24
using ICSharpCode.CodeConverter.Util;
35
using Microsoft.CodeAnalysis;
6+
using Microsoft.CodeAnalysis.CSharp;
7+
using VBasic = Microsoft.CodeAnalysis.VisualBasic;
48
using VBSyntax = Microsoft.CodeAnalysis.VisualBasic.Syntax;
59

610
namespace ICSharpCode.CodeConverter.CSharp
@@ -18,7 +22,13 @@ public static bool MustInlinePropertyWithEventsAccess(SyntaxNode anyNodePossibly
1822

1923
public static bool InMethodCalledInitializeComponent(SyntaxNode anyNodePossiblyWithinMethod)
2024
{
21-
return anyNodePossiblyWithinMethod.GetAncestor<VBSyntax.MethodBlockSyntax>()?.SubOrFunctionStatement.Identifier.Text == "InitializeComponent";
25+
var methodBlockSyntax = anyNodePossiblyWithinMethod.GetAncestor<VBSyntax.MethodBlockSyntax>();
26+
return IsInitializeComponent(methodBlockSyntax);
27+
}
28+
29+
private static bool IsInitializeComponent(VBSyntax.MethodBlockSyntax methodBlockSyntax)
30+
{
31+
return methodBlockSyntax?.SubOrFunctionStatement.Identifier.Text == "InitializeComponent";
2232
}
2333

2434
/// <summary>
@@ -32,5 +42,32 @@ assignment.Left is VBSyntax.MemberAccessExpressionSyntax maes &&
3242
!(maes.Expression is VBSyntax.MeExpressionSyntax) &&
3343
maes.Name.ToString() == "Name";
3444
}
45+
46+
private static T LastOrDefaultDescendant<T>(this VBasic.VisualBasicSyntaxNode syntaxNode) {
47+
return syntaxNode.DescendantNodes().OfType<T>().LastOrDefault();
48+
}
49+
50+
internal static IEnumerable<Assignment> GetNameAssignments((VBSyntax.TypeBlockSyntax Type, SemanticModel SemanticModel)[] otherPartsOfType)
51+
{
52+
return otherPartsOfType.SelectMany(typePart =>
53+
typePart.Type.Members.OfType<VBSyntax.MethodBlockSyntax>()
54+
.Where(IsInitializeComponent)
55+
.SelectMany(GetAssignments)
56+
);
57+
}
58+
59+
private static IEnumerable<Assignment> GetAssignments(VBSyntax.MethodBlockSyntax initializeComponent)
60+
{
61+
return initializeComponent.Statements
62+
.OfType<VBSyntax.AssignmentStatementSyntax>()
63+
.Where(ShouldPrefixAssignedNameWithUnderscore)
64+
.Select(s => (s.Left as VBSyntax.MemberAccessExpressionSyntax)?.Expression.LastOrDefaultDescendant<VBSyntax.IdentifierNameSyntax>())
65+
.Where(s => s != null)
66+
.Select(id => {
67+
var nameAccess = ValidSyntaxFactory.MemberAccess(SyntaxFactory.IdentifierName("_" + id.Identifier.Text), "Name");
68+
var originalRuntimeNameToRestore = SyntaxFactory.LiteralExpression(SyntaxKind.StringLiteralExpression, SyntaxFactory.Literal(id.Identifier.Text));
69+
return new Assignment(nameAccess, SyntaxKind.SimpleAssignmentExpression, originalRuntimeNameToRestore, true);
70+
});
71+
}
3572
}
3673
}

Tests/CSharp/MemberTests/EventMemberTests.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -525,6 +525,7 @@ public partial class TestHandlesAdded
525525
public TestHandlesAdded()
526526
{
527527
InitializeComponent();
528+
_POW_btnV2DBM.Name = ""POW_btnV2DBM"";
528529
}
529530
530531
public void InitializeComponent()

Tests/TestData/MultiFileCharacterization/VBToCSResults/ConvertWholeSolution/WindowsAppVb/Folder/FolderForm.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,22 @@ public partial class FolderForm
1212
public FolderForm()
1313
{
1414
InitializeComponent();
15+
_ToolStrip1.Name = "ToolStrip1";
16+
_ToolStripButton1.Name = "ToolStripButton1";
17+
_ToolStripButton2.Name = "ToolStripButton2";
18+
_ToolStripButton3.Name = "ToolStripButton3";
19+
_ToolStripButton4.Name = "ToolStripButton4";
20+
_ToolStripButton5.Name = "ToolStripButton5";
21+
_ToolStripButton6.Name = "ToolStripButton6";
22+
_ToolStripButton7.Name = "ToolStripButton7";
23+
_ToolStripButton8.Name = "ToolStripButton8";
24+
_ToolStripButton9.Name = "ToolStripButton9";
25+
_ToolStripButton10.Name = "ToolStripButton10";
26+
_ToolStripButton11.Name = "ToolStripButton11";
27+
_ToolStripButton12.Name = "ToolStripButton12";
28+
_ToolStripButton13.Name = "ToolStripButton13";
29+
_ToolStripButton14.Name = "ToolStripButton14";
30+
_ToolStripButton15.Name = "ToolStripButton15";
1531
}
1632

1733
private void FolderForm_Load(object sender, EventArgs e)

Tests/TestData/MultiFileCharacterization/VBToCSResults/ConvertWholeSolution/WindowsAppVb/WinformsDesignerTest.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ public partial class WinformsDesignerTest
88
public WinformsDesignerTest()
99
{
1010
InitializeComponent();
11+
_Button1.Name = "Button1";
12+
_CheckBox1.Name = "CheckBox1";
13+
_Button2.Name = "Button2";
1114
}
1215

1316
private void Button1_Click(object sender, EventArgs e)

0 commit comments

Comments
 (0)