Repository: dotnet/roslyn
File: src/Features/Core/Portable/AddConstructorParametersFromMembers/AddConstructorParametersFromMembersCodeRefactoringProvider.AddConstructorParametersCodeAction.cs (C#)

Code before:

            // Now add initializers to each member
            for (var i = 0; i < _missingParameters.Length; ++i)
            {
                var member = _constructorCandidate.MissingMembers[i];
                var parameter = _missingParameters[i];

                await AddInitializerToMemberAsync(
                    solutionEditor, member, parameter, cancellationToken).ConfigureAwait(false);
            }

            return solutionEditor.GetChangedSolution();
        }

        private async Task AddInitializerToMemberAsync(
            SolutionEditor solutionEditor,
            ISymbol member,
            IParameterSymbol parameter,
            CancellationToken cancellationToken)
        {
            var solution = solutionEditor.OriginalSolution;
            var generator = _document.GetRequiredLanguageService<SyntaxGenerator>();

            if (member is IPropertySymbol property)
            {
                foreach (var syntaxRef in property.DeclaringSyntaxReferences)
                {
                    var propertySyntax = syntaxRef.GetSyntax(cancellationToken);
                    var propertyDocument = solution.GetRequiredDocument(propertySyntax.SyntaxTree);
                    var propertyEditor = await solutionEditor.GetDocumentEditorAsync(propertyDocument.Id, cancellationToken).ConfigureAwait(false);

                    // Create the initializer expression using the parameter name
                    var initializerExpression = generator.IdentifierName(parameter.Name);
                    
                    // Wrap the initializer expression in an EqualsValueClause
                    var equalsValueClause = generator.SyntaxGeneratorInternal.EqualsValueClause(default, initializerExpression);
                    
                    // Add the initializer to the property using SyntaxGeneratorInternal
                    var newProperty = generator.SyntaxGeneratorInternal.WithPropertyInitializer(propertySyntax, equalsValueClause);
                    propertyEditor.ReplaceNode(propertySyntax, newProperty);
                    break;
                }
            }
            else if (member is IFieldSymbol field)
            {
                foreach (var syntaxRef in field.DeclaringSyntaxReferences)
                {
                    var fieldSyntax = syntaxRef.GetSyntax(cancellationToken);
                    var fieldDocument = solution.GetRequiredDocument(fieldSyntax.SyntaxTree);
                    var fieldEditor = await solutionEditor.GetDocumentEditorAsync(fieldDocument.Id, cancellationToken).ConfigureAwait(false);


Review comment (suggestion):
@copilot have the for loop be outside the 'if'.  Almost all the logic can be shared between the property and field code.  Then, just change the lgoic when doing the final WithInitializer or WithPropertyInitializer depending on if you have a field or property.  This will remove a lot of duplication here.

Code after:
                .Select(r => r.GetSyntax(cancellationToken))
                .First();

            var oldConstructorSyntaxTree = oldConstructor.SyntaxTree;

            foreach (var (parameter, member) in MissingParameters)
            {
                await AddInitializerToMemberAsync(
                    solutionEditor, member, parameter, cancellationToken).ConfigureAwait(false);
            }

            var syntaxTree = oldConstructor.SyntaxTree;
            var documentToUpdate = solution.GetRequiredDocument(syntaxTree);
            var editor = await solutionEditor.GetDocumentEditorAsync(documentToUpdate.Id, cancellationToken).ConfigureAwait(false);

            editor.ReplaceNode(
                oldConstructor,
                (currentOldConstructor, _) =>
                {
                    var newConstructor = GetNewConstructor(currentOldConstructor, cancellationToken);
                    return newConstructor.WithAdditionalAnnotations(Formatter.Annotation);
                });

            return solutionEditor.GetChangedSolution();
        }

        private async Task AddInitializerToMemberAsync(
            SolutionEditor solutionEditor,
            ISymbol member,
            IParameterSymbol parameter,
            CancellationToken cancellationToken)
        {
            var solution = solutionEditor.OriginalSolution;
            var generator = _document.GetRequiredLanguageService<SyntaxGenerator>();

            if (member.DeclaringSyntaxReferences is not [var syntaxRef, ..])
                return;

            var memberSyntax = syntaxRef.GetSyntax(cancellationToken);
            var memberDocument = solution.GetRequiredDocument(memberSyntax.SyntaxTree);
            var memberEditor = await solutionEditor.GetDocumentEditorAsync(memberDocument.Id, cancellationToken).ConfigureAwait(false);

            var equalsValueClause = generator.SyntaxGeneratorInternal.EqualsValueClause(
                generator.IdentifierName(parameter.Name));

            // Add the initializer to the member - use different methods for properties vs fields
            var newMemberSyntax = member is IPropertySymbol
                ? generator.SyntaxGeneratorInternal.WithPropertyInitializer(memberSyntax, equalsValueClause)
                : generator.WithInitializer(memberSyntax, equalsValueClause);

            memberEditor.ReplaceNode(memberSyntax, newMemberSyntax);