Docs Update

This commit is contained in:
Josef 2026-01-20 15:34:33 +01:00
parent 122d885ebd
commit 5d62a26e2f
21 changed files with 1571 additions and 103 deletions

View File

@ -107,6 +107,17 @@ namespace Rokojori
}
}
public T LoadJSON<T>() where T:new()
{
return (T) FilesSync.LoadJSON<T>( absolutePath );
}
public string LoadUTF8()
{
return FilesSync.LoadUTF8( absolutePath );
}
public static FilePath Create( string path, FilePathType type = FilePathType.Relative, FilePath parent = null )
{
@ -154,7 +165,7 @@ namespace Rokojori
}
}
public string absoluteParentPath
public string parentAbsolutePath
{
get
{
@ -164,7 +175,7 @@ namespace Rokojori
public FilePath ChangeFileName( string fileName )
{
var parentPath = absoluteParentPath;
var parentPath = parentAbsolutePath;
if ( ! parentPath.EndsWith( "/" ) )
{
@ -225,7 +236,7 @@ namespace Rokojori
if ( ! ownIsDir )
{
itPath = absoluteParentPath;
itPath = parentAbsolutePath;
}
itPath = itPath.ReplaceStart( commonPath );
@ -273,7 +284,12 @@ namespace Rokojori
return MakeRelative( relativePath );
}
public FilePath CreateRelativeFromAbsolutePathWithParent( string absolutePath, FilePath absoluteParent )
public FilePath MakeRelative( FilePath path )
{
return CreateRelativeFromAbsolutePathWithParent( path.absolutePath, this );
}
public static FilePath CreateRelativeFromAbsolutePathWithParent( string absolutePath, FilePath absoluteParent )
{
var rp = new FilePath();

View File

@ -97,6 +97,11 @@ namespace Rokojori
return list;
}
public static List<FilePath> GetFilesRecursive( string path, System.Func<FilePath,bool> evaluator = null )
{
return GetFiles( path, evaluator, true );
}
public static List<FilePath> GetFiles( string path, System.Func<FilePath,bool> evaluator = null, bool recursive = false )
{
var list = new List<FilePath>();

View File

@ -8,10 +8,10 @@ namespace Rokojori
{
public class LexerEvent
{
string _type;
int _offset;
int _length;
string _match;
protected string _type;
protected int _offset;
protected int _length;
protected string _match;
public string match => _match;
@ -20,6 +20,13 @@ namespace Rokojori
Set( type, offset, length );
}
public static LexerEvent WithMatch( string type, int offset, string match )
{
var le = new LexerEvent( type, offset, offset + match.Length );
le._match = match;
return le;
}
public string type { get { return _type; } }
public int offset { get { return _offset; } }
public int length { get { return _length; } }
@ -80,6 +87,7 @@ namespace Rokojori
{
get { return this._offset + _length; }
}
public override string ToString()
{
if ( match != null )
@ -185,7 +193,7 @@ namespace Rokojori
public bool found => FindResultType.Found == type;
public int index;
public int index = -1;
public FindResult()
@ -328,6 +336,55 @@ namespace Rokojori
return result;
}
public static List<RangeI> Seperate( List<LexerEvent> tokens, int start, int end, string match = "," )
{
if ( start < 0 || start >= tokens.Count || end < 0 || end >= tokens.Count )
{
RJLog.Log( "Ivalid range:", start, end, "count:", tokens.Count );
return null;
}
var separators = new List<int>();
for ( int i = start; i <= end; i++ )
{
if ( tokens[ i ].MatchIs( match ) )
{
separators.Add( i );
}
}
if ( separators.Count == 0 )
{
return new List<RangeI>();
}
var ranges = new List<RangeI>();
// a, b, c //
if ( separators[ 0 ] != start )
{
ranges.Add( new RangeI( start, separators[ 0 ] - 1 ) );
}
for ( int i = 1; i < separators.Count; i++ )
{
var before = separators[ i - 1 ];
ranges.Add( new RangeI( before + 1, separators[ i ] - 1 ) );
}
if ( separators[ separators.Count - 1 ] != end )
{
ranges.Add( new RangeI( separators[ separators.Count - 1 ] + 1, end ) );
}
// RJLog.Log( "Seperated:", ranges.Map( r => r.min + " / " + r.max ).Join( "" ) );
return ranges;
}
public static List<int> GetSeparatorsInBrackets( List<LexerEvent> tokens, int offset, string seperator = "," )
{
var openTypes = new List<string>(){ "(","[","{" };
@ -370,8 +427,8 @@ namespace Rokojori
static List<string> openTypes = new List<string>(){ "(","[","{" };
static List<string> closingTypes = new List<string>(){ ")","]","}" };
static List<string> openTypes = new List<string>(){ "(","[","{","<" };
static List<string> closingTypes = new List<string>(){ ")","]","}",">" };
public static FindResult FindClosingBracket( List<LexerEvent> tokens, int offset )
{
@ -390,12 +447,12 @@ namespace Rokojori
var counter = ( LexerEvent le ) =>
{
if ( le.Is( LexerMatcherLibrary.BracketMatcher, closer ) )
if ( le.Is( LexerMatcherLibrary.BracketMatcher, closer ) || le.Is( LexerMatcherLibrary.OperatorMatcher, closer ) )
{
return -1;
}
if ( le.Is( LexerMatcherLibrary.BracketMatcher, opener ) )
if ( le.Is( LexerMatcherLibrary.BracketMatcher, opener ) || le.Is( LexerMatcherLibrary.OperatorMatcher, opener ) )
{
return 1;
}
@ -452,7 +509,8 @@ namespace Rokojori
var result = Find( tokens, offset,
( le ) =>
{
return le.Is( LexerMatcherLibrary.BracketMatcher, blockBracket ) ? FindResultType.Found : FindResultType.KeepSearching;
return le.Is( LexerMatcherLibrary.BracketMatcher, blockBracket ) || le.Is( LexerMatcherLibrary.OperatorMatcher, blockBracket )
? FindResultType.Found : FindResultType.KeepSearching;
}
);
@ -477,12 +535,12 @@ namespace Rokojori
var counter = ( LexerEvent le ) =>
{
if ( le.Is( LexerMatcherLibrary.BracketMatcher, closer ) )
if ( le.Is( LexerMatcherLibrary.BracketMatcher, closer ) || le.Is( LexerMatcherLibrary.OperatorMatcher, closer ) )
{
return 1;
}
if ( le.Is( LexerMatcherLibrary.BracketMatcher, opener ) )
if ( le.Is( LexerMatcherLibrary.BracketMatcher, opener ) || le.Is( LexerMatcherLibrary.OperatorMatcher, opener ) )
{
return -1;
}
@ -493,7 +551,19 @@ namespace Rokojori
return FindCloser( tokens, offset, counter, false );
}
public static RangeI GetNextBlock( List<LexerEvent> tokens, int offset = 0)
{
var opener = FindOpeningBracket( tokens, offset );
if ( opener.type != FindResultType.Found )
{
return null;
}
var closer = FindClosingBracket( tokens, opener.index );
return new RangeI( opener.index, closer.index );
}
public static List<RangeI> GetBlocks( List<LexerEvent> tokens )
{

View File

@ -4,6 +4,14 @@ using System.Text.RegularExpressions;
namespace Rokojori
{
public class CSharpObjectDefinition
{
public LexerEvent type;
public LexerEvent name;
}
public class CSharpLexer:Lexer
{
public static List<LexerEvent> Lex( string source )
@ -20,10 +28,21 @@ namespace Rokojori
return events;
}
public static List<List<LexerEvent>> GetAllObjectDefinitions( string source )
public static List<CSharpObjectDefinition> GetAllObjectDefinitions( string source )
{
var tokens = Lex( source ).Filter( e => ! ( e.isDone || e.isError ) );
return GetAllObjectDefinitions( tokens );
}
public static List<CSharpObjectDefinition> GetAllObjectDefinitions( List<LexerEvent> tokens )
{
var START = Trillean.True;
var END = Trillean.False;
var INSIDE = Trillean.Any;
var sequences = LexerEvent.FindSequences( tokens,
( int index, bool inSequence ) =>
{
@ -38,19 +57,19 @@ namespace Rokojori
le.Is( LexerMatcherLibrary.EnumMatcher )
)
{
return Trillean.True;
return START;
}
if ( inSequence && le.Is( LexerMatcherLibrary.CwordMatcher ) )
{
return Trillean.False;
return END;
}
return Trillean.Any;
return INSIDE;
}
);
return sequences;
return sequences.Map( s => new CSharpObjectDefinition{ type = s[ 0 ], name = s[ s.Count - 1 ] } );
}
public CSharpLexer()

View File

@ -7,17 +7,40 @@ namespace Rokojori
public class LexerList
{
protected List<LexerEvent> _events;
protected LexerMatcher[] _ignore = null;
public LexerMatcher[] ignore
{
get { return _ignore; }
set { _ignore = value; }
}
public List<LexerEvent> events => _events;
public LexerList Filter( System.Predicate<LexerEvent> le )
{
return Create( events.Filter( e => le( e ) ) );
var list = Create( events.Filter( e => le( e ) ), ignore );
return list;
}
public LexerEvent this[ int index ]
{
get
{
return _events[ index ];
}
set
{
_events[ index ] = value;
}
}
public LexerList GetAll( LexerMatcher lexerMatcher )
{
return Create( events.Filter( e => e.Is( lexerMatcher ) ) );
return Create( events.Filter( e => e.Is( lexerMatcher ) ), ignore );
}
public List<RangeI> Seperate( int start, int end, LexerMatcher[] ignore = null )
@ -25,8 +48,10 @@ namespace Rokojori
return Seperate( ",", start, end, ignore );
}
public List<RangeI> Seperate( string seperator, int start, int end, LexerMatcher[] ignore = null )
public List<RangeI> Seperate( string seperator, int start, int end, LexerMatcher[] ignoring = null )
{
ignoring = GetIgnore( ignoring );
var list = new List<RangeI>();
var currentStart = -1;
@ -42,7 +67,7 @@ namespace Rokojori
currentStart = -1;
}
else if ( ignore != null && _events[ i ].IsAnyOf( ignore ) )
else if ( ignoring != null && _events[ i ].IsAnyOf( ignoring ) )
{
continue;
}
@ -81,11 +106,39 @@ namespace Rokojori
return LexerEvent.FindOpeningBracket( _events, offset, blockBracket );
}
public LexerEvent.FindResult FindClosingBracket( int offset )
{
return LexerEvent.FindClosingBracket( _events, offset );
}
public LexerEvent.FindResult ReverseFindOpeningBracket( int offset )
{
return LexerEvent.ReverseFindOpeningBracket( _events, offset );
}
public List<RangeI> GetParameters( int offset )
{
var opener = FindOpeningBracket( offset, "(" ).index;
if ( opener == -1 )
{
RJLog.Log( "No open bracket:", events[ offset ].match );
return null;
}
var closer = FindClosingBracket( opener ).index;
if ( closer == -1 )
{
RJLog.Log( "No closing bracket:", events[ offset ].match );
return null;
}
// RJLog.Log( "GetParameters", opener, closer );
return LexerEvent.Seperate( _events, opener + 1, closer - 1 );
}
public LexerEvent.FindResult ReverseFind( int offset, System.Func<LexerEvent,LexerEvent.FindResultType> evaluator )
{
return LexerEvent.Find( _events, offset, evaluator, false );
@ -96,6 +149,98 @@ namespace Rokojori
return LexerEvent.Find( _events, offset, evaluator, true );
}
public bool Is( int offset, string type, string match, LexerMatcher[] ignoring )
{
var next = Get( offset, ignoring );
return next.Is( type, match );
}
public bool MatchIs( int offset, string match, LexerMatcher[] ignoring = null )
{
var next = Get( offset, ignoring );
return next.MatchIs( match );
}
LexerMatcher[] GetIgnore( LexerMatcher[] ignoring )
{
ignoring = ignoring != null ? ignoring : _ignore;
ignoring = ignoring != null ? ignoring : [];
return ignoring;
}
public LexerEvent Get( int offset, LexerMatcher[] ignoring = null )
{
return events[ GetIndex( offset, ignoring ) ];
}
public LexerEvent GetReverse( int offset, LexerMatcher[] ignoring = null )
{
return events[ GetIndexReverse( offset, ignoring ) ];
}
public int GetIndex( int offset, LexerMatcher[] ignoring = null )
{
ignoring = GetIgnore( ignoring );
for ( int i = offset; i < _events.Count; i++ )
{
if ( _events[ i ].IsAnyOf( ignoring ) )
{
continue;
}
return i;
}
return -1;
}
public int GetIndexReverse( int offset, LexerMatcher[] ignoring = null )
{
ignoring = GetIgnore( ignoring );
for ( int i = offset; i >= 0; i-- )
{
if ( _events[ i ].IsAnyOf( ignoring ) )
{
continue;
}
return i;
}
return -1;
}
public int FindIndexOfType( int offset, string type )
{
for ( int i = offset; i < _events.Count; i++ )
{
if ( _events[ i ].type == type )
{
return i;
}
}
return -1;
}
public int FindIndexOfMatch( int offset, string match )
{
for ( int i = offset; i < _events.Count; i++ )
{
if ( _events[ i ].match == match )
{
return i;
}
}
return -1;
}
public LexerEvent.FindResult Find( int offset, List<LexerEventSelector> found,
List<LexerEventSelector> keepSearching = null, List<LexerEventSelector> errors = null )
{
@ -141,27 +286,119 @@ namespace Rokojori
return LexerEvent.GetBlocks( _events );
}
public void ReplaceBlocks( System.Func<RangeI,LexerEvent> blockReplacer )
{
ReplaceRanges( GetBlocks(), blockReplacer );
}
public void ReplaceRanges( List<RangeI> ranges, System.Func<RangeI,LexerEvent> blockReplacer )
{
for ( int i = 0; i < ranges.Count; i++ )
{
var r = ranges[ ranges.Count - 1 - i ];
var le = blockReplacer( r );
_events.ReplaceRange( r.min, r.max - r.min + 1, [ le ] );
}
}
public int MoveIndexForward( int start, string[] matches, LexerMatcher[] ignoring = null )
{
return MoveIndex( start, -1, matches, ignoring );
}
public int MoveIndexBackwards( int start, string[] matches, LexerMatcher[] ignoring = null )
{
return MoveIndex( start, -1, matches, ignoring );
}
public int MoveIndex( int start, int direction, string[] matches, LexerMatcher[] ignoring = null )
{
ignoring = GetIgnore( ignoring );
var tokenIndex = start;
var token = _events[ tokenIndex ];
var moving = true;
var moveIndex = start;
while ( moving && token != null && token.IsAnyOf( ignoring ) )
{
moveIndex = tokenIndex;
tokenIndex += direction;
token = tokenIndex < 0 || tokenIndex >= _events.Count ? null : events[ tokenIndex ];
if ( token != null && token.IsAnyOf( ignoring ) )
{
continue;
}
if ( token.MatchIsAny( matches ) )
{
moveIndex = tokenIndex;
tokenIndex += direction;
token = tokenIndex < 0 || tokenIndex >= _events.Count ? null : events[ tokenIndex ];
}
}
return moveIndex;
}
public int Index( LexerEvent lexerEvent, int offset = 0 )
{
return _events.IndexOf( lexerEvent, offset );
}
public RangeI NextBlock( int offset )
{
return LexerEvent.GetNextBlock( _events, offset );
}
public LexerList Range( RangeI range )
{
return Range( range.min, range.max );
}
public LexerList Range( int start, int end = -1 )
public string match
{
if ( end == -1 )
{
end = _events.Count;
}
return Create( _events.Sub( start, end - start + 1 ) );
get { return _events.Map( e => e.match ).Join( "" ); }
}
public static LexerList Create( List<LexerEvent> lexerEvents )
public LexerList RangeInside( RangeI range )
{
return Range( range.min + 1, range.max - 1);
}
public int size => _events.Count;
public LexerList Range( int start, int end = -1 )
{
if ( end == -1 )
{
end = _events.Count - 1;
}
if ( start < 0 || start >= _events.Count || end < 0 || end >= _events.Count )
{
RJLog.Log( "Range invalid", start, end, "count:", _events.Count );
return null;
}
var list = Create( _events.Sub( start, end - start + 1 ), ignore );
return list;
}
public static LexerList Create( List<LexerEvent> lexerEvents, LexerMatcher[] ignore = null )
{
var list = new LexerList();
list._events = lexerEvents;
list.ignore = ignore;
return list;
}
}
}

View File

@ -414,6 +414,34 @@ namespace Rokojori
return list;
}
public static Dictionary<U,T> ToMap<T,U>( this List<T> list, Func<T,U> mapper )
{
var d = new Dictionary<U,T>();
list.ForEach(
( item )=>
{
d[ mapper( item ) ] = item;
}
);
return d;
}
public static void ReplaceRange<T>( this List<T> list, int start, int count, List<T> replacement )
{
if ( count > 0 )
{
list.RemoveRange( start, count );
}
if ( replacement.Count > 0 )
{
list.InsertRange( start, replacement );
}
}
public static List<T> From<T>( params T[] elements )
{
return ToList( elements );
@ -715,6 +743,11 @@ namespace Rokojori
public static string Join<T>( this List<T> array, string seperator = ", " )
{
if ( array == null )
{
return "null";
}
var sb = new StringBuilder();
for ( var i = 0; i < array.Count; i++ )

View File

@ -0,0 +1,12 @@
{
"refactorings":
[
{
"context": "Renamed Camera Manager",
"from":"res://addons/rokojori_action_library/Runtime/VirtualCameras/VirtualCamera3DManager.cs",
"to":"res://addons/rokojori_action_library/Runtime/Cameras/CameraManager.cs",
"date": null,
"version":"4.5"
}
]
}

View File

@ -0,0 +1,30 @@
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 ClassBlock:LexerEvent
{
public static readonly string LexerType = "ClassBlock";
public int originalStartIndex = -1;
public int originalEndIndex = -1;
public ClassBlock( int s, int e, int originalStartIndex, int originalEndIndex ):base( LexerType, s, e )
{
this.originalEndIndex = originalEndIndex;
this.originalStartIndex = originalStartIndex;
}
public void SetMatch( string match )
{
_match = match;
}
}
}

View File

@ -0,0 +1 @@
uid://wrytq8ayur0j

View File

@ -0,0 +1,154 @@
using Godot;
using Rokojori;
using System.Collections.Generic;
using System;
using System.Reflection;
using System.Text.RegularExpressions;
using System.Linq;
using Rokojori.Tools;
namespace Rokojori.DocGenerator
{
public class ClassDocEditor
{
public static readonly bool NO_SIGNATURE_FALLBACK_MODE = true;
public string source;
public LexerList originalTokens;
ClassDocParser parser;
public void Process( CSharpObjectDefinition definition, OnlineDocJSON onlineDocJSON )
{
parser = new ClassDocParser();
parser.orginalTokens = originalTokens;
parser.orginalTokens.ignore = LexerMatcherLibrary.Ignore;
parser.linesMapper = new TextLinesMapper();
parser.linesMapper.Map( source );
parser.Parse( definition );
var members = parser.GetMembers();
members.ForEach(
( m )=>
{
var name = parser.innerTokens[ m.name ].match;
var type = parser.innerTokens.Range( m.type ).match;
var parameters = "";
var isMethod = m.IsMethod( parser.innerTokens );
if ( isMethod )
{
var types = m.GetMethodParameterTypes( parser.innerTokens );
parameters = "(" + types.Join( "," ) + ")";
}
else
{
var next = parser.innerTokens.Get( m.name, LexerMatcherLibrary.Ignore );
var anchorNext = parser.linesMapper.GetAnchor( next.offset, true );
var anchorName = parser.linesMapper.GetAnchor( parser.innerTokens[ m.name ].offset, true );
// RJLog.Log( anchorName.info, anchorNext.info );
}
var comment = "/** */";
if ( m.comment != -1 )
{
comment = parser.innerTokens[ m.comment ].match;
}
var onlineDocEntries = GetOnlineDoc( members, members.IndexOf( m ), onlineDocJSON );
// RJLog.Log( "Online docs:", onlineDocEntries == null ? "---" : onlineDocEntries.Count );
if ( onlineDocEntries != null )
{
var title = onlineDocEntries[ 0 ].content;
var description = onlineDocEntries[ 1 ].content;
comment =
@$"
/**
<summary>
<title>
{title}
</title>
<description>
{description}
</description>
</summary>
*/
".Indent( "" );
}
RJLog.Log( "[color=#888888]" + comment + "[/color]", "\n" + type, name + parameters );
}
);
}
List<OnlineDocJSONDocEntry> GetOnlineDoc( List<ClassDocMember> members, int index, OnlineDocJSON onlineDoc )
{
if ( NO_SIGNATURE_FALLBACK_MODE )
{
return GetOnlineDoc_FALLBACK( members, index, onlineDoc );
}
return null;
}
List<OnlineDocJSONDocEntry> GetOnlineDoc_FALLBACK( List<ClassDocMember> members, int index, OnlineDocJSON onlineDoc )
{
var member = members[ index ];
var membersWithSameName = members.Filter( m => m.name == member.name );
var name = parser.innerTokens[ member.name ].match;
var docNames = onlineDoc.content.Map( e => OnlineDocsTarget.From( e.target ).memberName ).Join( "," );
var docEntries = onlineDoc.content.Filter( e => OnlineDocsTarget.From( e.target ).memberName == name );
if ( docEntries == null || docEntries.Count == 0 )
{
// RJLog.Log( "No doc entries for:", "'" + name + "'", ">>", docNames );
return null;
}
if ( membersWithSameName.Count == 1 )
{
return docEntries;
}
var memberIndex = membersWithSameName.IndexOf( member );
var docEntryIndex = memberIndex * 2;
if ( ( docEntryIndex + 1 ) >= docEntries.Count )
{
return null;
}
return docEntries.Sub( docEntryIndex, 2 );
}
}
}

View File

@ -0,0 +1 @@
uid://crrgiu20gemhx

View File

@ -0,0 +1,62 @@
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 ClassDocMember
{
public int start;
public RangeI attributes;
public RangeI modifiers;
public RangeI type;
public int name;
public int end;
public int comment;
public bool IsMethod( LexerList lexerList )
{
var next = lexerList.Get( name + 1, LexerMatcherLibrary.Ignore );
// RJLog.Log( lexerList[ name ].match, ">>", next.match );
return lexerList.MatchIs( name + 1, "(", LexerMatcherLibrary.Ignore );
}
public List<string> GetMethodParameterTypes( LexerList lexerList )
{
var parameters = lexerList.GetParameters( name );
if ( parameters == null || parameters.Count == 0 )
{
return [];
}
var list = parameters.Map(
( r )=>
{
var tokens = lexerList.Range( r );
tokens = tokens.Filter( t => ! t.IsAnyOf( LexerMatcherLibrary.Ignore ) );
var assignmentIndex = tokens.FindIndexOfMatch( 0, "=" );
if ( assignmentIndex != -1 )
{
tokens.events.RemoveRange( assignmentIndex, tokens.events.Count - assignmentIndex );
}
tokens.events.RemoveAt( tokens.events.Count - 1 );
return tokens.match;
}
);
return list;
}
}
}

View File

@ -0,0 +1 @@
uid://dehc4ssbjfrkq

View File

@ -0,0 +1,652 @@
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 ClassDocParser
{
public static readonly string[] ModifierTypes =
[
// Access modifiers
"public",
"protected",
"internal",
"protected internal",
"private",
"private protected",
// Type behavior modifiers
"abstract",
"sealed",
"static",
"partial",
// Type-specific modifiers
"readonly",
"ref",
"unsafe",
"new",
"override",
"virtual",
// Modern / contextual
"record",
"record struct"
];
public LexerList orginalTokens;
public LexerList innerTokens;
public TextLinesMapper linesMapper;
public List<ClassDocMember> GetMembers()
{
return members;
}
public CSharpObjectDefinition definition;
public int definitionStart = -1;
public void Parse( CSharpObjectDefinition definition )
{
this.definition = definition;
// RJLog.Log( "\n\n PARSING START \n\n" );
ParseObjectDefinition();
ParseInnerObject();
ParseMembers();
ParseComments();
// RJLog.Log( "\n\n PARSING DONE \n\n" );
}
protected void ParseObjectDefinition()
{
var typeIndex = orginalTokens.Index( definition.type ) ;
var tokenIndex = orginalTokens.MoveIndexBackwards( typeIndex, ModifierTypes );
var prevIndex = orginalTokens.GetIndexReverse( tokenIndex );
if ( prevIndex == -1 )
{
definitionStart = tokenIndex;
return;
}
var prev = prevIndex == -1 ? null : orginalTokens[ prevIndex ];
while ( prev != null && prev.MatchIs( "]" ) )
{
var opening = LexerEvent.ReverseFindOpeningBracket( orginalTokens.events, prevIndex );
tokenIndex = opening.index;
prevIndex = orginalTokens.GetIndexReverse( tokenIndex );
prev = prevIndex == -1 ? null : orginalTokens[ prevIndex ];
}
definitionStart = tokenIndex;
}
protected void ParseInnerObject()
{
var index = orginalTokens.Index( definition.name );
var block = orginalTokens.NextBlock( index );
innerTokens = orginalTokens.RangeInside( block );
innerTokens.ReplaceBlocks(
( r )=>
{
var opener = orginalTokens[ r.min ];
var closer = orginalTokens[ r.min ];
var block = new ClassBlock( opener.offset, closer.end, r.min, r.max );
block.SetMatch( "{ /* - inner block - */ }" );
return block;
}
);
var innerObjects = CSharpLexer.GetAllObjectDefinitions( innerTokens.events );
var objectRanges = innerObjects.Map(
( io )=>
{
var startIndex = innerTokens.Index( io.type );
var endIndex = innerTokens.Index( io.name, startIndex );
var end = innerTokens.FindIndexOfType( endIndex, ClassBlock.LexerType );
var modifierStart = startIndex;
var searching = true;
while ( searching )
{
var result = LexerEvent.ReverseFind( innerTokens.events, modifierStart - 1,
( le ) =>
{
if ( le.MatchIsAny( ModifierTypes ) )
{
return LexerEvent.FindResultType.Found;
}
if ( le.IsAnyOf( LexerMatcherLibrary.Ignore ) )
{
return LexerEvent.FindResultType.KeepSearching;
}
return LexerEvent.FindResultType.NotFound;
}
);
if ( result.type == LexerEvent.FindResultType.Found )
{
modifierStart = result.index;
}
else
{
searching = false;
}
}
return new RangeI( modifierStart, end );
}
);
innerTokens.ReplaceRanges( objectRanges,
( r ) =>
{
var start = innerTokens.events[ r.min ];
var end = innerTokens.events[ r.max ];
return LexerEvent.WithMatch( LexerMatcherLibrary.MultiLineCommentMatcher.type, start.offset, "/* - inner object - */" );
}
);
}
enum ParsePhase
{
Attributes,
Modifiers,
Type,
Name,
MemberEnd
}
List<ClassDocMember> members = new List<ClassDocMember>();
void ParseMembers()
{
var phase = ParsePhase.Attributes;
var tokenIndex = 0;
var memberStart = -1;
RangeI attributes = null;
RangeI modifiers = null;
RangeI type = null;
var name = -1;
var checkIndex = -1;
while ( tokenIndex < innerTokens.size && checkIndex <= tokenIndex )
{
checkIndex = Mathf.Max( checkIndex, tokenIndex );
var token = innerTokens[ tokenIndex ];
// RJLog.Log( phase, "index", tokenIndex, "token", token.type, token.match, "line", linesMapper.GetAnchor( token.offset, true ).info );
if ( token.IsAnyOf( LexerMatcherLibrary.Ignore ) )
{
tokenIndex ++;
continue;
}
if ( memberStart == -1 )
{
memberStart = tokenIndex;
}
if ( ParsePhase.Attributes == phase )
{
attributes = null;
var attributesEndIndex = GetAttributesEndIndex( tokenIndex );
phase = ParsePhase.Modifiers;
if ( attributesEndIndex != -1 )
{
attributes = new RangeI( tokenIndex, attributesEndIndex );
tokenIndex = attributesEndIndex + 1;
}
continue;
}
if ( ParsePhase.Modifiers == phase )
{
modifiers = null;
var modifiersEndIndex = GetModifiersEndIndex( tokenIndex );
phase = ParsePhase.Type;
if ( modifiersEndIndex != -1 )
{
tokenIndex = modifiersEndIndex + 1;
}
continue;
}
if ( ParsePhase.Type == phase )
{
if ( token.Is( LexerMatcherLibrary.CFunctionMatcher ) )
{
type = new RangeI( tokenIndex, tokenIndex );
name = tokenIndex;
phase = ParsePhase.MemberEnd;
tokenIndex++;
}
else
{
var typeEndIndex = GetTypeEndIndex( tokenIndex );
type = new RangeI( tokenIndex, typeEndIndex );
tokenIndex = typeEndIndex + 1;
phase = ParsePhase.Name;
}
continue;
}
if ( ParsePhase.Name == phase )
{
if ( token.MatchIs( "(") )
{
name = type.max;
}
else
{
name = tokenIndex;
tokenIndex++;
}
phase = ParsePhase.MemberEnd;
continue;
}
if ( ParsePhase.MemberEnd == phase )
{
var memberEndIndex = GetMemberEndIndex( tokenIndex );
if ( memberEndIndex == -1 )
{
if ( tokenIndex != -1 && memberStart != -1 )
{
var memberEnd = tokenIndex < memberStart ? innerTokens.size - 1 : tokenIndex;
RJLog.Error( tokenIndex, memberStart );
RJLog.Error(
"Could not parse", innerTokens.Range( new RangeI( memberStart, memberEnd ) ).match
// "Type:", "'" + innerTokens.Range( type ).match + "'"
);
}
return;
}
phase = ParsePhase.Attributes;
var cdMember = new ClassDocMember();
cdMember.start = memberStart;
cdMember.attributes = attributes;
cdMember.modifiers = modifiers;
cdMember.type = type;
cdMember.name = name;
cdMember.end = memberEndIndex;
members.Add( cdMember );
// RJLog.Log(
// "-------------\n",
// innerTokens.Range( cdMember.type ).match, innerTokens[ cdMember.name ].match, "\n" +
// "-------------"
// );
tokenIndex = memberEndIndex + 1;
memberStart = -1;
continue;
}
}
if ( checkIndex > tokenIndex )
{
RJLog.Log( "CheckIndex > TokenIndex", checkIndex, tokenIndex );
}
}
int GetAttributesEndIndex( int tokenIndex )
{
if ( tokenIndex >= innerTokens.size )
{
return -1;
}
var token = innerTokens[ tokenIndex ];
var end = -1;
while ( token != null && token.MatchIs( "[" ) )
{
var endResult = innerTokens.FindClosingBracket( tokenIndex );
if ( LexerEvent.FindResultType.Found != endResult.type )
{
return end;
}
end = endResult.index;
tokenIndex = endResult.index + 1;
token = tokenIndex < innerTokens.size ? innerTokens[ tokenIndex ] : null;
while ( token != null && token.IsAnyOf( LexerMatcherLibrary.Ignore ) )
{
tokenIndex ++;
token = tokenIndex < innerTokens.size ? innerTokens[ tokenIndex ] : null;
}
}
return end;
}
int GetModifiersEndIndex( int tokenIndex )
{
if ( tokenIndex >= innerTokens.size )
{
return -1;
}
var token = innerTokens[ tokenIndex ];
var end = -1;
while ( token != null && token.MatchIsAny( ModifierTypes ) )
{
end = tokenIndex;
tokenIndex ++;
token = tokenIndex < innerTokens.size ? innerTokens[ tokenIndex ] : null;
while ( token != null && token.IsAnyOf( LexerMatcherLibrary.Ignore ) )
{
tokenIndex ++;
token = tokenIndex < innerTokens.size ? innerTokens[ tokenIndex ] : null;
}
}
return end;
}
int GetTypeEndIndex( int tokenIndex )
{
if ( tokenIndex >= innerTokens.size )
{
return -1;
}
tokenIndex = GetNameEndIndex( tokenIndex );
tokenIndex = GetGenericsEndIndex( tokenIndex );
tokenIndex = GetPointerArraysEndIndex( tokenIndex );
tokenIndex = GetNullableEndIndex( tokenIndex );
return tokenIndex;
}
int GetNameEndIndex( int tokenIndex )
{
if ( tokenIndex >= innerTokens.size )
{
return -1;
}
var token = innerTokens[ tokenIndex ];
var end = -1;
while ( token != null && token.Is( LexerMatcherLibrary.CwordMatcher ) )
{
end = tokenIndex;
tokenIndex ++;
token = tokenIndex < innerTokens.size ? innerTokens[ tokenIndex ] : null;
while ( token != null && token.IsAnyOf( LexerMatcherLibrary.Ignore ) )
{
tokenIndex ++;
token = tokenIndex < innerTokens.size ? innerTokens[ tokenIndex ] : null;
}
if ( ! token.Is( LexerMatcherLibrary.OperatorMatcher, "." ) )
{
return end;
}
tokenIndex ++;
token = tokenIndex < innerTokens.size ? innerTokens[ tokenIndex ] : null;
while ( token != null && token.IsAnyOf( LexerMatcherLibrary.Ignore ) )
{
tokenIndex ++;
token = tokenIndex < innerTokens.size ? innerTokens[ tokenIndex ] : null;
}
}
return end;
}
int GetGenericsEndIndex( int tokenIndex )
{
if ( tokenIndex >= innerTokens.size )
{
return -1;
}
var orignalIndex = tokenIndex;
tokenIndex ++;
var token = innerTokens[ tokenIndex ];
while ( token != null && token.IsAnyOf( LexerMatcherLibrary.Ignore ) )
{
tokenIndex ++;
token = tokenIndex < innerTokens.size ? innerTokens[ tokenIndex ] : null;
}
if ( token.MatchIs( "<" ) )
{
var end = innerTokens.FindClosingBracket( tokenIndex ).index;
// RJLog.Log( "Has Generics", innerTokens.Range( new RangeI( orignalIndex, end ) ).match );
return end;
}
else
{
// RJLog.Log( "Has No Generics", token.match );
}
return orignalIndex;
}
int GetPointerArraysEndIndex( int tokenIndex )
{
if ( tokenIndex < 0 || tokenIndex >= innerTokens.size )
{
return -1;
}
var token = innerTokens[ tokenIndex ];
var lastTokenIndex = tokenIndex;
tokenIndex ++;
while ( token != null && token.IsAnyOf( LexerMatcherLibrary.Ignore ) || token.MatchIs( "*" ) || token.MatchIs( "[" ) )
{
if ( token.MatchIs( "[" ) )
{
tokenIndex = innerTokens.FindClosingBracket( tokenIndex ).index;
}
lastTokenIndex = tokenIndex;
tokenIndex ++;
token = tokenIndex < innerTokens.size ? innerTokens[ tokenIndex ] : null;
}
return lastTokenIndex;
}
int GetNullableEndIndex( int tokenIndex )
{
if ( tokenIndex < 0 || tokenIndex >= innerTokens.size )
{
return -1;
}
var orignalIndex = tokenIndex;
var token = innerTokens[ tokenIndex ];
while ( token != null && token.IsAnyOf( LexerMatcherLibrary.Ignore ) )
{
tokenIndex ++;
token = tokenIndex < innerTokens.size ? innerTokens[ tokenIndex ] : null;
}
if ( token != null && token.MatchIs( "?" ) )
{
return tokenIndex;
}
return orignalIndex;
}
int GetMemberEndIndex( int tokenIndex )
{
if ( tokenIndex < 0 || tokenIndex >= innerTokens.size )
{
return -1;
}
var token = innerTokens[ tokenIndex ];
while ( token != null && token.IsAnyOf( LexerMatcherLibrary.Ignore ) )
{
tokenIndex ++;
token = tokenIndex < innerTokens.size ? innerTokens[ tokenIndex ] : null;
}
if ( token.MatchIs( ";" ) )
{
// RJLog.Log( "Member has no assignment" );
return tokenIndex;
}
if ( token.MatchIs( "=" ) || token.MatchIs( "=>" ) )
{
// RJLog.Log( "Member has assignment" );
return innerTokens.FindIndexOfMatch( tokenIndex, ";" );
}
if ( token.MatchIs( "(" ) )
{
// RJLog.Log( "Member is function" );
tokenIndex = innerTokens.FindClosingBracket( tokenIndex ).index + 1;
token = tokenIndex < innerTokens.size ? innerTokens[ tokenIndex ] : null;
}
while ( token != null && token.IsAnyOf( LexerMatcherLibrary.Ignore ) )
{
tokenIndex ++;
token = tokenIndex < innerTokens.size ? innerTokens[ tokenIndex ] : null;
}
if ( token.Is( ClassBlock.LexerType ) )
{
// RJLog.Log( "Member is function with block" );
return tokenIndex;
}
if ( token.MatchIs( "=>" ) )
{
// RJLog.Log( "Member is function with assigner reference" );
return innerTokens.FindIndexOfMatch( tokenIndex, ";" );
}
RJLog.Log( "Member not found, token", token.match );
return -1;
}
void ParseComments()
{
var endIndex = 0;
for ( int i = 0; i < members.Count; i++ )
{
members[ i ].comment = GetComment( members[ i ].start, endIndex );
endIndex = members[ i ].end;
}
}
int GetComment( int start, int end )
{
var it = start - 1;
while ( it > end )
{
var token = innerTokens[ it ];
if ( token.Is( LexerMatcherLibrary.MultiLineCommentMatcher ) )
{
var comment = token.match;
var startRegex = @"^\/\*\*(\s|\n|\r)*<summary ";
var endRegex = @"<\/summary>(\s|\n|\r)*\*\/$";
if ( RegexUtility.Matches( comment, startRegex ) && RegexUtility.Matches( comment, endRegex ) )
{
return it;
}
return -1;
}
it --;
}
return -1;
}
}
}

View File

@ -0,0 +1 @@
uid://bry7q2thf5p5k

View File

@ -91,6 +91,7 @@ namespace Rokojori.DocGenerator
info.modificationTime = FilesSync.GetModificationTimeStamp( filePath );
info.name = typeName;
info.csNameSpace = typeNameSpace;
info.isCSOnly = true;
info.definitionType = definitionType;
info.sourcePath = filePath.SubstringAfterMatching( "addons/rokojori_action_library/");
@ -140,7 +141,41 @@ namespace Rokojori.DocGenerator
info.icon = GetIcon( data, info.name, info.extendingClasses, icons );
var constructors = Lists.ToList( classType.GetConstructors( allBindings ) );
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 );
memberInfo.attributes = GetExports( f );
if ( f.IsStatic )
{
memberInfo.modifiers.Add( "static" );
}
memberInfo.modifiers.Add( f.IsPublic ? "public" : "protected" );
info.memberInfos.Add( memberInfo );
}
);
var constructors = Lists.ToList( classType.GetConstructors( allBindings ) );
constructors = Lists.Filter( constructors, m => ! m.IsPrivate );
constructors.ForEach(
@ -178,38 +213,6 @@ namespace Rokojori.DocGenerator
);
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 );
memberInfo.attributes = GetExports( f );
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 );

View File

@ -26,16 +26,22 @@ namespace Rokojori.DocGenerator
public int lineIndex;
public int lineOffset;
public List<string> modifiers = new List<string>();
public List<string> generics;
public List<ParameterType> parameters = new List<ParameterType>();
public string value;
// memberType
public static readonly string Field = "Field";
public static readonly string Method = "Method";
public static readonly string Constructor = "Constructor";
public static readonly string Signal = "Signal";
public static readonly string Uniform = "Uniform";
public static readonly string Varying = "Varying";
public static MemberInfo Create( string memberType )
{
var m = new MemberInfo();
@ -72,8 +78,10 @@ namespace Rokojori.DocGenerator
public class ClassDocInfo
{
public string csNameSpace = "";
public bool isCSOnly = true;
public string name ="";
public string doc;
public string docMode;
public string icon;
public string sourcePath;
public string definitionType;

View File

@ -3,27 +3,10 @@ using Godot;
using System.Collections.Generic;
using System;
using Rokojori.Tools;
namespace Rokojori.DocGenerator
{
public class SomeArrayClass
{
public int index = 2;
public string value = "Hello World";
}
public class SomeClass
{
public float x = 0;
public float GetX()
{
return x * 2;
}
public List<SomeArrayClass> values = new List<SomeArrayClass>();
}
[GlobalClass][Tool]
public partial class CreateDoc : Node
{
@ -46,22 +29,9 @@ namespace Rokojori.DocGenerator
public int hoursCheckTime = 12;
[ExportToolButton( "Create")]
public Callable createButton => Callable.From( ()=>{ Generate(); } );
public Callable createButton => Callable.From( ()=>{ Create(); } );
void Test()
{
var obj = new SomeClass();
var sa = new SomeArrayClass();
var sb = new SomeArrayClass();
sb.value = "Huhu";
obj.values.Add( sa );
obj.values.Add( sb );
var testJSON = JSON.StringifyObject( obj );
RJLog.Log( testJSON );
}
void Generate()
void Create()
{
var absoluteLibraryPath = ProjectSettings.GlobalizePath( "res://addons/rokojori_action_library/Runtime" );
@ -82,5 +52,103 @@ namespace Rokojori.DocGenerator
var icons = Lists.Map( FilesSync.GetFiles( absoluteIconPath, ( fp => fp.fileExtension == ".svg" ) ), fp => fp.fullFileName );
generator.Generate( absoluteLibraryPath, absoluteOutputPath, icons );
}
[Export(PropertyHint.Dir)]
public string externalDocsPath;
[ExportToolButton( "Intergrate External")]
public Callable integrateExternalButton => Callable.From( ()=>{ IntegrateExtarnel(); } );
void IntegrateExtarnel()
{
var absoluteLibraryPath = ProjectSettings.GlobalizePath( "res://addons/rokojori_action_library/Runtime" );
var absoluteExternalPath = ProjectSettings.GlobalizePath( externalDocsPath );
var libraryFilePath = FilePath.Absolute( absoluteLibraryPath );
var externalPath = FilePath.Absolute( absoluteExternalPath );
var externalDocFiles = FilesSync.GetFilesRecursive( absoluteExternalPath,
( fp )=>
{
return fp.HasFileExtension( "json" );
}
);
var codeFiles = FilesSync.GetFilesRecursive( absoluteLibraryPath,
( fp )=>
{
return fp.HasFileExtension( "cs" );
}
);
var namesMap = codeFiles.ToMap( cf => cf.fullFileName );
var missing = new List<FilePath>();
var mapped = new Dictionary<FilePath,FilePath>();
var found = new List<FilePath>();
var csToDocs = new Dictionary<FilePath,FilePath>();
externalDocFiles.ForEach(
( docFile )=>
{
var relativeFilePath = externalPath.MakeRelative( docFile );
var relativePath = docFile.path.ReplaceEnd( ".json" );
var libPath = libraryFilePath.MakeRelative( relativePath );
if ( ! libPath.Exists() )
{
var name = libPath.fullFileName;
if ( namesMap.ContainsKey( name ) )
{
// this.LogInfo( "Remapping:", relativePath, "using:", namesMap[ name ].path );
mapped[ docFile ] = namesMap[ name ];
}
else
{
this.LogInfo( "Could not find:", relativePath );
missing.Add( docFile );
}
}
else
{
found.Add( libPath );
csToDocs[ libPath ] = docFile;
}
}
);
// if ( missing.Count == 0 )
// {
// this.LogInfo( "All good" );
// return;
// }
if ( found.Count == 0 )
{
return;
}
var editor = new ClassDocEditor();
var source = found[ 0 ].LoadUTF8();
editor.originalTokens = LexerList.Create( CSharpLexer.Lex( source ), LexerMatcherLibrary.Ignore );
var objects = CSharpLexer.GetAllObjectDefinitions( editor.originalTokens.events );
var classObject = objects.Find( obj => obj.type.Is( LexerMatcherLibrary.ClassMatcher ) );
editor.source = source;
var doc = csToDocs[ found[ 0 ] ].LoadJSON<OnlineDocJSON>();
editor.Process( classObject, doc );
// this.LogInfo( editing );
}
}
}

View File

@ -126,8 +126,8 @@ namespace Rokojori.DocGenerator
for ( int i = 0; i < definitions.Count; i++ )
{
var sequence = definitions[ i ];
var definitionType = sequence[ 0 ];
var definitionName = sequence[ 1 ];
var definitionType = sequence.type;
var definitionName = sequence.name;
// RJLog.Log( "Adding definition:", definitionName.match );
AddCSharpsClassType( cf, definitionName.match, definitionType.match, namespaceLabel, assembly );

View File

@ -0,0 +1,94 @@
#if TOOLS
using Godot;
using Rokojori;
using System.Diagnostics;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Linq;
namespace Rokojori.Tools
{
public enum OnlineDocsTargetType
{
Member,
Class
}
public class OnlineDocsTarget
{
public OnlineDocsTargetType type = OnlineDocsTargetType.Member;
public string memberName;
public string memberType = null ;
public List<string> parameters = null;
public string docTarget;
public bool isFunction = false;
public bool hasSignature => memberType != null;
public static readonly string Delimiter = ":::";
public static OnlineDocsTarget From( string target )
{
var odt = new OnlineDocsTarget();
if ( target.IndexOf( Delimiter ) == -1 )
{
// RJLog.Log( "No delimiter:", target );
odt.type = OnlineDocsTargetType.Class;
odt.docTarget = target;
return odt;
}
var splits = target.Split( Delimiter );
// RJLog.Log( "Splitting:", target, ">>", "'" + splits.Join( "','" ) + "'" );
odt.docTarget = splits[ 1 ];
var memberTarget = splits[ 0 ];
var typeIndex = memberTarget.IndexOf( ":" );
if ( typeIndex != -1 )
{
odt.memberType = memberTarget.Substring( typeIndex + 1 );
}
var bracketIndex = memberTarget.IndexOf( "(" );
if ( bracketIndex != -1 )
{
odt.isFunction = true;
var closingIndex = memberTarget.IndexOf( ")", bracketIndex + 1 );
odt.parameters = memberTarget.Substring( bracketIndex + 1, closingIndex ).Split( "," ).ToList();
}
var nameEndIndex = typeIndex != -1 ? typeIndex :
bracketIndex != -1 ? bracketIndex : memberTarget.Count();
odt.memberName = memberTarget.Substring( 0, nameEndIndex );
return odt;
}
}
public class OnlineDocJSONDocEntry
{
public string content;
public string target;
}
public class OnlineDocJSON
{
public string key = "";
public string sourcePath = "";
public List<OnlineDocJSONDocEntry> content = [];
public ISOTimeStamp changeDate;
public string version;
}
}
#endif

View File

@ -0,0 +1 @@
uid://c8t6fm027suvq