using Godot; using Rokojori; using System.Collections.Generic; using System; using System.Reflection; using System.Text.RegularExpressions; 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://Scripts/Rokojori/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 type, List icons ) { var data = filePath == null ? "" : FilesSync.LoadUTF8( filePath ); var comments = new DocComments(); comments.Grab( data ); RJLog.Log( type.Name, "Comments:", comments.entries.Count ); info.name = type.Name; info.csNameSpace = type.Namespace; info.doc = comments.FindDoc( "class", type.Name ); info.generics = Lists.Map( type.GenericTypeArguments, t => t + "" ); var allBindings = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly; var fields = Lists.ToList( type.GetFields( allBindings ) ); fields = Lists.Filter( fields, f => ! f.IsPrivate ); var godotTypes = new List() { "Node", "Resource" }; var it = type.BaseType; 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( it.Name ); it = it.BaseType; } } info.icon = GetIcon( data, info.name, info.extendingClasses, icons ); fields.ForEach( ( f )=> { var memberInfo = MemberInfo.CreateField(); memberInfo.name = f.Name; memberInfo.csNameSpace = f.FieldType.Namespace; memberInfo.dataType = f.FieldType.Name; 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( type.GetMethods( allBindings ) ); methods = Lists.Filter( methods, m => ! m.IsPrivate ); var godotInternalMethods = new List() { "GetGodotMethodList", "InvokeGodotClassMethod", "HasGodotClassMethod", "SetGodotClassPropertyValue", "GetGodotClassPropertyValue", "GetGodotPropertyList", "GetGodotPropertyDefaultValues", "SaveGodotObjectData", "RestoreGodotObjectData" }; methods.ForEach( m => { if ( godotInternalMethods.IndexOf( m.Name ) != -1 ) { return; } var memberInfo = MemberInfo.CreateMethod(); memberInfo.name = m.Name; memberInfo.dataType = m.ReturnType.Name; 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 = p.ParameterType.Name; parameterType.csNameSpace = p.ParameterType.Namespace; parameterType.generics = Lists.Map( p.ParameterType.GenericTypeArguments, t => t + "" ); memberInfo.parameters.Add( parameterType ); } ); info.memberInfos.Add( memberInfo ); } ); return info; } } }