/// <summary>
        /// If a method returns a type that is marshalled as struct,
        /// then this is incompatible with C.
        /// Append an out parameter that will receive the struct.
        /// </summary>
        private void CreateStructOutParameters()
        {
            foreach (var method in Project.ClassDefinitions.Values.SelectMany(c => c.Methods))
            {
                var type = method.ReturnType;
                TypeRefDefinition targetType;
                if (type.Target != null && type.Target.MarshalAsStruct)
                {
                    targetType = type;
                }
                else if (type.Kind == TypeKind.LValueReference &&
                         type.Referenced.Target != null && type.Referenced.Target.MarshalAsStruct)
                {
                    targetType = type.Referenced;
                }
                else
                {
                    continue;
                }

                targetType         = targetType.Copy();
                targetType.IsConst = false;

                var outType = new TypeRefDefinition
                {
                    Kind       = TypeKind.Pointer,
                    Referenced = targetType
                };
                method.OutValueParameter = new ParameterDefinition("value", outType)
                {
                    MarshalDirection = MarshalDirection.Out
                };
            }
        }
        void AddForwardReference(List <ManagedClass> forwardRefs, TypeRefDefinition type, HeaderDefinition header)
        {
            if (type.IsBasic)
            {
                return;
            }

            switch (type.Kind)
            {
            case TypeKind.Pointer:
            case TypeKind.LValueReference:
                AddForwardReference(forwardRefs, type.Referenced, header);
                return;
            }

            var target = type.Target;

            if (target == null)
            {
                return;
            }
            if (target.IsExcluded || target.MarshalAsStruct || target.Header == header)
            {
                return;
            }

            var targetManaged = DotNetParser.GetManaged(target);

            if (!forwardRefs.Contains(targetManaged))
            {
                forwardRefs.Add(targetManaged);
            }
        }
Exemple #3
0
        public override bool Equals(object obj)
        {
            if (obj == null)
            {
                return(false);
            }

            TypeRefDefinition t = obj as TypeRefDefinition;

            if (t == null)
            {
                return(false);
            }

            if (t.IsBasic != IsBasic ||
                t.IsConstantArray != IsConstantArray ||
                t.IsPointer != IsPointer ||
                t.IsReference != IsReference)
            {
                return(false);
            }

            if (IsPointer || IsReference || IsConstantArray)
            {
                return(t.Referenced.Equals(Referenced));
            }

            if (Name == null)
            {
                return(t.Name == null);
            }
            return(t.Name.Equals(Name));
        }
        void AddForwardReference(List <ClassDefinition> forwardRefs, TypeRefDefinition type, HeaderDefinition header)
        {
            if (type.IsBasic)
            {
                return;
            }

            if (type.IsPointer || type.IsReference)
            {
                AddForwardReference(forwardRefs, type.Referenced, header);
                return;
            }

            if (type.Target == null)
            {
                return;
            }
            if (type.Target.IsExcluded ||
                forwardRefs.Contains(type.Target) ||
                PrecompiledHeaderReferences.Contains(type.Target.ManagedName))
            {
                return;
            }

            // Forward ref to class in another header
            if (type.Target.Header != header)
            {
                forwardRefs.Add(type.Target);
            }
        }
 void WriteTypeCS(TypeRefDefinition type)
 {
     if (type.IsBasic)
     {
         Write(type.ManagedNameCS, WriteTo.CS);
     }
     else if (type.HasTemplateTypeParameter)
     {
         Write(type.ManagedNameCS, WriteTo.CS);
     }
     else if (type.Referenced != null)
     {
         if (type.IsPointer && type.Referenced.ManagedNameCS.Equals("void")) // void*
         {
             Write("IntPtr", WriteTo.CS);
         }
         else
         {
             Write(BulletParser.GetTypeNameCS(type), WriteTo.CS);
         }
     }
     else
     {
         Write(BulletParser.GetTypeNameCS(type), WriteTo.CS);
     }
 }
Exemple #6
0
        public static string GetTypeRefName(TypeRefDefinition type)
        {
            if (!string.IsNullOrEmpty(type.Name) && type.Name.Equals("btAlignedObjectArray"))
            {
                if (type.SpecializedTemplateType != null)
                {
                    return("Aligned" + type.SpecializedTemplateType.ManagedName + "Array^");
                }
            }

            switch (type.ManagedName)
            {
            case "Matrix3x3":
                return("Matrix");

            case "Transform":
                return("Matrix");

            case "Quaternion":
            case "Vector3":
            case "Vector4":
                return(type.ManagedName);
            }

            if (type.ManagedName.Equals("float") && "btScalar".Equals(type.Name))
            {
                return("btScalar");
            }
            return(type.ManagedTypeRefName);
        }
Exemple #7
0
 bool IsCacheableType(TypeRefDefinition t)
 {
     if (t.IsBasic)
     {
         return(false);
     }
     if (t.Target != null)
     {
         if (t.Target.IsPureEnum)
         {
             return(false);
         }
     }
     if (t.Referenced != null)
     {
         return(IsCacheableType(t.Referenced));
     }
     switch (t.Name)
     {
     case "btTransform":
     case "btQuaternion":
     case "btVector3":
     case "btVector4":
         return(false);
     }
     return(true);
 }
Exemple #8
0
        public static string GetTypeNameCS(TypeRefDefinition type)
        {
            switch (type.ManagedName)
            {
            case "Matrix3x3":
            case "Transform":
                return("Matrix");
            }

            if (type.IsConstantArray)
            {
                switch (type.Referenced.Name)
                {
                case "bool":
                    return("BoolArray");

                case "int":
                    return("IntArray");

                case "unsigned int":
                    return("UIntArray");

                case "unsigned short":
                    return("UShortArray");

                case "btScalar":
                    return("FloatArray");

                case "btVector3":
                    return("Vector3Array");

                case "btDbvt":
                    return("DbvtArray");

                case "btSoftBody::Body":
                    return("BodyArray");
                }

                if (type.Referenced.Referenced != null)
                {
                    switch (type.Referenced.Referenced.Name)
                    {
                    case "btDbvtNode":
                        return("DbvtNodePtrArray");

                    case "btDbvtProxy":
                        return("DbvtProxyPtrArray");

                    case "btSoftBody::Node":
                        return("NodePtrArray");
                    }
                }

                return(GetTypeNameCS(type.Referenced) + "[]");
            }

            return(type.ManagedNameCS);
        }
Exemple #9
0
        public string GetName(TypeRefDefinition type)
        {
            switch (type.Kind)
            {
            case TypeKind.Typedef:
                if (type.Referenced.Kind == TypeKind.Pointer &&
                    type.Referenced.Referenced.Kind == TypeKind.FunctionProto)
                {
                    if (type.Target != null && !type.Target.IsExcluded)
                    {
                        return(GetManaged(type.Target).Name);
                    }
                    break;
                }
                else if (type.Referenced.IsBasic)
                {
                    // TODO: C++/CLI: typedef to basic type can return typedef
                    // TODO: Pinvoke: typedef to basic type returns basic type
                    return(GetName(type.Referenced));
                }
                else
                {
                    return(GetName(type.Referenced));
                }

            case TypeKind.ConstantArray:
            case TypeKind.LValueReference:
            case TypeKind.Pointer:
                return(GetName(type.Referenced));

            case TypeKind.Enum:
            case TypeKind.Record:
            case TypeKind.Unexposed:
                if (type.Target != null && !type.Target.IsExcluded)
                {
                    return(GetManaged(type.Target).Name);
                }
                break;
            }

            if (type.IsBasic)
            {
                if (type.Name.Equals("unsigned char"))
                {
                    return("byte");
                }
                return(type.Name);
            }

            if (type.HasTemplateTypeParameter)
            {
                return(type.Name);
            }

            Console.WriteLine("Unresolved reference to " + type.Name);

            return(type.Name);
        }
        private static string GetTypeNameC(TypeRefDefinition type)
        {
            string name = "";

            if (type.IsConst)
            {
                // Note: basic type can be const
                if (type.Referenced == null ||
                    (type.Referenced != null && !type.Referenced.ConstCanonical))
                {
                    name = "const ";
                }
            }

            if (type.IsBasic)
            {
                return(name + type.Name);
            }

            if (type.Kind == TypeKind.Typedef)
            {
                if (type.Referenced.IsBasic)
                {
                    return(type.Name);
                }
                if (type.Referenced.Kind == TypeKind.Pointer &&
                    type.Referenced.Referenced.Kind == TypeKind.FunctionProto)
                {
                    return(type.Name);
                }
                return(name + GetTypeNameC(type.Referenced));
            }

            if (type.Referenced != null)
            {
                return(name + GetTypeNameC(type.Referenced) + "*");
            }

            var target = type.Target;

            if (target != null && target is EnumDefinition)
            {
                if (target.Parent != null && target.Parent.IsPureEnum)
                {
                    return(target.Parent.FullName.Replace("::", "_"));
                }
            }

            // Template name to C form
            if (type.FullName.Contains("<"))
            {
                string template = type.FullName.Replace('<', '_').Replace(">", "").Replace(" *", "Ptr");
                template = template.Replace(' ', '_');
                return(name + template.Replace("::", "_"));
            }

            return(name + type.FullName.Replace("::", "_"));
        }
        void ResolveTypeRef(TypeRefDefinition typeRef)
        {
            switch (typeRef.Kind)
            {
            case TypeKind.Enum:
            case TypeKind.Record:
            case TypeKind.Unexposed:
                if (Project.ClassDefinitions.ContainsKey(typeRef.Name))
                {
                    typeRef.Target = Project.ClassDefinitions[typeRef.Name];
                    return;
                }

                Console.WriteLine($"Unresolved reference: {typeRef.Name}");

                if (typeRef.TemplateParams != null)
                {
                    typeRef.TemplateParams.ForEach(ResolveTypeRef);

                    // Create template specialization class
                    string templateName = typeRef.Name.Substring(0, typeRef.Name.IndexOf('<'));

                    ClassDefinition template;
                    if (Project.ClassDefinitions.TryGetValue(templateName, out template))
                    {
                        if (!template.IsExcluded)
                        {
                            //string name = $"{typeRef.Name}<{typeRef.TemplateParams.First().Name}>";
                            string name = typeRef.Name;

                            var classTemplate    = template as ClassTemplateDefinition;
                            var header           = classTemplate.Header;
                            var specializedClass = new ClassDefinition(name, header);
                            specializedClass.BaseClass = template;
                            header.Classes.Add(specializedClass);
                            Project.ClassDefinitions.Add(name, specializedClass);
                        }
                    }
                }
                break;

            case TypeKind.Typedef:
                var underlying = typeRef.Canonical;
                if (underlying.Kind == TypeKind.Pointer &&
                    underlying.Referenced.Kind == TypeKind.FunctionProto)
                {
                    typeRef.Target = Project.ClassDefinitions[typeRef.Name];
                    return;
                }
                break;
            }

            if (typeRef.Referenced != null)
            {
                ResolveTypeRef(typeRef.Referenced);
            }
        }
        public string GetName(TypeRefDefinition type)
        {
            switch (type.Kind)
            {
                case TypeKind.Typedef:
                    if (type.Referenced.Kind == TypeKind.Pointer &&
                        type.Referenced.Referenced.Kind == TypeKind.FunctionProto)
                    {
                        if (type.Target != null && !type.Target.IsExcluded)
                        {
                            return GetManaged(type.Target).Name;
                        }
                        break;
                    }
                    else if (type.Referenced.IsBasic)
                    {
                        // TODO: C++/CLI: typedef to basic type can return typedef
                        // TODO: Pinvoke: typedef to basic type returns basic type
                        return GetName(type.Referenced);
                    }
                    else
                    {
                        return GetName(type.Referenced);
                    }

                case TypeKind.ConstantArray:
                case TypeKind.LValueReference:
                case TypeKind.Pointer:
                    return GetName(type.Referenced);

                case TypeKind.Enum:
                case TypeKind.Record:
                case TypeKind.Unexposed:
                    if (type.Target != null && !type.Target.IsExcluded)
                    {
                        return GetManaged(type.Target).Name;
                    }
                    break;
            }

            if (type.IsBasic)
            {
                if (type.Name.Equals("unsigned char"))
                {
                    return "byte";
                }
                return type.Name;
            }

            if (type.HasTemplateTypeParameter) return type.Name;

            Console.WriteLine("Unresolved reference to " + type.Name);

            return type.Name;
        }
        void ParseTemplateBaseCursor(Cursor cursor)
        {
            var tokens = _context.TranslationUnit.Tokenize(cursor.Extent)
                         .TakeWhile(t => !t.Spelling.Equals("{"))
                         .SkipWhile(t => !t.Spelling.Equals(":"));

            if (!tokens.Any())
            {
                return;
            }

            var baseTokens = tokens.ToList();
            int templSpecStart = -1, templSpecEnd = -1;

            for (int i = 0; i < baseTokens.Count; i++)
            {
                var token = baseTokens[i];
                if (token.Spelling == "<")
                {
                    templSpecStart = i;
                }
                else if (token.Spelling == ">")
                {
                    templSpecEnd = i;
                }
            }

            if (templSpecStart != -1 && templSpecEnd != -1)
            {
                string template     = baseTokens[templSpecStart - 1].Spelling;
                string templateSpec = string.Join(" ",
                                                  baseTokens.GetRange(templSpecStart + 1, templSpecEnd - templSpecStart - 1)
                                                  .Select(t => t.Spelling));
                templateSpec = TypeRefDefinition.GetBasicName(templateSpec);

                string          templateName = $"{template}<{templateSpec}>";
                ClassDefinition classTemplate;
                if (!project.ClassDefinitions.TryGetValue(templateName, out classTemplate))
                {
                    var classTemplateNew = new ClassTemplateDefinition(template, _context.Header);
                    classTemplateNew.TemplateParameters.Add(templateSpec);

                    var baseTemplate = project.ClassDefinitions.FirstOrDefault(c => c.Value.Name.Equals(template));
                    classTemplateNew.BaseClass = baseTemplate.Value;

                    project.ClassDefinitions[templateName] = classTemplateNew;
                    _context.Header.Classes.Add(classTemplateNew);
                    classTemplate = classTemplateNew;
                }

                _context.Class.BaseClass = classTemplate;
            }
        }
        // Does the type require additional lines of code to marshal?
        public static bool TypeRequiresMarshal(TypeRefDefinition type)
        {
            switch (type.Kind)
            {
            case TypeKind.ConstantArray:
            case TypeKind.LValueReference:
            case TypeKind.Pointer:
                return(TypeRequiresMarshal(type.Referenced));
            }

            return(type.Target != null && type.Target.MarshalAsStruct);
        }
Exemple #15
0
        void ResolveTypeRef(TypeRefDefinition typeRef)
        {
            if (typeRef.IsBasic || typeRef.HasTemplateTypeParameter)
            {
                return;
            }
            if (typeRef.IsPointer || typeRef.IsReference || typeRef.IsConstantArray)
            {
                ResolveTypeRef(typeRef.Referenced);
            }
            else if (!Project.ClassDefinitions.ContainsKey(typeRef.Name))
            {
                // Search for unscoped enums
                bool resolvedEnum = false;
                foreach (var @class in Project.ClassDefinitions.Values.Where(c => c is EnumDefinition))
                {
                    if (typeRef.Name.Equals(@class.FullyQualifiedName + "::" + @class.Name))
                    {
                        typeRef.Target = @class;
                        resolvedEnum   = true;
                    }
                }
                if (!resolvedEnum)
                {
                    Console.WriteLine("Class " + typeRef.Name + " not found!");
                }
            }
            else
            {
                typeRef.Target = Project.ClassDefinitions[typeRef.Name];
            }

            if (typeRef.SpecializedTemplateType != null)
            {
                ResolveTypeRef(typeRef.SpecializedTemplateType);

                // Create template specialization class
                string name = string.Format("{0}<{1}>", typeRef.Name, typeRef.SpecializedTemplateType.Name);
                if (!Project.ClassDefinitions.ContainsKey(name))
                {
                    var templateClass = typeRef.Target;
                    if (templateClass != null && !templateClass.IsExcluded)
                    {
                        var header           = templateClass.Header;
                        var specializedClass = new ClassDefinition(name, header);
                        specializedClass.BaseClass = templateClass;
                        header.Classes.Add(specializedClass);
                        Project.ClassDefinitions.Add(name, specializedClass);
                    }
                }
            }
        }
        // Return condition unless type is already used under the same condition.
        string GetTypeConditional(TypeRefDefinition type, HeaderDefinition header)
        {
            string typeConditional = GetTypeConditional(type);

            if (typeConditional != null && headerConditional.ContainsKey(header.ManagedName))
            {
                if (headerConditional[header.ManagedName].Equals(typeConditional))
                {
                    return(null);
                }
            }
            return(typeConditional);
        }
        // Return condition unless type is already used under the same condition.
        private string GetTypeConditional(TypeRefDefinition type, ManagedHeader header)
        {
            string typeConditional = GetTypeConditional(type);

            if (typeConditional != null && headerConditionals.ContainsKey(header.Name))
            {
                if (headerConditionals[header.Name].Equals(typeConditional))
                {
                    return(null);
                }
            }
            return(typeConditional);
        }
        private string GetTypeName(TypeRefDefinition type)
        {
            if (type.Kind == TypeKind.Typedef)
            {
                if (type.Referenced.Kind == TypeKind.Pointer &&
                    type.Referenced.Referenced.Kind == TypeKind.FunctionProto)
                {
                    return(GetName(type));
                }
                if (type.Canonical.IsBasic)
                {
                    return(type.Name);
                }
                return(GetTypeName(type.Referenced));
            }

            if (type.Kind == TypeKind.LValueReference)
            {
                return(GetTypeName(type.Referenced));
            }

            if (!string.IsNullOrEmpty(type.Name) && type.Name.Equals("btAlignedObjectArray"))
            {
                if (type.TemplateParams != null)
                {
                    return("Aligned" + GetName(type.TemplateParams[0]) + "Array^");
                }
            }

            switch (type.Kind)
            {
            case TypeKind.Pointer:
            case TypeKind.LValueReference:
            case TypeKind.ConstantArray:
                if (type.Referenced.Kind == TypeKind.Void)
                {
                    return("IntPtr");
                }
                switch (GetName(type))
                {
                case "char":
                    return("String^");

                case "float":
                    return(string.Format("array<{0}>^", type.Referenced.Name));
                }
                return(GetName(type) + '^');
            }
            return(GetName(type));
        }
        private void CreateFieldGetter(FieldDefinition field, ClassDefinition @class, string getterName, MethodDefinition setter)
        {
            MethodDefinition getter;

            // Use getter with an out parameter for structs
            if (field.Type.Target != null && field.Type.Target.MarshalAsStruct)
            {
                getter            = new MethodDefinition(getterName, @class, 1);
                getter.ReturnType = new TypeRefDefinition("void");

                string paramName = setter != null ? setter.Parameters[0].Name : "value";
                var    paramType = new TypeRefDefinition(field.Type.Name)
                {
                    Kind       = TypeKind.Pointer,
                    Referenced = field.Type.Copy()
                };
                getter.Parameters[0] = new ParameterDefinition(paramName, paramType)
                {
                    MarshalDirection = MarshalDirection.Out
                };
            }
            else
            {
                TypeRefDefinition type;
                if (field.Type.Canonical.Kind == TypeKind.Record)
                {
                    type = new TypeRefDefinition()
                    {
                        Kind       = TypeKind.Pointer,
                        Referenced = field.Type.Copy()
                    };
                }
                else if (field.Type.Canonical.Kind == TypeKind.Unexposed)
                {
                    // TODO:
                    type = field.Type;
                }
                else
                {
                    type = field.Type;
                }

                getter            = new MethodDefinition(getterName, @class, 0);
                getter.ReturnType = type;
            }

            getter.Field = field;
            field.Getter = getter;
        }
Exemple #20
0
        // Does the type require additional lines of code to marshal?
        public static bool TypeRequiresMarshal(TypeRefDefinition type)
        {
            switch (type.ManagedName)
            {
            case "Matrix3x3":
            case "Quaternion":
            case "Transform":
            case "Vector3":
            case "Vector4":
                return(true);

            default:
                return(false);
            }
        }
Exemple #21
0
        public static string GetTypeName(TypeRefDefinition type)
        {
            switch (type.ManagedName)
            {
            case "Matrix3x3":
            case "Quaternion":
            case "Transform":
            case "Vector3":
            case "Vector4":
                return("btScalar");

            default:
                return(type.FullName);
            }
        }
        private void CreateFieldSetter(FieldDefinition field, ClassDefinition @class, string setterName)
        {
            var type          = field.Type;
            var typeCanonical = type.Canonical;

            // Can't assign value to reference or constant array
            switch (typeCanonical.Kind)
            {
            case TypeKind.LValueReference:
            case TypeKind.ConstantArray:
                return;

            case TypeKind.Record:
                if (typeCanonical.Target == null)
                {
                    return;
                }
                if (!typeCanonical.Target.MarshalAsStruct)
                {
                    return;
                }

                type = new TypeRefDefinition
                {
                    IsConst    = true,
                    Kind       = TypeKind.Pointer,
                    Referenced = type.Copy()
                };
                break;

            default:
                type = type.Copy();
                break;
            }

            var setter = new MethodDefinition(setterName, @class, 1)
            {
                Field      = field,
                ReturnType = new TypeRefDefinition("void")
            };

            setter.Parameters[0] = new ParameterDefinition("value", type)
            {
                MarshalDirection = MarshalDirection.In
            };

            field.Setter = setter;
        }
        // If the type is defined in a conditionally compiled header, return the condition string.
        string GetTypeConditional(TypeRefDefinition type)
        {
            var target = type.Target;

            if (target == null && type.Referenced != null)
            {
                target = type.Referenced.Target;
            }

            if (target != null && headerConditional.ContainsKey(target.Header.ManagedName))
            {
                return(headerConditional[target.Header.ManagedName]);
            }

            return(null);
        }
Exemple #24
0
        public TypeRefDefinition Copy()
        {
            var t = new TypeRefDefinition
            {
                HasTemplateTypeParameter = HasTemplateTypeParameter,
                IsConst      = IsConst,
                IsIncomplete = IsIncomplete,
                Name         = Name,
                Referenced   = Referenced != null?Referenced.Copy() : null,
                                   TemplateParams = TemplateParams?.Select(p => p.Copy()).ToList(),
                                   Target         = Target,
                                   Kind           = Kind
            };

            return(t);
        }
Exemple #25
0
        public TypeRefDefinition Copy()
        {
            var t = new TypeRefDefinition();

            t.HasTemplateTypeParameter = HasTemplateTypeParameter;
            t.IsBasic                 = IsBasic;
            t.IsConst                 = IsConst;
            t.IsConstantArray         = IsConstantArray;
            t.IsPointer               = IsPointer;
            t.IsReference             = IsReference;
            t.Name                    = Name;
            t.Referenced              = Referenced;
            t.SpecializedTemplateType = SpecializedTemplateType;
            t.Target                  = Target;
            return(t);
        }
        private void CopyTemplateMethods(ClassDefinition thisClass, ClassTemplateDefinition template,
                                         Dictionary <string, string> templateParams = null)
        {
            if (templateParams == null)
            {
                templateParams = new Dictionary <string, string>();
                var templateBase = template.BaseClass as ClassTemplateDefinition;

                for (int i = 0; i < template.TemplateParameters.Count; i++)
                {
                    string param      = templateBase.TemplateParameters[i];
                    string paramValue = template.TemplateParameters[i];
                    templateParams[param] = TypeRefDefinition.GetBasicName(paramValue);
                }

                CopyTemplateMethods(thisClass, templateBase, templateParams);
                return;
            }

            thisClass.BaseClass = template.BaseClass;

            var scriptedNameMapping = Project.ClassNameMapping as ScriptedMapping;

            if (scriptedNameMapping != null)
            {
                scriptedNameMapping.Globals.Header = thisClass.Header;
            }
            // TODO:
            //template.ManagedName = Project.ClassNameMapping.Map(template.Name);

            foreach (var templateClass in template.NestedClasses)
            {
                var classSpec = new ClassDefinition(templateClass.Name, thisClass.Header, thisClass);
                Project.ClassDefinitions.Add(classSpec.FullyQualifiedName, classSpec);

                foreach (var templateMethod in templateClass.Methods)
                {
                    SpecializeTemplateMethod(classSpec, templateMethod, templateParams);
                }
            }

            foreach (var templateMethod in template.Methods.Where(m => !m.IsConstructor))
            {
                SpecializeTemplateMethod(thisClass, templateMethod, templateParams);
            }
        }
Exemple #27
0
        public static string GetTypeGetterCSMarshal(PropertyDefinition prop, int level)
        {
            StringBuilder     output = new StringBuilder();
            TypeRefDefinition type   = prop.Type;

            // If cached property can only be set in constructor,
            // the getter can simply return the cached value
            // TODO: check if cached value is initialized in all constructors
            CachedProperty cachedProperty;

            if (prop.Parent.CachedProperties.TryGetValue(prop.Name, out cachedProperty))
            {
                if (cachedProperty.Property.Setter == null)
                {
                    output.AppendLine(GetTabs(level + 2) + string.Format("get {{ return {0}; }}", cachedProperty.CacheFieldName));
                    return(output.ToString());
                }
            }

            if (!type.IsBasic)
            {
                switch (type.ManagedNameCS)
                {
                case "Matrix3x3":
                case "Quaternion":
                case "Transform":
                case "Vector3":
                case "Vector4":
                    output.AppendLine(GetTabs(level + 2) + "get");
                    output.AppendLine(GetTabs(level + 2) + "{");
                    output.AppendLine(GetTabs(level + 3) + GetTypeNameCS(type) + " value;");
                    output.AppendLine(GetTabs(level + 3) + string.Format("{0}_{1}(_native, out value);", prop.Parent.FullNameCS, prop.Getter.Name));
                    output.AppendLine(GetTabs(level + 3) + "return value;");
                    output.AppendLine(GetTabs(level + 2) + '}');
                    return(output.ToString());
                }
            }

            output.AppendLine(GetTabs(level + 2) + string.Format("get {{ return {0}{1}_{2}(_native){3}; }}",
                                                                 GetTypeMarshalConstructorStartCS(prop.Getter),
                                                                 prop.Parent.FullNameCS, prop.Getter.Name,
                                                                 GetTypeMarshalConstructorEndCS(prop.Getter)));
            return(output.ToString());
        }
Exemple #28
0
        private static string GetTypeSetterCSMarshal(TypeRefDefinition type)
        {
            type = type.Canonical;

            if ((type.Target != null && type.Target.MarshalAsStruct) ||
                (type.Kind == TypeKind.LValueReference && type.Referenced.Target != null && type.Referenced.Target.MarshalAsStruct))
            {
                return("ref value");
            }
            if (!type.IsBasic)
            {
                if (type.Kind == TypeKind.Pointer && type.Referenced.Kind == TypeKind.Void)
                {
                    return("value");
                }
                return("value._native");
            }

            return("value");
        }
Exemple #29
0
        // Is the struct passed by value or by reference?
        public static bool MarshalStructByValue(TypeRefDefinition type)
        {
            if (type.IsPointer)
            {
                return(false);
            }

            switch (type.ManagedName)
            {
            case "Matrix3x3":
            case "Quaternion":
            case "Transform":
            case "Vector3":
            case "Vector4":
                return(true);

            default:
                return(false);
            }
        }
        public TypeRefDefinition CopyTypeTemplated(TypeRefDefinition templateType, IDictionary <string, string> templateParams)
        {
            // Clang shows template parameters only as unexposed
            if (templateType.HasTemplateTypeParameter)
            {
                return(new TypeRefDefinition(templateParams[templateType.Name]));
            }

            if (templateType.Target != null)
            {
                // TODO: smarter replacement
                string specializedName = templateType.Target.FullyQualifiedName;
                foreach (var param in templateParams)
                {
                    specializedName = specializedName.Replace(param.Key, param.Value);
                }
                if (!specializedName.Equals(templateType.Target.FullyQualifiedName))
                {
                    var specializedType = new TypeRefDefinition(specializedName)
                    {
                        Kind = templateType.Kind
                    };
                    ResolveTypeRef(specializedType);
                    return(specializedType);
                }
            }

            var t = new TypeRefDefinition
            {
                HasTemplateTypeParameter = templateType.HasTemplateTypeParameter,
                IsConst      = templateType.IsConst,
                IsIncomplete = templateType.IsIncomplete,
                Name         = templateType.Name,
                Referenced   = templateType.Referenced != null?CopyTypeTemplated(templateType.Referenced, templateParams) : null,
                                   TemplateParams = templateType.TemplateParams?.Select(p => CopyTypeTemplated(p, templateParams)).ToList(),
                                   Target         = templateType.Target,
                                   Kind           = templateType.Kind
            };

            return(t);
        }
Exemple #31
0
        public static string GetTypeSetterCSMarshal(TypeRefDefinition type)
        {
            if (!type.IsBasic)
            {
                switch (type.ManagedNameCS)
                {
                case "Matrix3x3":
                case "Quaternion":
                case "Transform":
                case "Vector3":
                case "Vector4":
                    return("ref value");
                }
                if (type.ManagedTypeRefName.Equals("IntPtr"))
                {
                    return("value");
                }
                return("value._native");
            }

            return("value");
        }
Exemple #32
0
        public TypeRefDefinition CopyTemplated(IDictionary <string, string> templateParams)
        {
            // Clang shows template parameters only as unexposed
            if (HasTemplateTypeParameter && Kind == TypeKind.Unexposed)
            {
                return(new TypeRefDefinition(templateParams[Name]));
            }

            var t = new TypeRefDefinition
            {
                HasTemplateTypeParameter = HasTemplateTypeParameter,
                IsConst      = IsConst,
                IsIncomplete = IsIncomplete,
                Name         = Name,
                Referenced   = Referenced != null?Referenced.CopyTemplated(templateParams) : null,
                                   TemplateParams = TemplateParams?.Select(p => p.CopyTemplated(templateParams)).ToList(),
                                   Target         = Target,
                                   Kind           = Kind
            };

            return(t);
        }
        void ResolveTypeRef(TypeRefDefinition typeRef)
        {
            if (typeRef.IsBasic || typeRef.HasTemplateTypeParameter)
            {
                return;
            }
            if (typeRef.IsPointer || typeRef.IsReference || typeRef.IsConstantArray)
            {
                ResolveTypeRef(typeRef.Referenced);
            }
            else if (!classDefinitions.ContainsKey(typeRef.Name))
            {
                // Search for unscoped enums
                bool resolvedEnum = false;
                foreach (var c in classDefinitions.Values.Where(c => c.Enum != null))
                {
                    if (typeRef.Name.Equals(c.FullName + "::" + c.Enum.Name))
                    {
                        typeRef.Target = c;
                        resolvedEnum = true;
                    }
                }
                if (!resolvedEnum)
                {
                    Console.WriteLine("Class " + typeRef.Name + " not found!");
                }
            }
            else
            {
                typeRef.Target = classDefinitions[typeRef.Name];
            }

            if (typeRef.SpecializedTemplateType != null)
            {
                ResolveTypeRef(typeRef.SpecializedTemplateType);
            }
        }
        // If the type is defined in a conditionally compiled header, return the condition string.
        private string GetTypeConditional(TypeRefDefinition type)
        {
            var target = type.Target;
            if (target == null && type.Referenced != null)
            {
                target = type.Referenced.Target;
            }

            if (target == null) return null;

            string headerConditional;
            string targetHeaderName = DotNetParser.GetManaged(target.Header).Name;
            if (headerConditionals.TryGetValue(targetHeaderName, out headerConditional))
            {
                return headerConditional;
            }

            return null;
        }
        void AddForwardReference(List<ManagedClass> forwardRefs, TypeRefDefinition type, HeaderDefinition header)
        {
            if (type.IsBasic) return;

            switch (type.Kind)
            {
                case TypeKind.Pointer:
                case TypeKind.LValueReference:
                    AddForwardReference(forwardRefs, type.Referenced, header);
                    return;
            }

            var target = type.Target;
            if (target == null) return;
            if (target.IsExcluded || target.MarshalAsStruct || target.Header == header) return;

            var targetManaged = DotNetParser.GetManaged(target);
            if (!forwardRefs.Contains(targetManaged))
            {
                forwardRefs.Add(targetManaged);
            }
        }
        void WriteType(TypeRefDefinition type, WriteTo writeTo)
        {
            if (type.IsBasic)
            {
                Write(type.Name.Replace("::", "_"), writeTo & WriteTo.Header);
                Write(type.Name, writeTo & WriteTo.Source);
            }
            else if (type.HasTemplateTypeParameter)
            {

            }
            else
            {
                string typeName;
                if (type.Referenced != null)
                {
                    if (type.Referenced.IsConst) // || type.IsConst
                    {
                        Write("const ", writeTo);
                    }

                    typeName = BulletParser.GetTypeName(type.Referenced) ?? string.Empty;
                }
                else
                {
                    if (type.IsConst)
                    {
                        Write("const ", writeTo);
                    }

                    typeName = BulletParser.GetTypeName(type);
                }
                if (type.Target != null && type.Target.IsPureEnum)
                {
                    Write(typeName + "::" + type.Target.Enum.Name, writeTo & WriteTo.Source);
                    Write(typeName.Replace("::", "_"), writeTo & WriteTo.Header);
                }
                else
                {
                    Write(typeName + '*', writeTo & WriteTo.Source);
                    Write(typeName.Replace("::", "_") + '*', writeTo & WriteTo.Header);
                }
            }
        }
        private string GetTypeName(TypeRefDefinition type)
        {
            if (type.Kind == TypeKind.Typedef)
            {
                if (type.Referenced.Kind == TypeKind.Pointer &&
                    type.Referenced.Referenced.Kind == TypeKind.FunctionProto)
                {
                    return GetName(type);
                }
                if (type.Canonical.IsBasic)
                {
                    return type.Name;
                }
                return GetTypeName(type.Referenced);
            }

            if (type.Kind == TypeKind.LValueReference)
            {
                return GetTypeName(type.Referenced);
            }

            if (!string.IsNullOrEmpty(type.Name) && type.Name.Equals("btAlignedObjectArray"))
            {
                if (type.TemplateParams != null)
                {
                    return "Aligned" + GetName(type.TemplateParams[0]) + "Array^";
                }
            }

            switch (type.Kind)
            {
                case TypeKind.Pointer:
                case TypeKind.LValueReference:
                case TypeKind.ConstantArray:
                    if (type.Referenced.Kind == TypeKind.Void)
                    {
                        return "IntPtr";
                    }
                    switch (GetName(type))
                    {
                        case "char":
                            return "String^";
                        case "float":
                            return string.Format("array<{0}>^", type.Referenced.Name);
                    }
                    return GetName(type) + '^';
            }
            return GetName(type);
        }
        // Does the type require additional lines of code to marshal?
        public static bool TypeRequiresMarshal(TypeRefDefinition type)
        {
            switch (type.Kind)
            {
                case TypeKind.ConstantArray:
                case TypeKind.LValueReference:
                case TypeKind.Pointer:
                    return TypeRequiresMarshal(type.Referenced);
            }

            return type.Target != null && type.Target.MarshalAsStruct;
        }
        private static string GetTypeNameC(TypeRefDefinition type)
        {
            string name = "";

            if (type.IsConst)
            {
                // Note: basic type can be const
                if (type.Referenced == null ||
                    (type.Referenced != null && !type.Referenced.ConstCanonical))
                {
                    name = "const ";
                }
            }

            if (type.IsBasic) return name + type.Name;

            if (type.Kind == TypeKind.Typedef)
            {
                if (type.Referenced.IsBasic) return type.Name;
                if (type.Referenced.Kind == TypeKind.Pointer &&
                    type.Referenced.Referenced.Kind == TypeKind.FunctionProto)
                {
                    return type.Name;
                }
                return name + GetTypeNameC(type.Referenced);
            }

            if (type.Referenced != null) return name + GetTypeNameC(type.Referenced) + "*";

            var target = type.Target;
            if (target != null && target is EnumDefinition)
            {
                if (target.Parent != null && target.Parent.IsPureEnum)
                {
                    return target.Parent.FullName.Replace("::", "_");
                }
            }

            // Template name to C form
            if (type.FullName.Contains("<"))
            {
                string template = type.FullName.Replace('<', '_').Replace(">", "").Replace(" *", "Ptr");
                template = template.Replace(' ', '_');
                return name + template.Replace("::", "_");
            }

            return name + type.FullName.Replace("::", "_");
        }
 // Return condition unless type is already used under the same condition.
 string GetTypeConditional(TypeRefDefinition type, HeaderDefinition header)
 {
     string typeConditional = GetTypeConditional(type);
     if (typeConditional != null && headerConditionals.ContainsKey(header.ManagedName))
     {
         if (headerConditionals[header.ManagedName].Equals(typeConditional))
         {
             return null;
         }
     }
     return typeConditional;
 }
        public TypeRefDefinition CopyTypeTemplated(TypeRefDefinition templateType, IDictionary<string, string> templateParams)
        {
            // Clang shows template parameters only as unexposed
            if (templateType.HasTemplateTypeParameter)
            {
                return new TypeRefDefinition(templateParams[templateType.Name]);
            }

            if (templateType.Target != null)
            {
                // TODO: smarter replacement
                string specializedName = templateType.Target.FullyQualifiedName;
                foreach (var param in templateParams)
                {
                    specializedName = specializedName.Replace(param.Key, param.Value);
                }
                if (!specializedName.Equals(templateType.Target.FullyQualifiedName))
                {
                    var specializedType = new TypeRefDefinition(specializedName)
                    {
                        Kind = templateType.Kind
                    };
                    ResolveTypeRef(specializedType);
                    return specializedType;
                }
            }

            var t = new TypeRefDefinition
            {
                HasTemplateTypeParameter = templateType.HasTemplateTypeParameter,
                IsConst = templateType.IsConst,
                IsIncomplete = templateType.IsIncomplete,
                Name = templateType.Name,
                Referenced = templateType.Referenced != null ? CopyTypeTemplated(templateType.Referenced, templateParams) : null,
                TemplateParams = templateType.TemplateParams?.Select(p => CopyTypeTemplated(p, templateParams)).ToList(),
                Target = templateType.Target,
                Kind = templateType.Kind
            };
            return t;
        }
        public TypeRefDefinition(ClangSharp.Type type, Cursor cursor = null)
        {
            Kind = (TypeKind)type.TypeKind;

            if (!type.Declaration.IsInvalid &&
                !type.Declaration.IsDefinition &&
                type.Declaration.SpecializedCursorTemplate.IsInvalid)
            {
                // Forward reference
                IsIncomplete = true;
            }

            IsConst = type.IsConstQualifiedType;

            if (type.Pointee.TypeKind != ClangSharp.Type.Kind.Invalid)
            {
                Cursor pointeeCursor = cursor?.Children.FirstOrDefault(c => c.Type.Equals(type.Pointee));
                if (pointeeCursor == null)
                {
                    pointeeCursor = cursor?.Children.FirstOrDefault(c => c.Kind == CursorKind.TypeRef)?.Referenced;
                }
                Referenced = new TypeRefDefinition(type.Pointee, pointeeCursor);
            }
            else if (Kind != TypeKind.Typedef)
            {
                if (cursor != null && (Kind == TypeKind.Record || Kind == TypeKind.Unexposed))
                {
                    if (cursor.Kind == CursorKind.TypeRef)
                    {
                        if (cursor.Referenced.Kind == CursorKind.TemplateTypeParameter)
                        {
                            HasTemplateTypeParameter = true;
                        }
                    }
                    else if (cursor.Kind == CursorKind.CxxMethod)
                    {
                        var children = cursor.Children.TakeWhile(c => c.Kind != CursorKind.ParmDecl);
                        var typeRef = children.FirstOrDefault();
                        if (typeRef != null && typeRef.Kind == CursorKind.TypeRef)
                        {
                            if (typeRef.Referenced.Kind == CursorKind.TemplateTypeParameter)
                            {
                                HasTemplateTypeParameter = true;
                            }
                        }
                    }
                    else if (cursor.Kind == CursorKind.ParmDecl)
                    {
                        var typeRef = cursor.Children.FirstOrDefault();
                        if (typeRef != null && typeRef.Kind == CursorKind.TypeRef)
                        {
                            if (typeRef.Referenced.Kind == CursorKind.TemplateTypeParameter)
                            {
                                HasTemplateTypeParameter = true;
                            }
                        }
                    }
                }

                // Capture template parameters
                var firstChild = cursor?.Children.FirstOrDefault();
                if (firstChild != null && firstChild.Kind == CursorKind.TemplateRef)
                {
                    if (cursor.Children.Count == 1)
                    {
                        string displayName = GetFullyQualifiedName(type, cursor);
                        int typeStart = displayName.IndexOf('<') + 1;
                        int typeEnd = displayName.LastIndexOf('>');
                        displayName = displayName.Substring(typeStart, typeEnd - typeStart);
                        TemplateParams = new List<TypeRefDefinition> { new TypeRefDefinition(displayName) };
                    }
                    else
                    {
                        TemplateParams = cursor.Children.Skip(1)
                            .Select(c => new TypeRefDefinition(c.Type, c)).ToList();
                    }
                }
            }

            switch (Kind)
            {
                case TypeKind.Void:
                case TypeKind.Bool:
                case TypeKind.Char_S:
                case TypeKind.Double:
                case TypeKind.Float:
                case TypeKind.Int:
                case TypeKind.UChar:
                case TypeKind.UInt:
                    Name = type.Spelling;
                    break;
                case TypeKind.Long:
                    Name = "long";
                    break;
                case TypeKind.LongLong:
                    Name = "long long";
                    break;
                case TypeKind.Short:
                    Name = "short";
                    break;
                case TypeKind.ULong:
                    Name = "unsigned long";
                    break;
                case TypeKind.ULongLong:
                    Name = "unsigned long long";
                    break;
                case TypeKind.UShort:
                    Name = "unsigned short";
                    break;

                case TypeKind.Typedef:
                    Name = GetFullyQualifiedName(type);
                    Referenced = new TypeRefDefinition(type.Canonical, cursor?.Referenced);
                    break;

                case TypeKind.FunctionProto:
                case TypeKind.LValueReference:
                case TypeKind.Pointer:
                    break;
                case TypeKind.ConstantArray:
                    Referenced = new TypeRefDefinition(type.ArrayElementType, cursor);
                    break;

                case TypeKind.Enum:
                    Name = type.Canonical.Declaration.Spelling;
                    break;
                case TypeKind.Record:
                    Name = GetFullyQualifiedName(type, cursor);
                    break;
                case TypeKind.Unexposed:
                    if (type.Canonical.TypeKind != ClangSharp.Type.Kind.Unexposed)
                    {
                        Kind = (TypeKind)type.Canonical.TypeKind;
                        Name = GetFullyQualifiedName(type.Canonical, cursor);
                    }
                    else
                    {
                        Name = GetFullyQualifiedName(type, cursor);
                    }
                    break;
                case TypeKind.DependentSizedArray:
                    break;
                default:
                    throw new NotImplementedException();
            }
        }
        void AddForwardReference(List<ClassDefinition> forwardRefs, TypeRefDefinition type, HeaderDefinition header)
        {
            if (type.IsBasic)
            {
                return;
            }

            if (type.IsPointer || type.IsReference)
            {
                AddForwardReference(forwardRefs, type.Referenced, header);
                return;
            }

            if (type.Target == null)
            {
                return;
            }
            if (type.Target.IsExcluded ||
                forwardRefs.Contains(type.Target) ||
                PrecompiledHeaderReferences.Contains(type.Target.ManagedName))
            {
                return;
            }

            // Forward ref to class in another header
            if (type.Target.Header != header)
            {
                forwardRefs.Add(type.Target);
            }
        }
        public static string GetTypeDllImport(TypeRefDefinition type)
        {
            switch (type.ManagedNameCS)
            {
                case "Matrix3x3":
                case "Quaternion":
                case "Transform":
                case "Vector3":
                case "Vector4":
                    {
                        if (type.Referenced != null && !(type.IsConst || type.Referenced.IsConst))
                        {
                            return "[Out] out " + GetTypeNameCS(type);
                        }
                        return "[In] ref " + GetTypeNameCS(type);
                    }
            }

            if (type.Referenced != null && !type.IsBasic)
            {
                if ("btScalar".Equals(type.Referenced.Name))
                {
                    if (type.IsPointer)
                    {
                        return type.ManagedNameCS + "[]";
                    }
                    else
                    {
                        // reference
                        if (!(type.IsConst || type.Referenced.IsConst))
                        {
                            return "[Out] out " + type.ManagedNameCS;
                        }
                    }
                }
                return "IntPtr";
            }

            return type.ManagedNameCS;
        }
        private string GetTypeNameCS(TypeRefDefinition type)
        {
            if (type.Kind == TypeKind.Typedef)
            {
                if (type.Referenced.Kind == TypeKind.Pointer &&
                    type.Referenced.Referenced.Kind == TypeKind.FunctionProto)
                {
                    return GetName(type);
                }
                return GetTypeNameCS(type.Referenced);
            }

            if (type.Kind == TypeKind.LValueReference)
            {
                return GetTypeNameCS(type.Referenced);
            }

            if (type.IsBasic)
            {
                switch (type.Kind)
                {
                    case TypeKind.UShort:
                        return "ushort";
                    case TypeKind.UInt:
                        return "uint";
                    case TypeKind.ULong:
                        return "ulong";
                }
                return GetName(type);
            }

            if (type.Kind == TypeKind.Pointer && type.Referenced.Kind == TypeKind.Void)
            {
                return "IntPtr";
            }

            if (type.Kind == TypeKind.ConstantArray)
            {
                switch (type.Referenced.Name)
                {
                    case "bool":
                        return "BoolArray";
                    case "int":
                        return "IntArray";
                    case "unsigned int":
                        return "UIntArray";
                    case "unsigned short":
                        return "UShortArray";
                    case "btScalar":
                        return "FloatArray";
                    case "btDbvt":
                        return "DbvtArray";
                    case "btSoftBody::Body":
                        return "BodyArray";
                }

                if (type.Referenced.Referenced != null)
                {
                    switch (type.Referenced.Referenced.Name)
                    {
                        case "btDbvtNode":
                            return "DbvtNodePtrArray";
                        case "btDbvtProxy":
                            return "DbvtProxyPtrArray";
                        case "btSoftBody::Node":
                            return "NodePtrArray";
                    }
                }

                return GetTypeNameCS(type.Referenced) + "[]";
            }

            return GetName(type);
        }
        /// <summary>
        /// If a method returns a type that is marshalled as struct,
        /// then this is incompatible with C.
        /// Append an out parameter that will receive the struct.
        /// </summary>
        private void CreateStructOutParameters()
        {
            foreach (var method in Project.ClassDefinitions.Values.SelectMany(c => c.Methods))
            {
                var type = method.ReturnType;
                TypeRefDefinition targetType;
                if (type.Target != null && type.Target.MarshalAsStruct)
                {
                    targetType = type;
                }
                else if (type.Kind == TypeKind.LValueReference &&
                    type.Referenced.Target != null && type.Referenced.Target.MarshalAsStruct)
                {
                    targetType = type.Referenced;
                }
                else
                {
                    continue;
                }

                targetType = targetType.Copy();
                targetType.IsConst = false;

                var outType = new TypeRefDefinition
                {
                    Kind = TypeKind.Pointer,
                    Referenced = targetType
                };
                method.OutValueParameter = new ParameterDefinition("value", outType)
                {
                    MarshalDirection = MarshalDirection.Out
                };
            }
        }
 // Does the type require additional lines of code to marshal?
 public static bool TypeRequiresMarshal(TypeRefDefinition type)
 {
     switch (type.ManagedName)
     {
         case "Matrix3x3":
         case "Quaternion":
         case "Transform":
         case "Vector3":
         case "Vector4":
             return true;
         default:
             return false;
     }
 }
 public TypeRefDefinition Copy()
 {
     var t = new TypeRefDefinition
     {
         HasTemplateTypeParameter = HasTemplateTypeParameter,
         IsBasic = IsBasic,
         IsConst = IsConst,
         IsConstantArray = IsConstantArray,
         IsIncomplete = IsIncomplete,
         IsPointer = IsPointer,
         IsReference = IsReference,
         Name = Name,
         Referenced = Referenced,
         SpecializedTemplateType = SpecializedTemplateType,
         Target = Target
     };
     return t;
 }
 void WriteType(TypeRefDefinition type, WriteTo writeTo)
 {
     string typeName = BulletParser.GetTypeName(type) ?? string.Empty;
     Write(typeName.Replace("::", "_"), writeTo & (WriteTo.Source | WriteTo.Header));
 }
        private void ResolveInclude(TypeRefDefinition type, HeaderDefinition parentHeader)
        {
            switch (type.Kind)
            {
                case TypeKind.Pointer:
                case TypeKind.LValueReference:
                case TypeKind.ConstantArray:
                    ResolveInclude(type.Referenced, parentHeader);
                    return;
            }
            if (type.TemplateParams != null)
            {
                type.TemplateParams.ForEach(p => ResolveInclude(p, parentHeader));
            }
            else if (type.IsIncomplete && type.Target != null)
            {
                if (type.Target.MarshalAsStruct) return;

                parentHeader.Includes.Add(type.Target.Header);
            }
        }
        // If the type is defined in a conditionally compiled header, return the condition string.
        string GetTypeConditional(TypeRefDefinition type)
        {
            var target = type.Target;
            if (target == null && type.Referenced != null)
            {
                target = type.Referenced.Target;
            }

            if (target != null && headerConditionals.ContainsKey(target.Header.ManagedName))
            {
                return headerConditionals[target.Header.ManagedName];
            }

            return null;
        }
 public static string GetReturnValueMarshalStart(TypeRefDefinition type)
 {
     switch (type.ManagedName)
     {
         case "Quaternion":
         case "Matrix3x3":
         case "Transform":
         case "Vector3":
         case "Vector4":
             if (type.IsPointer)
             {
                 return type.ManagedName.ToUpper() + "_OUT(";
             }
             if (type.IsReference)
             {
                 return type.ManagedName.ToUpper() + "_OUT(&";
             }
             return type.ManagedName.ToUpper() + "_OUT_VAL(";
         default:
             return null;
     }
 }
        public TypeRefDefinition(ClangSharp.Type type)
        {
            if (!type.Declaration.IsInvalid &&
                !type.Declaration.IsDefinition &&
                type.Declaration.SpecializedCursorTemplate.IsInvalid)
            {
                // Forward reference
                IsIncomplete = true;
            }

            IsConst = type.IsConstQualifiedType;

            switch (type.TypeKind)
            {
                case ClangSharp.Type.Kind.Void:
                case ClangSharp.Type.Kind.Bool:
                case ClangSharp.Type.Kind.CharS:
                case ClangSharp.Type.Kind.Double:
                case ClangSharp.Type.Kind.Float:
                case ClangSharp.Type.Kind.Int:
                case ClangSharp.Type.Kind.UChar:
                case ClangSharp.Type.Kind.UInt:
                    Name = type.Spelling;
                    IsBasic = true;
                    break;
                case ClangSharp.Type.Kind.Long:
                    Name = "long";
                    IsBasic = true;
                    break;
                case ClangSharp.Type.Kind.LongLong:
                    Name = "long long";
                    IsBasic = true;
                    break;
                case ClangSharp.Type.Kind.Short:
                    Name = "short";
                    IsBasic = true;
                    break;
                case ClangSharp.Type.Kind.ULong:
                    Name = "unsigned long";
                    IsBasic = true;
                    break;
                case ClangSharp.Type.Kind.UShort:
                    Name = "unsigned short";
                    IsBasic = true;
                    break;
                case ClangSharp.Type.Kind.Typedef:
                    Name = GetFullyQualifiedName(type);
                    Referenced = new TypeRefDefinition(type.Canonical);
                    IsBasic = Referenced.IsBasic;
                    break;
                case ClangSharp.Type.Kind.Pointer:
                    Referenced = new TypeRefDefinition(type.Pointee);
                    IsPointer = true;
                    break;
                case ClangSharp.Type.Kind.LValueReference:
                    Referenced = new TypeRefDefinition(type.Pointee);
                    IsReference = true;
                    break;
                case ClangSharp.Type.Kind.ConstantArray:
                    Referenced = new TypeRefDefinition(type.ArrayElementType);
                    IsConstantArray = true;
                    break;
                case ClangSharp.Type.Kind.FunctionProto:
                    // ??
                    break;
                case ClangSharp.Type.Kind.Enum:
                    Name = type.Canonical.Declaration.Spelling;
                    IsBasic = true;
                    break;
                case ClangSharp.Type.Kind.Record:
                case ClangSharp.Type.Kind.Unexposed:
                    Name = GetFullyQualifiedName(type);
                    break;
                case ClangSharp.Type.Kind.DependentSizedArray:
                    break;
                default:
                    throw new NotImplementedException();
            }
        }
        void ResolveTypeRef(TypeRefDefinition typeRef)
        {
            switch (typeRef.Kind)
            {
                case TypeKind.Enum:
                case TypeKind.Record:
                case TypeKind.Unexposed:
                    if (Project.ClassDefinitions.ContainsKey(typeRef.Name))
                    {
                        typeRef.Target = Project.ClassDefinitions[typeRef.Name];
                        return;
                    }

                    Console.WriteLine($"Unresolved reference: {typeRef.Name}");

                    if (typeRef.TemplateParams != null)
                    {
                        typeRef.TemplateParams.ForEach(ResolveTypeRef);

                        // Create template specialization class
                        string templateName = typeRef.Name.Substring(0, typeRef.Name.IndexOf('<'));

                        ClassDefinition template;
                        if (Project.ClassDefinitions.TryGetValue(templateName, out template))
                        {
                            if (!template.IsExcluded)
                            {
                                //string name = $"{typeRef.Name}<{typeRef.TemplateParams.First().Name}>";
                                string name = typeRef.Name;

                                var classTemplate = template as ClassTemplateDefinition;
                                var header = classTemplate.Header;
                                var specializedClass = new ClassDefinition(name, header);
                                specializedClass.BaseClass = template;
                                header.Classes.Add(specializedClass);
                                Project.ClassDefinitions.Add(name, specializedClass);
                            }
                        }
                    }
                    break;
                case TypeKind.Typedef:
                    var underlying = typeRef.Canonical;
                    if (underlying.Kind == TypeKind.Pointer &&
                        underlying.Referenced.Kind == TypeKind.FunctionProto)
                    {
                        typeRef.Target = Project.ClassDefinitions[typeRef.Name];
                        return;
                    }
                    break;
            }

            if (typeRef.Referenced != null)
            {
                ResolveTypeRef(typeRef.Referenced);
            }
        }
        private static string GetTypeSetterCSMarshal(TypeRefDefinition type)
        {
            type = type.Canonical;

            if ((type.Target != null && type.Target.MarshalAsStruct) ||
                (type.Kind == TypeKind.LValueReference && type.Referenced.Target != null && type.Referenced.Target.MarshalAsStruct))
            {
                return "ref value";
            }
            if (!type.IsBasic)
            {
                if (type.Kind == TypeKind.Pointer && type.Referenced.Kind == TypeKind.Void)
                {
                    return "value";
                }
                return "value._native";
            }

            return "value";
        }
        public TypeRefDefinition(string name)
        {
            switch (name)
            {
                case "bool":
                    Kind = TypeKind.Bool;
                    break;
                case "char":
                    Kind = TypeKind.Char_U;
                    break;
                case "double":
                    Kind = TypeKind.Double;
                    break;
                case "float":
                    Kind = TypeKind.Float;
                    break;
                case "int":
                    Kind = TypeKind.Int;
                    break;
                case "unsigned char":
                    Kind = TypeKind.UChar;
                    break;
                case "unsigned int":
                    Kind = TypeKind.UInt;
                    break;
                case "void":
                    Kind = TypeKind.Void;
                    break;
                case "long":
                case "long int":
                    Kind = TypeKind.Long;
                    break;
                case "long long":
                case "long long int":
                    Kind = TypeKind.LongLong;
                    break;
                case "short":
                case "short int":
                    Kind = TypeKind.Short;
                    break;
                case "unsigned long":
                case "unsigned long int":
                    Kind = TypeKind.ULong;
                    break;
                case "unsigned long long":
                case "unsigned long long int":
                    Kind = TypeKind.ULongLong;
                    break;
                case "unsigned short":
                case "unsigned short int":
                    Kind = TypeKind.UShort;
                    break;
            }

            if (IsBasic)
            {
                Name = GetBasicName(name);
            }
            else if (name.EndsWith(" *"))
            {
                Referenced = new TypeRefDefinition(name.Substring(0, name.Length - 2));
                Kind = TypeKind.Pointer;
            }
            else
            {
                Name = name;
            }
        }
        private void CreateFieldGetter(FieldDefinition field, ClassDefinition @class, string getterName, MethodDefinition setter)
        {
            MethodDefinition getter;

            // Use getter with an out parameter for structs
            if (field.Type.Target != null && field.Type.Target.MarshalAsStruct)
            {
                getter = new MethodDefinition(getterName, @class, 1);
                getter.ReturnType = new TypeRefDefinition("void");

                string paramName = setter != null ? setter.Parameters[0].Name : "value";
                var paramType = new TypeRefDefinition(field.Type.Name)
                {
                    Kind = TypeKind.Pointer,
                    Referenced = field.Type.Copy()
                };
                getter.Parameters[0] = new ParameterDefinition(paramName, paramType)
                {
                    MarshalDirection = MarshalDirection.Out
                };
            }
            else
            {
                TypeRefDefinition type;
                if (field.Type.Canonical.Kind == TypeKind.Record)
                {
                    type = new TypeRefDefinition()
                    {
                        Kind = TypeKind.Pointer,
                        Referenced = field.Type.Copy()
                    };
                }
                else if (field.Type.Canonical.Kind == TypeKind.Unexposed)
                {
                    // TODO:
                    type = field.Type;
                }
                else
                {
                    type = field.Type;
                }

                getter = new MethodDefinition(getterName, @class, 0);
                getter.ReturnType = type;
            }

            getter.Field = field;
            field.Getter = getter;
        }
 public TypeRefDefinition Copy()
 {
     var t = new TypeRefDefinition
     {
         HasTemplateTypeParameter = HasTemplateTypeParameter,
         IsConst = IsConst,
         IsIncomplete = IsIncomplete,
         Name = Name,
         Referenced = Referenced != null ? Referenced.Copy() : null,
         TemplateParams = TemplateParams?.Select(p => p.Copy()).ToList(),
         Target = Target,
         Kind = Kind
     };
     return t;
 }
        void WriteMethod(MethodDefinition method, int level, ref int overloadIndex, int numOptionalParams = 0, MethodDefinition returnParamMethod = null)
        {
            // Can't return whole structures, so append an output parameter
            // referencing the struct that will hold the return value.
            // convert "v method(param)" to "void method(param, &v)"
            if (!method.IsConstructor && !method.ReturnType.IsBasic &&
                !method.ReturnType.IsPointer && BulletParser.MarshalStructByValue(method.ReturnType))
            {
                var method2 = method.Copy();
                var paras = method2.Parameters;
                Array.Resize<ParameterDefinition>(ref paras, paras.Length + 1);
                string paramName;
                if (method.Property != null && method.Property.Setter != null)
                {
                    // Borrow out parameter name from setter
                    paramName = method.Property.Setter.Parameters[0].Name;
                }
                else
                {
                    paramName = "value";
                }
                var valueType = new TypeRefDefinition()
                {
                    IsBasic = false,
                    IsPointer = true,
                    Referenced = method2.ReturnType
                };
                paras[paras.Length - 1] = new ParameterDefinition(paramName, valueType);
                paras[paras.Length - 1].ManagedName = paramName;
                method2.Parameters = paras;
                method2.ReturnType = new TypeRefDefinition();
                WriteMethod(method2, level, ref overloadIndex, numOptionalParams, method);
                return;
            }

            EnsureWhiteSpace(WriteTo.Source | WriteTo.CS);

            // Skip methods wrapped by C# properties
            WriteTo propertyTo = WriteTo.Header | WriteTo.Source | ((method.Property == null) ? WriteTo.CS : 0);

            int numOptionalParamsTotal = method.NumOptionalParameters;
            int numParameters = method.Parameters.Length - numOptionalParamsTotal + numOptionalParams;

            WriteMethodDeclaration(method, numParameters, level, overloadIndex, returnParamMethod);

            if (method.Name.Equals("delete"))
            {
                WriteLine('{', WriteTo.Source);
                WriteTabs(1, WriteTo.Source);
                WriteLine("delete obj;", WriteTo.Source);
                WriteLine('}', WriteTo.Source);
                hasSourceWhiteSpace = false;
                hasCSWhiteSpace = false;
                return;
            }

            // Constructor base call
            if (method.IsConstructor && method.Parent.BaseClass != null)
            {
                WriteTabs(level + 2, WriteTo.CS & propertyTo);
                Write(": base(", WriteTo.CS & propertyTo);
            }
            else
            {
                WriteTabs(level + 1, WriteTo.CS & propertyTo);
                WriteLine('{', WriteTo.CS & propertyTo);
                WriteTabs(level + 2, WriteTo.CS & propertyTo);
            }

            // Method body
            WriteLine('{', WriteTo.Source);

            WriteMethodDefinition(method, numParameters, overloadIndex, level, returnParamMethod);

            WriteTabs(level + 1, WriteTo.CS & propertyTo);
            WriteLine('}', WriteTo.Source | WriteTo.CS & propertyTo);
            hasSourceWhiteSpace = false;
            if (method.Property == null)
            {
                hasCSWhiteSpace = false;
            }

            // If there are optional parameters, then output all possible combinations of calls
            overloadIndex++;
            if (numOptionalParams < numOptionalParamsTotal)
            {
                WriteMethod(method, level, ref overloadIndex, numOptionalParams + 1, returnParamMethod);
            }
        }
        private void CreateFieldSetter(FieldDefinition field, ClassDefinition @class, string setterName)
        {
            var type = field.Type;
            var typeCanonical = type.Canonical;

            // Can't assign value to reference or constant array
            switch (typeCanonical.Kind)
            {
                case TypeKind.LValueReference:
                case TypeKind.ConstantArray:
                    return;
                case TypeKind.Record:
                    if (typeCanonical.Target == null) return;
                    if (!typeCanonical.Target.MarshalAsStruct) return;

                    type = new TypeRefDefinition
                    {
                        IsConst = true,
                        Kind = TypeKind.Pointer,
                        Referenced = type.Copy()
                    };
                    break;
                default:
                    type = type.Copy();
                    break;
            }

            var setter = new MethodDefinition(setterName, @class, 1)
            {
                Field = field,
                ReturnType = new TypeRefDefinition("void")
            };
            setter.Parameters[0] = new ParameterDefinition("value", type)
            {
                MarshalDirection = MarshalDirection.In
            };

            field.Setter = setter;
        }