private IEnumerable GenerateNativeByRefProlog()

in SharpGen/Generator/ReverseCallablePrologCodeGenerator.cs [110:230]


        private IEnumerable<StatementSyntax> GenerateNativeByRefProlog(CsMarshalCallableBase publicElement,
                                                                       ExpressionSyntax nativeParameter,
                                                                       TypeSyntax nativeParameterType)
        {
            var marshaller = GetMarshaller(publicElement);
            var marshalTypeSyntax = marshaller.GetMarshalTypeSyntax(publicElement);
            var publicType = ParseTypeName(publicElement.PublicType.QualifiedName);
            var generatesMarshalVariable = marshaller.GeneratesMarshalVariable(publicElement);
            ExpressionSyntax publicDefaultValue = publicElement.UsedAsReturn ? default : DefaultLiteral;

            var refToNativeClause = GenerateAsRefInitializer(publicElement, nativeParameter, marshalTypeSyntax);

            TypeSyntax publicVariableType, marshalVariableType;
            ExpressionSyntax publicVariableInitializer, marshalVariableInitializer;

            if (publicElement is CsParameter {IsOptional: true, IsLocalManagedReference: true} parameter)
            {
                Debug.Assert(marshaller is RefWrapperMarshaller);

                var refVariableDeclaration = LocalDeclarationStatement(
                    VariableDeclaration(
                        RefType(marshalTypeSyntax),
                        SingletonSeparatedList(
                            VariableDeclarator(
                                MarshallerBase.GetRefLocationIdentifier(publicElement),
                                default, EqualsValueClause(refToNativeClause)
                            )
                        )
                    )
                );

                publicVariableType = publicType;
                marshalVariableType = marshalTypeSyntax;
                publicVariableInitializer = publicDefaultValue;
                marshalVariableInitializer = DefaultLiteral;

                if (generatesMarshalVariable && parameter is {IsRef: true})
                {
                    Logger.Error(
                        null, "Optional ref parameter [{0}] that requires generating marshal variable is unsupported.",
                        parameter.QualifiedName
                    );
                }
                else
                {
                    Debug.Assert(!generatesMarshalVariable || parameter is {IsOut: true});
                }

                yield return refVariableDeclaration;
            }
            else
            {
                Debug.Assert(marshaller is not RefWrapperMarshaller);

                marshalVariableInitializer = refToNativeClause;

                if (publicElement is {IsLocalManagedReference: true})
                {
                    Debug.Assert(publicElement is CsReturnValue or CsParameter {IsOptional: false});

                    marshalVariableType = RefType(marshalTypeSyntax);
                    publicVariableType = generatesMarshalVariable
                                             ? publicType
                                             : RefType(publicType);
                    publicVariableInitializer = generatesMarshalVariable
                                                    ? publicDefaultValue
                                                    : refToNativeClause;

                }
                else
                {
                    Debug.Assert(publicElement is CsParameter {IsRefIn: true});

                    var isNullable = publicElement is CsParameter {PassedByNullableInstance: true};

                    marshalVariableType = marshalTypeSyntax;
                    publicVariableType = isNullable ? NullableType(publicType) : publicType;
                    publicVariableInitializer = generatesMarshalVariable
                                                    ? isNullable
                                                          ? ConditionalExpression(
                                                              BinaryExpression(
                                                                  SyntaxKind.NotEqualsExpression,
                                                                  nativeParameter, DefaultLiteral
                                                              ),
                                                              ImplicitObjectCreationExpression(),
                                                              LiteralExpression(SyntaxKind.NullLiteralExpression)
                                                          )
                                                          : publicDefaultValue
                                                    : refToNativeClause;
                }
            }

            if (generatesMarshalVariable)
            {
                yield return LocalDeclarationStatement(
                    VariableDeclaration(
                        marshalVariableType,
                        SingletonSeparatedList(
                            VariableDeclarator(
                                MarshallerBase.GetMarshalStorageLocationIdentifier(publicElement),
                                default, EqualsValueClause(marshalVariableInitializer)
                            )
                        )
                    )
                );
            }

            yield return LocalDeclarationStatement(
                VariableDeclaration(
                    publicVariableType,
                    SingletonSeparatedList(
                        VariableDeclarator(
                            Identifier(publicElement.Name), default,
                            publicVariableInitializer != default
                                ? EqualsValueClause(publicVariableInitializer)
                                : default
                        )
                    )
                )
            );
        }