public static DocItem CreateDocumentation(params Assembly[] assemblies)
        {
            var bindings = new ScriptBindings();

            bindings.BindAssembly(assemblies);

            DocItem doc = new DocItem(DocItemType.Table, null, "Root", "Root", "");
            var     bi  = bindings.bindItems.Values;

            foreach (var item in bi)
            {
                if (item is BindTable bTable)
                {
                    doc.SubDocs.Add(DocumentTable(bTable, "", 0));
                }
                else if (item is BindFunc func)
                {
                    doc.SubDocs.Add(DocumentFunction(func, ""));
                }
                else if (item is BindUserType bUserType)
                {
                    doc.SubDocs.Add(DocumentType(bUserType, "", 0));
                }
                else if (item is BindUserObject bUserObj)
                {
                    doc.SubDocs.Add(DocumentObject(bUserObj, "", 0));
                }
                else if (item is BindEnum bEnum)
                {
                    doc.SubDocs.Add(DocumentEnum(bEnum, ""));
                }
            }

            doc.Sort();

            return(doc);
        }
        private static DocItem DocumentEnum(BindEnum enu, string prefix)
        {
            string name       = enu.Name;
            string fullName   = prefix + name;
            string definition = fullName;
            string copy       = definition;
            var    nextPrefix = prefix + name + ".";

            string documentation = enu.Documentation ?? "";
            string example       = enu.Example ?? "";

            var doc = new DocItem(DocItemType.Enum, enu.EnumType, name, fullName, definition, copy, documentation, example)
            {
                DataType = enu.EnumType
            };

            for (int i = 0; i < enu.EnumVals.Count; i++)
            {
                var field = enu.EnumVals[i];
                var iobj  = DocumentInstanceObject(typeof(int), field.Key, nextPrefix, 0, enu.EnumType, enu.FieldDocumentations[i], enu.FieldExamples[i]);
                doc.SubDocs.Add(iobj);
            }
            return(doc);
        }
        private static DocItem DocumentType(BindUserType userType, string prefix, int curLevel)
        {
            //Get attributes
            string documentation = userType.Documentation ?? "";
            string example       = userType.Example ?? "";

            DocItem doc = new DocItem(DocItemType.StaticType, userType.UserType, userType.Name, prefix + userType.Name, userType.Name, userType.Name, documentation, example, userType.Name, userType.Name, userType.Name)
            {
                DataType = userType.UserType
            };
            var type       = userType.UserType;
            var nextPrefix = prefix + userType.Name + ".";
            //STATIC
            var fields = type.GetFields(BindingFlags.Static | BindingFlags.Public).Where(a => !a.IsSpecialName && a.Name != "ToString" && a.Name != "GetHashCode" && a.Name != "GetType" && a.Name != "Equals" && a.Name != "GetTypeCode")
                         .Where(x => !x.CustomAttributes.Any(y => y.AttributeType == typeof(MoonSharpHiddenAttribute) || y.AttributeType == typeof(MoonSharpHideMemberAttribute) || y.AttributeType == typeof(LunarBindHideAttribute)));
            var properties = type.GetProperties(BindingFlags.Static | BindingFlags.Public).Where(a => !a.IsSpecialName && a.Name != "ToString" && a.Name != "GetHashCode" && a.Name != "GetType" && a.Name != "Equals" && a.Name != "GetTypeCode")
                             .Where(x => !x.CustomAttributes.Any(y => y.AttributeType == typeof(MoonSharpHiddenAttribute) || y.AttributeType == typeof(MoonSharpHideMemberAttribute) || y.AttributeType == typeof(LunarBindHideAttribute)));
            var funcs = type.GetMethods(BindingFlags.Static | BindingFlags.Public).Where(a => !a.IsSpecialName && a.Name != "ToString" && a.Name != "GetHashCode" && a.Name != "GetType" && a.Name != "Equals" && a.Name != "GetTypeCode")
                        .Where(x => !x.CustomAttributes.Any(y => y.AttributeType == typeof(MoonSharpHiddenAttribute) || y.AttributeType == typeof(MoonSharpHideMemberAttribute) || y.AttributeType == typeof(LunarBindHideAttribute)));

            //TODO: events
            //var events = type.GetEvents(BindingFlags.Static | BindingFlags.Public)
            //    .Where(x => !x.CustomAttributes.Any(y => y.AttributeType == typeof(MoonSharpHiddenAttribute) || y.AttributeType == typeof(MoonSharpHideMemberAttribute) || y.AttributeType == typeof(LunarBindHideAttribute)));

            foreach (var field in fields)
            {
                string docu = "";
                string ex   = "";

                var docAttrib2 = field.GetCustomAttribute <LunarBindDocumentationAttribute>();
                if (docAttrib2 != null)
                {
                    docu = docAttrib2.Data;
                }
                var exampleAttrib2 = field.GetCustomAttribute <LunarBindExampleAttribute>();
                if (exampleAttrib2 != null)
                {
                    ex = exampleAttrib2.Data;
                }

                var fdoc = DocumentInstanceObject(field.FieldType, field.Name, nextPrefix, curLevel + 1, type, docu, ex);

                if (fdoc != null)
                {
                    doc.SubDocs.Add(fdoc);
                }
            }

            foreach (var property in properties)
            {
                string docu = "";
                string ex   = "";

                var docAttrib2 = property.GetCustomAttribute <LunarBindDocumentationAttribute>();
                if (docAttrib2 != null)
                {
                    docu = docAttrib2.Data;
                }
                var exampleAttrib2 = property.GetCustomAttribute <LunarBindExampleAttribute>();
                if (exampleAttrib2 != null)
                {
                    ex = exampleAttrib2.Data;
                }

                var pdoc = DocumentInstanceObject(property.PropertyType, property.Name, nextPrefix, curLevel + 1, type, docu, ex);
                if (pdoc != null)
                {
                    doc.SubDocs.Add(pdoc);
                }
            }

            foreach (var func in funcs)
            {
                var pdoc = DocumentFunction(func, nextPrefix);
                if (pdoc != null)
                {
                    doc.SubDocs.Add(pdoc);
                }
            }

            return(doc);
        }
        /// <summary>
        /// CAN RETURN NULL
        /// </summary>
        private static DocItem DocumentInstanceObject(Type type, string name, string prefix, int curLevel, Type declType = null, string documentation = "", string example = "")
        {
            string fullName   = prefix + name;
            var    nextPrefix = prefix + name + ".";

            if (type.IsPrimitive || type == typeof(string))
            {
                //Stop recursing
                return(new DocItem(DocItemType.InstanceObject, declType ?? type, name, fullName, fullName, fullName, documentation, example, name, name, name)
                {
                    DataType = type
                });
            }
            else if (!UserData.IsTypeRegistered(type))
            {
                return(null);
            }

            DocItem doc = new DocItem(DocItemType.InstanceObject, type, name, fullName, fullName, fullName, documentation, example, name, name, name)
            {
                DataType = type
            };

            if (curLevel > MaxRecursion)
            {
                doc.SubDocs.Add(new DocItem(DocItemType.None, typeof(void), "Max Recursion Reached", "Max Recursion Reached", "Max Recursion Reached", "", "", "")
                {
                    DataType = typeof(string)
                });
                return(doc);
            }


            var fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public).Where(a => !a.IsSpecialName && a.Name != "ToString" && a.Name != "GetHashCode" && a.Name != "GetType" && a.Name != "Equals" && a.Name != "GetTypeCode")
                         .Where(x => !x.CustomAttributes.Any(y => y.AttributeType == typeof(MoonSharpHiddenAttribute) || y.AttributeType == typeof(MoonSharpHideMemberAttribute) || y.AttributeType == typeof(LunarBindHideAttribute)));
            var properties = type.GetProperties(BindingFlags.Instance | BindingFlags.Public).Where(a => !a.IsSpecialName && a.Name != "ToString" && a.Name != "GetHashCode" && a.Name != "GetType" && a.Name != "Equals" && a.Name != "GetTypeCode")
                             .Where(x => !x.CustomAttributes.Any(y => y.AttributeType == typeof(MoonSharpHiddenAttribute) || y.AttributeType == typeof(MoonSharpHideMemberAttribute) || y.AttributeType == typeof(LunarBindHideAttribute)));
            var funcs = type.GetMethods(BindingFlags.Instance | BindingFlags.Public).Where(a => !a.IsSpecialName && a.Name != "ToString" && a.Name != "GetHashCode" && a.Name != "GetType" && a.Name != "Equals" && a.Name != "GetTypeCode")
                        .Where(x => !x.CustomAttributes.Any(y => y.AttributeType == typeof(MoonSharpHiddenAttribute) || y.AttributeType == typeof(MoonSharpHideMemberAttribute) || y.AttributeType == typeof(LunarBindHideAttribute)));

            //TODO: events
            //var events = type.GetEvents(BindingFlags.Instance | BindingFlags.Public)
            //    .Where(x => !x.CustomAttributes.Any(y => y.AttributeType == typeof(MoonSharpHiddenAttribute) || y.AttributeType == typeof(MoonSharpHideMemberAttribute) || y.AttributeType == typeof(LunarBindHideAttribute)));

            foreach (var field in fields)
            {
                if (field.FieldType.IsEnum)
                {
                    BindEnum bindEnum = new BindEnum(field.Name, field.FieldType);
                    doc.SubDocs.Add(DocumentEnum(bindEnum, prefix));
                }
                else
                {
                    string docu = "";
                    string ex   = "";

                    var docAttrib = field.GetCustomAttribute <LunarBindDocumentationAttribute>();
                    if (docAttrib != null)
                    {
                        docu = docAttrib.Data;
                    }
                    var exampleAttrib = field.GetCustomAttribute <LunarBindExampleAttribute>();
                    if (exampleAttrib != null)
                    {
                        ex = exampleAttrib.Data;
                    }


                    var fdoc = DocumentInstanceObject(field.FieldType, field.Name, nextPrefix, curLevel + 1, type, docu, ex);
                    if (fdoc != null)
                    {
                        doc.SubDocs.Add(fdoc);
                    }
                }
            }

            foreach (var property in properties)
            {
                string docu = "";
                string ex   = "";

                var docAttrib = property.GetCustomAttribute <LunarBindDocumentationAttribute>();
                if (docAttrib != null)
                {
                    docu = docAttrib.Data;
                }
                var exampleAttrib = property.GetCustomAttribute <LunarBindExampleAttribute>();
                if (exampleAttrib != null)
                {
                    ex = exampleAttrib.Data;
                }

                var pdoc = DocumentInstanceObject(property.PropertyType, property.Name, nextPrefix, curLevel + 1, type, docu, ex);
                if (pdoc != null)
                {
                    doc.SubDocs.Add(pdoc);
                }
            }

            foreach (var func in funcs)
            {
                var pdoc = DocumentFunction(func, nextPrefix);
                if (pdoc != null)
                {
                    doc.SubDocs.Add(pdoc);
                }
            }

            return(doc);
        }
        private static DocItem DocumentTable(BindTable table, string prefix, int curLevel)
        {
            DocItem doc = new DocItem(DocItemType.Table, typeof(Table), table.Name, prefix + table.Name, prefix + table.Name, prefix + table.Name);

            if (curLevel > MaxRecursion)
            {
                doc.SubDocs.Add(new DocItem(DocItemType.None, typeof(void), "Max Recursion Reached", "Max Recursion Reached", "Max Recursion Reached", "", "", ""));
                return(doc);
            }
            var nextPrefix = prefix + table.Name + ".";

            //var items = table.GetAllItems();

            //Functions
            foreach (var item in table.bindFunctions.Values)
            {
                var docItem = DocumentFunction(item, nextPrefix);
                if (docItem != null)
                {
                    doc.SubDocs.Add(docItem);
                }
            }

            //Types
            foreach (var item in table.bindTypes.Values)
            {
                var docItem = DocumentType(item, nextPrefix, curLevel + 1);
                if (docItem != null)
                {
                    doc.SubDocs.Add(docItem);
                }
            }

            //Enums
            foreach (var item in table.bindEnums.Values)
            {
                var docItem = DocumentEnum(item, nextPrefix);
                if (docItem != null)
                {
                    doc.SubDocs.Add(docItem);
                }
            }

            //User Objects
            foreach (var item in table.bindObjects.Values)
            {
                var docItem = DocumentObject(item, nextPrefix, curLevel + 1);
                if (docItem != null)
                {
                    doc.SubDocs.Add(docItem);
                }
            }

            //Tables last
            foreach (var item in table.bindTables.Values)
            {
                //Add to prefix
                var documentTable = DocumentTable(item, nextPrefix, curLevel + 1);
                if (documentTable != null)
                {
                    doc.SubDocs.Add(documentTable);
                }
            }

            return(doc);
        }