Skip to content

Commit 65254e0

Browse files
Extract method
1 parent a90e7fd commit 65254e0

File tree

1 file changed

+80
-77
lines changed

1 file changed

+80
-77
lines changed

CodeConverter/CSharp/DeclarationNodeVisitor.cs

Lines changed: 80 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -467,101 +467,104 @@ private async Task<List<MemberDeclarationSyntax>> GetMemberDeclarations(VBSyntax
467467
foreach (var declarator in node.Declarators)
468468
{
469469
var splitDeclarations = await CommonConversions.SplitVariableDeclarations(declarator, preferExplicitType: true);
470-
declarations.AddRange(CreateFieldDeclarations(splitDeclarations, isWithEvents, convertedModifiers, attributes));
470+
declarations.AddRange(CreateMemberDeclarations(splitDeclarations.Variables, isWithEvents, convertedModifiers, attributes));
471471
declarations.AddRange(splitDeclarations.Methods.Cast<MemberDeclarationSyntax>());
472472
}
473473

474474
return declarations;
475475
}
476476

477-
private IEnumerable<MemberDeclarationSyntax> CreateFieldDeclarations((IReadOnlyCollection<VariableDeclarationSyntax> Variables, IReadOnlyCollection<CSharpSyntaxNode> Methods) splitDeclarations,
477+
private IEnumerable<MemberDeclarationSyntax> CreateMemberDeclarations(IReadOnlyCollection<VariableDeclarationSyntax> splitDeclarationVariables,
478478
bool isWithEvents, SyntaxTokenList convertedModifiers, List<AttributeListSyntax> attributes)
479479
{
480-
foreach (var decl in splitDeclarations.Variables)
480+
foreach (var decl in splitDeclarationVariables)
481481
{
482482
if (isWithEvents) {
483-
_extraUsingDirectives.Add("System.Runtime.CompilerServices");
484-
var initializers = decl.Variables
485-
.Where(a => a.Initializer != null)
486-
.ToDictionary(v => v.Identifier.Text, v => v.Initializer);
487-
var fieldDecl = decl.RemoveNodes(initializers.Values, SyntaxRemoveOptions.KeepNoTrivia);
488-
var initializerCollection = convertedModifiers.Any(m => m.IsKind(Microsoft.CodeAnalysis.CSharp.SyntaxKind.StaticKeyword))
489-
? _additionalInitializers.AdditionalStaticInitializers
490-
: _additionalInitializers.AdditionalInstanceInitializers;
491-
foreach (var initializer in initializers)
483+
var fieldDecls = CreateWithEventsMembers(convertedModifiers, attributes, decl);
484+
foreach (var f in fieldDecls) yield return f;
485+
} else
486+
{
487+
if (_additionalLocals.Count() > 0) {
488+
foreach (var additionalDecl in CreateAdditionalLocalMembers(convertedModifiers, attributes, decl)) {
489+
yield return additionalDecl;
490+
}
491+
} else
492492
{
493-
initializerCollection.Add((SyntaxFactory.IdentifierName(initializer.Key), Microsoft.CodeAnalysis.CSharp.SyntaxKind.SimpleAssignmentExpression, initializer.Value.Value));
493+
yield return SyntaxFactory.FieldDeclaration(SyntaxFactory.List(attributes), convertedModifiers, decl);
494494
}
495495

496-
var fieldDecls = _methodsWithHandles.GetDeclarationsForFieldBackedProperty(fieldDecl,
497-
convertedModifiers, SyntaxFactory.List(attributes));
498-
foreach(var f in fieldDecls) yield return f;
496+
499497
}
500-
else
501-
{
502-
FieldDeclarationSyntax baseFieldDeclarationSyntax;
503-
if (_additionalLocals.Count() > 0)
504-
{
505-
if (decl.Variables.Count > 1)
506-
{
507-
// Currently no way to tell which _additionalLocals would apply to which initializer
508-
throw new NotImplementedException(
509-
"Fields with multiple declarations and initializers with ByRef parameters not currently supported");
510-
}
498+
}
499+
}
511500

512-
var v = decl.Variables.First();
513-
var invocations = v.Initializer.Value.DescendantNodesAndSelf().OfType<InvocationExpressionSyntax>().ToArray();
514-
if (invocations.Length > 1)
515-
{
516-
throw new NotImplementedException(
517-
"Field initializers with nested method calls not currently supported");
518-
}
501+
private IEnumerable<MemberDeclarationSyntax> CreateWithEventsMembers(SyntaxTokenList convertedModifiers, List<AttributeListSyntax> attributes, VariableDeclarationSyntax decl)
502+
{
503+
_extraUsingDirectives.Add("System.Runtime.CompilerServices");
504+
var initializers = decl.Variables
505+
.Where(a => a.Initializer != null)
506+
.ToDictionary(v => v.Identifier.Text, v => v.Initializer);
507+
var fieldDecl = decl.RemoveNodes(initializers.Values, SyntaxRemoveOptions.KeepNoTrivia);
508+
var initializerCollection = convertedModifiers.Any(m => m.IsKind(Microsoft.CodeAnalysis.CSharp.SyntaxKind.StaticKeyword))
509+
? _additionalInitializers.AdditionalStaticInitializers
510+
: _additionalInitializers.AdditionalInstanceInitializers;
511+
foreach (var initializer in initializers) {
512+
initializerCollection.Add((SyntaxFactory.IdentifierName(initializer.Key), Microsoft.CodeAnalysis.CSharp.SyntaxKind.SimpleAssignmentExpression, initializer.Value.Value));
513+
}
519514

520-
var invocationExpressionSyntax = invocations.First();
521-
var methodName = invocationExpressionSyntax.Expression
522-
.ChildNodes().OfType<SimpleNameSyntax>().Last();
523-
var newMethodName = $"{methodName.Identifier.ValueText}_{v.Identifier.ValueText}";
524-
var localVars = _additionalLocals.Select(l => l.Value)
525-
.Select(al =>
526-
SyntaxFactory.LocalDeclarationStatement(
527-
CommonConversions.CreateVariableDeclarationAndAssignment(al.Prefix, al.Initializer)))
528-
.Cast<StatementSyntax>().ToList();
529-
var newInitializer = v.Initializer.Value.ReplaceNodes(
530-
v.Initializer.Value.GetAnnotatedNodes(AdditionalLocals.Annotation), (an, _) =>
531-
{
532-
// This should probably use a unique name like in MethodBodyVisitor - a collision is far less likely here
533-
var id = ((IdentifierNameSyntax) an).Identifier.ValueText;
534-
return SyntaxFactory.IdentifierName(_additionalLocals[id].Prefix);
535-
});
536-
var body = SyntaxFactory.Block(
537-
localVars.Concat(SyntaxFactory.SingletonList(SyntaxFactory.ReturnStatement(newInitializer))));
538-
var methodAttrs = SyntaxFactory.List<AttributeListSyntax>();
539-
// Method calls in initializers must be static in C# - Supporting this is #281
540-
var modifiers = SyntaxFactory.TokenList(SyntaxFactory.Token(Microsoft.CodeAnalysis.CSharp.SyntaxKind.StaticKeyword));
541-
var typeConstraints = SyntaxFactory.List<TypeParameterConstraintClauseSyntax>();
542-
var parameterList = SyntaxFactory.ParameterList();
543-
var methodDecl = SyntaxFactory.MethodDeclaration(methodAttrs, modifiers, decl.Type, null,
544-
SyntaxFactory.Identifier(newMethodName), null, parameterList, typeConstraints, body, null);
545-
yield return methodDecl;
546-
547-
var newVar =
548-
v.WithInitializer(SyntaxFactory.EqualsValueClause(
549-
SyntaxFactory.InvocationExpression(SyntaxFactory.IdentifierName(newMethodName))));
550-
var newVarDecl =
551-
SyntaxFactory.VariableDeclaration(decl.Type, SyntaxFactory.SingletonSeparatedList(newVar));
552-
553-
baseFieldDeclarationSyntax =
554-
SyntaxFactory.FieldDeclaration(SyntaxFactory.List(attributes), convertedModifiers, newVarDecl);
555-
}
556-
else
557-
{
558-
baseFieldDeclarationSyntax =
559-
SyntaxFactory.FieldDeclaration(SyntaxFactory.List(attributes), convertedModifiers, decl);
560-
}
515+
var fieldDecls = _methodsWithHandles.GetDeclarationsForFieldBackedProperty(fieldDecl,
516+
convertedModifiers, SyntaxFactory.List(attributes));
517+
return fieldDecls;
518+
}
561519

562-
yield return baseFieldDeclarationSyntax;
563-
}
520+
private IEnumerable<MemberDeclarationSyntax> CreateAdditionalLocalMembers(SyntaxTokenList convertedModifiers, List<AttributeListSyntax> attributes, VariableDeclarationSyntax decl)
521+
{
522+
if (decl.Variables.Count > 1) {
523+
// Currently no way to tell which _additionalLocals would apply to which initializer
524+
throw new NotImplementedException(
525+
"Fields with multiple declarations and initializers with ByRef parameters not currently supported");
526+
}
527+
528+
var v = decl.Variables.First();
529+
var invocations = v.Initializer.Value.DescendantNodesAndSelf().OfType<InvocationExpressionSyntax>().ToArray();
530+
if (invocations.Length > 1) {
531+
throw new NotImplementedException(
532+
"Field initializers with nested method calls not currently supported");
564533
}
534+
535+
var invocationExpressionSyntax = invocations.First();
536+
var methodName = invocationExpressionSyntax.Expression
537+
.ChildNodes().OfType<SimpleNameSyntax>().Last();
538+
var newMethodName = $"{methodName.Identifier.ValueText}_{v.Identifier.ValueText}";
539+
var localVars = _additionalLocals.Select(l => l.Value)
540+
.Select(al =>
541+
SyntaxFactory.LocalDeclarationStatement(
542+
CommonConversions.CreateVariableDeclarationAndAssignment(al.Prefix, al.Initializer)))
543+
.Cast<StatementSyntax>().ToList();
544+
var newInitializer = v.Initializer.Value.ReplaceNodes(
545+
v.Initializer.Value.GetAnnotatedNodes(AdditionalLocals.Annotation), (an, _) => {
546+
// This should probably use a unique name like in MethodBodyVisitor - a collision is far less likely here
547+
var id = ((IdentifierNameSyntax)an).Identifier.ValueText;
548+
return SyntaxFactory.IdentifierName(_additionalLocals[id].Prefix);
549+
});
550+
var body = SyntaxFactory.Block(
551+
localVars.Concat(SyntaxFactory.SingletonList(SyntaxFactory.ReturnStatement(newInitializer))));
552+
var methodAttrs = SyntaxFactory.List<AttributeListSyntax>();
553+
// Method calls in initializers must be static in C# - Supporting this is #281
554+
var modifiers = SyntaxFactory.TokenList(SyntaxFactory.Token(Microsoft.CodeAnalysis.CSharp.SyntaxKind.StaticKeyword));
555+
var typeConstraints = SyntaxFactory.List<TypeParameterConstraintClauseSyntax>();
556+
var parameterList = SyntaxFactory.ParameterList();
557+
var methodDecl = SyntaxFactory.MethodDeclaration(methodAttrs, modifiers, decl.Type, null,
558+
SyntaxFactory.Identifier(newMethodName), null, parameterList, typeConstraints, body, null);
559+
yield return methodDecl;
560+
561+
var newVar =
562+
v.WithInitializer(SyntaxFactory.EqualsValueClause(
563+
SyntaxFactory.InvocationExpression(SyntaxFactory.IdentifierName(newMethodName))));
564+
var newVarDecl =
565+
SyntaxFactory.VariableDeclaration(decl.Type, SyntaxFactory.SingletonSeparatedList(newVar));
566+
567+
yield return SyntaxFactory.FieldDeclaration(SyntaxFactory.List(attributes), convertedModifiers, newVarDecl);
565568
}
566569

567570
private List<MethodWithHandles> GetMethodWithHandles(VBSyntax.TypeBlockSyntax parentType)

0 commit comments

Comments
 (0)