MixinRefactoring.InjectConstructorImplementationStrategy.ExtendConstructorInitialization C# (CSharp) Method

ExtendConstructorInitialization() public method

the constructor initializer will be extended so that it will accept the mixin as parameter. See rule 3 from above
public ExtendConstructorInitialization ( ConstructorInitializerSyntax oldConstructorInitializer ) : ConstructorInitializerSyntax
oldConstructorInitializer ConstructorInitializerSyntax
return ConstructorInitializerSyntax
        public ConstructorInitializerSyntax ExtendConstructorInitialization(
            ConstructorInitializerSyntax oldConstructorInitializer)
        {
            // don't do anything if initializer points to base
            if (oldConstructorInitializer.IsKind(SyntaxKind.BaseConstructorInitializer))
                return oldConstructorInitializer;
            var parameterName = _mixin.Name.ConvertFieldNameToParameterName();

            // arguments that are already used in the constructor initializer
            var arguments = oldConstructorInitializer
                .ArgumentList
                .Arguments
                .ToArray();

            // the initializer can have default parameters that are not visible in the syntax tree,
            // therefore we have to use some additional semantic information here
            var initalizerSymbol = _semantic.GetSymbolInfo(oldConstructorInitializer).Symbol as IMethodSymbol;
            if (initalizerSymbol != null)
            {
                var constructorArguments = new List<ConstructorArgument>();

                // special case: the initializer does not have any parameters yet
                // so we simply add one
                if(initalizerSymbol.Parameters.Length == 0)
                {
                    return oldConstructorInitializer
                        .AddArgumentListArguments(
                            Argument(IdentifierName(parameterName)));
                }

                // otherwise, try to map the arguments from the initializer
                // with the parameters of the constructor and add the new argument
                // at the correct position
                for (var i=0; i < initalizerSymbol.Parameters.Length;i++)
                {
                    var parameter = initalizerSymbol.Parameters[i];
                    // this constructor argument will hold our new mixin
                    if (parameter.Name == parameterName)
                    {
                        constructorArguments.Add(
                            new ConstructorArgument(
                                parameter.Name,
                                expression: IdentifierName(parameterName),
                                isMixinParameter: true));
                    }
                    else
                    {
                        // we either have an argument with an explicit name
                        // or we have an argument at the same position
                        // or we can ommit this parameter
                        ArgumentSyntax argument = arguments
                            .Where(x => x.NameColon != null)
                            .FirstOrDefault(x => x.NameColon.Name.GetText().ToString() == parameter.Name);
                        // argument identified by name or by position
                        if (argument == null)
                            if (arguments.Length > i)
                                argument = arguments[i];
                        if (argument != null)
                            constructorArguments.Add(new ConstructorArgument(parameter.Name,expression: argument.Expression));
                        else // no argument found => argument was omitted
                            constructorArguments.Add(new ConstructorArgument(parameter.Name,canBeOmitted:true));
                    }
                }

                // now we have to check again if we must use explicit naming
                // this is the case if a previous parameter is omitted but
                // the current one is not
                ConstructorArgument previous = null;
                foreach (var constructorArgument in constructorArguments)
                {
                    constructorArgument.NeedsExplicitNaming =
                        previous != null &&
                        previous.CanBeOmitted &&
                        !constructorArgument.CanBeOmitted;
                    previous = constructorArgument;
                }                    

                // create the new initializer by recreating the complete argument list
                var newConstructorInitializer = oldConstructorInitializer
                    .WithArgumentList(ArgumentList()
                    .AddArguments(constructorArguments
                        .Where(x => x.Expression != null)
                        .Select(x => x.NeedsExplicitNaming ? 
                            Argument(NameColon(x.Name), default(SyntaxToken),x.Expression) : 
                            Argument(x.Expression))                           
                        .ToArray()));
                return newConstructorInitializer;
            }

            return oldConstructorInitializer;
        }