using Godot; using Rokojori; using System.Collections.Generic; using System; using System.Reflection; using System.Text.RegularExpressions; using System.Linq; namespace Rokojori.DocGenerator { public class ClassDocGenerator { ClassDocInfo info = new ClassDocInfo(); public string GetIcon( string classFile, string name, List baseTypes, List icons ) { var iconMatcher = new Regex( "Icon\\(\"res://addons/rokojori_action_library/Icons/(\\w+\\.svg)" ); var result = iconMatcher.Matches( classFile ); if ( result != null && result.Count == 1 ) { return result[ 0 ].Groups[ 1 ].Value; } if ( icons.IndexOf( name + ".svg" ) != -1 ) { return name + ".svg"; } foreach ( var bt in baseTypes ) { if ( icons.IndexOf( bt + ".svg" ) != -1 ) { return bt + ".svg"; } } return "CSharp.svg"; } public ClassDocInfo Create( string filePath, Type classType, string definitionType, List icons ) { var data = filePath == null ? "" : FilesSync.LoadUTF8( filePath ); var comments = new DocComments(); comments.Grab( data ); var typeName = GetDocsType.Of( classType ); var baseTypeName = classType.BaseType; var typeNameSpace = classType.Namespace; RJLog.Log( typeName, "Comments:", comments.entries.Count ); info.name = typeName; info.csNameSpace = typeNameSpace; info.definitionType = definitionType; info.sourcePath = filePath.SubstringAfterMatching( "addons/rokojori_action_library/"); info.doc = comments.FindDoc( "class", typeName ); var genericArguments = classType.GetGenericArguments().ToList(); info.generics = genericArguments.Map( t => t.Name ); info.interfaces = classType.GetInterfaces().ToList().Map( i => GetDocsType.Of( i ) ); var allBindings = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly; var fields = Lists.ToList( classType.GetFields( allBindings ) ); fields = Lists.Filter( fields, f => ! f.IsPrivate ); var godotTypes = new List() { "Node", "Resource" }; var it = baseTypeName; while ( it != null ) { if ( godotTypes.IndexOf( it.Name) != -1 ) { if ( "Node" == it.Name ) { info.extendingClasses.AddRange( new string[]{ "Node", "Object" } ); } else if ( "Resource" == it.Name ) { info.extendingClasses.AddRange( new string[]{ "Resource", "RefCounted", "Object" } ); } it = null; } else { info.extendingClasses.Add( GetDocsType.Of( it ) ); it = it.BaseType; } } info.icon = GetIcon( data, info.name, info.extendingClasses, icons ); var constructors = Lists.ToList( classType.GetConstructors( allBindings ) ); constructors = Lists.Filter( constructors, m => ! m.IsPrivate ); constructors.ForEach( ( con ) => { var memberInfo = MemberInfo.CreateConstructor(); memberInfo.name = typeName; memberInfo.dataType = typeName; memberInfo.csNameSpace = typeNameSpace; // memberInfo.generics = info.generics; // memberInfo.doc = comments.FindDoc( "constructor", con.Name ); memberInfo.modifiers.Add( con.IsPublic ? "public" : "protected" ); var parameters = Lists.ToList( con.GetParameters() ); parameters.ForEach( ( p )=> { var parameterType = new ParameterType(); parameterType.name = p.Name; parameterType.type = GetDocsType.Of( p.ParameterType ); parameterType.csNameSpace = p.ParameterType.Namespace; parameterType.generics = Lists.Map( p.ParameterType.GetGenericArguments(), t => t + "" ); memberInfo.parameters.Add( parameterType ); } ); info.memberInfos.Add( memberInfo ); } ); fields.ForEach( ( f )=> { if ( f.Name == "value__" ) { return; } var memberInfo = MemberInfo.CreateField(); memberInfo.name = f.Name; memberInfo.csNameSpace = f.FieldType.Namespace; memberInfo.dataType = GetDocsType.Of( f.FieldType ); memberInfo.generics = Lists.Map( f.FieldType.GetGenericArguments(), t => t + "" ); memberInfo.doc = comments.FindDoc( "field", f.Name ); if ( f.IsStatic ) { memberInfo.modifiers.Add( "static" ); } memberInfo.modifiers.Add( f.IsPublic ? "public" : "protected" ); info.memberInfos.Add( memberInfo ); } ); var methods = Lists.ToList( classType.GetMethods( allBindings ) ); methods = Lists.Filter( methods, m => ! m.IsPrivate ); var godotInternalMethods = new List() { "GetGodotMethodList", "InvokeGodotClassMethod", "HasGodotClassMethod", "SetGodotClassPropertyValue", "GetGodotClassPropertyValue", "GetGodotPropertyList", "GetGodotPropertyDefaultValues", "SaveGodotObjectData", "RestoreGodotObjectData", "InvokeGodotClassStaticMethod" }; methods.ForEach( m => { if ( godotInternalMethods.IndexOf( m.Name ) != -1 ) { return; } var memberInfo = MemberInfo.CreateMethod(); memberInfo.isAccessor = GetDocsType.isAccessorMethod( m ); memberInfo.name = m.Name; memberInfo.dataType = GetDocsType.Of( m.ReturnType ); memberInfo.csNameSpace = m.ReturnType.Namespace; memberInfo.generics = Lists.Map( m.GetGenericArguments(), t => t + "" ); memberInfo.doc = comments.FindDoc( "method", m.Name ); if ( m.IsStatic ) { memberInfo.modifiers.Add( "static" ); } memberInfo.modifiers.Add( m.IsPublic ? "public" : "protected" ); var parameters = Lists.ToList( m.GetParameters() ); parameters.ForEach( ( p )=> { var parameterType = new ParameterType(); parameterType.name = p.Name; parameterType.type = GetDocsType.Of( p.ParameterType ); parameterType.csNameSpace = p.ParameterType.Namespace; parameterType.generics = Lists.Map( p.ParameterType.GetGenericArguments(), t => t + "" ); memberInfo.parameters.Add( parameterType ); } ); info.memberInfos.Add( memberInfo ); } ); return info; } } }