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); } }