Пример #1
0
        void OutputMethod(MethodDefinition method, int level, int numOptionalParams = 0)
        {
            var parentClass = method.Parent;

            // No whitespace between get/set methods
            if (!(method.Property != null &&
                  method.Equals(method.Property.Setter)))
            {
                EnsureSourceWhiteSpace();
                hasHeaderWhiteSpace = false;
            }

            // #ifndef DISABLE_FEATURE
            bool hasConditional = false;

            if (method.Property == null)
            {
                foreach (var param in method.Parameters)
                {
                    string typeConditional = GetTypeConditional(param.Type, parentClass.Header);
                    if (typeConditional != null)
                    {
                        Write("#ifndef ");
                        WriteLine(typeConditional);
                        hasSourceWhiteSpace = true;
                        hasConditional      = true;
                    }
                }
            }

            WriteTabs(level + 1);

            // "static"
            if (method.IsStatic)
            {
                HeaderWrite("static ");
            }

            // Definition: return type
            if (!method.IsConstructor)
            {
                var returnType = method.ReturnType;

                if (method.Property != null)
                {
                    if (method.Equals(method.Property.Getter))
                    {
                        // If property name matches type name, resolve ambiguity
                        if (method.Property.Name.Equals(method.Property.Type.ManagedName))
                        {
                            HeaderWrite(NamespaceName + "::");
                        }

                        // Getter with parameter for return value
                        if (method.Parameters.Length == 1)
                        {
                            returnType = method.Parameters[0].Type;
                        }
                    }
                }

                Write(BulletParser.GetTypeRefName(returnType));
                Write(' ');
            }

            // Definition: name
            SourceWrite(parentClass.FullNameManaged);
            SourceWrite("::");
            if (method.IsConstructor)
            {
                Write(parentClass.ManagedName);
            }
            else
            {
                if (method.Property != null)
                {
                    SourceWrite(method.Property.Name);
                    SourceWrite("::");
                    if (method.Property.Getter.Equals(method))
                    {
                        Write("get");
                    }
                    else
                    {
                        Write("set");
                    }
                }
                else
                {
                    Write(method.ManagedName);
                }
            }
            Write('(');

            // Definition: parameters
            int numParameters = method.Parameters.Length - numOptionalParams;

            // Getters with parameter for return value
            if (numParameters == 1 && method.Property != null && method.Equals(method.Property.Getter))
            {
                numParameters = 0;
            }
            bool hasOptionalParam = false;

            for (int i = 0; i < numParameters; i++)
            {
                var param = method.Parameters[i];
                Write(BulletParser.GetTypeRefName(param.Type));
                Write(' ');
                Write(param.ManagedName);

                if (param.IsOptional)
                {
                    hasOptionalParam = true;
                }

                if (i != numParameters - 1)
                {
                    if (_headerLineLength >= LineBreakWidth)
                    {
                        HeaderWriteLine(",");
                        WriteTabs(level + 2);
                    }
                    else
                    {
                        HeaderWrite(", ");
                    }

                    if (_sourceLineLength >= LineBreakWidth)
                    {
                        SourceWriteLine(",");
                        WriteTabs(1, true);
                    }
                    else
                    {
                        SourceWrite(", ");
                    }
                }
            }
            HeaderWriteLine(");");
            SourceWriteLine(')');


            // Constructor chaining
            bool doConstructorChaining = false;

            if (method.IsConstructor && parentClass.BaseClass != null)
            {
                // If there is no need for marshalling code, we can chain constructors
                doConstructorChaining = true;
                foreach (var param in method.Parameters)
                {
                    if (BulletParser.TypeRequiresMarshal(param.Type))
                    {
                        doConstructorChaining = false;
                        break;
                    }
                }

                WriteTabs(1, true);
                SourceWrite(": ");
                SourceWrite(parentClass.BaseClass.ManagedName);
                SourceWrite('(');

                if (doConstructorChaining)
                {
                    SourceWrite("new ");
                    OutputMethodMarshal(method, numParameters);
                    if (parentClass.BaseClass.Target.HasPreventDelete)
                    {
                        SourceWrite(", false");
                    }
                }
                else
                {
                    SourceWrite('0');
                }

                SourceWriteLine(')');
            }

            // Method definition
            SourceWriteLine('{');

            if (!doConstructorChaining)
            {
                // Type marshalling prologue
                bool needTypeMarshalEpilogue = false;
                if (method.Field == null)
                {
                    for (int i = 0; i < numParameters; i++)
                    {
                        var    param    = method.Parameters[i];
                        string prologue = BulletParser.GetTypeMarshalPrologueCppCli(param);
                        if (!string.IsNullOrEmpty(prologue))
                        {
                            WriteTabs(1, true);
                            SourceWriteLine(prologue);
                        }

                        // Do we need a type marshalling epilogue?
                        if (!needTypeMarshalEpilogue)
                        {
                            string epilogue = BulletParser.GetTypeMarshalEpilogueCppCli(param);
                            if (!string.IsNullOrEmpty(epilogue))
                            {
                                needTypeMarshalEpilogue = true;
                            }
                        }
                    }
                }

                WriteTabs(1, true);
                if (method.IsConstructor)
                {
                    SourceWrite("_native = new ");
                }
                else
                {
                    if (!method.IsVoid)
                    {
                        //if (method.ReturnType.IsBasic || method.ReturnType.Referenced != null)
                        if (needTypeMarshalEpilogue)
                        {
                            // Return after epilogue (cleanup)
                            SourceWrite(BulletParser.GetTypeRefName(method.ReturnType));
                            SourceWrite(" ret = ");
                        }
                        else
                        {
                            // Return immediately
                            SourceWrite("return ");
                        }
                        SourceWrite(BulletParser.GetTypeMarshalConstructorStart(method));
                    }
                    else
                    {
                        if (method.Property != null && method.Equals(method.Property.Getter))
                        {
                            SourceWrite(BulletParser.GetTypeMarshalConstructorStart(method));
                        }
                    }
                }

                // Native is defined as static_cast<className*>(_native)
                string nativePointer = (parentClass.BaseClass != null) ? "Native" : "_native";

                if (method.Field != null)
                {
                    if (method.Equals(method.Property.Getter))
                    {
                        SourceWrite(nativePointer);
                        SourceWrite("->");
                        SourceWrite(method.Field.Name);
                    }

                    var setter = method.Property.Setter;
                    if (setter != null && method.Equals(setter))
                    {
                        var param    = method.Parameters[0];
                        var fieldSet = BulletParser.GetTypeMarshalFieldSetCppCli(method.Field, param, nativePointer);
                        if (!string.IsNullOrEmpty(fieldSet))
                        {
                            SourceWrite(fieldSet);
                        }
                        else
                        {
                            SourceWrite(string.Format("{0}->{1} = ", nativePointer, method.Field.Name));
                            if (param.Type.IsPointer || param.Type.IsReference)
                            {
                                if (param.Type.IsReference)
                                {
                                    // Dereference
                                    SourceWrite('*');
                                }

                                if (param.Type.Referenced.Target != null &&
                                    param.Type.Referenced.Target.BaseClass != null)
                                {
                                    // Cast native pointer from base class
                                    SourceWrite(string.Format("({0}*)", param.Type.Referenced.FullName));
                                }
                            }
                            SourceWrite(param.ManagedName);
                            if (!param.Type.IsBasic)
                            {
                                SourceWrite("->_native");
                            }
                        }
                    }
                }
                else
                {
                    if (!method.IsConstructor)
                    {
                        if (method.IsStatic)
                        {
                            SourceWrite(parentClass.FullName);
                            SourceWrite("::");
                        }
                        else
                        {
                            SourceWrite(nativePointer);
                            SourceWrite("->");
                        }
                    }
                    OutputMethodMarshal(method, numParameters);
                }
                if (!method.IsConstructor && !method.IsVoid)
                {
                    SourceWrite(BulletParser.GetTypeMarshalConstructorEnd(method));
                }
                SourceWriteLine(';');

                // Write type marshalling epilogue
                if (needTypeMarshalEpilogue)
                {
                    for (int i = 0; i < numParameters; i++)
                    {
                        var    param    = method.Parameters[i];
                        string epilogue = BulletParser.GetTypeMarshalEpilogueCppCli(param);
                        if (!string.IsNullOrEmpty(epilogue))
                        {
                            WriteTabs(1, true);
                            SourceWriteLine(epilogue);
                        }
                    }
                    if (!method.IsVoid)
                    {
                        WriteTabs(1, true);
                        SourceWriteLine("return ret;");
                    }
                }
            }
            SourceWriteLine('}');
            hasSourceWhiteSpace = false;

            // #endif // DISABLE_FEATURE
            if (hasConditional)
            {
                foreach (var param in method.Parameters)
                {
                    string typeConditional = GetTypeConditional(param.Type, method.Parent.Header);
                    if (typeConditional != null)
                    {
                        WriteLine("#endif");
                        hasHeaderWhiteSpace = true;
                    }
                }
            }

            // If there are optional parameters, then output all possible combinations of calls
            if (hasOptionalParam)
            {
                OutputMethod(method, level, numOptionalParams + 1);
            }
        }
        void OutputMethod(MethodDefinition method, int level, int numOptionalParams = 0)
        {
            var parentClass = method.Parent;

            // No whitespace between get/set methods
            if (!(method.Property != null &&
                  method.Equals(method.Property.Setter)))
            {
                EnsureSourceWhiteSpace();
                hasHeaderWhiteSpace = false;
            }

            // #ifndef DISABLE_FEATURE
            bool hasConditional = false;

            if (method.Property == null)
            {
                foreach (var param in method.Parameters)
                {
                    string typeConditional = GetTypeConditional(param.Type, parentClass.Header);
                    if (typeConditional != null)
                    {
                        WriteLine(string.Format("#ifndef {0}", typeConditional));
                        hasSourceWhiteSpace = true;
                        hasConditional      = true;
                    }
                }
            }

            WriteTabs(level + 1);

            // "static"
            if (method.IsStatic)
            {
                HeaderWrite("static ");
            }

            // Definition: return type
            if (!method.IsConstructor)
            {
                var returnType = method.ReturnType;

                if (method.Property != null)
                {
                    if (method.Equals(method.Property.Getter))
                    {
                        // If property name matches type name, resolve ambiguity
                        if (method.Property.Name.Equals(method.Property.Type.ManagedName))
                        {
                            HeaderWrite(NamespaceName + "::");
                        }

                        // Getter with parameter for return value
                        if (method.Parameters.Length == 1)
                        {
                            returnType = method.Parameters[0].Type;
                        }
                    }
                }

                Write(BulletParser.GetTypeRefName(returnType));
                Write(' ');
            }

            // Definition: name
            string headerMethodName;
            string sourceMethodName;

            if (method.IsConstructor)
            {
                headerMethodName = parentClass.ManagedName;
                sourceMethodName = headerMethodName;
            }
            else if (method.Property != null)
            {
                headerMethodName = method.Property.Getter.Equals(method) ? "get" : "set";
                sourceMethodName = string.Format("{0}::{1}", method.Property.Name, headerMethodName);
            }
            else
            {
                headerMethodName = method.ManagedName;
                sourceMethodName = headerMethodName;
            }
            HeaderWrite(string.Format("{0}(", headerMethodName));
            SourceWrite(string.Format("{0}::{1}(", parentClass.FullNameManaged, sourceMethodName));

            // Definition: parameters
            int numParameters = method.Parameters.Length - numOptionalParams;

            // Getters with parameter for return value
            if (numParameters == 1 && method.Property != null && method.Equals(method.Property.Getter))
            {
                numParameters = 0;
            }
            bool hasOptionalParam = false;

            for (int i = 0; i < numParameters; i++)
            {
                var param = method.Parameters[i];
                Write(string.Format("{0} {1}",
                                    BulletParser.GetTypeRefName(param.Type), param.ManagedName));

                if (param.IsOptional)
                {
                    hasOptionalParam = true;
                }

                if (i != numParameters - 1)
                {
                    if (_headerLineLength >= LineBreakWidth)
                    {
                        HeaderWriteLine(",");
                        WriteTabs(level + 2);
                    }
                    else
                    {
                        HeaderWrite(", ");
                    }

                    if (_sourceLineLength >= LineBreakWidth)
                    {
                        SourceWriteLine(",");
                        WriteTabs(1, true);
                    }
                    else
                    {
                        SourceWrite(", ");
                    }
                }
            }
            HeaderWriteLine(");");
            SourceWriteLine(')');


            // Constructor chaining
            bool doConstructorChaining = false;

            if (method.IsConstructor && parentClass.BaseClass != null)
            {
                // If there is no need for marshalling code, we can chain constructors
                doConstructorChaining = method.Parameters.All(p => !BulletParser.TypeRequiresMarshal(p.Type));

                WriteTabs(1, true);
                SourceWrite(string.Format(": {0}(", parentClass.BaseClass.ManagedName));

                if (doConstructorChaining)
                {
                    SourceWrite("new ");
                    OutputMethodMarshal(method, numParameters);
                    if (parentClass.BaseClass.HasPreventDelete)
                    {
                        SourceWrite(", false");
                    }
                }
                else
                {
                    SourceWrite('0');
                }

                SourceWriteLine(')');
            }

            // Method definition
            SourceWriteLine('{');
            if (!doConstructorChaining)
            {
                WriteMethodDefinition(method, numParameters);
            }
            // Cache property values
            if (method.IsConstructor)
            {
                var assignments  = new List <string>();
                var methodParent = method.Parent;
                while (methodParent != null)
                {
                    foreach (var cachedProperty in methodParent.CachedProperties.OrderBy(p => p.Key))
                    {
                        foreach (var param in method.Parameters)
                        {
                            if (param.ManagedName.ToLower() == cachedProperty.Key.ToLower() &&
                                param.Type.ManagedName == cachedProperty.Value.Property.Type.ManagedName)
                            {
                                string assignment = string.Format("\t{0} = {1};", cachedProperty.Value.CacheFieldName, param.ManagedName);
                                assignments.Add(assignment);
                            }
                        }
                    }
                    methodParent = methodParent.BaseClass;
                }
                if (assignments.Count != 0)
                {
                    EnsureSourceWhiteSpace();
                    foreach (string assignment in assignments)
                    {
                        SourceWriteLine(assignment);
                    }
                    hasSourceWhiteSpace = false;
                }
            }
            SourceWriteLine('}');
            hasSourceWhiteSpace = false;

            // #endif // DISABLE_FEATURE
            if (hasConditional)
            {
                foreach (var param in method.Parameters)
                {
                    string typeConditional = GetTypeConditional(param.Type, method.Parent.Header);
                    if (typeConditional != null)
                    {
                        WriteLine("#endif");
                        hasHeaderWhiteSpace = true;
                    }
                }
            }

            // If there are optional parameters, then output all possible combinations of calls
            if (hasOptionalParam)
            {
                OutputMethod(method, level, numOptionalParams + 1);
            }
        }