Merge branch 'main' of https://community.rokojori.com/Rokojori/rj-action-library
This commit is contained in:
commit
c955b0546f
|
|
@ -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();
|
||||
|
||||
|
|
|
|||
|
|
@ -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>();
|
||||
|
|
|
|||
|
|
@ -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 )
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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 string match
|
||||
{
|
||||
get { return _events.Map( e => e.match ).Join( "" ); }
|
||||
}
|
||||
|
||||
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;
|
||||
end = _events.Count - 1;
|
||||
}
|
||||
|
||||
return Create( _events.Sub( start, end - start + 1 ) );
|
||||
if ( start < 0 || start >= _events.Count || end < 0 || end >= _events.Count )
|
||||
{
|
||||
RJLog.Log( "Range invalid", start, end, "count:", _events.Count );
|
||||
return null;
|
||||
}
|
||||
|
||||
public static LexerList Create( List<LexerEvent> lexerEvents )
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -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++ )
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
uid://wrytq8ayur0j
|
||||
|
|
@ -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 );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
uid://crrgiu20gemhx
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
uid://dehc4ssbjfrkq
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
uid://bry7q2thf5p5k
|
||||
|
|
@ -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,6 +141,40 @@ namespace Rokojori.DocGenerator
|
|||
|
||||
info.icon = GetIcon( data, info.name, info.extendingClasses, icons );
|
||||
|
||||
|
||||
|
||||
|
||||
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 );
|
||||
|
||||
|
|
@ -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 );
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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 );
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -0,0 +1 @@
|
|||
uid://c8t6fm027suvq
|
||||
Loading…
Reference in New Issue