diff --git a/Icons/ASTViewAttribute.svg b/Icons/ASTViewAttribute.svg new file mode 100644 index 0000000..8deb19b --- /dev/null +++ b/Icons/ASTViewAttribute.svg @@ -0,0 +1,454 @@ + +t diff --git a/Icons/ASTViewAttribute.svg.import b/Icons/ASTViewAttribute.svg.import new file mode 100644 index 0000000..611751a --- /dev/null +++ b/Icons/ASTViewAttribute.svg.import @@ -0,0 +1,43 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://c1ga7dfggit3m" +path="res://.godot/imported/ASTViewAttribute.svg-3d90376a97e463f5e8c1d51842ca649c.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/rokojori_action_library/Icons/ASTViewAttribute.svg" +dest_files=["res://.godot/imported/ASTViewAttribute.svg-3d90376a97e463f5e8c1d51842ca649c.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 +svg/scale=1.0 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/Icons/ASTViewBracketToken.svg b/Icons/ASTViewBracketToken.svg new file mode 100644 index 0000000..4790e0c --- /dev/null +++ b/Icons/ASTViewBracketToken.svg @@ -0,0 +1,340 @@ + + diff --git a/Icons/ASTViewBracketToken.svg.import b/Icons/ASTViewBracketToken.svg.import new file mode 100644 index 0000000..d1776e1 --- /dev/null +++ b/Icons/ASTViewBracketToken.svg.import @@ -0,0 +1,43 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://6yg4233g51mp" +path="res://.godot/imported/ASTViewBracketToken.svg-5e10f2c1c361be5543104858ef26cbe4.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/rokojori_action_library/Icons/ASTViewBracketToken.svg" +dest_files=["res://.godot/imported/ASTViewBracketToken.svg-5e10f2c1c361be5543104858ef26cbe4.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 +svg/scale=1.0 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/Icons/ASTViewConstantToken.svg b/Icons/ASTViewConstantToken.svg new file mode 100644 index 0000000..b213665 --- /dev/null +++ b/Icons/ASTViewConstantToken.svg @@ -0,0 +1,339 @@ + + diff --git a/Icons/ASTViewConstantToken.svg.import b/Icons/ASTViewConstantToken.svg.import new file mode 100644 index 0000000..ae7a75b --- /dev/null +++ b/Icons/ASTViewConstantToken.svg.import @@ -0,0 +1,43 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://bgttfb7berwwu" +path="res://.godot/imported/ASTViewConstantToken.svg-4ea6a09e1d41b9affda10122b9f35341.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/rokojori_action_library/Icons/ASTViewConstantToken.svg" +dest_files=["res://.godot/imported/ASTViewConstantToken.svg-4ea6a09e1d41b9affda10122b9f35341.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 +svg/scale=1.0 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/Icons/ASTViewContext.svg b/Icons/ASTViewContext.svg new file mode 100644 index 0000000..6c0f674 --- /dev/null +++ b/Icons/ASTViewContext.svg @@ -0,0 +1,457 @@ + +t diff --git a/Icons/ASTViewContext.svg.import b/Icons/ASTViewContext.svg.import new file mode 100644 index 0000000..bf82867 --- /dev/null +++ b/Icons/ASTViewContext.svg.import @@ -0,0 +1,43 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://cp8x3tr0r6dv3" +path="res://.godot/imported/ASTViewContext.svg-01873566028d83c30ccc4aea92a1915d.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/rokojori_action_library/Icons/ASTViewContext.svg" +dest_files=["res://.godot/imported/ASTViewContext.svg-01873566028d83c30ccc4aea92a1915d.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 +svg/scale=1.0 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/Icons/ASTViewElement.svg b/Icons/ASTViewElement.svg new file mode 100644 index 0000000..daacab1 --- /dev/null +++ b/Icons/ASTViewElement.svg @@ -0,0 +1,366 @@ + +t diff --git a/Icons/ASTViewElement.svg.import b/Icons/ASTViewElement.svg.import new file mode 100644 index 0000000..b5b42ec --- /dev/null +++ b/Icons/ASTViewElement.svg.import @@ -0,0 +1,43 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://horcg6ltlipv" +path="res://.godot/imported/ASTViewElement.svg-854db37c734331d0f1952d7a8058264f.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/rokojori_action_library/Icons/ASTViewElement.svg" +dest_files=["res://.godot/imported/ASTViewElement.svg-854db37c734331d0f1952d7a8058264f.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 +svg/scale=1.0 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/Icons/ASTViewExpression.svg b/Icons/ASTViewExpression.svg new file mode 100644 index 0000000..b47c364 --- /dev/null +++ b/Icons/ASTViewExpression.svg @@ -0,0 +1,354 @@ + +t diff --git a/Icons/ASTViewExpression.svg.import b/Icons/ASTViewExpression.svg.import new file mode 100644 index 0000000..153d5c0 --- /dev/null +++ b/Icons/ASTViewExpression.svg.import @@ -0,0 +1,43 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://dfspdjcjiiud2" +path="res://.godot/imported/ASTViewExpression.svg-b2561a31e28b205e21b61323451031cb.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/rokojori_action_library/Icons/ASTViewExpression.svg" +dest_files=["res://.godot/imported/ASTViewExpression.svg-b2561a31e28b205e21b61323451031cb.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 +svg/scale=1.0 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/Icons/ASTViewIgnoreToken.svg b/Icons/ASTViewIgnoreToken.svg new file mode 100644 index 0000000..8d4b208 --- /dev/null +++ b/Icons/ASTViewIgnoreToken.svg @@ -0,0 +1,342 @@ + + diff --git a/Icons/ASTViewIgnoreToken.svg.import b/Icons/ASTViewIgnoreToken.svg.import new file mode 100644 index 0000000..1997d0d --- /dev/null +++ b/Icons/ASTViewIgnoreToken.svg.import @@ -0,0 +1,43 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://cwn7ynt0xlpy7" +path="res://.godot/imported/ASTViewIgnoreToken.svg-b324e16e97be55e89c97922164f734bd.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/rokojori_action_library/Icons/ASTViewIgnoreToken.svg" +dest_files=["res://.godot/imported/ASTViewIgnoreToken.svg-b324e16e97be55e89c97922164f734bd.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 +svg/scale=1.0 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/Icons/ASTViewLogicToken.svg b/Icons/ASTViewLogicToken.svg new file mode 100644 index 0000000..dc7c605 --- /dev/null +++ b/Icons/ASTViewLogicToken.svg @@ -0,0 +1,346 @@ + + diff --git a/Icons/ASTViewLogicToken.svg.import b/Icons/ASTViewLogicToken.svg.import new file mode 100644 index 0000000..d069a70 --- /dev/null +++ b/Icons/ASTViewLogicToken.svg.import @@ -0,0 +1,43 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://cw2raas8cijij" +path="res://.godot/imported/ASTViewLogicToken.svg-9c4a472fc688c1b5e4a5cd3c2618c538.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/rokojori_action_library/Icons/ASTViewLogicToken.svg" +dest_files=["res://.godot/imported/ASTViewLogicToken.svg-9c4a472fc688c1b5e4a5cd3c2618c538.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 +svg/scale=1.0 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/Icons/ASTViewMember.svg b/Icons/ASTViewMember.svg new file mode 100644 index 0000000..a06d296 --- /dev/null +++ b/Icons/ASTViewMember.svg @@ -0,0 +1,353 @@ + +t diff --git a/Icons/ASTViewMember.svg.import b/Icons/ASTViewMember.svg.import new file mode 100644 index 0000000..613ffe0 --- /dev/null +++ b/Icons/ASTViewMember.svg.import @@ -0,0 +1,43 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://n0eycqqk7w70" +path="res://.godot/imported/ASTViewMember.svg-f9e37ae7dc9e996efbf68cb90fb61814.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/rokojori_action_library/Icons/ASTViewMember.svg" +dest_files=["res://.godot/imported/ASTViewMember.svg-f9e37ae7dc9e996efbf68cb90fb61814.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 +svg/scale=1.0 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/Icons/ASTViewObject.svg b/Icons/ASTViewObject.svg new file mode 100644 index 0000000..c017b4e --- /dev/null +++ b/Icons/ASTViewObject.svg @@ -0,0 +1,424 @@ + +t diff --git a/Icons/ASTViewObject.svg.import b/Icons/ASTViewObject.svg.import new file mode 100644 index 0000000..314fc3f --- /dev/null +++ b/Icons/ASTViewObject.svg.import @@ -0,0 +1,43 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://c3f13n683odcg" +path="res://.godot/imported/ASTViewObject.svg-7328724af634e78eee79503f51e11949.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/rokojori_action_library/Icons/ASTViewObject.svg" +dest_files=["res://.godot/imported/ASTViewObject.svg-7328724af634e78eee79503f51e11949.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 +svg/scale=1.0 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/Icons/ASTViewOperatorToken.svg b/Icons/ASTViewOperatorToken.svg new file mode 100644 index 0000000..dc44919 --- /dev/null +++ b/Icons/ASTViewOperatorToken.svg @@ -0,0 +1,337 @@ + + diff --git a/Icons/ASTViewOperatorToken.svg.import b/Icons/ASTViewOperatorToken.svg.import new file mode 100644 index 0000000..aef61b3 --- /dev/null +++ b/Icons/ASTViewOperatorToken.svg.import @@ -0,0 +1,43 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://bqmehmdpv5a0e" +path="res://.godot/imported/ASTViewOperatorToken.svg-7367f1664d57ff060ff40c39c407dc2e.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/rokojori_action_library/Icons/ASTViewOperatorToken.svg" +dest_files=["res://.godot/imported/ASTViewOperatorToken.svg-7367f1664d57ff060ff40c39c407dc2e.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 +svg/scale=1.0 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/Icons/ASTViewStatement.svg b/Icons/ASTViewStatement.svg new file mode 100644 index 0000000..01fde4b --- /dev/null +++ b/Icons/ASTViewStatement.svg @@ -0,0 +1,343 @@ + + diff --git a/Icons/ASTViewStatement.svg.import b/Icons/ASTViewStatement.svg.import new file mode 100644 index 0000000..903d05d --- /dev/null +++ b/Icons/ASTViewStatement.svg.import @@ -0,0 +1,43 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://bagmilfojhs02" +path="res://.godot/imported/ASTViewStatement.svg-e422165cc4577de625ca5f7421a00574.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/rokojori_action_library/Icons/ASTViewStatement.svg" +dest_files=["res://.godot/imported/ASTViewStatement.svg-e422165cc4577de625ca5f7421a00574.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 +svg/scale=1.0 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/Icons/ASTViewToken.svg b/Icons/ASTViewToken.svg new file mode 100644 index 0000000..a06d672 --- /dev/null +++ b/Icons/ASTViewToken.svg @@ -0,0 +1,344 @@ + +t diff --git a/Icons/ASTViewToken.svg.import b/Icons/ASTViewToken.svg.import new file mode 100644 index 0000000..a161357 --- /dev/null +++ b/Icons/ASTViewToken.svg.import @@ -0,0 +1,43 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://gbib2673nwww" +path="res://.godot/imported/ASTViewToken.svg-7b92a75ae1051663a96d916309e348e2.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/rokojori_action_library/Icons/ASTViewToken.svg" +dest_files=["res://.godot/imported/ASTViewToken.svg-7b92a75ae1051663a96d916309e348e2.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 +svg/scale=1.0 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/Icons/ASTViewWordToken.svg b/Icons/ASTViewWordToken.svg new file mode 100644 index 0000000..818bc62 --- /dev/null +++ b/Icons/ASTViewWordToken.svg @@ -0,0 +1,347 @@ + + diff --git a/Icons/ASTViewWordToken.svg.import b/Icons/ASTViewWordToken.svg.import new file mode 100644 index 0000000..703cdb6 --- /dev/null +++ b/Icons/ASTViewWordToken.svg.import @@ -0,0 +1,43 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://bbuyxy0mdp7gc" +path="res://.godot/imported/ASTViewWordToken.svg-47ef9a555e6f707ad89ffb9fe548a1ca.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/rokojori_action_library/Icons/ASTViewWordToken.svg" +dest_files=["res://.godot/imported/ASTViewWordToken.svg-47ef9a555e6f707ad89ffb9fe548a1ca.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 +svg/scale=1.0 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/Runtime/Actions/Action.cs b/Runtime/Actions/Action.cs index 56d1fb8..77eb37a 100644 --- a/Runtime/Actions/Action.cs +++ b/Runtime/Actions/Action.cs @@ -7,6 +7,7 @@ namespace Rokojori; [Tool] [GlobalClass, Icon("res://addons/rokojori_action_library/Icons/Action.svg")] +[RokojoriActionCoreExport] public partial class Action : NetworkNode { public enum ActionTriggerMode diff --git a/Runtime/Actions/ActionList.cs b/Runtime/Actions/ActionList.cs index e21a0e2..ac65a53 100644 --- a/Runtime/Actions/ActionList.cs +++ b/Runtime/Actions/ActionList.cs @@ -4,7 +4,7 @@ using Godot; namespace Rokojori { - /** + /** Executes multiple actions (Action) at once. @@ -21,14 +21,15 @@ namespace Rokojori [Tool] [GlobalClass, Icon("res://addons/rokojori_action_library/Icons/ActionList.svg") ] + [RokojoriActionCoreExport] public partial class ActionList : Action { - /** <summary for="field actions">Actions to execute</summary>*/ + /** <summary>Actions to execute</summary> */ [Export] public Action[] actions = new Action[ 0 ]; - /** <summary for="field triggerDirectChildren">Whether to execute Action child nodes</summary>*/ + /** <summary>Whether to execute Action child nodes</summary>*/ [Export] public bool triggerDirectChildren = true; diff --git a/Runtime/Actions/RJ_Action.gd b/Runtime/Actions/RJ_Action.gd new file mode 100644 index 0000000..ca73e3e --- /dev/null +++ b/Runtime/Actions/RJ_Action.gd @@ -0,0 +1,23 @@ + +@tool +@icon("res://addons/rokojori_action_library/Icons/Action.svg") +class_name RJ_Action extends RJ_NetworkNode + +enum ActionTriggerMode +{ + Only_When_Processing_In_Hierarchy, + Always +} + +@export +var trigger_mode: ActionTriggerMode; + +func trigger() -> void: + pass +## --- + + +func _on_trigger() -> void: + pass +## --- + diff --git a/Runtime/Actions/RJ_Action.gd.uid b/Runtime/Actions/RJ_Action.gd.uid new file mode 100644 index 0000000..c952971 --- /dev/null +++ b/Runtime/Actions/RJ_Action.gd.uid @@ -0,0 +1 @@ +uid://dcqjcsh20ndon diff --git a/Runtime/Actions/RJ_ActionList.gd b/Runtime/Actions/RJ_ActionList.gd new file mode 100644 index 0000000..8fabcdc --- /dev/null +++ b/Runtime/Actions/RJ_ActionList.gd @@ -0,0 +1,14 @@ + +@tool +@icon("res://addons/rokojori_action_library/Icons/ActionList.svg") +class_name RJ_ActionList extends RJ_Action + +@export +var actions: Action[]; +@export +var trigger_direct_children: bool; + +func _on_trigger() -> void: + pass +## --- + diff --git a/Runtime/Actions/RJ_ActionList.gd.uid b/Runtime/Actions/RJ_ActionList.gd.uid new file mode 100644 index 0000000..221e527 --- /dev/null +++ b/Runtime/Actions/RJ_ActionList.gd.uid @@ -0,0 +1 @@ +uid://ctnc7tsiwxp3j diff --git a/Runtime/Godot/Extensions/NodeExtensions.cs b/Runtime/Godot/Extensions/NodeExtensions.cs index ed163db..d6dbfcb 100644 --- a/Runtime/Godot/Extensions/NodeExtensions.cs +++ b/Runtime/Godot/Extensions/NodeExtensions.cs @@ -60,6 +60,46 @@ namespace Rokojori } + public static List<U> MapDirectChildren<T,U>( this Node node, Func<T,U> mapper ) where T:Node + { + var list = new List<U>(); + + node.ForEachDirectChild<T>( + n => + { + if ( n is T t) + { + list.Add( mapper( t ) ); + } + } + ); + + return list; + } + + public static bool HasDirectChildWithName<T>( this Node node, string name, bool includeInternal = false ) + { + return IndexOfDirectChildWithName<T>( node, name, includeInternal ) != -1; + } + + public static int IndexOfDirectChildWithName<T>( this Node node, string name, bool includeInternal = false ) + { + var numKids = node.GetChildCount( includeInternal ); + + for ( int i = 0; i < numKids; i++ ) + { + var child = node.GetChild( i, includeInternal ); + + if ( child is T t && child.Name == name ) + { + return i; + } + + } + + return -1; + } + public static T GetNextSiblingOrChild<T>( this Node node ) where T:Node { var index = node.GetIndex(); diff --git a/Runtime/Godot/Nodes.cs b/Runtime/Godot/Nodes.cs index b2cdd0e..16ad5ce 100644 --- a/Runtime/Godot/Nodes.cs +++ b/Runtime/Godot/Nodes.cs @@ -672,6 +672,30 @@ namespace Rokojori } } + public static void RemoveChildren<T>( this Node parent, bool includeInternal = false ) where T:Node + { + if ( parent == null ) + { + return; + } + + var numChildren = parent.GetChildCount( includeInternal ); + + for ( int i = numChildren - 1; i >= 0; i-- ) + { + var node = parent.GetChild( i, includeInternal ); + + var t = node as T; + + if ( t == null ) + { + continue; + } + + parent.RemoveChild( node ); + } + } + public static void DestroyChildren( this Node parent, bool includeInternal = false, bool queue = true ) { diff --git a/Runtime/Godot/NodesWalker.cs b/Runtime/Godot/NodesWalker.cs index bac5ac6..dc75d3b 100644 --- a/Runtime/Godot/NodesWalker.cs +++ b/Runtime/Godot/NodesWalker.cs @@ -42,5 +42,46 @@ namespace Rokojori } + } + + public class InternalNodesWalker: TreeWalker<Node> + { + static InternalNodesWalker _singleton = new InternalNodesWalker(); + public static InternalNodesWalker Get() + { + return _singleton; + } + + public override Node Parent( Node n ) + { + if ( n == null ) + { + return null; + } + + return n.GetParent(); + } + + public override Node ChildAt( Node n, int index ) + { + if ( n == null ) + { + return null; + } + + return n.GetChild( index, true ); + } + + public override int NumChildren( Node n ) + { + if ( n == null ) + { + return 0; + } + + return n.GetChildCount( true ); + } + + } } \ No newline at end of file diff --git a/Runtime/Graphs/Trees/TreeWalker.cs b/Runtime/Graphs/Trees/TreeWalker.cs index 5a61af4..721099e 100644 --- a/Runtime/Graphs/Trees/TreeWalker.cs +++ b/Runtime/Graphs/Trees/TreeWalker.cs @@ -207,6 +207,13 @@ namespace Rokojori return FindChild( node, false, selector ); } + public T FindAnyChildOfType<T>( N node ) where T:class + { + var v = FindAnyChild( node, n => n is T ); + + return v == null ? default( T ) : ( v as T ); + } + public N FindChild( N node, bool directChildrenOnly, Predicate<N> selector ) { if ( directChildrenOnly ) @@ -405,6 +412,26 @@ namespace Rokojori return false; } + + public N ResolveToCommonParent( N nestedChild, N parent ) + { + var it = nestedChild; + + + while ( it != null ) + { + var p = Parent( it ); + + if ( p == parent ) + { + return it; + } + + it = p; + } + + return null; + } public int NumParents( N node ) @@ -658,6 +685,13 @@ namespace Rokojori Iterate( node, addToList, childrenOnly ); } + public List<N> Filter( N node, Predicate<N> predicate, bool childrenOnly ) + { + var list = new List<N>(); + Filter( list, node, predicate, childrenOnly ); + return list; + } + public void FilterAndMap<U>( List<U> list, N node, Predicate<N> predicate, Func<N,U> mapper, bool childrenOnly ) { Action<N> addToList = ( N n ) => @@ -671,7 +705,19 @@ namespace Rokojori Iterate( node, addToList, childrenOnly ); } - public void Map<U>( List<U> list, N node, Predicate<N> predicate, Func<N,U> mapper, bool childrenOnly ) + public List<U> FilterAndMap<U>( N node, Predicate<N> predicate, Func<N,U> mapper, bool childrenOnly ) + { + var list = new List<U>(); + FilterAndMap( list, node, predicate, mapper, childrenOnly ); + return list; + } + + public List<U> FilterType<U>( N node, bool childrenOnly = true ) where U:class + { + return FilterAndMap( node, n => n is U, n => n as U, childrenOnly ); + } + + public void Map<U>( List<U> list, N node, Func<N,U> mapper, bool childrenOnly ) { Action<N> addToList = ( N n ) => { diff --git a/Runtime/Networking/Nodes/NetworkNode.cs b/Runtime/Networking/Nodes/NetworkNode.cs index b098e08..725deb0 100644 --- a/Runtime/Networking/Nodes/NetworkNode.cs +++ b/Runtime/Networking/Nodes/NetworkNode.cs @@ -2,56 +2,60 @@ using Godot; using Rokojori.Tools; using System.Collections.Generic; -namespace Rokojori -{ - [Tool] - [GlobalClass] - public partial class NetworkNode : Node, INetworkNode +namespace Rokojori; + +[Tool] +[GlobalClass] +[RokojoriActionCoreExport] +public partial class NetworkNode : Node, INetworkNode +{ + #if !GD_SCRIPT_TRANSPILING + + [ExportGroup("Network Settings")] + [Export] + public NetworkTransportType networkType = NetworkTransportType.Never_Networked; + public NetworkTransportType GetNetworkType(){ return networkType; } + + [Export] + public int networkOwner; + public int GetNetworkOwner(){ return networkOwner; } + + + protected List<NetworkNodeMember> _networkNodeMembers = null; + protected NetworkNodeSlot _networkNodeSlot = new NetworkNodeSlot(); + + public virtual List<NetworkNodeMember> GetNetworkNodeMembers() { - [ExportGroup("Network Settings")] - [Export] - public NetworkTransportType networkType = NetworkTransportType.Never_Networked; - public NetworkTransportType GetNetworkType(){ return networkType; } - - [Export] - public int networkOwner; - public int GetNetworkOwner(){ return networkOwner; } - - - protected List<NetworkNodeMember> _networkNodeMembers = null; - protected NetworkNodeSlot _networkNodeSlot = new NetworkNodeSlot(); - - public virtual List<NetworkNodeMember> GetNetworkNodeMembers() + if ( _networkNodeMembers != null ) { - if ( _networkNodeMembers != null ) - { - return _networkNodeMembers; - } - - _networkNodeMembers = CreateNetworkNodeMembers(); - _networkNodeSlot.onMessage.AddAction( _OnNetworkMessageReceived ); - - InitializeNetworkMembers(); - return _networkNodeMembers; } - protected virtual List<NetworkNodeMember> CreateNetworkNodeMembers() - { - return new List<NetworkNodeMember>(){ _networkNodeSlot }; - } + _networkNodeMembers = CreateNetworkNodeMembers(); + _networkNodeSlot.onMessage.AddAction( _OnNetworkMessageReceived ); - protected virtual void InitializeNetworkMembers() - { - for ( int i = 0; i < _networkNodeMembers.Count; i++ ) - { - _networkNodeMembers[ i ]._SetNode( this ); - } - } + InitializeNetworkMembers(); - protected virtual void _OnNetworkMessageReceived( NetworkMessageEvent m ) - { + return _networkNodeMembers; + } + protected virtual List<NetworkNodeMember> CreateNetworkNodeMembers() + { + return new List<NetworkNodeMember>(){ _networkNodeSlot }; + } + + protected virtual void InitializeNetworkMembers() + { + for ( int i = 0; i < _networkNodeMembers.Count; i++ ) + { + _networkNodeMembers[ i ]._SetNode( this ); } } -} \ No newline at end of file + + protected virtual void _OnNetworkMessageReceived( NetworkMessageEvent m ) + { + + } + + #endif +} diff --git a/Runtime/Text/CodeGenerators/GDScript/CSDocToGDScriptDoc.cs b/Runtime/Text/CodeGenerators/GDScript/CSDocToGDScriptDoc.cs new file mode 100644 index 0000000..e517b06 --- /dev/null +++ b/Runtime/Text/CodeGenerators/GDScript/CSDocToGDScriptDoc.cs @@ -0,0 +1,121 @@ +using System.Collections; +using System.Collections.Generic; +using System.Text.RegularExpressions; +using System.Text; + +namespace Rokojori; + +class CSDocToGDScriptDoc +{ + static void AddChildrenToIgnoreSet( XMLNode n, HashSet<XMLNode> ignoreSet ) + { + var walker = XMLWalker.instance; + + walker.Iterate( n, + ( n )=> + { + ignoreSet.Add( n ); + } + ); + } + + public static string ConvertDoc( string docComment ) + { + if ( docComment == null || docComment == "" ) + { + return " (...) "; + } + + var xml = XMLDocument.From( docComment ); + var walker = XMLWalker.instance; + + var d = new StringBuilder(); + + var docRoot = xml.documentElement; + + var formats = new List<string>(){ "i", "b", "s", "u" }; + var ignoreSet = new HashSet<XMLNode>(); + + + walker.Iterate( docRoot, + n => + { + if ( ignoreSet.Contains( n ) ) + { + return; + } + + if ( n is XMLElementNode br && br.nodeName == "br" ) + { + d.Append( "[br]" ); + AddChildrenToIgnoreSet( n, ignoreSet ); + } + else if ( n is XMLElementNode url && url.nodeName == "url" ) + { + d.Append( "[url=" + url.GetAttribute( "data-path" ) + "]"); + d.Append( url.textContent ); + d.Append( "[/url]"); + + AddChildrenToIgnoreSet( n, ignoreSet ); + } + else if ( n is XMLElementNode s && formats.IndexOf( s.nodeName ) != -1 ) + { + d.Append( "[" + s.nodeName + "]"); + d.Append( s.textContent ); + d.Append( "[/" + s.nodeName + "]"); + + AddChildrenToIgnoreSet( n, ignoreSet ); + } + else if ( n is XMLElementNode c && c.nodeName.StartsWith( "doc-code" )) + { + if ( c.nodeName == "doc-code-block" ) + { + d.Append( "[codeblock]"); + d.Append( c.textContent ); + d.Append( "[/codeblock]"); + } + else + { + d.Append( "[code]"); + d.Append( c.textContent ); + d.Append( "[/code]"); + } + + AddChildrenToIgnoreSet( n, ignoreSet ); + } + else if ( n is XMLElementNode m && m.nodeName.StartsWith( "doc-link-" )) + { + d.Append( "["); + + var name = m.nodeName.Replace( "doc-link-", "" ); + + if ( name != "class" ) + { + d.Append( name ); + d.Append( " " ); + } + + d.Append( m.textContent ); + d.Append( "]"); + + AddChildrenToIgnoreSet( n, ignoreSet ); + } + else if ( n is XMLTextNode ) + { + d.Append( n.textContent ); + } + }, + false + ); + + + var dString = RegexUtility.Indent( d.ToString(), " "); + + var docLines = RegexUtility.SplitLines( dString ); + + var gdComment = "##" + docLines.Join( "\n##" ) + "\n"; + + return gdComment; + } + +} \ No newline at end of file diff --git a/Runtime/Text/CodeGenerators/GDScript/CSDocToGDScriptDoc.cs.uid b/Runtime/Text/CodeGenerators/GDScript/CSDocToGDScriptDoc.cs.uid new file mode 100644 index 0000000..833f03c --- /dev/null +++ b/Runtime/Text/CodeGenerators/GDScript/CSDocToGDScriptDoc.cs.uid @@ -0,0 +1 @@ +uid://bwskdk8sbbaqo diff --git a/Runtime/Text/CodeGenerators/GDScript/GDScriptFromCSAST.cs b/Runtime/Text/CodeGenerators/GDScript/GDScriptFromCSAST.cs index 8fdf53f..de27579 100644 --- a/Runtime/Text/CodeGenerators/GDScript/GDScriptFromCSAST.cs +++ b/Runtime/Text/CodeGenerators/GDScript/GDScriptFromCSAST.cs @@ -46,27 +46,116 @@ public class GDScriptFromCSAST return sb.ToString(); } + static HashSet<string> godotBuiltIn = new HashSet<string>(){ + "Node", "Node3D", "Node2D", "Control", + "Resource", + "Vector2", "Vector3", "Vector4" + }; + + + public static bool IsGodotBuiltIn( string type ) + { + return godotBuiltIn.Contains( type ); + } + + + public static bool IsCSBuiltIn( string type ) + { + + return godotBuiltIn.Contains( type ); + } + + public static string GetNamespaceForType( string typeName, List<string> namespaces ) + { + var assemblies = System.AppDomain.CurrentDomain.GetAssemblies(); + + foreach ( var ns in namespaces ) + { + string fullName = ns + "." + typeName; + + foreach ( var asm in assemblies ) + { + if ( asm.GetType( fullName, false ) != null) + { + return ns; + } + } + } + + return null; + } public string GetClassName( string className, string ns ) { - if ( ns.StartsWith( "Rokojori" ) ) + if ( ns != null && ! ns.StartsWith( "Rokojori" ) ) { - return rokojoriPrefix + className; + return className; } - return className; + if ( ns == null && IsGodotBuiltIn( className ) ) + { + return className; + } + + return rokojoriPrefix + className; } + List<string> namespaces = new List<string>{ + "Godot","Godot.Collections", + "Rokojori" + }; + + + string ConvertRawType( string type ) + { + var ns = GetNamespaceForType( type, namespaces ); + + if ( ns == null ) + { + return type; + } + + if ( ns.StartsWith( "Rokojori" ) ) + { + return rokojoriPrefix + type; + } + + return type; + } + + string ConvertType( CSTypeDefinition parent ) + { + if ( parent.IsGenericList() ) + { + var convertedType = ConvertRawType( parent.GetGenericType() ); + return "Array[" + convertedType + "]"; + } + + if ( parent.IsArrayType() ) + { + var convertedType = ConvertRawType( parent.GetBaseType() ); + return "Array[" + convertedType + "]"; + } + + return ConvertRawType( parent.GetBaseType() ); + } + + public void Convert( CSFileRoot root ) { var walker = root.walker; var csClass = walker.Find( root, n => n is CSClassDeclaration, true ) as CSClassDeclaration; - gdClass.name = GetClassName( csClass.GetClassName(), "Rokojori" ); + gdClass.name = GetClassName( csClass.GetClassName(), csClass.GetNamespace() ); if ( csClass.objectTail != null && csClass.objectTail.inheritanceDeclaration != null ) { - gdClass.extendingClassName = GetClassName( csClass.objectTail.GetExtendingObject(), "Rokojori" ); + gdClass.extendingClassName = GetClassName( csClass.objectTail.GetExtendingObject(), null ); + } + + if ( csClass.docComment != null ) + { + gdClass.doc = CSDocToGDScriptDoc.ConvertDoc( csClass.GetDocumentation() ); } var atts = CSModifierAttributesParser.GetAttributes( csClass.attributeBrackets ); @@ -122,7 +211,7 @@ public class GDScriptFromCSAST { var gdField = new GDScriptGeneratorField(); gdField.name = CStoGDVariable( f.GetMemberName() ); - gdField.memberType = f.GetMemberType(); + gdField.memberType = ConvertType( f.memberType ); gdMember = gdField; } @@ -130,7 +219,7 @@ public class GDScriptFromCSAST { var gdMethod = new GDScriptGeneratorMethod(); gdMethod.name = me.isContructor ? "_init" : CStoGDVariable( me.GetMemberName() ); - gdMethod.memberType = me.GetMemberType(); + gdMethod.memberType = me.isContructor ? me.GetMemberType() : ConvertType( me.memberType ); gdMethod.isConstructor = me.isContructor; if ( me.parametersContent != null ) @@ -142,7 +231,7 @@ public class GDScriptFromCSAST var gdParameter = new GDScriptGeneratorParameter(); gdParameter.name = p.GetParameterName(); - gdParameter.parameterType = p.GetParameterType(); + gdParameter.parameterType = ConvertType( p.parameterType ); gdMethod.parameters.Add( gdParameter ); @@ -162,6 +251,11 @@ public class GDScriptFromCSAST return; } + if ( m.docComment != null ) + { + gdMember.doc = CSDocToGDScriptDoc.ConvertDoc( m.GetDocumentation() ); + } + if ( CSModifierAttributesParser.IsExported( m.attributeBrackets ) ) { gdMember.annotations.Add( "export" ); diff --git a/Runtime/Text/CodeGenerators/GDScript/GDScriptGenerator.cs b/Runtime/Text/CodeGenerators/GDScript/GDScriptGenerator.cs index 585981c..d5c6b48 100644 --- a/Runtime/Text/CodeGenerators/GDScript/GDScriptGenerator.cs +++ b/Runtime/Text/CodeGenerators/GDScript/GDScriptGenerator.cs @@ -10,7 +10,6 @@ public class GDScriptGenerator public static readonly string GD_SCRIPT_TRANSPILING = "GD_SCRIPT_TRANSPILING"; public List<GDScriptGeneratorClass> gdClasses = new List<GDScriptGeneratorClass>(); - public void Generate( string outputPath ) { gdClasses.ForEach( diff --git a/Runtime/Text/CodeGenerators/GDScript/GDScriptGeneratorClass.cs b/Runtime/Text/CodeGenerators/GDScript/GDScriptGeneratorClass.cs index d733200..61810b8 100644 --- a/Runtime/Text/CodeGenerators/GDScript/GDScriptGeneratorClass.cs +++ b/Runtime/Text/CodeGenerators/GDScript/GDScriptGeneratorClass.cs @@ -9,6 +9,7 @@ public class GDScriptGeneratorClass { public List<string> annotations = []; public string name; + public string doc; public string extendingClassName; public List<GDScriptGeneratorMember> members = []; @@ -28,12 +29,23 @@ public class GDScriptGeneratorClass ); AddClassHeader(); - sb.Append( "\n" ); + + + if ( doc != null ) + { + sb.Append( doc ); + sb.Append( "\n" ); + } members.ForEach( m => { + if ( m.doc != null ) + { + sb.Append( m.doc ); + } + m.Generate( sb ); - sb.Append( "\n" ); + sb.Append( "\n\n" ); }); return sb.ToString(); diff --git a/Runtime/Text/CodeGenerators/GDScript/GDScriptGeneratorMember.cs b/Runtime/Text/CodeGenerators/GDScript/GDScriptGeneratorMember.cs index 7684242..c7bbcef 100644 --- a/Runtime/Text/CodeGenerators/GDScript/GDScriptGeneratorMember.cs +++ b/Runtime/Text/CodeGenerators/GDScript/GDScriptGeneratorMember.cs @@ -8,6 +8,7 @@ namespace Rokojori; public abstract class GDScriptGeneratorMember { public string name; + public string doc; public string memberType; public List<string> annotations = []; diff --git a/Runtime/Text/Lexing/LexerLibrary/XMLLexer.cs b/Runtime/Text/Lexing/LexerLibrary/XMLLexer.cs index 0233feb..8569344 100644 --- a/Runtime/Text/Lexing/LexerLibrary/XMLLexer.cs +++ b/Runtime/Text/Lexing/LexerLibrary/XMLLexer.cs @@ -36,7 +36,7 @@ namespace Rokojori public static readonly LexerMatcher XMLText = - new LexerMatcher( "XMLText", @"([^<].)" ); + new LexerMatcher( "XMLText", @"([^<]+)" ); public static readonly LexerMatcher XMLAttributeName = new LexerMatcher( "XMLAttributeName", @@ -126,6 +126,7 @@ namespace Rokojori XMLLexer.XMLAttributeAssignment, XMLLexer.InsideStartTag_WhiteSpaceMatcher, XMLLexer.InsideStartTag_BreakMatcher + ); } diff --git a/Runtime/Text/Lexing/LexerMatcherLibrary.cs b/Runtime/Text/Lexing/LexerMatcherLibrary.cs index fa998f9..238e4a0 100644 --- a/Runtime/Text/Lexing/LexerMatcherLibrary.cs +++ b/Runtime/Text/Lexing/LexerMatcherLibrary.cs @@ -60,7 +60,7 @@ namespace Rokojori new LexerMatcher( "Bool", "true|false" ); public static readonly LexerMatcher LogicMatcher = - new LexerMatcher( "Logic", "if|else|switch|do|while|for|break|continue|return" ); + new LexerMatcher( "Logic", "if|else|switch|do|while|foreach|for|break|continue|return|try|catch|lock|throw|await" ); public static readonly LexerMatcher OperatorMatcher = new LexerMatcher( "Operator", "(?:\\=\\=)|(?:\\+\\+)|(?:\\-\\-)|(?:\\+\\=)|(?:\\*\\=)|(?:\\-\\=)|(?:\\/\\=)|(?:\\=\\>)|\\+|\\-|\\*|\\/|\\^|\\|\\||\\||\\~|\\&\\&|\\&|\\%|\\<|\\>|\\=|\\!|\\.|\\:|\\,|\\;" ); diff --git a/Runtime/Text/Parsing/AST/ASTNode.cs b/Runtime/Text/Parsing/AST/ASTNode.cs index f1e43ee..0f77ca9 100644 --- a/Runtime/Text/Parsing/AST/ASTNode.cs +++ b/Runtime/Text/Parsing/AST/ASTNode.cs @@ -39,6 +39,63 @@ public abstract class ASTNode } + public virtual ASTViewNode CreateViewNode() + { + var viewNode = new ASTViewElement(); + + if ( this is OperatorExpression ) + { + viewNode = new ASTViewExpression(); + } + else if ( + this is ClassDeclaration || + this is EnumDeclaration || + this is InterfaceDeclaration + ) + { + viewNode = new ASTViewObject(); + } + else if ( this is MemberDeclaration ) + { + viewNode = new ASTViewMember(); + } + else if ( this is Statement ) + { + viewNode = new ASTViewStatement(); + } + + + viewNode.astNodeReference = this; + + + var type = GetType(); + viewNode.astNodeType = type.Name; + viewNode.Name = type.Name; + + if ( viewNode is ASTViewMember ) + { + var md = this as MemberDeclaration; + viewNode.Name += " [ " + md.GetMemberName() + " ]"; + } + + if ( this is ClassDeclaration cd ) + { + viewNode.Name += " [ " + cd.GetClassName() + " ]"; + } + + if ( this is InterfaceDeclaration id ) + { + viewNode.Name += " [ " + id.GetInterfaceName() + " ]"; + } + + if ( this is EnumDeclaration ed ) + { + viewNode.Name += " [ " + ed.GetEnumName() + " ]"; + } + + return viewNode; + } + public string CreateDebugTreeInfo() { var walker = ASTWalker.instance; @@ -128,6 +185,11 @@ public abstract class ASTNode var start = indexStart + 1; var length = indexEnd - start; + if ( length <= 0 ) + { + return null; + } + return MergeChildrenWith<T>( start, length ); } @@ -188,9 +250,40 @@ public abstract class ASTNode return tk.match; } - var tokens = children.FilterType<ASTNode,Token>(); + var sb = new StringBuilder(); - return tokens.Map( t => t.match ).Join( "" ); + for ( int i = 0; i < children.Count; i++ ) + { + sb.Append( children[ i ].CombinedMatch() ); + } + + // var tokens = children.FilterType<ASTNode,Token>(); + + // return tokens.Map( t => t.match ).Join( "" ); + + return sb.ToString(); + } + + public void ExpandToNext( ASTNode nextSibling ) + { + if ( parent == null || nextSibling == null || parent != nextSibling.parent ) + { + RJLog.Error( "Invalid sibling", nextSibling?.GetType().Name ?? "null" ); + return; + } + + var start = childIndex + 1; // A, B, C, D + var length = ( nextSibling.childIndex - start ) + 1 ; + + var beforeCount = children.Count; + + var range = parent.children.Sub( start, length ); + parent.children.RemoveRange( start, length ); + + range.ForEach( r => r.parent = this ); + children.AddRange( range ); + + RJLog.Log( "Expanded from", beforeCount, "to", children.Count, "( " + length + " )" ); } public void ExpandToPrevious( ASTNode previousSibling ) @@ -489,6 +582,29 @@ public abstract class ASTNode return IsAnyTokenOf( LexerMatcherLibrary.Ignore ); } + public bool IsEmptyOrIgnore() + { + if ( IsIgnoreToken() ) + { + return true; + } + + if ( children.Count == 0 ) + { + return true; + } + + for ( int i = 0; i < children.Count; i++ ) + { + if ( ! children[ i ].IsIgnoreToken() ) + { + return false; + } + } + + return true; + } + public int IndexOffset( int index, int offset ) { if ( offset < 0 ) @@ -852,6 +968,11 @@ public abstract class ASTNode return false; } + public int FindSemicolonIndex( int offset ) + { + return FindTriggerTokenIndex( offset, TokenPredicateData.Semicolon, TokenPredicateData.BlockPredicates ); + } + public int FindTriggerTokenIndex( int offset, List<TokenPredicateData> triggerPredicates, List<TokenPredicateData> blockPredicates ) { var blockTypesCounter = new List<int>(); @@ -915,4 +1036,28 @@ public abstract class ASTNode return -1; } + public string GetOuterRangeMatch( int start, int end ) + { + var sb = new StringBuilder(); + + for ( int i = start; i <= end; i++ ) + { + sb.Append( children[ i ].CombinedMatch() ); + } + + return sb.ToString(); + } + + public string GetInnerRangeMatch( int start, int end ) + { + var sb = new StringBuilder(); + + for ( int i = start + 1; i < end ; i++ ) + { + sb.Append( children[ i ].CombinedMatch() ); + } + + return sb.ToString(); + } + } \ No newline at end of file diff --git a/Runtime/Text/Parsing/AST/ASTWalker.cs b/Runtime/Text/Parsing/AST/ASTWalker.cs index a8b42e7..62b3849 100644 --- a/Runtime/Text/Parsing/AST/ASTWalker.cs +++ b/Runtime/Text/Parsing/AST/ASTWalker.cs @@ -6,6 +6,7 @@ using System.Text; using System.Globalization; using Godot; using System; +using System.Reflection; namespace Rokojori; @@ -33,4 +34,107 @@ public class ASTWalker:TreeWalker<ASTNode> { return node?.children.Count ?? 0; } -} \ No newline at end of file +} + +public class ASTReferenceWalker:TreeWalker<ASTNode> +{ + public override ASTNode Parent( ASTNode node ) + { + return node?.parent; + } + + public override int NumChildren( ASTNode node ) + { + if ( node == null ) + { + return 0; + } + + if ( node is ASTFileRoot || node is ASTNodeList ) + { + return node.children.Count; + } + + if ( node is SeparatedSequenceExpression se ) + { + return se.GetExpressions().Count; + } + + GrabInfo( node ); + return _typeFieldInfos[ node.GetType() ].Count; + } + + public override ASTNode ChildAt( ASTNode node, int index ) + { + if ( node == null || index < 0 || index >= node.children.Count ) + { + return null; + } + + if ( node is ASTFileRoot || node is ASTNodeList ) + { + return node.children[ index ]; + } + + if ( node is SeparatedSequenceExpression se ) + { + return se.GetExpressions()[ index ]; + } + + GrabInfo( node ); + var fieldInfos = _typeFieldInfos[ node.GetType() ]; + return fieldInfos[ index ].GetValue( node ) as ASTNode; + } + + public string GetParentReferenceName( ASTNode node ) + { + var parent = Parent( node ); + + if ( parent == null ) + { + return ""; + } + + + var index = ChildIndexOf( node ); + + return GetChildReferenceName( parent, index ); + } + + public string GetChildReferenceName( ASTNode node, int index ) + { + if ( node is ASTFileRoot || node is ASTNodeList || node is SeparatedSequenceExpression ) + { + return index + ""; + } + + GrabInfo( node ); + + var fieldInfos = _typeFieldInfos[ node.GetType() ]; + + return fieldInfos[ index ].Name; + } + + Dictionary<Type,List<FieldInfo>> _typeFieldInfos = new Dictionary<Type, List<FieldInfo>>(); + + void GrabInfo( ASTNode node ) + { + if ( node == null ) + { + return; + } + + var type = node.GetType(); + + if ( _typeFieldInfos.ContainsKey( type ) ) + { + return; + } + + _typeFieldInfos[ type ] = ReflectionHelper.GetFieldInfosOfType<ASTNode>( node ); + + + } + + +} diff --git a/Runtime/Text/Parsing/AST/Debug/ASTViewAttribute.cs b/Runtime/Text/Parsing/AST/Debug/ASTViewAttribute.cs new file mode 100644 index 0000000..e3eaf2a --- /dev/null +++ b/Runtime/Text/Parsing/AST/Debug/ASTViewAttribute.cs @@ -0,0 +1,16 @@ +using System.Collections; +using System.Collections.Generic; +using System.Text.RegularExpressions; +using System.Text; + +using System.Globalization; +using Godot; +using System; + +namespace Rokojori; + +[Tool, Icon("res://addons/rokojori_action_library/Icons/ASTViewAttribute.svg")] +public partial class ASTViewAttribute:ASTViewElement +{ + +} \ No newline at end of file diff --git a/Runtime/Text/Parsing/AST/Debug/ASTViewAttribute.cs.uid b/Runtime/Text/Parsing/AST/Debug/ASTViewAttribute.cs.uid new file mode 100644 index 0000000..17330c6 --- /dev/null +++ b/Runtime/Text/Parsing/AST/Debug/ASTViewAttribute.cs.uid @@ -0,0 +1 @@ +uid://byagp5r8ju6rb diff --git a/Runtime/Text/Parsing/AST/Debug/ASTViewBracketToken.cs b/Runtime/Text/Parsing/AST/Debug/ASTViewBracketToken.cs new file mode 100644 index 0000000..e89ad64 --- /dev/null +++ b/Runtime/Text/Parsing/AST/Debug/ASTViewBracketToken.cs @@ -0,0 +1,15 @@ +using System.Collections; +using System.Collections.Generic; +using System.Text.RegularExpressions; +using System.Text; + +using System.Globalization; +using Godot; +using System; + +namespace Rokojori; + +[Tool, Icon("res://addons/rokojori_action_library/Icons/ASTViewBracketToken.svg")] +public partial class ASTViewBracketToken: ASTViewToken +{ +} \ No newline at end of file diff --git a/Runtime/Text/Parsing/AST/Debug/ASTViewBracketToken.cs.uid b/Runtime/Text/Parsing/AST/Debug/ASTViewBracketToken.cs.uid new file mode 100644 index 0000000..edfe5a3 --- /dev/null +++ b/Runtime/Text/Parsing/AST/Debug/ASTViewBracketToken.cs.uid @@ -0,0 +1 @@ +uid://xtiqx3nv83cr diff --git a/Runtime/Text/Parsing/AST/Debug/ASTViewConstantToken.cs b/Runtime/Text/Parsing/AST/Debug/ASTViewConstantToken.cs new file mode 100644 index 0000000..b60c2ce --- /dev/null +++ b/Runtime/Text/Parsing/AST/Debug/ASTViewConstantToken.cs @@ -0,0 +1,15 @@ +using System.Collections; +using System.Collections.Generic; +using System.Text.RegularExpressions; +using System.Text; + +using System.Globalization; +using Godot; +using System; + +namespace Rokojori; + +[Tool, Icon("res://addons/rokojori_action_library/Icons/ASTViewConstantToken.svg")] +public partial class ASTViewConstantToken: ASTViewToken +{ +} \ No newline at end of file diff --git a/Runtime/Text/Parsing/AST/Debug/ASTViewConstantToken.cs.uid b/Runtime/Text/Parsing/AST/Debug/ASTViewConstantToken.cs.uid new file mode 100644 index 0000000..ac99d06 --- /dev/null +++ b/Runtime/Text/Parsing/AST/Debug/ASTViewConstantToken.cs.uid @@ -0,0 +1 @@ +uid://geu1beuih0rh diff --git a/Runtime/Text/Parsing/AST/Debug/ASTViewContext.cs b/Runtime/Text/Parsing/AST/Debug/ASTViewContext.cs new file mode 100644 index 0000000..9c4e0e0 --- /dev/null +++ b/Runtime/Text/Parsing/AST/Debug/ASTViewContext.cs @@ -0,0 +1,249 @@ +using System.Collections; +using System.Collections.Generic; +using System.Text.RegularExpressions; +using System.Text; + +using System.Globalization; +using Godot; +using System; + +namespace Rokojori; + +[Tool, Icon("res://addons/rokojori_action_library/Icons/ASTViewContext.svg")] +public partial class ASTViewContext:Node +{ + bool _hideTokens = false; + + [Export] + public bool hideTokens + { + get => _hideTokens; + set { _hideTokens = value; UpdateValue(); } + } + + void UpdateValue() + { + this.ForEach<ASTViewNode>( + ( n )=> + { + n.UpdateFromViewContext( this ); + } + ); + } + + + public enum ViewType + { + Tree_Structure, + References_Only + } + + [Export] + public ViewType viewType = ViewType.Tree_Structure; + + + Dictionary<ASTNode,ASTViewNode> _nodeToView = new Dictionary<ASTNode, ASTViewNode>(); + List<ASTViewElement> _elements = []; + + public void ClearFilters() + { + _hideTokens = false; + } + + public void Create( ASTNode root ) + { + if ( ViewType.Tree_Structure == viewType ) + { + CreateTreeStructure( root ); + } + else + { + CreateReferenceStructure( root ); + } + } + + void CreateReferenceElement( string referenceName, ASTNode node, HashSet<ASTNode> processed, ASTViewNode parentViewNode, ASTReferenceWalker walker ) + { + if ( node == null || node.IsIgnoreToken() || processed.Contains( node ) ) + { + return; + } + + processed.Add( node ); + + + + Node attachingNode = parentViewNode == null ? this : parentViewNode; + + var viewNode = node.CreateViewNode(); + viewNode.Name = "-[ " + referenceName + " ] '" + viewNode.Name + "'"; + + if ( attachingNode.HasDirectChildWithName<Node>( viewNode.Name ) ) + { + viewNode.Name += "(" + node.childIndex +")"; + } + + + attachingNode.AddChild( viewNode ); + + + viewNode.Owner = this.Owner; + + var numKids = walker.NumChildren( node ); + + for ( int i = 0; i < numKids; i++ ) + { + var name = walker.GetChildReferenceName( node, i ); + CreateReferenceElement( name, walker.ChildAt( node, i ), processed, viewNode, walker ); + } + } + + void CreateReferenceStructure( ASTNode root ) + { + this.ClearFilters(); + + this.DestroyChildren(); + _nodeToView.Clear(); + _elements.Clear(); + + + var walker = new ASTReferenceWalker(); + + var processed = new HashSet<ASTNode>(); + + CreateReferenceElement( "root", root, processed, null, walker ); + + // var it = root; + // var id = 0; + + // while ( it != null ) + // { + // if ( it.IsIgnoreToken() ) + // { + // var before = it; + + // it = walker.NextNode( it ); + // this.LogInfo( "Ignoring:", before, " next:", it ); + // continue; + // } + + // var viewNode = it.CreateViewNode(); + // var references = new List<string>(); + + + + // var numKids = walker.NumChildren( it ); + // var parentName = walker.GetParentReferenceName( it ); + + // this.LogInfo( viewNode.Name, parentName, numKids ); + + // viewNode.Name = walker.GetParentReferenceName( it ) + " " + viewNode.Name +" (" + id + ")"; + // id ++; + // Node parentNode = it == root ? this : _nodeToView[ it.parent ]; + + // parentNode.AddChild( viewNode ); + + // if ( viewNode is ASTViewElement el ) + // { + // _elements.Add( el ); + // } + + // _nodeToView[ it ] = viewNode; + + // viewNode.Owner = Owner; + // it = walker.NextNode( it ); + // } + + // _elements.ForEach( + // ( e )=> + // { + // var references = ReflectionHelper.GetFieldInfosOfType<ASTNode>( e.astNodeReference ); + // references.ForEach( + // r => + // { + // // if ( r.Name == "parent" ) + // // { + // // return; + // // } + + // var nodeRef = new ASTViewNodeReference(); + // nodeRef.name = r.Name; + + // var node = r.GetValue( e.astNodeReference ) as ASTNode; + // var viewNode = _nodeToView[ node ]; + // nodeRef.node = e.GetPathTo( viewNode ); + + // e.references = e.references.Add( nodeRef ); + // } + // ); + // } + // ); + } + + void CreateTreeStructure( ASTNode root ) + { + this.ClearFilters(); + + this.DestroyChildren(); + _nodeToView.Clear(); + _elements.Clear(); + + + var walker = new ASTWalker(); + + var it = root; + var id = 0; + + while ( it != null ) + { + if ( it.IsIgnoreToken() ) + { + it = walker.NextNode( it ); + continue; + } + + var viewNode = it.CreateViewNode(); + viewNode.Name += " (" + id + ")"; + id ++; + Node parentNode = it == root ? this : _nodeToView[ it.parent ]; + + parentNode.AddChild( viewNode ); + + if ( viewNode is ASTViewElement el ) + { + _elements.Add( el ); + } + + _nodeToView[ it ] = viewNode; + + viewNode.Owner = Owner; + it = walker.NextNode( it ); + } + + _elements.ForEach( + ( e )=> + { + var references = ReflectionHelper.GetFieldInfosOfType<ASTNode>( e.astNodeReference ); + references.ForEach( + r => + { + // if ( r.Name == "parent" ) + // { + // return; + // } + + var nodeRef = new ASTViewNodeReference(); + nodeRef.name = r.Name; + + var node = r.GetValue( e.astNodeReference ) as ASTNode; + var viewNode = _nodeToView[ node ]; + nodeRef.node = e.GetPathTo( viewNode ); + + e.references = e.references.Add( nodeRef ); + } + ); + } + ); + } + +} \ No newline at end of file diff --git a/Runtime/Text/Parsing/AST/Debug/ASTViewContext.cs.uid b/Runtime/Text/Parsing/AST/Debug/ASTViewContext.cs.uid new file mode 100644 index 0000000..f11467a --- /dev/null +++ b/Runtime/Text/Parsing/AST/Debug/ASTViewContext.cs.uid @@ -0,0 +1 @@ +uid://mj8247c4u8xo diff --git a/Runtime/Text/Parsing/AST/Debug/ASTViewElement.cs b/Runtime/Text/Parsing/AST/Debug/ASTViewElement.cs new file mode 100644 index 0000000..92cb11c --- /dev/null +++ b/Runtime/Text/Parsing/AST/Debug/ASTViewElement.cs @@ -0,0 +1,51 @@ +using System.Collections; +using System.Collections.Generic; +using System.Text.RegularExpressions; +using System.Text; + +using System.Globalization; +using Godot; +using System; + +namespace Rokojori; + +[Tool, Icon("res://addons/rokojori_action_library/Icons/ASTViewElement.svg")] +public partial class ASTViewElement:ASTViewNode +{ + [Export] + public ASTViewNodeReference[] references = []; + + + List<ASTViewNode> originalNodes; + + + public override void UpdateFromViewContext( ASTViewContext context ) + { + if ( originalNodes == null ) + { + originalNodes = this.GetDirectChildren<ASTViewNode>(); + // this.LogInfo( "Grabbed children:", originalNodes.Count ); + } + + var removalNodes = new List<Node>(); + + originalNodes.ForEach( + n => + { + if ( n.astNodeReference is Token && context.hideTokens ) + { + removalNodes.Add( n ); + } + } + ); + + removalNodes.ForEach( + ( n )=> + { + RemoveChild( n ); + } + ); + + } + +} \ No newline at end of file diff --git a/Runtime/Text/Parsing/AST/Debug/ASTViewElement.cs.uid b/Runtime/Text/Parsing/AST/Debug/ASTViewElement.cs.uid new file mode 100644 index 0000000..d96ab75 --- /dev/null +++ b/Runtime/Text/Parsing/AST/Debug/ASTViewElement.cs.uid @@ -0,0 +1 @@ +uid://duaphjoad55ay diff --git a/Runtime/Text/Parsing/AST/Debug/ASTViewExpression.cs b/Runtime/Text/Parsing/AST/Debug/ASTViewExpression.cs new file mode 100644 index 0000000..2e387ee --- /dev/null +++ b/Runtime/Text/Parsing/AST/Debug/ASTViewExpression.cs @@ -0,0 +1,16 @@ +using System.Collections; +using System.Collections.Generic; +using System.Text.RegularExpressions; +using System.Text; + +using System.Globalization; +using Godot; +using System; + +namespace Rokojori; + +[Tool, Icon("res://addons/rokojori_action_library/Icons/ASTViewExpression.svg")] +public partial class ASTViewExpression:ASTViewElement +{ + +} \ No newline at end of file diff --git a/Runtime/Text/Parsing/AST/Debug/ASTViewExpression.cs.uid b/Runtime/Text/Parsing/AST/Debug/ASTViewExpression.cs.uid new file mode 100644 index 0000000..c3a2532 --- /dev/null +++ b/Runtime/Text/Parsing/AST/Debug/ASTViewExpression.cs.uid @@ -0,0 +1 @@ +uid://blesadf7ul1pb diff --git a/Runtime/Text/Parsing/AST/Debug/ASTViewIgnoreToken.cs b/Runtime/Text/Parsing/AST/Debug/ASTViewIgnoreToken.cs new file mode 100644 index 0000000..d7d2893 --- /dev/null +++ b/Runtime/Text/Parsing/AST/Debug/ASTViewIgnoreToken.cs @@ -0,0 +1,15 @@ +using System.Collections; +using System.Collections.Generic; +using System.Text.RegularExpressions; +using System.Text; + +using System.Globalization; +using Godot; +using System; + +namespace Rokojori; + +[Tool, Icon("res://addons/rokojori_action_library/Icons/ASTViewIgnoreToken.svg")] +public partial class ASTViewIgnoreToken: ASTViewToken +{ +} \ No newline at end of file diff --git a/Runtime/Text/Parsing/AST/Debug/ASTViewIgnoreToken.cs.uid b/Runtime/Text/Parsing/AST/Debug/ASTViewIgnoreToken.cs.uid new file mode 100644 index 0000000..59e2027 --- /dev/null +++ b/Runtime/Text/Parsing/AST/Debug/ASTViewIgnoreToken.cs.uid @@ -0,0 +1 @@ +uid://dpxl5ulh7ebnm diff --git a/Runtime/Text/Parsing/AST/Debug/ASTViewLogicToken.cs b/Runtime/Text/Parsing/AST/Debug/ASTViewLogicToken.cs new file mode 100644 index 0000000..4acb16d --- /dev/null +++ b/Runtime/Text/Parsing/AST/Debug/ASTViewLogicToken.cs @@ -0,0 +1,15 @@ +using System.Collections; +using System.Collections.Generic; +using System.Text.RegularExpressions; +using System.Text; + +using System.Globalization; +using Godot; +using System; + +namespace Rokojori; + +[Tool, Icon("res://addons/rokojori_action_library/Icons/ASTViewLogicToken.svg")] +public partial class ASTViewLogicToken: ASTViewToken +{ +} \ No newline at end of file diff --git a/Runtime/Text/Parsing/AST/Debug/ASTViewLogicToken.cs.uid b/Runtime/Text/Parsing/AST/Debug/ASTViewLogicToken.cs.uid new file mode 100644 index 0000000..46a3455 --- /dev/null +++ b/Runtime/Text/Parsing/AST/Debug/ASTViewLogicToken.cs.uid @@ -0,0 +1 @@ +uid://gm0ntnqork55 diff --git a/Runtime/Text/Parsing/AST/Debug/ASTViewMember.cs b/Runtime/Text/Parsing/AST/Debug/ASTViewMember.cs new file mode 100644 index 0000000..bf80458 --- /dev/null +++ b/Runtime/Text/Parsing/AST/Debug/ASTViewMember.cs @@ -0,0 +1,17 @@ +using System.Collections; +using System.Collections.Generic; +using System.Text.RegularExpressions; +using System.Text; + +using System.Globalization; +using Godot; +using System; + +namespace Rokojori; + +[Tool, Icon("res://addons/rokojori_action_library/Icons/ASTViewMember.svg")] +public partial class ASTViewMember:ASTViewElement +{ + [Export] + public string memberName; +} \ No newline at end of file diff --git a/Runtime/Text/Parsing/AST/Debug/ASTViewMember.cs.uid b/Runtime/Text/Parsing/AST/Debug/ASTViewMember.cs.uid new file mode 100644 index 0000000..c85397a --- /dev/null +++ b/Runtime/Text/Parsing/AST/Debug/ASTViewMember.cs.uid @@ -0,0 +1 @@ +uid://cbdpgoxkdef7n diff --git a/Runtime/Text/Parsing/AST/Debug/ASTViewNode.cs b/Runtime/Text/Parsing/AST/Debug/ASTViewNode.cs new file mode 100644 index 0000000..08dcd6d --- /dev/null +++ b/Runtime/Text/Parsing/AST/Debug/ASTViewNode.cs @@ -0,0 +1,25 @@ +using System.Collections; +using System.Collections.Generic; +using System.Text.RegularExpressions; +using System.Text; + +using System.Globalization; +using Godot; +using System; + +namespace Rokojori; + +[Tool] +public abstract partial class ASTViewNode:Node +{ + [Export] + public string astNodeType; + + public ASTNode astNodeReference; + + public virtual void UpdateFromViewContext( ASTViewContext context ) + { + + } + +} \ No newline at end of file diff --git a/Runtime/Text/Parsing/AST/Debug/ASTViewNode.cs.uid b/Runtime/Text/Parsing/AST/Debug/ASTViewNode.cs.uid new file mode 100644 index 0000000..6fe8f17 --- /dev/null +++ b/Runtime/Text/Parsing/AST/Debug/ASTViewNode.cs.uid @@ -0,0 +1 @@ +uid://bwwarqqq0sy8f diff --git a/Runtime/Text/Parsing/AST/Debug/ASTViewNodeReference.cs b/Runtime/Text/Parsing/AST/Debug/ASTViewNodeReference.cs new file mode 100644 index 0000000..89f3136 --- /dev/null +++ b/Runtime/Text/Parsing/AST/Debug/ASTViewNodeReference.cs @@ -0,0 +1,20 @@ +using System.Collections; +using System.Collections.Generic; +using System.Text.RegularExpressions; +using System.Text; + +using System.Globalization; +using Godot; +using System; + +namespace Rokojori; + +[Tool] +public partial class ASTViewNodeReference:Resource +{ + [Export] + public string name; + + [Export] + public NodePath node; +} \ No newline at end of file diff --git a/Runtime/Text/Parsing/AST/Debug/ASTViewNodeReference.cs.uid b/Runtime/Text/Parsing/AST/Debug/ASTViewNodeReference.cs.uid new file mode 100644 index 0000000..4cfa079 --- /dev/null +++ b/Runtime/Text/Parsing/AST/Debug/ASTViewNodeReference.cs.uid @@ -0,0 +1 @@ +uid://dmojbxb76nklf diff --git a/Runtime/Text/Parsing/AST/Debug/ASTViewObject.cs b/Runtime/Text/Parsing/AST/Debug/ASTViewObject.cs new file mode 100644 index 0000000..7381c62 --- /dev/null +++ b/Runtime/Text/Parsing/AST/Debug/ASTViewObject.cs @@ -0,0 +1,16 @@ +using System.Collections; +using System.Collections.Generic; +using System.Text.RegularExpressions; +using System.Text; + +using System.Globalization; +using Godot; +using System; + +namespace Rokojori; + +[Tool, Icon("res://addons/rokojori_action_library/Icons/ASTViewObject.svg")] +public partial class ASTViewObject:ASTViewElement +{ + +} \ No newline at end of file diff --git a/Runtime/Text/Parsing/AST/Debug/ASTViewObject.cs.uid b/Runtime/Text/Parsing/AST/Debug/ASTViewObject.cs.uid new file mode 100644 index 0000000..1d7e04d --- /dev/null +++ b/Runtime/Text/Parsing/AST/Debug/ASTViewObject.cs.uid @@ -0,0 +1 @@ +uid://c6vg57y73dsaj diff --git a/Runtime/Text/Parsing/AST/Debug/ASTViewOperatorToken.cs b/Runtime/Text/Parsing/AST/Debug/ASTViewOperatorToken.cs new file mode 100644 index 0000000..2343bdd --- /dev/null +++ b/Runtime/Text/Parsing/AST/Debug/ASTViewOperatorToken.cs @@ -0,0 +1,15 @@ +using System.Collections; +using System.Collections.Generic; +using System.Text.RegularExpressions; +using System.Text; + +using System.Globalization; +using Godot; +using System; + +namespace Rokojori; + +[Tool, Icon("res://addons/rokojori_action_library/Icons/ASTViewOperatorToken.svg")] +public partial class ASTViewOperatorToken: ASTViewToken +{ +} \ No newline at end of file diff --git a/Runtime/Text/Parsing/AST/Debug/ASTViewOperatorToken.cs.uid b/Runtime/Text/Parsing/AST/Debug/ASTViewOperatorToken.cs.uid new file mode 100644 index 0000000..66fe3d4 --- /dev/null +++ b/Runtime/Text/Parsing/AST/Debug/ASTViewOperatorToken.cs.uid @@ -0,0 +1 @@ +uid://ceb3clbln6hj7 diff --git a/Runtime/Text/Parsing/AST/Debug/ASTViewRoot.cs b/Runtime/Text/Parsing/AST/Debug/ASTViewRoot.cs new file mode 100644 index 0000000..a2a8ea8 --- /dev/null +++ b/Runtime/Text/Parsing/AST/Debug/ASTViewRoot.cs @@ -0,0 +1,15 @@ +using System.Collections; +using System.Collections.Generic; +using System.Text.RegularExpressions; +using System.Text; + +using System.Globalization; +using Godot; +using System; + +namespace Rokojori; + +[Tool, Icon("res://addons/rokojori_action_library/Icons/ASTViewRoot.svg")] +public partial class ASTViewRoot:ASTViewElement +{ +} \ No newline at end of file diff --git a/Runtime/Text/Parsing/AST/Debug/ASTViewRoot.cs.uid b/Runtime/Text/Parsing/AST/Debug/ASTViewRoot.cs.uid new file mode 100644 index 0000000..75e2ab6 --- /dev/null +++ b/Runtime/Text/Parsing/AST/Debug/ASTViewRoot.cs.uid @@ -0,0 +1 @@ +uid://dw5wntaroqkip diff --git a/Runtime/Text/Parsing/AST/Debug/ASTViewStatement.cs b/Runtime/Text/Parsing/AST/Debug/ASTViewStatement.cs new file mode 100644 index 0000000..4cd6fee --- /dev/null +++ b/Runtime/Text/Parsing/AST/Debug/ASTViewStatement.cs @@ -0,0 +1,16 @@ +using System.Collections; +using System.Collections.Generic; +using System.Text.RegularExpressions; +using System.Text; + +using System.Globalization; +using Godot; +using System; + +namespace Rokojori; + +[Tool, Icon("res://addons/rokojori_action_library/Icons/ASTViewStatement.svg")] +public partial class ASTViewStatement:ASTViewElement +{ + +} \ No newline at end of file diff --git a/Runtime/Text/Parsing/AST/Debug/ASTViewStatement.cs.uid b/Runtime/Text/Parsing/AST/Debug/ASTViewStatement.cs.uid new file mode 100644 index 0000000..7dde1fe --- /dev/null +++ b/Runtime/Text/Parsing/AST/Debug/ASTViewStatement.cs.uid @@ -0,0 +1 @@ +uid://cyurgwe2nq4xq diff --git a/Runtime/Text/Parsing/AST/Debug/ASTViewToken.cs b/Runtime/Text/Parsing/AST/Debug/ASTViewToken.cs new file mode 100644 index 0000000..6cf4d0e --- /dev/null +++ b/Runtime/Text/Parsing/AST/Debug/ASTViewToken.cs @@ -0,0 +1,30 @@ +using System.Collections; +using System.Collections.Generic; +using System.Text.RegularExpressions; +using System.Text; + +using System.Globalization; +using Godot; +using System; + +namespace Rokojori; + +[Tool, Icon("res://addons/rokojori_action_library/Icons/ASTViewToken.svg")] +public partial class ASTViewToken: ASTViewNode +{ + [Export] + public string tokenType; + + [Export] + public string match; + + [Export] + public int characterOffset; + + [Export] + public int line; + + [Export] + public int lineOffset; + +} \ No newline at end of file diff --git a/Runtime/Text/Parsing/AST/Debug/ASTViewToken.cs.uid b/Runtime/Text/Parsing/AST/Debug/ASTViewToken.cs.uid new file mode 100644 index 0000000..5e042e5 --- /dev/null +++ b/Runtime/Text/Parsing/AST/Debug/ASTViewToken.cs.uid @@ -0,0 +1 @@ +uid://dm77biqwbp4fc diff --git a/Runtime/Text/Parsing/AST/Debug/ASTViewWordToken.cs b/Runtime/Text/Parsing/AST/Debug/ASTViewWordToken.cs new file mode 100644 index 0000000..aa48aeb --- /dev/null +++ b/Runtime/Text/Parsing/AST/Debug/ASTViewWordToken.cs @@ -0,0 +1,15 @@ +using System.Collections; +using System.Collections.Generic; +using System.Text.RegularExpressions; +using System.Text; + +using System.Globalization; +using Godot; +using System; + +namespace Rokojori; + +[Tool, Icon("res://addons/rokojori_action_library/Icons/ASTViewWordToken.svg")] +public partial class ASTViewWordToken: ASTViewToken +{ +} \ No newline at end of file diff --git a/Runtime/Text/Parsing/AST/Debug/ASTViewWordToken.cs.uid b/Runtime/Text/Parsing/AST/Debug/ASTViewWordToken.cs.uid new file mode 100644 index 0000000..b6e7c76 --- /dev/null +++ b/Runtime/Text/Parsing/AST/Debug/ASTViewWordToken.cs.uid @@ -0,0 +1 @@ +uid://cxfsprsr12ker diff --git a/Runtime/Text/Parsing/AST/Matchers/ASTMatchResult.cs b/Runtime/Text/Parsing/AST/Matchers/ASTMatchResult.cs index d0ea560..05b552f 100644 --- a/Runtime/Text/Parsing/AST/Matchers/ASTMatchResult.cs +++ b/Runtime/Text/Parsing/AST/Matchers/ASTMatchResult.cs @@ -34,6 +34,8 @@ public class ASTMatchResult matched = true; } + + public int matchLength => ( resultEnd - resultStart ) + 1; @@ -51,5 +53,14 @@ public class ASTMatchResult return c; } + public void CopyFrom( ASTMatchResult other ) + { + parent = other.parent; + childOffset = other.childOffset; + resultStart = other.resultStart; + resultEnd = other.resultEnd; + matched = other.matched; + } + } diff --git a/Runtime/Text/Parsing/AST/Matchers/NotIgnoreNodeMatcher.cs b/Runtime/Text/Parsing/AST/Matchers/NotIgnoreNodeMatcher.cs new file mode 100644 index 0000000..a608527 --- /dev/null +++ b/Runtime/Text/Parsing/AST/Matchers/NotIgnoreNodeMatcher.cs @@ -0,0 +1,28 @@ +using System.Collections; +using System.Collections.Generic; +using System.Text.RegularExpressions; +using System.Text; + +using System.Globalization; +using Godot; +using System; + +namespace Rokojori; + +public class NotIgnoreNodeMatcher:ASTMatcher +{ + public override void Match( ASTMatchResult result ) + { + var parent = result.parent; + var searchOffset = result.childOffset; + var node = parent.children[ searchOffset ]; + + if ( node.IsIgnoreToken() ) + { + return; + } + + result.SetMatched( node.childIndex ); + + } +} diff --git a/Runtime/Text/Parsing/AST/Matchers/NotIgnoreNodeMatcher.cs.uid b/Runtime/Text/Parsing/AST/Matchers/NotIgnoreNodeMatcher.cs.uid new file mode 100644 index 0000000..b2645da --- /dev/null +++ b/Runtime/Text/Parsing/AST/Matchers/NotIgnoreNodeMatcher.cs.uid @@ -0,0 +1 @@ +uid://dnchqhhc46n13 diff --git a/Runtime/Text/Parsing/AST/Matchers/TokenMatcher.cs b/Runtime/Text/Parsing/AST/Matchers/TokenMatcher.cs new file mode 100644 index 0000000..0e98594 --- /dev/null +++ b/Runtime/Text/Parsing/AST/Matchers/TokenMatcher.cs @@ -0,0 +1,28 @@ +using System.Collections; +using System.Collections.Generic; +using System.Text.RegularExpressions; +using System.Text; + +using System.Globalization; +using Godot; +using System; + +namespace Rokojori; + +public class TokenMatcher:ASTMatcher +{ + public TokenPredicateData matchData; + + public override void Match( ASTMatchResult result ) + { + var parent = result.parent; + var searchOffset = result.childOffset; + var node = parent.children[ searchOffset ]; + + if ( matchData.Matches( node ) ) + { + result.SetMatched( node.childIndex ); + } + + } +} diff --git a/Runtime/Text/Parsing/AST/Matchers/TokenMatcher.cs.uid b/Runtime/Text/Parsing/AST/Matchers/TokenMatcher.cs.uid new file mode 100644 index 0000000..b603c43 --- /dev/null +++ b/Runtime/Text/Parsing/AST/Matchers/TokenMatcher.cs.uid @@ -0,0 +1 @@ +uid://cq2mxjoy6p5im diff --git a/Runtime/Text/Parsing/AST/Resolver/ASTParser.cs b/Runtime/Text/Parsing/AST/Resolver/ASTParser.cs index 5f2167d..a5accfa 100644 --- a/Runtime/Text/Parsing/AST/Resolver/ASTParser.cs +++ b/Runtime/Text/Parsing/AST/Resolver/ASTParser.cs @@ -18,19 +18,19 @@ public class ASTParser public void Process() { - var result = Resolve(); + var result = ResolveAll(); var steps = 0; while ( result && steps < maxSteps) { RJLog.Log( "Step", steps ); - result = Resolve(); + result = ResolveAll(); steps ++; } } - bool Resolve() + bool ResolveAll() { var hasResult = false; @@ -47,39 +47,87 @@ public class ASTParser matchResult.childOffset = tokenOffset; matchResult.parent = root; - for ( int resolverIndex = 0; resolverIndex < resolvers.Count; resolverIndex++ ) - { - var matcherResolver = resolvers[ resolverIndex ]; - matcherResolver.matcher.Match( matchResult ); + var nextTokenOffset = ResolveNext( matchResult ); - if ( ! matchResult.matched ) - { - // RJLog.Log( ">>> Not Matched:", resolverIndex, matcherResolver.matcher, matcherResolver ); - - continue; - } - - RJLog.Log( ">>> Matched:", resolverIndex, matcherResolver.matcher, matcherResolver ); - - if ( root.children[ tokenOffset ] is Token tk ) - { - RJLog.Log( "...", tk.lineInfo ); - } - - var resolvedOffset = matcherResolver.Resolve( matchResult, matcherResolver.matcher ); - tokenOffset = resolvedOffset; - + if ( nextTokenOffset != -1 ) + { hasResult = true; - resolverIndex = resolvers.Count; - - // RJLog.Log( "Matched:", matcherIndex, matcherResolver.matcher, matcherResolver ); - //return true; + tokenOffset = nextTokenOffset; } + + // for ( int resolverIndex = 0; resolverIndex < resolvers.Count; resolverIndex++ ) + // { + // var matcherResolver = resolvers[ resolverIndex ]; + // matcherResolver.matcher.Match( matchResult ); + + // if ( ! matchResult.matched ) + // { + // // RJLog.Log( ">>> Not Matched:", resolverIndex, matcherResolver.matcher, matcherResolver ); + + // continue; + // } + + // RJLog.Log( ">>> Matched:", resolverIndex, matcherResolver.matcher, matcherResolver ); + + // if ( root.children[ tokenOffset ] is Token tk ) + // { + // RJLog.Log( "...", tk.lineInfo ); + // } + + // var resolvedOffset = matcherResolver.Resolve( matchResult, matcherResolver.matcher ); + // tokenOffset = resolvedOffset; + + // hasResult = true; + // resolverIndex = resolvers.Count; + + // // RJLog.Log( "Matched:", matcherIndex, matcherResolver.matcher, matcherResolver ); + // //return true; + // } } return hasResult; } + + public int ResolveNext( ASTMatchResult matchResult, bool debug = false ) + { + var originalResult = matchResult.Clone(); + + for ( int resolverIndex = 0; resolverIndex < resolvers.Count; resolverIndex++ ) + { + var matcherResolver = resolvers[ resolverIndex ]; + matcherResolver.matcher.Match( matchResult ); + + if ( ! matchResult.matched ) + { + if ( debug ) + { + var token = matchResult.parent.children[ matchResult.childOffset ] as Token; + RJLog.Log( ">>> Not Matched:", resolverIndex, matcherResolver.matcher, matcherResolver, "at:", token, token?.lineInfo ); + } + continue; + } + + if ( debug ) + { + RJLog.Log( ">>> Matched:", resolverIndex, matcherResolver.matcher, matcherResolver ); + } + + var resolvedOffset = matcherResolver.Resolve( matchResult, matcherResolver.matcher ); + + if ( resolvedOffset == -1 ) + { + matchResult.CopyFrom( originalResult ); + continue; + } + + return resolvedOffset; + + } + + return -1; + } + // bool ResolveOld() // { // var hasResult = false; diff --git a/Runtime/Text/Parsing/AST/Token.cs b/Runtime/Text/Parsing/AST/Token.cs index fa6893e..dd27fc0 100644 --- a/Runtime/Text/Parsing/AST/Token.cs +++ b/Runtime/Text/Parsing/AST/Token.cs @@ -69,6 +69,50 @@ public class Token:ASTNode return lexerEvent.Is( matcher.type, match ); } + public override ASTViewNode CreateViewNode() + { + LexerMatcher[] wordLike = + [ + LexerMatcherLibrary.CwordMatcher, + LexerMatcherLibrary.CFunctionMatcher, + LexerMatcherLibrary.UsingMatcher, + + LexerMatcherLibrary.AccessModifierMatcher, + LexerMatcherLibrary.CSAccessModifierMatcher, + LexerMatcherLibrary.ClassMatcher, + LexerMatcherLibrary.RecordMatcher, + LexerMatcherLibrary.StructMatcher, + LexerMatcherLibrary.InterfaceMatcher, + LexerMatcherLibrary.EnumMatcher, + ]; + + LexerMatcher[] constants = + [ + LexerMatcherLibrary.BoolMatcher, + LexerMatcherLibrary.SingleQuotedStringMatcher, + LexerMatcherLibrary.DoubleQuotedStringMatcher, + LexerMatcherLibrary.NumberMatcher, + LexerMatcherLibrary.NullMatcher + ]; + + + var viewNode = IsIgnoreToken() ? new ASTViewIgnoreToken() : + IsAnyTokenOf( wordLike ) ? new ASTViewWordToken() : + IsAnyTokenOf( constants ) ? new ASTViewConstantToken() : + IsToken( LexerMatcherLibrary.LogicMatcher ) ? new ASTViewLogicToken() : + IsToken( LexerMatcherLibrary.BracketMatcher ) ? new ASTViewBracketToken() : + IsToken( LexerMatcherLibrary.OperatorMatcher ) ? new ASTViewOperatorToken() : + new ASTViewToken(); + viewNode.astNodeReference = this; + viewNode.astNodeType = GetType().Name; + viewNode.tokenType = type; + viewNode.match = match; + viewNode.characterOffset = lexerEvent.offset; + viewNode.Name = "Token " + type + " '" + match + "'"; + + + return viewNode; + } ASTFileRoot _root; @@ -82,7 +126,8 @@ public class Token:ASTNode } var textLine = _root.GetTextLinesMapper().GetLine( lexerEvent.offset ); - return "[ " + textLine.textEditorLineIndex + " ] | " + textLine.GetContent( _root.GetSource() ); + var anchor = _root.GetTextLinesMapper().GetAnchor( lexerEvent.offset, true ); + return "[ " + anchor.lineIndex + ":" + anchor.characterIndex + " ] | " + textLine.GetContent( _root.GetSource() ); } } diff --git a/Runtime/Text/Parsing/AST/TokenPredicateData.cs b/Runtime/Text/Parsing/AST/TokenPredicateData.cs index 7fd1837..687b9ed 100644 --- a/Runtime/Text/Parsing/AST/TokenPredicateData.cs +++ b/Runtime/Text/Parsing/AST/TokenPredicateData.cs @@ -12,9 +12,11 @@ namespace Rokojori; public class TokenPredicateData { + public string type; public string match; + public bool Matches( ASTNode node ) { return node.IsToken( type, match ); @@ -42,4 +44,39 @@ public class TokenPredicateData var lexedSequence = Token.CreateLexedSequenceData( lexer, value ); return lexedSequence[ 0 ]; } + + public static readonly List<TokenPredicateData> Semicolon = [ + TokenPredicateData.Create( + LexerMatcherLibrary.OperatorMatcher.type, ";" + ), + ]; + + public static readonly List<TokenPredicateData> BlockPredicates = [ + + TokenPredicateData.Create( + LexerMatcherLibrary.BracketMatcher.type, "(" + ), + + TokenPredicateData.Create( + LexerMatcherLibrary.BracketMatcher.type, ")" + ), + + + TokenPredicateData.Create( + LexerMatcherLibrary.BracketMatcher.type, "{" + ), + + TokenPredicateData.Create( + LexerMatcherLibrary.BracketMatcher.type, "{" + ), + + + TokenPredicateData.Create( + LexerMatcherLibrary.BracketMatcher.type, "[" + ), + + TokenPredicateData.Create( + LexerMatcherLibrary.BracketMatcher.type, "]" + ) + ]; } diff --git a/Runtime/Text/Parsing/Expressions/ExpressionParser.cs b/Runtime/Text/Parsing/Expressions/ExpressionParser.cs index dbcf1f5..b0dc82c 100644 --- a/Runtime/Text/Parsing/Expressions/ExpressionParser.cs +++ b/Runtime/Text/Parsing/Expressions/ExpressionParser.cs @@ -12,8 +12,18 @@ public class ExpressionParser:ParserPhase ProcessExpression( parser.root ); } - public void ProcessExpression( ASTNode expressionParent ) + public void ProcessExpression( ASTNode expressionParent, bool checkEmpty = true ) { + if ( expressionParent == null ) + { + return; + } + + if ( checkEmpty && expressionParent.IsEmptyOrIgnore() ) + { + return; + } + var parser = expressionParent.parser; for ( int i = 0; i < levels.Count; i++ ) diff --git a/Runtime/Text/Parsing/Expressions/Operators/ArrayExpression.cs b/Runtime/Text/Parsing/Expressions/Operators/ArrayExpression.cs new file mode 100644 index 0000000..846f51b --- /dev/null +++ b/Runtime/Text/Parsing/Expressions/Operators/ArrayExpression.cs @@ -0,0 +1,49 @@ +using System.Collections.Generic; +using System.Linq; + +namespace Rokojori; + +public interface IArrayExpression:OperatorExpression +{ + public void InitializeArrayExpression( ASTNode caller, Token leftBracket, ASTNode indexExpression, Token rightBracket ); + public ASTNode GetCallerExpression(); + public Token GetLeftBracket(); + public ASTNode GetIndexExpression(); + public Token GetRightBracket(); +} + +public class ArrayExpression:ASTNode,IArrayExpression +{ + public ASTNode caller; + public Token leftBracket; + public ASTNode indexExpression; + public Token rightBracket; + + public void InitializeArrayExpression( ASTNode caller, Token leftBracket, ASTNode indexExpression, Token rightBracket ) + { + this.caller = caller; + this.leftBracket = leftBracket; + this.indexExpression = indexExpression; + this.rightBracket = rightBracket; + } + + public ASTNode GetCallerExpression() + { + return caller; + } + + public Token GetLeftBracket() + { + return leftBracket; + } + + public ASTNode GetIndexExpression() + { + return indexExpression; + } + + public Token GetRightBracket() + { + return rightBracket; + } +} \ No newline at end of file diff --git a/Runtime/Text/Parsing/Expressions/Operators/ArrayExpression.cs.uid b/Runtime/Text/Parsing/Expressions/Operators/ArrayExpression.cs.uid new file mode 100644 index 0000000..461a598 --- /dev/null +++ b/Runtime/Text/Parsing/Expressions/Operators/ArrayExpression.cs.uid @@ -0,0 +1 @@ +uid://hxennrht20l0 diff --git a/Runtime/Text/Parsing/Expressions/Operators/ArrayOperator.cs b/Runtime/Text/Parsing/Expressions/Operators/ArrayOperator.cs new file mode 100644 index 0000000..dbcb9a3 --- /dev/null +++ b/Runtime/Text/Parsing/Expressions/Operators/ArrayOperator.cs @@ -0,0 +1,43 @@ +using System.Collections.Generic; +using System.Linq; + +namespace Rokojori; + +public class ArrayOperator<T>:ExpressionOperator where T:ASTNode,IArrayExpression, new() +{ + bool _fromLeft = false; + TokenPredicateData endTokenPredicate; + + public ArrayOperator() + { + startTokenPredicate = TokenPredicateData.Create( LexerMatcherLibrary.BracketMatcher.type, "[" ); + endTokenPredicate = TokenPredicateData.Create( LexerMatcherLibrary.BracketMatcher.type, "]" ); + } + + public override bool IsFromLeft() + { + return _fromLeft; + } + + public override bool ProcessStartNode( ASTNode parent, int startChildIndex ) + { + var callerIndex = parent.PreviousIndex( startChildIndex ); + + var closingIndex = parent.FindBracketCloserIndex( "[" , "]", startChildIndex ); + + if ( callerIndex < 0 || closingIndex == -1 ) + { + parent.parser.AddError( "Could not find caller expressions for " + this + " in parent:" + parent + " child start: " + startChildIndex ); + return false; + } + + var caller = parent.children[ callerIndex ]; + var leftBracket = parent.children[ startChildIndex ] as Token; + var rightBracket = parent.children[ closingIndex ] as Token; + + var arrayExpression = parent.MergeOuter<T>( caller, rightBracket ); + var indexExpression = arrayExpression.MergeInner<ASTNodeList>( leftBracket, rightBracket ); + arrayExpression.InitializeArrayExpression( caller, leftBracket, indexExpression, rightBracket ); + return true; + } +} \ No newline at end of file diff --git a/Runtime/Text/Parsing/Expressions/Operators/ArrayOperator.cs.uid b/Runtime/Text/Parsing/Expressions/Operators/ArrayOperator.cs.uid new file mode 100644 index 0000000..443c131 --- /dev/null +++ b/Runtime/Text/Parsing/Expressions/Operators/ArrayOperator.cs.uid @@ -0,0 +1 @@ +uid://md8g11odugrx diff --git a/Runtime/Text/Parsing/Expressions/Operators/ExpressionOperator.cs b/Runtime/Text/Parsing/Expressions/Operators/ExpressionOperator.cs index dc5ce79..cf783dd 100644 --- a/Runtime/Text/Parsing/Expressions/Operators/ExpressionOperator.cs +++ b/Runtime/Text/Parsing/Expressions/Operators/ExpressionOperator.cs @@ -6,6 +6,7 @@ namespace Rokojori; public abstract class ExpressionOperator { public TokenPredicateData startTokenPredicate; + // public ExpressionParser expressionParser; public virtual bool IsFromLeft() { diff --git a/Runtime/Text/Parsing/Expressions/Operators/FunctionExpression.cs b/Runtime/Text/Parsing/Expressions/Operators/FunctionExpression.cs new file mode 100644 index 0000000..f29298e --- /dev/null +++ b/Runtime/Text/Parsing/Expressions/Operators/FunctionExpression.cs @@ -0,0 +1,33 @@ +using System.Collections.Generic; +using System.Linq; + +namespace Rokojori; + +public interface IFunctionExpression:OperatorExpression +{ + public void InitializeFunctionExpression( Token name, GroupExpression group ); + public Token GetFunctionName(); + public GroupExpression GetFunctionGroup(); +} + +public class FunctionExpression:ASTNode,IFunctionExpression +{ + public Token functionName; + public GroupExpression functionGroup; + + public void InitializeFunctionExpression( Token name, GroupExpression group ) + { + this.functionName = name; + this.functionGroup = group; + } + + public Token GetFunctionName() + { + return functionName; + } + + public GroupExpression GetFunctionGroup() + { + return functionGroup; + } +} diff --git a/Runtime/Text/Parsing/Expressions/Operators/FunctionExpression.cs.uid b/Runtime/Text/Parsing/Expressions/Operators/FunctionExpression.cs.uid new file mode 100644 index 0000000..6c9f0fe --- /dev/null +++ b/Runtime/Text/Parsing/Expressions/Operators/FunctionExpression.cs.uid @@ -0,0 +1 @@ +uid://dsrmqy8g0u1na diff --git a/Runtime/Text/Parsing/Expressions/Operators/FunctionOperator.cs b/Runtime/Text/Parsing/Expressions/Operators/FunctionOperator.cs new file mode 100644 index 0000000..de7f31c --- /dev/null +++ b/Runtime/Text/Parsing/Expressions/Operators/FunctionOperator.cs @@ -0,0 +1,31 @@ +using System.Collections.Generic; +using System.Linq; + +namespace Rokojori; + +public class FunctionOperator<T>:ExpressionOperator where T:ASTNode,IFunctionExpression, new() +{ + + public FunctionOperator() + { + startTokenPredicate = TokenPredicateData.Create( LexerMatcherLibrary.CFunctionMatcher.type ); + } + + public override bool ProcessStartNode( ASTNode parent, int startChildIndex ) + { + var next = parent.NextNode( startChildIndex ); + + if ( next == null || ! ( next is GroupExpression ) ) + { + return false; + } + + var functionName = parent.children[ startChildIndex ] as Token; + var functionGroup = next as GroupExpression; + + var functionExpression = parent.MergeOuter<T>( functionName, functionGroup ); + functionExpression.InitializeFunctionExpression( functionName, functionGroup ); + + return false; + } +} \ No newline at end of file diff --git a/Runtime/Text/Parsing/Expressions/Operators/FunctionOperator.cs.uid b/Runtime/Text/Parsing/Expressions/Operators/FunctionOperator.cs.uid new file mode 100644 index 0000000..cb78413 --- /dev/null +++ b/Runtime/Text/Parsing/Expressions/Operators/FunctionOperator.cs.uid @@ -0,0 +1 @@ +uid://bh3mwwxr8f7xm diff --git a/Runtime/Text/Parsing/Expressions/Operators/GenericFunctionExpression.cs b/Runtime/Text/Parsing/Expressions/Operators/GenericFunctionExpression.cs new file mode 100644 index 0000000..c129e0d --- /dev/null +++ b/Runtime/Text/Parsing/Expressions/Operators/GenericFunctionExpression.cs @@ -0,0 +1,41 @@ +using System.Collections.Generic; +using System.Linq; + +namespace Rokojori; + +public interface IGenericFunctionExpression:OperatorExpression +{ + public void InitializeGenericFunctionExpression( Token name, ASTNode genericType, GroupExpression group ); + public Token GetFunctionName(); + public ASTNode GetGenericType(); + public GroupExpression GetFunctionGroup(); +} + +public class GenericFunctionExpression:ASTNode,IGenericFunctionExpression +{ + public Token functionName; + public ASTNode genericType; + public GroupExpression functionGroup; + + public void InitializeGenericFunctionExpression( Token name, ASTNode genericType, GroupExpression group ) + { + this.functionName = name; + this.genericType = genericType; + this.functionGroup = group; + } + + public Token GetFunctionName() + { + return functionName; + } + + public ASTNode GetGenericType() + { + return functionName; + } + + public GroupExpression GetFunctionGroup() + { + return functionGroup; + } +} diff --git a/Runtime/Text/Parsing/Expressions/Operators/GenericFunctionExpression.cs.uid b/Runtime/Text/Parsing/Expressions/Operators/GenericFunctionExpression.cs.uid new file mode 100644 index 0000000..2b07cbc --- /dev/null +++ b/Runtime/Text/Parsing/Expressions/Operators/GenericFunctionExpression.cs.uid @@ -0,0 +1 @@ +uid://b3dbaycmkmvkh diff --git a/Runtime/Text/Parsing/Expressions/Operators/GenericFunctionOperator.cs b/Runtime/Text/Parsing/Expressions/Operators/GenericFunctionOperator.cs new file mode 100644 index 0000000..7653244 --- /dev/null +++ b/Runtime/Text/Parsing/Expressions/Operators/GenericFunctionOperator.cs @@ -0,0 +1,89 @@ +using System.Collections.Generic; +using System.Linq; + +namespace Rokojori; + +public class GenericFunctionOperator<T>:ExpressionOperator where T:ASTNode,IGenericFunctionExpression, new() +{ + public GenericFunctionOperator() + { + startTokenPredicate = TokenPredicateData.Create( LexerMatcherLibrary.CwordMatcher.type ); + } + + bool CanBeGenericType( ASTNode parent, int start, int length ) + { + List<string> tokenSymbols = [ + ".", "<", ">", "[", "]", "*", "," + ]; + + for ( int i = 0; i < length; i++ ) + { + var child = parent.children[ start + i ]; + + if ( child.IsIgnoreToken() ) + { + continue; + } + else if ( child.IsToken( LexerMatcherLibrary.CwordMatcher ) ) + { + continue; + } + else if ( child is Token tk ) + { + if ( tokenSymbols.IndexOf( tk.match ) != -1 ) + { + continue; + } + } + + + return false; + } + + return false; + } + + public override bool ProcessStartNode( ASTNode parent, int startChildIndex ) + { + var next = parent.NextNode( startChildIndex ); + + if ( next == null || ! next.IsToken( LexerMatcherLibrary.OperatorMatcher, "<" ) ) + { + return false; + } + + + var closerIndex = parent.FindBracketCloserIndex( "<", ">", next.childIndex ); + + if ( closerIndex == -1 ) + { + return false; + } + + var startIndex = next.childIndex; + var length = ( closerIndex - startIndex ) - 1; + + if ( ! CanBeGenericType( parent, startIndex + 1, length ) ) + { + return false; + } + + + + var group = parent.NextNode( closerIndex ); + + if ( group == null || ! ( group is GroupExpression ) ) + { + return false; + } + + var functionName = parent.children[ startChildIndex ] as Token; + var functionGroup = group as GroupExpression; + + var genericFunctionExpression = parent.MergeOuter<T>( functionName, functionGroup ); + var genericType = genericFunctionExpression.MergeInner<ASTNodeList>( functionName, functionGroup ); + genericFunctionExpression.InitializeGenericFunctionExpression( functionName, genericType, functionGroup ); + + return false; + } +} \ No newline at end of file diff --git a/Runtime/Text/Parsing/Expressions/Operators/GenericFunctionOperator.cs.uid b/Runtime/Text/Parsing/Expressions/Operators/GenericFunctionOperator.cs.uid new file mode 100644 index 0000000..6386ba8 --- /dev/null +++ b/Runtime/Text/Parsing/Expressions/Operators/GenericFunctionOperator.cs.uid @@ -0,0 +1 @@ +uid://dbajt0qt2oxc3 diff --git a/Runtime/Text/Parsing/Expressions/Operators/GroupOperator.cs b/Runtime/Text/Parsing/Expressions/Operators/GroupOperator.cs index a3bba34..bc65e9a 100644 --- a/Runtime/Text/Parsing/Expressions/Operators/GroupOperator.cs +++ b/Runtime/Text/Parsing/Expressions/Operators/GroupOperator.cs @@ -28,6 +28,7 @@ public class GroupOperator<T>:ExpressionOperator where T:ASTNode,IGroupExpressio var start = parent.children[ startChildIndex ]; var end = parent.children[ endIndex ]; + RJLog.Log( "Group:", start, end, startChildIndex, endIndex ); var groupBodyExpression = parent.MergeInner<ASTNodeList>( start, end ); var groupExpression = parent.MergeOuter<T>( start, end ); diff --git a/Runtime/Text/Parsing/Expressions/Operators/SeparatedSequenceExpression.cs b/Runtime/Text/Parsing/Expressions/Operators/SeparatedSequenceExpression.cs new file mode 100644 index 0000000..407686b --- /dev/null +++ b/Runtime/Text/Parsing/Expressions/Operators/SeparatedSequenceExpression.cs @@ -0,0 +1,26 @@ +using System.Collections.Generic; +using System.Linq; + +namespace Rokojori; + +public interface ISeparatedSequenceExpression:OperatorExpression +{ + public void InitializeSeparatedSequenceExpression( List<ASTNode> expressions ); + public List<ASTNode> GetExpressions(); + +} + +public class SeparatedSequenceExpression:ASTNode,ISeparatedSequenceExpression +{ + public List<ASTNode> expressions; + + public void InitializeSeparatedSequenceExpression( List<ASTNode> expressions ) + { + this.expressions = expressions; + } + + public List<ASTNode> GetExpressions() + { + return expressions; + } +} \ No newline at end of file diff --git a/Runtime/Text/Parsing/Expressions/Operators/SeparatedSequenceExpression.cs.uid b/Runtime/Text/Parsing/Expressions/Operators/SeparatedSequenceExpression.cs.uid new file mode 100644 index 0000000..f6681ed --- /dev/null +++ b/Runtime/Text/Parsing/Expressions/Operators/SeparatedSequenceExpression.cs.uid @@ -0,0 +1 @@ +uid://brh7y1ya7b4fq diff --git a/Runtime/Text/Parsing/Expressions/Operators/SeparatedSequenceOperator.cs b/Runtime/Text/Parsing/Expressions/Operators/SeparatedSequenceOperator.cs new file mode 100644 index 0000000..0f99b7b --- /dev/null +++ b/Runtime/Text/Parsing/Expressions/Operators/SeparatedSequenceOperator.cs @@ -0,0 +1,64 @@ +using System.Collections.Generic; +using System.Linq; + +namespace Rokojori; + +public class SeparatedSequenceOperator<T>:ExpressionOperator where T:ASTNode,ISeparatedSequenceExpression, new() +{ + public SeparatedSequenceOperator() + { + startTokenPredicate = TokenPredicateData.Create( LexerMatcherLibrary.OperatorMatcher.type, "," ); + } + + public override bool ProcessStartNode( ASTNode parent, int startChildIndex ) + { + var firstSeparator = parent.children[ startChildIndex ]; + var nodes = parent.children.Filter( c => ! c.IsIgnoreToken() ); + var index = nodes.IndexOf( firstSeparator ); + + if ( index != 1 ) + { + parent.parser.AddError( "Unexpected separator position. Expected 1, but got: "+ index+ " at " + parent ); + return false; + } + + List<ASTNode> expressions = []; + + for ( int i = 0; i < nodes.Count; i++ ) + { + var node = nodes[ i ]; + var indexModulo2 = i % 2; + + var shouldBeExpression = indexModulo2 == 0; + var shouldBeSeperator = indexModulo2 == 1; + + var isSeparator = startTokenPredicate.Matches( node ); + + if ( shouldBeSeperator && ! isSeparator ) + { + parent.parser.AddError( "Expected separator" ); + return false; + } + else if ( shouldBeExpression && isSeparator ) + { + parent.parser.AddError( "Expected separator" ); + return false; + } + + if ( shouldBeSeperator ) + { + continue; + } + + expressions.Add( node ); + + } + + var sequence = parent.MergeOuter<T>( nodes[ 0 ], nodes.Last() ); + sequence.InitializeSeparatedSequenceExpression( expressions ); + + return true; + } + + +} \ No newline at end of file diff --git a/Runtime/Text/Parsing/Expressions/Operators/SeparatedSequenceOperator.cs.uid b/Runtime/Text/Parsing/Expressions/Operators/SeparatedSequenceOperator.cs.uid new file mode 100644 index 0000000..3f599df --- /dev/null +++ b/Runtime/Text/Parsing/Expressions/Operators/SeparatedSequenceOperator.cs.uid @@ -0,0 +1 @@ +uid://dcq26co5w17o8 diff --git a/Runtime/Text/Parsing/Expressions/Operators/TernaryExpression.cs b/Runtime/Text/Parsing/Expressions/Operators/TernaryExpression.cs new file mode 100644 index 0000000..1428433 --- /dev/null +++ b/Runtime/Text/Parsing/Expressions/Operators/TernaryExpression.cs @@ -0,0 +1,58 @@ +using System.Collections.Generic; +using System.Linq; + +namespace Rokojori; + +public interface ITernaryExpression:OperatorExpression +{ + public void InitializeTernaryExpression( ASTNode conditionalExpression, Token symbol, ASTNode trueExpression, Token seperator, ASTNode falseExpression ); + public ASTNode GetConditionalExpression(); + public Token GetSymbol(); + public ASTNode GetTrueExpression(); + public Token GetSeperator(); + public ASTNode GetFalseExpression(); + +} + +public class TernaryExpression:ASTNode,ITernaryExpression +{ + public ASTNode conditionalExpression; + public Token symbol; + public ASTNode trueExpression; + public Token seperator; + public ASTNode falseExpression; + + public void InitializeTernaryExpression( ASTNode conditionalExpression, Token symbol, ASTNode trueExpression, Token seperator, ASTNode falseExpression ) + { + this.conditionalExpression = conditionalExpression; + this.symbol = symbol; + this.trueExpression = trueExpression; + this.seperator = seperator; + this.falseExpression = falseExpression; + } + + public ASTNode GetConditionalExpression() + { + return conditionalExpression; + } + + public Token GetSymbol() + { + return symbol; + } + + public ASTNode GetTrueExpression() + { + return trueExpression; + } + + public Token GetSeperator() + { + return seperator; + } + + public ASTNode GetFalseExpression() + { + return falseExpression; + } +} \ No newline at end of file diff --git a/Runtime/Text/Parsing/Expressions/Operators/TernaryExpression.cs.uid b/Runtime/Text/Parsing/Expressions/Operators/TernaryExpression.cs.uid new file mode 100644 index 0000000..59f7e86 --- /dev/null +++ b/Runtime/Text/Parsing/Expressions/Operators/TernaryExpression.cs.uid @@ -0,0 +1 @@ +uid://bxd4gytorurt8 diff --git a/Runtime/Text/Parsing/Expressions/Operators/TernaryOperator.cs b/Runtime/Text/Parsing/Expressions/Operators/TernaryOperator.cs new file mode 100644 index 0000000..a47c91d --- /dev/null +++ b/Runtime/Text/Parsing/Expressions/Operators/TernaryOperator.cs @@ -0,0 +1,38 @@ +using System.Collections.Generic; +using System.Linq; + +namespace Rokojori; + +public class TernaryOperator<T>:ExpressionOperator where T:ASTNode,ITernaryExpression, new() +{ + public override bool IsFromLeft() + { + return false; + } + + public TernaryOperator() + { + startTokenPredicate = TokenPredicateData.Create( LexerMatcherLibrary.OperatorMatcher.type, "?" ); + } + + public override bool ProcessStartNode( ASTNode parent, int startChildIndex ) + { + var separatorIndex = parent.FindTriggerTokenIndex( startChildIndex, + [ startTokenPredicate ], + TokenPredicateData.BlockPredicates + ); + + var conditional = parent.PreviousNode( startChildIndex ); + var symbol = parent.children[ startChildIndex ] as Token; + var trueExpression = parent.PreviousNode( separatorIndex ); + var separator = parent.children[ separatorIndex ] as Token; + var falseExpression = parent.NextNode( separatorIndex ); + + var ternaryExpression = parent.MergeOuter<T>( conditional, falseExpression ); + ternaryExpression.InitializeTernaryExpression( conditional, symbol, trueExpression, separator, falseExpression ); + + return true; + } + + +} \ No newline at end of file diff --git a/Runtime/Text/Parsing/Expressions/Operators/TernaryOperator.cs.uid b/Runtime/Text/Parsing/Expressions/Operators/TernaryOperator.cs.uid new file mode 100644 index 0000000..f3bd907 --- /dev/null +++ b/Runtime/Text/Parsing/Expressions/Operators/TernaryOperator.cs.uid @@ -0,0 +1 @@ +uid://crsr4mtgogmwy diff --git a/Runtime/Text/Parsing/ParserLibrary/CSharp/CSCommentGrabber.cs b/Runtime/Text/Parsing/ParserLibrary/CSharp/CSCommentGrabber.cs new file mode 100644 index 0000000..9db364a --- /dev/null +++ b/Runtime/Text/Parsing/ParserLibrary/CSharp/CSCommentGrabber.cs @@ -0,0 +1,96 @@ +using System.Collections.Generic; + +namespace Rokojori; + +public class CSCommentGrabber +{ + public static List<Token> Get( ASTNode start ) + { + var p = start.parent; + + for ( int i = start.childIndex - 1; i >= 0; i -- ) + { + var n = p.children[ i ]; + + if ( ! n.IsIgnoreToken() ) + { + return null; + } + + if ( + ! n.IsAnyTokenOf( + [ LexerMatcherLibrary.MultiLineCommentMatcher, + LexerMatcherLibrary.SingleLineCommentMatcher ] + ) + ) + { + continue; + } + + if ( n.IsToken( LexerMatcherLibrary.MultiLineCommentMatcher ) ) + { + var tk = n as Token; + + if ( tk.match.StartsWith( "/**" ) ) + { + return [ tk ]; + } + + return null; + } + else if ( IsSingleLineCommentLine( n ) ) + { + var tokens = GetCompleteSingleLineComments( n as Token ); + + if ( tokens != null ) + { + return tokens; + } + + return null; + } + + } + + return null; + } + + static bool IsSingleLineCommentLine( ASTNode node ) + { + if ( ! node.IsToken( LexerMatcherLibrary.SingleLineCommentMatcher ) ) + { + return false; + } + + var tk = node as Token; + + return tk.match.StartsWith( "///" ); + } + + static List<Token> GetCompleteSingleLineComments( Token lastLine ) + { + var list = new List<Token>(); + var p = lastLine.parent; + + for ( int i = lastLine.childIndex; i >= 0; i -- ) + { + var n = p.children[ i ]; + + if ( IsSingleLineCommentLine( n ) ) + { + list.Add( n as Token ); + } + else if ( n.IsAnyTokenOf( [ LexerMatcherLibrary.WhiteSpaceMatcher, LexerMatcherLibrary.BreakMatcher ]) ) + { + continue; + } + else + { + i = -1; + } + } + + list.Reverse(); + return list; + } +} \ No newline at end of file diff --git a/Runtime/Text/Parsing/ParserLibrary/CSharp/CSCommentGrabber.cs.uid b/Runtime/Text/Parsing/ParserLibrary/CSharp/CSCommentGrabber.cs.uid new file mode 100644 index 0000000..c143edd --- /dev/null +++ b/Runtime/Text/Parsing/ParserLibrary/CSharp/CSCommentGrabber.cs.uid @@ -0,0 +1 @@ +uid://cf37yn2r2o8re diff --git a/Runtime/Text/Parsing/ParserLibrary/CSharp/CSParser.cs b/Runtime/Text/Parsing/ParserLibrary/CSharp/CSParser.cs index 96ab705..49fa06b 100644 --- a/Runtime/Text/Parsing/ParserLibrary/CSharp/CSParser.cs +++ b/Runtime/Text/Parsing/ParserLibrary/CSharp/CSParser.cs @@ -23,4 +23,9 @@ public class CSParser:Parser Parse( FilesSync.LoadUTF8( filePath ) ); } + + public override ExpressionParser GetExpressionParser() + { + return CSExpressionParser.instance; + } } \ No newline at end of file diff --git a/Runtime/Text/Parsing/ParserLibrary/CSharp/CSParserTest.cs b/Runtime/Text/Parsing/ParserLibrary/CSharp/CSParserTest.cs index a0e560f..e72a3cf 100644 --- a/Runtime/Text/Parsing/ParserLibrary/CSharp/CSParserTest.cs +++ b/Runtime/Text/Parsing/ParserLibrary/CSharp/CSParserTest.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using Godot; +using Rokojori.DocGenerator; namespace Rokojori; @@ -25,8 +26,21 @@ public partial class CSParserTest:Node [Export] public bool createGD = false; + [Export] + public bool createDocInfo = false; + + [Export] + public bool createASTView = false; + + [Export] + public ASTViewContext.ViewType viewType = ASTViewContext.ViewType.Tree_Structure; + + + [Export] + public string docInfoPath = "res://.rokojori/cache/docs"; + [ExportToolButton( "Parse" )] public Callable parseButton => Callable.From( ()=> @@ -56,8 +70,42 @@ public partial class CSParserTest:Node { CreateGDClass( root ); } + + if ( createDocInfo ) + { + CreateDocInfo( root ); + } + + if ( createASTView ) + { + CreateASTView( root ); + } } + void CreateASTView( CSFileRoot root ) + { + var astView = this.GetOrCreateChild<ASTViewContext>( "AST View"); + astView.viewType = viewType; + astView.Create( root ); + } + + void CreateDocInfo( CSFileRoot root ) + { + var objects = root.walker.FilterType<CSObjectDeclaration>( root ); + + var originalPath = FilePath.Absolute( root.GetFilePath() ); + + var name = originalPath.fullFileName + ".json"; + + var outputPath = FilePath.Join( ProjectSettings.GlobalizePath( docInfoPath ), name ); + + var doc = ClassDocFromParser.CreateFrom( objects[ 0 ] ); + + this.LogInfo( "saving:", outputPath, JSON.StringifyObject( doc ) ); + FilesSync.SaveJSON( outputPath, doc ); + } + + void CreateGDClass( CSFileRoot root ) { var originalPath = FilePath.Absolute( root.GetFilePath() ); diff --git a/Runtime/Text/Parsing/ParserLibrary/CSharp/Nodes/CSFileRoot.cs b/Runtime/Text/Parsing/ParserLibrary/CSharp/Nodes/CSFileRoot.cs index 8535a8e..56b64b1 100644 --- a/Runtime/Text/Parsing/ParserLibrary/CSharp/Nodes/CSFileRoot.cs +++ b/Runtime/Text/Parsing/ParserLibrary/CSharp/Nodes/CSFileRoot.cs @@ -22,6 +22,11 @@ public class CSFileRoot:ASTNode, ASTFileRoot return _parser.source; } + public List<CSObjectDeclaration> GetObjectDeclarations() + { + return walker.FilterType<CSObjectDeclaration>( this ); + } + TextLinesMapper _textLinesMapper = null; public TextLinesMapper GetTextLinesMapper() diff --git a/Runtime/Text/Parsing/ParserLibrary/CSharp/Nodes/CSImportDeclaration.cs b/Runtime/Text/Parsing/ParserLibrary/CSharp/Nodes/CSImportDeclaration.cs index e0c8093..1cfc0ea 100644 --- a/Runtime/Text/Parsing/ParserLibrary/CSharp/Nodes/CSImportDeclaration.cs +++ b/Runtime/Text/Parsing/ParserLibrary/CSharp/Nodes/CSImportDeclaration.cs @@ -34,7 +34,7 @@ public class CSImportDeclaration: ASTNode, ImportDeclaration var usingIndex = imp.FindTokenIndex( LexerMatcherLibrary.UsingMatcher ); var endIndex = imp.ReverseFindTokenIndex( LexerMatcherLibrary.OperatorMatcher ); - RJLog.Log( "Endindex:", endIndex ); + RJLog.Log( "Endindex:", endIndex, usingIndex ); imp.usingToken = imp.children[ usingIndex ] as Token; imp.end = imp.children[ endIndex ] as Token; diff --git a/Runtime/Text/Parsing/ParserLibrary/CSharp/Nodes/CSNamespaceBlock.cs b/Runtime/Text/Parsing/ParserLibrary/CSharp/Nodes/CSNamespaceBlock.cs index cbbf2de..eb275fe 100644 --- a/Runtime/Text/Parsing/ParserLibrary/CSharp/Nodes/CSNamespaceBlock.cs +++ b/Runtime/Text/Parsing/ParserLibrary/CSharp/Nodes/CSNamespaceBlock.cs @@ -5,12 +5,74 @@ namespace Rokojori; public class CSNamespaceBlock: ASTNode, NamespaceBlock { public Token namespaceToken; - public List<Token> namespacePath; + public List<Token> namespacePath = []; public Token blockStart; public Token blockEnd; + public ASTNodeList blockContent; public string GetNamespace() { return namespacePath.Map( tk => tk.match ).Join( "" ); } + + public static ASTMatcherResolver<CSNamespaceBlock> Resolver() + { + var namespaceMR = new ASTMatcherResolver<CSNamespaceBlock>(); + + var sequenceMatcher = TokenRepeatSequenceASTMatcher.CreateWithLexer( new CSLexer(), + "namespace cword",".cword","{" + ); + + namespaceMR.matcher = sequenceMatcher; + + namespaceMR.initializer = ( nsb, matcher ) => + { + var parent = nsb.parent; + var blockStartIndex = nsb.childIndex; + var blockEndIndex = parent.FindBracketCloserIndex( "{", "}", blockStartIndex ); + var blockEnd = parent.children[ blockEndIndex ]; + + nsb.ExpandToNext( blockEnd ); + + blockStartIndex = nsb.FindTokenIndex( LexerMatcherLibrary.BracketMatcher, "{" ); + blockEndIndex = blockEnd.childIndex; + + var nsIndex = nsb.FindTokenIndex( LexerMatcherLibrary.NamespaceMatcher ); + + + + RJLog.Log( "Matched ns block:", blockStartIndex, blockEndIndex ); + nsb.namespaceToken = nsb.children[ nsIndex ] as Token; + nsb.blockStart = nsb.children[ blockStartIndex ] as Token; + nsb.blockEnd = blockEnd as Token; + + var inbetween = nsb.children.Sub( nsIndex + 1, blockStartIndex - 1 ); + nsb.namespacePath = inbetween.Filter( n => ! n.IsIgnoreToken() ).Map( n => n as Token ); + + nsb.blockContent = nsb.MergeInner<ASTNodeList>( nsb.blockStart, nsb.blockEnd ); + + var parser = CSRootFileParser.CreateParser(); + parser.root = nsb.blockContent; + parser.Process(); + + + RJLog.Log( + "INIT NAMESPACE BLOCK:", nsb.namespaceToken, ">>", inbetween.Join( ", " ), + "path only:",nsb.namespacePath.Join( "|| ") ); + + var root = nsb.GetParentWithType<CSFileRoot>(); + + if ( root == null ) + { + return nsb.childIndex; + } + + root.parsedNodes.Add( nsb ); + root.blocks.Add( nsb ); + + return nsb.childIndex; + }; + + return namespaceMR; + } } \ No newline at end of file diff --git a/Runtime/Text/Parsing/ParserLibrary/CSharp/Nodes/CSNamespaceDeclaration.cs b/Runtime/Text/Parsing/ParserLibrary/CSharp/Nodes/CSNamespaceDeclaration.cs index 9d0e81b..5333cdf 100644 --- a/Runtime/Text/Parsing/ParserLibrary/CSharp/Nodes/CSNamespaceDeclaration.cs +++ b/Runtime/Text/Parsing/ParserLibrary/CSharp/Nodes/CSNamespaceDeclaration.cs @@ -41,7 +41,7 @@ public class CSNamespaceDeclaration: ASTNode, NamespaceDeclaration nsd.namespacePath = inbetween.Filter( n => ! n.IsIgnoreToken() ).Map( n => n as Token ); RJLog.Log( - "INIT IMPORT:", nsd.namespaceToken, ">>", inbetween.Join( ", " ), ">>", nsd.end, + "INIT NAMESPACE FILE DECLARATION:", nsd.namespaceToken, ">>", inbetween.Join( ", " ), ">>", nsd.end, nsd.children.Last(), "path only:",nsd.namespacePath.Join( "|| ") ); diff --git a/Runtime/Text/Parsing/ParserLibrary/CSharp/Nodes/CSTypeDefinition.cs b/Runtime/Text/Parsing/ParserLibrary/CSharp/Nodes/CSTypeDefinition.cs index 3feb2cd..00b981d 100644 --- a/Runtime/Text/Parsing/ParserLibrary/CSharp/Nodes/CSTypeDefinition.cs +++ b/Runtime/Text/Parsing/ParserLibrary/CSharp/Nodes/CSTypeDefinition.cs @@ -4,10 +4,67 @@ namespace Rokojori; public class CSTypeDefinition: ASTNode { + public string GetTypeDefinition() { return CombinedMatch().Trim(); } + public string GetBaseType() + { + var stringType = GetTypeDefinition(); + + var bracketStart = stringType.IndexOf( "<" ); + bracketStart = bracketStart == -1 ? stringType.IndexOf( "[" ) : bracketStart; + + var end = bracketStart == -1 ? stringType.Length : bracketStart; + + return stringType.Substring( 0, end ); + } + + public bool IsGenericList() + { + return GetBaseType() == "List" && IsGeneric(); + } + + + public bool IsGeneric() + { + var stringType = GetTypeDefinition(); + var bracketStart = stringType.IndexOf( "<" ); + + return bracketStart != -1; + } + + public string GetGenericType() + { + if ( ! IsGeneric() ) + { + return null; + } + + var genericStartIndex = FindTokenIndex( LexerMatcherLibrary.BracketMatcher, "<" ); + var genericEndIndex = FindBracketCloserIndex( "<", ">", genericStartIndex ); + + return GetInnerRangeMatch( genericStartIndex, genericEndIndex ); + } + + public bool IsArrayType() + { + var stringType = GetTypeDefinition(); + + if ( stringType.EndsWith( "]" ) ) + { + return true; + } + + // if ( stringType.StartsWith( "List<" ) ) + // { + // return true; + // } + + return false; + } + } \ No newline at end of file diff --git a/Runtime/Text/Parsing/ParserLibrary/CSharp/Nodes/MemberDeclarations/CSMemberDeclaration.cs b/Runtime/Text/Parsing/ParserLibrary/CSharp/Nodes/MemberDeclarations/CSMemberDeclaration.cs index 71cd34e..379a216 100644 --- a/Runtime/Text/Parsing/ParserLibrary/CSharp/Nodes/MemberDeclarations/CSMemberDeclaration.cs +++ b/Runtime/Text/Parsing/ParserLibrary/CSharp/Nodes/MemberDeclarations/CSMemberDeclaration.cs @@ -1,17 +1,49 @@ using System.Collections.Generic; +using System.Text; namespace Rokojori; public abstract class CSMemberDeclaration: ASTNode, MemberDeclaration { + public List<Token> docComment; public List<Token> attributeBrackets; public List<Token> modifiers; public Token memberName; public CSTypeDefinition memberType; + public string GetDocumentation() + { + if ( docComment == null ) + { + return ""; + } + + if ( docComment.Count == 1 && docComment[ 0 ].IsToken( LexerMatcherLibrary.MultiLineCommentMatcher ) ) + { + var match = docComment[ 0 ].match; + return match.Substring( 3, match.Length - 5 ); + } + + var sb = new StringBuilder(); + + docComment.ForEach( + ( tk )=> + { + sb.Append( tk.match.Substring( 3 ) ); + } + ); + + return sb.ToString(); + } + public List<string> GetMemberModifiers() { - return new List<string>(); + return modifiers.Map( m => m.match ); + } + + public List<string> GetMemberAttributes() + { + return CSModifierAttributesParser.GetAttributes( attributeBrackets ); } public string GetMemberName() diff --git a/Runtime/Text/Parsing/ParserLibrary/CSharp/Nodes/ObjectDeclarations/CSObjectDeclaration.cs b/Runtime/Text/Parsing/ParserLibrary/CSharp/Nodes/ObjectDeclarations/CSObjectDeclaration.cs index 5426afd..49f3d6b 100644 --- a/Runtime/Text/Parsing/ParserLibrary/CSharp/Nodes/ObjectDeclarations/CSObjectDeclaration.cs +++ b/Runtime/Text/Parsing/ParserLibrary/CSharp/Nodes/ObjectDeclarations/CSObjectDeclaration.cs @@ -1,9 +1,11 @@ using System.Collections.Generic; +using System.Text; namespace Rokojori; public abstract class CSObjectDeclaration: ASTNode { + public List<Token> docComment; public List<Token> attributeBrackets = []; public List<Token> modifiers = []; public Token objectType; @@ -15,6 +17,62 @@ public abstract class CSObjectDeclaration: ASTNode public ASTNode objectBody; public Token blockEnd; + + public List<string> GetMemberModifiers() + { + return modifiers.Map( m => m.match ); + } + + public List<string> GetMemberAttributes() + { + return CSModifierAttributesParser.GetAttributes( attributeBrackets ); + } + + public string GetDocumentation() + { + if ( docComment == null ) + { + return ""; + } + + if ( docComment.Count == 1 && docComment[ 0 ].IsToken( LexerMatcherLibrary.MultiLineCommentMatcher ) ) + { + var match = docComment[ 0 ].match; + return match.Substring( 3, match.Length - 5 ); + } + + var sb = new StringBuilder(); + + docComment.ForEach( + ( tk )=> + { + sb.Append( tk.match.Substring( 3 ) ); + } + ); + + return sb.ToString(); + } + + public string GetNamespace() + { + var nestedNSBlock = walker.GetParentWithType<CSNamespaceBlock>( this ); + + if ( nestedNSBlock != null ) + { + return nestedNSBlock.GetNamespace(); + } + + var nsDeclaration = walker.FindAnyChildOfType<CSNamespaceDeclaration>( parser.root ); + + if ( nsDeclaration != null ) + { + return nsDeclaration.GetNamespace(); + } + + return null; + } + + public override string ToString() { var modsInfo = ""; @@ -74,6 +132,8 @@ public abstract class CSObjectDeclaration: ASTNode var parent = t.parent; var parentIndex = parent.children.IndexOf( t ); + + // for ( int i = 0; i < parent.children.Count; i++ ) // { // RJLog.Log( i, parent.children[ i ].CombinedMatch(), parent.children[ i ].parent?.GetType().Name ); @@ -111,6 +171,8 @@ public abstract class CSObjectDeclaration: ASTNode } } + t.docComment = CSCommentGrabber.Get( t ); + t.objectType = t.FindToken( odPredicate ); t.objectName = t.FindToken( LexerMatcherLibrary.CwordMatcher, t.children.IndexOf( t.objectType ) + 1 ); diff --git a/Runtime/Text/Parsing/ParserLibrary/CSharp/Parsers/CSExpressions/CSExpressionParser.cs b/Runtime/Text/Parsing/ParserLibrary/CSharp/Parsers/CSExpressions/CSExpressionParser.cs new file mode 100644 index 0000000..be0699b --- /dev/null +++ b/Runtime/Text/Parsing/ParserLibrary/CSharp/Parsers/CSExpressions/CSExpressionParser.cs @@ -0,0 +1,281 @@ +using System; +using System.Collections.Generic; + +namespace Rokojori; + + +public class CSExpressionParser:ExpressionParser +{ + public static CSExpressionParser instance = new CSExpressionParser(); + + // GENERIC (3) + public ConstantOperator<ConstantExpression> boolConstantOperator; + + public GroupOperator<GroupExpression> groupOperator; + + public VariableOperator<VariableExpression> variableOperator; + + public BinaryOperator<BinaryExpression> memberOperator; + public ArrayOperator<ArrayExpression> arrayOperator; + + public FunctionOperator<FunctionExpression> functionOperator; + public GenericFunctionOperator<GenericFunctionExpression> genericFunctionOperator; + + + // BOOLEANS (5) + public BinaryOperator<BinaryExpression> andOperator; + public BinaryOperator<BinaryExpression> orOperator; + + public BinaryOperator<BinaryExpression> equalsOperator; + public BinaryOperator<BinaryExpression> notEqualsOperator; + + public UnaryOperator<UnaryExpression> notOperator; + + // ARITHMETIC A (6) + + public UnaryOperator<UnaryExpression> postfixIncrementOperator; + public UnaryOperator<UnaryExpression> postfixDecrementOperator; + + public UnaryOperator<UnaryExpression> prefixIncrementOperator; + public UnaryOperator<UnaryExpression> prefixDecrementOperator; + + public UnaryOperator<UnaryExpression> unaryPlusOperator; + public UnaryOperator<UnaryExpression> unaryMinusOperator; + + // ARITHMETIC B (5) + public BinaryOperator<BinaryExpression> plusOperator; + public BinaryOperator<BinaryExpression> multiplyOperator; + public BinaryOperator<BinaryExpression> minusOperator; + public BinaryOperator<BinaryExpression> divisionOperator; + public BinaryOperator<BinaryExpression> moduloOperator; + + // RELATIONAL (4) + public BinaryOperator<BinaryExpression> lessThanOperator; + public BinaryOperator<BinaryExpression> lessThanOrEqualOperator; + + public BinaryOperator<BinaryExpression> greaterThanOperator; + public BinaryOperator<BinaryExpression> greaterThanOrEqualOperator; + + // BITWISE LOGIC (6) + public UnaryOperator<UnaryExpression> bitwiseNotOperator; + + public BinaryOperator<BinaryExpression> bitwiseOrOperator; + public BinaryOperator<BinaryExpression> bitwiseAndOperator; + public BinaryOperator<BinaryExpression> bitwiseXorOperator; + + public BinaryOperator<BinaryExpression> bitwiseShiftLeftOperator; + public BinaryOperator<BinaryExpression> bitwiseShiftRightOperator; + + // ASSIGNEMENTS + + // =, => + public BinaryOperator<BinaryExpression> assignmentOperator; + public BinaryOperator<BinaryExpression> arrowAssignmentOperator; + public TernaryOperator<TernaryExpression> ternaryOperator; + + + // +, -, *, /, % + + public List<string> combinedAssignmentSymbols = + [ + "+", "-", "*", "/", "%", + "<<", ">>", + "&", "^","|", + "&&", "||" + ]; + + public List<BinaryOperator<BinaryExpression>> combinedAssignmentOperators; + + + // SEPERATOR + public SeparatedSequenceOperator<SeparatedSequenceExpression> separatedSequenceOperator; + + + public CSExpressionParser() + { + // GENERIC + boolConstantOperator = new ConstantOperator<ConstantExpression>( + TokenPredicateData.Create( LexerMatcherLibrary.BoolMatcher.type ) + ); + + groupOperator = new GroupOperator<GroupExpression>( "(", ")" ); + // groupOperator.expressionParser = this; + + variableOperator = new VariableOperator<VariableExpression>(); + + memberOperator = new BinaryOperator<BinaryExpression>( "." ); + arrayOperator = new ArrayOperator<ArrayExpression>(); + + functionOperator = new FunctionOperator<FunctionExpression>(); + genericFunctionOperator = new GenericFunctionOperator<GenericFunctionExpression>(); + + + // BOOLEANS (5) + andOperator = new BinaryOperator<BinaryExpression>( "&&" ); + orOperator = new BinaryOperator<BinaryExpression>( "||" ); + + equalsOperator = new BinaryOperator<BinaryExpression>( "==" ); + notEqualsOperator = new BinaryOperator<BinaryExpression>( "!=" ); + + notOperator = new UnaryOperator<UnaryExpression>( "!" ); + + // ARITHMETIC A (6) + + postfixIncrementOperator = new UnaryOperator<UnaryExpression>( "++" ); + postfixDecrementOperator = new UnaryOperator<UnaryExpression>( "--" ); + + prefixIncrementOperator = new UnaryOperator<UnaryExpression>( "++" ); + prefixDecrementOperator = new UnaryOperator<UnaryExpression>( "--" ); + + unaryPlusOperator = new UnaryOperator<UnaryExpression>( "+" ); + unaryMinusOperator = new UnaryOperator<UnaryExpression>( "-" ); + + // ARITHMETIC B (5) + plusOperator = new BinaryOperator<BinaryExpression>( "+" ); + multiplyOperator = new BinaryOperator<BinaryExpression>( "*" ); + minusOperator = new BinaryOperator<BinaryExpression>( "-" ); + divisionOperator = new BinaryOperator<BinaryExpression>( "/" ); + moduloOperator = new BinaryOperator<BinaryExpression>( "%" ); + + // RELATIONAL (4) + lessThanOperator = new BinaryOperator<BinaryExpression>( "<" ); + lessThanOrEqualOperator = new BinaryOperator<BinaryExpression>( "<=" ); + + greaterThanOperator = new BinaryOperator<BinaryExpression>( ">" ); + greaterThanOrEqualOperator = new BinaryOperator<BinaryExpression>( ">=" ); + + // BITWISE LOGIC (6) + bitwiseNotOperator = new UnaryOperator<UnaryExpression>( "~" ); + + bitwiseOrOperator = new BinaryOperator<BinaryExpression>( "|" ); + bitwiseAndOperator = new BinaryOperator<BinaryExpression>( "&" ); + bitwiseXorOperator = new BinaryOperator<BinaryExpression>( "^" ); + + bitwiseShiftLeftOperator = new BinaryOperator<BinaryExpression>( "<<" ); + bitwiseShiftRightOperator = new BinaryOperator<BinaryExpression>( ">>" ); + + // ASSIGNEMENTS + + assignmentOperator = new BinaryOperator<BinaryExpression>( "=", false ); + arrowAssignmentOperator = new BinaryOperator<BinaryExpression>( "=>", false ); + ternaryOperator = new TernaryOperator<TernaryExpression>(); + + combinedAssignmentOperators = combinedAssignmentSymbols.Map( + s => new BinaryOperator<BinaryExpression>( s + "=", false ) + ); + + // SEPARATOR + + separatedSequenceOperator = new SeparatedSequenceOperator<SeparatedSequenceExpression>(); + // separatedSequenceOperator.expressionParser = this; + + + SetPrecedenceLevels(); + + } + + + void SetPrecedenceLevels() + { + levels = []; + + AddPrecedenceLevel( + boolConstantOperator + ); + + AddPrecedenceLevel( + groupOperator + ); + + AddPrecedenceLevel( + variableOperator + ); + + AddPrecedenceLevel( + memberOperator, + arrayOperator, + functionOperator, + genericFunctionOperator + ); + + AddPrecedenceLevel( + postfixIncrementOperator, + postfixDecrementOperator + ); + + AddPrecedenceLevel( + prefixIncrementOperator, + prefixDecrementOperator, + notOperator, + bitwiseNotOperator, + unaryPlusOperator, + unaryMinusOperator + ); + + AddPrecedenceLevel( + multiplyOperator, + divisionOperator, + moduloOperator + ); + + AddPrecedenceLevel( + plusOperator, + minusOperator + ); + + AddPrecedenceLevel( + lessThanOperator, + lessThanOrEqualOperator, + greaterThanOperator, + greaterThanOrEqualOperator + ); + + AddPrecedenceLevel( + equalsOperator, + notEqualsOperator + ); + + AddPrecedenceLevel( + equalsOperator, + notEqualsOperator + ); + + AddPrecedenceLevel( + bitwiseAndOperator + ); + + AddPrecedenceLevel( + bitwiseXorOperator + ); + + AddPrecedenceLevel( + bitwiseOrOperator + ); + + AddPrecedenceLevel( + andOperator + ); + + AddPrecedenceLevel( + andOperator + ); + + AddPrecedenceLevel( + orOperator + ); + + var assginments = new List<ExpressionOperator>(); + + assginments.AddRange( [ assignmentOperator, arrowAssignmentOperator, ternaryOperator ] ); + assginments.AddRange( combinedAssignmentOperators ); + + AddPrecedenceLevel( + assginments.ToArray() + ); + + AddPrecedenceLevel( + separatedSequenceOperator + ); + } + +} \ No newline at end of file diff --git a/Runtime/Text/Parsing/ParserLibrary/CSharp/Parsers/CSExpressions/CSExpressionParser.cs.uid b/Runtime/Text/Parsing/ParserLibrary/CSharp/Parsers/CSExpressions/CSExpressionParser.cs.uid new file mode 100644 index 0000000..2bf9b46 --- /dev/null +++ b/Runtime/Text/Parsing/ParserLibrary/CSharp/Parsers/CSExpressions/CSExpressionParser.cs.uid @@ -0,0 +1 @@ +uid://qd5m0kkoxaw7 diff --git a/Runtime/Text/Parsing/ParserLibrary/CSharp/Parsers/CSMemberResolver.cs b/Runtime/Text/Parsing/ParserLibrary/CSharp/Parsers/CSMemberResolver.cs index 8bd00c3..1efecf7 100644 --- a/Runtime/Text/Parsing/ParserLibrary/CSharp/Parsers/CSMemberResolver.cs +++ b/Runtime/Text/Parsing/ParserLibrary/CSharp/Parsers/CSMemberResolver.cs @@ -78,6 +78,8 @@ public class CSMemberResolver:ASTMatcherResolver var typeFirstIndex = atts.nextNode.childIndex; var typeLastIndex = parent.PreviousIndex( mc.childIndex ); var memberType = parent.MergeOuter<CSTypeDefinition>( typeFirstIndex, typeLastIndex ); + + RJLog.Log( "MemberType:", typeFirstIndex, typeLastIndex, memberType.GetTypeDefinition() ); mc.memberType = memberType; if ( earliestNode == null ) @@ -89,9 +91,30 @@ public class CSMemberResolver:ASTMatcherResolver { var mm = mc as CSMethodMemberDeclaration; mm.isContructor = true; + } - mc.ExpandToPrevious( earliestNode ); + if ( earliestNode.parent != mc.parent ) + { + var walker = mc.walker; + + if ( walker.IsChildOf( earliestNode, mc.parent ) ) + { + earliestNode = walker.ResolveToCommonParent( earliestNode, mc.parent ); + } + } + + var commentStart = earliestNode != null ? earliestNode : mc; + var comment = CSCommentGrabber.Get( commentStart ); + mc.docComment = comment; + + + if ( earliestNode != null ) + { + mc.ExpandToPrevious( earliestNode ); + } + + RJLog.Log( "Found member", mc.memberType?.GetTypeDefinition() ?? "(constructor)" , mc.memberName ); @@ -206,6 +229,9 @@ public class CSMemberResolver:ASTMatcherResolver var memberDeclaration = parent.MergeOuter<CSMethodMemberDeclaration>( name, blockEnd ); memberDeclaration.parametersStart = parametersStart; memberDeclaration.parametersEnd = parametersEnd; + memberDeclaration.blockStart = blockStart; + memberDeclaration.blockEnd = blockEnd; + var hasParameterTokens = memberDeclaration.NextNode( parametersStart.childIndex ) != parametersEnd; @@ -236,6 +262,14 @@ public class CSMemberResolver:ASTMatcherResolver } memberDeclaration.memberName = name; + memberDeclaration.blockContent = memberDeclaration.MergeInner<ASTNodeList>( blockStart, blockEnd ); + + var statementsParser = new CSStatementsParser( memberDeclaration.blockContent ); + + RJLog.Log( "Processing statements:", memberDeclaration.blockContent.children.Count, memberDeclaration.blockContent.CombinedMatch() ); + statementsParser.Process(); + + return memberDeclaration; } diff --git a/Runtime/Text/Parsing/ParserLibrary/CSharp/Parsers/CSObjectParser.cs b/Runtime/Text/Parsing/ParserLibrary/CSharp/Parsers/CSObjectParser.cs index ec49e5f..8a1f1e5 100644 --- a/Runtime/Text/Parsing/ParserLibrary/CSharp/Parsers/CSObjectParser.cs +++ b/Runtime/Text/Parsing/ParserLibrary/CSharp/Parsers/CSObjectParser.cs @@ -2,8 +2,6 @@ using System.Collections.Generic; namespace Rokojori; - - public class CSObjectParser:ASTParserPhase { ASTNode objectRoot; @@ -22,6 +20,8 @@ public class CSObjectParser:ASTParserPhase List<ASTMatcherResolver> resolvers = [ + CSImportDeclaration.Resolver(), + CSClassDeclaration.Resolver(), CSStructDeclaration.Resolver(), CSEnumDeclaration.Resolver(), diff --git a/Runtime/Text/Parsing/ParserLibrary/CSharp/Parsers/CSRootFileParser.cs b/Runtime/Text/Parsing/ParserLibrary/CSharp/Parsers/CSRootFileParser.cs index e5bab43..c0c180f 100644 --- a/Runtime/Text/Parsing/ParserLibrary/CSharp/Parsers/CSRootFileParser.cs +++ b/Runtime/Text/Parsing/ParserLibrary/CSharp/Parsers/CSRootFileParser.cs @@ -12,6 +12,7 @@ public class CSRootFileParser:ASTParserPhase [ CSImportDeclaration.Resolver(), CSNamespaceDeclaration.Resolver(), + CSNamespaceBlock.Resolver(), CSClassDeclaration.Resolver(), CSStructDeclaration.Resolver(), diff --git a/Runtime/Text/Parsing/ParserLibrary/CSharp/Parsers/CSStatements/CSBlockStatementResolver.cs b/Runtime/Text/Parsing/ParserLibrary/CSharp/Parsers/CSStatements/CSBlockStatementResolver.cs new file mode 100644 index 0000000..0d5ffc5 --- /dev/null +++ b/Runtime/Text/Parsing/ParserLibrary/CSharp/Parsers/CSStatements/CSBlockStatementResolver.cs @@ -0,0 +1,42 @@ +using System.Collections.Generic; + +namespace Rokojori; + +public class CSBlockStatement:ASTNode,Statement +{ + public ASTNode start; + public ASTNode body; + public ASTNode end; +} + +public class CSBlockStatementResolver:CSStatementResolver +{ + public CSBlockStatementResolver():base( + TokenPredicateData.Create( + LexerMatcherLibrary.BracketMatcher.type, "{" ) + ) + {} + + public override int Resolve( ASTMatchResult result, ASTMatcher matcher ) + { + var parent = result.parent; + var start = parent.children[ result.resultStart ]; + var end = result.parent.FindBracketCloser( "{", "}", result.resultStart ); + + var blockStatement = parent.MergeOuter<CSBlockStatement>( start, end ); + var next = blockStatement.NextNode( start.childIndex ); + var body = next != end ? next : null; + + blockStatement.start = start; + blockStatement.body = body; + blockStatement.end = end; + + if ( blockStatement.body != null ) + { + new CSStatementsParser( body ).Process(); + } + + return blockStatement.childIndex; + } + +} \ No newline at end of file diff --git a/Runtime/Text/Parsing/ParserLibrary/CSharp/Parsers/CSStatements/CSBlockStatementResolver.cs.uid b/Runtime/Text/Parsing/ParserLibrary/CSharp/Parsers/CSStatements/CSBlockStatementResolver.cs.uid new file mode 100644 index 0000000..ceffc06 --- /dev/null +++ b/Runtime/Text/Parsing/ParserLibrary/CSharp/Parsers/CSStatements/CSBlockStatementResolver.cs.uid @@ -0,0 +1 @@ +uid://oogxfm0od0bs diff --git a/Runtime/Text/Parsing/ParserLibrary/CSharp/Parsers/CSStatements/CSElseIfStatementResolver.cs b/Runtime/Text/Parsing/ParserLibrary/CSharp/Parsers/CSStatements/CSElseIfStatementResolver.cs new file mode 100644 index 0000000..8a84afe --- /dev/null +++ b/Runtime/Text/Parsing/ParserLibrary/CSharp/Parsers/CSStatements/CSElseIfStatementResolver.cs @@ -0,0 +1,116 @@ +using System.Collections.Generic; + +namespace Rokojori; + +public class CSElseIfStatement:ASTNode,Statement +{ + public Token elseToken; + public Token ifToken; + public Token conditionStart; + public ASTNode condition; + public Token conditionEnd; + public ASTNode statement; +} + +public class CSElseIfStatementResolver:CSStatementResolver +{ + string symbol = ""; + public CSElseIfStatementResolver( string symbol ):base( + TokenPredicateData.Create( LexerMatcherLibrary.LogicMatcher.type, symbol ) + ) + { + this.symbol = symbol; + } + + public override int Resolve( ASTMatchResult result, ASTMatcher matcher ) + { + var parent = result.parent; + var start = parent.children[ result.resultStart ]; + + Token elseToken = null; + Token ifToken = null; + + + ASTNode lastNode = null; + + + if ( symbol == "if" ) + { + ifToken = start as Token; + lastNode = ifToken; + } + else + { + elseToken = start as Token; + lastNode = elseToken; + + var next = parent.NextNode( elseToken.childIndex ); + + + if ( next.IsToken( LexerMatcherLibrary.LogicMatcher, "if" ) ) + { + ifToken = next as Token; + lastNode = ifToken; + } + } + + var hasConditional = ifToken != null; + + + + Token conditionStart = null; + Token conditionEnd = null; + ASTNode condition = null; + + if ( hasConditional ) + { + var openBracketIndex = parent.FindTokenIndex( LexerMatcherLibrary.BracketMatcher, "(", start.childIndex ); + var closeBracketIndex = parent.FindBracketCloserIndex( "(", ")", openBracketIndex ); + + conditionStart = parent.children[ openBracketIndex ] as Token; + conditionEnd = parent.children[ closeBracketIndex ] as Token; + + condition = parent.MergeInner<ASTNodeList>( conditionStart, conditionEnd ); + + lastNode = conditionEnd; + + var expressionParser = parent.parser.GetExpressionParser(); + expressionParser.ProcessExpression( condition ); + + } + + + var elseIfStatement = parent.MergeOuter<CSElseIfStatement>( start, lastNode ); + elseIfStatement.ifToken = ifToken; + elseIfStatement.elseToken = elseToken; + + if ( hasConditional ) + { + elseIfStatement.conditionStart = conditionStart; + elseIfStatement.conditionEnd = conditionEnd; + elseIfStatement.condition = condition; + } + + var parser = new CSStatementsParser( parent ); + var matchResult = new ASTMatchResult(); + matchResult.parent = parent; + matchResult.childOffset = parent.NextNode( elseIfStatement.childIndex ).childIndex; + + var nextStatementIndex = parser.ResolveNext( matchResult ); + + if ( nextStatementIndex == -1 ) + { + RJLog.Error( "No statement found:", ifToken, symbol, hasConditional, ( start as Token ).lineInfo ); + parser.ResolveNext( matchResult, true ); + + } + + var nextStatement = parent.children[ nextStatementIndex ]; + + elseIfStatement.ExpandToNext( nextStatement ); + elseIfStatement.statement = nextStatement; + + return elseIfStatement.childIndex; + } + +} \ No newline at end of file diff --git a/Runtime/Text/Parsing/ParserLibrary/CSharp/Parsers/CSStatements/CSElseIfStatementResolver.cs.uid b/Runtime/Text/Parsing/ParserLibrary/CSharp/Parsers/CSStatements/CSElseIfStatementResolver.cs.uid new file mode 100644 index 0000000..f7b526b --- /dev/null +++ b/Runtime/Text/Parsing/ParserLibrary/CSharp/Parsers/CSStatements/CSElseIfStatementResolver.cs.uid @@ -0,0 +1 @@ +uid://c38c6xnmvpwea diff --git a/Runtime/Text/Parsing/ParserLibrary/CSharp/Parsers/CSStatements/CSExpressionStatementResolver.cs b/Runtime/Text/Parsing/ParserLibrary/CSharp/Parsers/CSStatements/CSExpressionStatementResolver.cs new file mode 100644 index 0000000..85ea8a9 --- /dev/null +++ b/Runtime/Text/Parsing/ParserLibrary/CSharp/Parsers/CSStatements/CSExpressionStatementResolver.cs @@ -0,0 +1,39 @@ +using System.Collections.Generic; + +namespace Rokojori; + +public class CSExpressionStatement:ASTNode,Statement +{ + public ASTNode expression; + public Token statementEnd; +} + +public class CSExpressionStatementResolver:CSStatementResolver +{ + public CSExpressionStatementResolver():base( null ) + {} + + public override int Resolve( ASTMatchResult result, ASTMatcher matcher ) + { + var parent = result.parent; + var endIndex = parent.FindSemicolonIndex( result.resultStart ); + + if ( endIndex == -1 ) + { + return -1; + } + + var end = parent.children[ endIndex ] as Token; + + var expression = parent.MergeOuter<CSExpressionStatement>( result.resultStart, endIndex ); + expression.statementEnd = end; + expression.expression = new ASTNodeList(); + expression.expression.parent = expression; + expression.MergeChildren( 0, expression.statementEnd.childIndex, expression.expression ); + + parent.parser.GetExpressionParser().ProcessExpression( expression.expression ); + + return expression.childIndex; + } + +} \ No newline at end of file diff --git a/Runtime/Text/Parsing/ParserLibrary/CSharp/Parsers/CSStatements/CSExpressionStatementResolver.cs.uid b/Runtime/Text/Parsing/ParserLibrary/CSharp/Parsers/CSStatements/CSExpressionStatementResolver.cs.uid new file mode 100644 index 0000000..dfd49e3 --- /dev/null +++ b/Runtime/Text/Parsing/ParserLibrary/CSharp/Parsers/CSStatements/CSExpressionStatementResolver.cs.uid @@ -0,0 +1 @@ +uid://g8mbldjmjpv4 diff --git a/Runtime/Text/Parsing/ParserLibrary/CSharp/Parsers/CSStatements/CSForEachStatementResolver.cs b/Runtime/Text/Parsing/ParserLibrary/CSharp/Parsers/CSStatements/CSForEachStatementResolver.cs new file mode 100644 index 0000000..0bd0ed1 --- /dev/null +++ b/Runtime/Text/Parsing/ParserLibrary/CSharp/Parsers/CSStatements/CSForEachStatementResolver.cs @@ -0,0 +1,64 @@ +using System.Collections.Generic; + +namespace Rokojori; + +public class CSForEachStatement:ASTNode,Statement +{ + public Token forEachToken; + public Token conditionStart; + public ASTNode condition; + public Token conditionEnd; + public ASTNode statement; +} + +public class CSForEachStatementResolver:CSStatementResolver +{ + public CSForEachStatementResolver():base( + TokenPredicateData.Create( + LexerMatcherLibrary.LogicMatcher.type, "foreach" ) + ) + {} + + public override int Resolve( ASTMatchResult result, ASTMatcher matcher ) + { + var parent = result.parent; + var start = parent.children[ result.resultStart ]; + + var forEachToken = start as Token; + + var openBracketIndex = parent.FindTokenIndex( LexerMatcherLibrary.BracketMatcher, "(", start.childIndex ); + var closeBracketIndex = parent.FindBracketCloserIndex( "(", ")", openBracketIndex ); + + var conditionStart = parent.children[ openBracketIndex ] as Token; + var conditionEnd = parent.children[ closeBracketIndex ] as Token; + + var condition = parent.MergeInner<ASTNodeList>( conditionStart, conditionEnd ); + + var lastNode = conditionEnd; + + var expressionParser = new CSExpressionParser(); + expressionParser.ProcessExpression( condition ); + + var forEachStatement = parent.MergeOuter<CSForEachStatement>( start, lastNode ); + forEachStatement.forEachToken = forEachToken; + + forEachStatement.conditionStart = conditionStart; + forEachStatement.conditionEnd = conditionEnd; + forEachStatement.condition = condition; + + + var parser = new CSStatementsParser( parent ); + var matchResult = new ASTMatchResult(); + matchResult.parent = parent; + matchResult.childOffset = parent.NextNode( forEachStatement.childIndex ).childIndex; + + var nextStatementIndex = parser.ResolveNext( matchResult ); + var nextStatement = parent.children[ nextStatementIndex ]; + + forEachStatement.ExpandToNext( nextStatement ); + forEachStatement.statement = nextStatement; + + return forEachStatement.childIndex; + } + +} \ No newline at end of file diff --git a/Runtime/Text/Parsing/ParserLibrary/CSharp/Parsers/CSStatements/CSForEachStatementResolver.cs.uid b/Runtime/Text/Parsing/ParserLibrary/CSharp/Parsers/CSStatements/CSForEachStatementResolver.cs.uid new file mode 100644 index 0000000..cb91c97 --- /dev/null +++ b/Runtime/Text/Parsing/ParserLibrary/CSharp/Parsers/CSStatements/CSForEachStatementResolver.cs.uid @@ -0,0 +1 @@ +uid://ccf10760cnijg diff --git a/Runtime/Text/Parsing/ParserLibrary/CSharp/Parsers/CSStatements/CSForStatementResolver.cs b/Runtime/Text/Parsing/ParserLibrary/CSharp/Parsers/CSStatements/CSForStatementResolver.cs new file mode 100644 index 0000000..d63d568 --- /dev/null +++ b/Runtime/Text/Parsing/ParserLibrary/CSharp/Parsers/CSStatements/CSForStatementResolver.cs @@ -0,0 +1,78 @@ +using System.Collections.Generic; + +namespace Rokojori; + +public class CSForStatement:ASTNode,Statement +{ + public Token forToken; + + public Token conditionStart; + + public ASTNode init; + public ASTNode condition; + public ASTNode update; + + public Token conditionEnd; + + public ASTNode statement; +} + +public class CSForStatementResolver:CSStatementResolver +{ + public CSForStatementResolver():base( + TokenPredicateData.Create( + LexerMatcherLibrary.LogicMatcher.type, "for" ) + ) + {} + + public override int Resolve( ASTMatchResult result, ASTMatcher matcher ) + { + var parent = result.parent; + var start = parent.children[ result.resultStart ]; + + var forToken = start as Token; + + var openBracketIndex = parent.FindTokenIndex( LexerMatcherLibrary.BracketMatcher, "(", start.childIndex ); + var closeBracketIndex = parent.FindBracketCloserIndex( "(", ")", openBracketIndex ); + + var conditionStart = parent.children[ openBracketIndex ] as Token; + var conditionEnd = parent.children[ closeBracketIndex ] as Token; + + var lastNode = conditionEnd; + + var expressionParser = new CSExpressionParser(); + + var forStatement = parent.MergeOuter<CSForStatement>( start, lastNode ); + forStatement.forToken = forToken; + forStatement.conditionStart = conditionStart; + forStatement.conditionEnd = conditionEnd; + + var firstSeparatorIndex = forStatement.FindSemicolonIndex( forStatement.conditionStart.childIndex ); + var nextSeparatorIndex = forStatement.FindSemicolonIndex( firstSeparatorIndex + 1 ); + + var firstS = forStatement.children[ firstSeparatorIndex ]; + var secondS = forStatement.children[ nextSeparatorIndex ]; + + forStatement.init = forStatement.MergeInner<ASTNodeList>( conditionStart, firstS ); + forStatement.condition = forStatement.MergeInner<ASTNodeList>( firstS, secondS ); + forStatement.update = forStatement.MergeInner<ASTNodeList>( secondS, conditionEnd ); + + expressionParser.ProcessExpression( forStatement.init ); + expressionParser.ProcessExpression( forStatement.condition ); + expressionParser.ProcessExpression( forStatement.update ); + + var parser = new CSStatementsParser( parent ); + var matchResult = new ASTMatchResult(); + matchResult.parent = parent; + matchResult.childOffset = parent.NextNode( forStatement.childIndex ).childIndex; + + var nextStatementIndex = parser.ResolveNext( matchResult ); + var nextStatement = parent.children[ nextStatementIndex ]; + + forStatement.ExpandToNext( nextStatement ); + forStatement.statement = nextStatement; + + return forStatement.childIndex; + } + +} \ No newline at end of file diff --git a/Runtime/Text/Parsing/ParserLibrary/CSharp/Parsers/CSStatements/CSForStatementResolver.cs.uid b/Runtime/Text/Parsing/ParserLibrary/CSharp/Parsers/CSStatements/CSForStatementResolver.cs.uid new file mode 100644 index 0000000..5bb95c0 --- /dev/null +++ b/Runtime/Text/Parsing/ParserLibrary/CSharp/Parsers/CSStatements/CSForStatementResolver.cs.uid @@ -0,0 +1 @@ +uid://cdjcmyg0ummtm diff --git a/Runtime/Text/Parsing/ParserLibrary/CSharp/Parsers/CSStatements/CSStatementResolver.cs b/Runtime/Text/Parsing/ParserLibrary/CSharp/Parsers/CSStatements/CSStatementResolver.cs new file mode 100644 index 0000000..4281f09 --- /dev/null +++ b/Runtime/Text/Parsing/ParserLibrary/CSharp/Parsers/CSStatements/CSStatementResolver.cs @@ -0,0 +1,27 @@ +using System.Collections.Generic; + +namespace Rokojori; + +public abstract class CSStatementResolver:ASTMatcherResolver +{ + public TokenPredicateData triggerToken; + + public CSStatementResolver( TokenPredicateData triggerToken ) + { + this.triggerToken = triggerToken; + + if ( this.triggerToken == null ) + { + matcher = new NotIgnoreNodeMatcher(); + } + else + { + var tokenMatcher = new TokenMatcher(); + tokenMatcher.matchData = triggerToken; + + matcher = tokenMatcher; + } + + } + +} \ No newline at end of file diff --git a/Runtime/Text/Parsing/ParserLibrary/CSharp/Parsers/CSStatements/CSStatementResolver.cs.uid b/Runtime/Text/Parsing/ParserLibrary/CSharp/Parsers/CSStatements/CSStatementResolver.cs.uid new file mode 100644 index 0000000..3471d01 --- /dev/null +++ b/Runtime/Text/Parsing/ParserLibrary/CSharp/Parsers/CSStatements/CSStatementResolver.cs.uid @@ -0,0 +1 @@ +uid://cw1xxsluowuok diff --git a/Runtime/Text/Parsing/ParserLibrary/CSharp/Parsers/CSStatements/CSStatementsParser.cs b/Runtime/Text/Parsing/ParserLibrary/CSharp/Parsers/CSStatements/CSStatementsParser.cs new file mode 100644 index 0000000..3a183ad --- /dev/null +++ b/Runtime/Text/Parsing/ParserLibrary/CSharp/Parsers/CSStatements/CSStatementsParser.cs @@ -0,0 +1,33 @@ +using System.Collections.Generic; + +namespace Rokojori; + +public class CSStatementsParser:ASTParser +{ + public static List<ASTMatcherResolver> statementResolvers = + [ + new CSBlockStatementResolver(), + + new CSStopStatementResolver( "return", true ), + new CSStopStatementResolver( "throw", true ), + + new CSStopStatementResolver( "break", false ), + new CSStopStatementResolver( "continue", false ), + + new CSElseIfStatementResolver( "if" ), + new CSElseIfStatementResolver( "else" ), + + new CSForStatementResolver(), + new CSForEachStatementResolver(), + + new CSExpressionStatementResolver() + ]; + + public CSStatementsParser( ASTNode root ) + { + this.root = root; + resolvers = statementResolvers; + } + + +} \ No newline at end of file diff --git a/Runtime/Text/Parsing/ParserLibrary/CSharp/Parsers/CSStatements/CSStatementsParser.cs.uid b/Runtime/Text/Parsing/ParserLibrary/CSharp/Parsers/CSStatements/CSStatementsParser.cs.uid new file mode 100644 index 0000000..6c57d9d --- /dev/null +++ b/Runtime/Text/Parsing/ParserLibrary/CSharp/Parsers/CSStatements/CSStatementsParser.cs.uid @@ -0,0 +1 @@ +uid://l08jw4vp71u2 diff --git a/Runtime/Text/Parsing/ParserLibrary/CSharp/Parsers/CSStatements/CSStopStatementResolver.cs b/Runtime/Text/Parsing/ParserLibrary/CSharp/Parsers/CSStatements/CSStopStatementResolver.cs new file mode 100644 index 0000000..70ab8c0 --- /dev/null +++ b/Runtime/Text/Parsing/ParserLibrary/CSharp/Parsers/CSStatements/CSStopStatementResolver.cs @@ -0,0 +1,64 @@ +using System.Collections.Generic; + +namespace Rokojori; + +public class CSStopStatement:ASTNode,Statement +{ + public Token stopToken; + public ASTNodeList expression; + public Token endToken; +} + +public class CSStopStatementResolver:CSStatementResolver +{ + bool postExpression; + + public CSStopStatementResolver( string symbol, bool postExpression ):base( + TokenPredicateData.Create( + LexerMatcherLibrary.LogicMatcher.type, symbol ) + ) + { + this.postExpression = postExpression; + } + + public override int Resolve( ASTMatchResult result, ASTMatcher matcher ) + { + var parent = result.parent; + var start = parent.children[ result.resultStart ]; + + var endIndex = parent.FindSemicolonIndex( result.resultStart ); + + + if ( ! postExpression ) + { + var next = parent.NextNode( start.childIndex ); + + if ( next.childIndex != endIndex ) + { + RJLog.Error( "Unexpected type:", next ); + throw new System.Exception( "Unexpected type:" ); + } + } + + var end = parent.children[ endIndex ] as Token; + var csStopStatement = parent.MergeOuter<CSStopStatement>( start.childIndex, endIndex ); + csStopStatement.stopToken = start as Token; + csStopStatement.endToken = end; + + if ( postExpression && ( end.childIndex - 1 ) > start.childIndex + 1 ) + { + csStopStatement.expression = csStopStatement.MergeInner<ASTNodeList>( + csStopStatement.stopToken, + csStopStatement.endToken + ); + } + + if ( csStopStatement.expression != null ) + { + new CSStatementsParser( csStopStatement.expression ).Process(); + } + + return csStopStatement.childIndex; + } + +} \ No newline at end of file diff --git a/Runtime/Text/Parsing/ParserLibrary/CSharp/Parsers/CSStatements/CSStopStatementResolver.cs.uid b/Runtime/Text/Parsing/ParserLibrary/CSharp/Parsers/CSStatements/CSStopStatementResolver.cs.uid new file mode 100644 index 0000000..aa98d88 --- /dev/null +++ b/Runtime/Text/Parsing/ParserLibrary/CSharp/Parsers/CSStatements/CSStopStatementResolver.cs.uid @@ -0,0 +1 @@ +uid://drcldxarg5lw6 diff --git a/Runtime/Text/Parsing/Statements/ASTStatement.cs b/Runtime/Text/Parsing/Statements/ASTStatement.cs new file mode 100644 index 0000000..caac1dd --- /dev/null +++ b/Runtime/Text/Parsing/Statements/ASTStatement.cs @@ -0,0 +1,8 @@ +using System.Collections.Generic; + +namespace Rokojori; + +public interface Statement +{ + +} diff --git a/Runtime/Text/Parsing/Statements/ASTStatement.cs.uid b/Runtime/Text/Parsing/Statements/ASTStatement.cs.uid new file mode 100644 index 0000000..6e9f2c9 --- /dev/null +++ b/Runtime/Text/Parsing/Statements/ASTStatement.cs.uid @@ -0,0 +1 @@ +uid://plrsvtf0xr3v diff --git a/Runtime/Text/TextLinesMapper.cs b/Runtime/Text/TextLinesMapper.cs index f9b0a43..c78fa0f 100644 --- a/Runtime/Text/TextLinesMapper.cs +++ b/Runtime/Text/TextLinesMapper.cs @@ -78,7 +78,11 @@ namespace Rokojori public TextAnchor GetAnchor( int characterIndex, bool forTextEditor ) { var line = GetLine( characterIndex ); - if ( line == null ) { return null; } + + if ( line == null ) + { + return null; + } return forTextEditor ? line.GetTextEditorAnchor( characterIndex ) : line.GetRawAnchor( characterIndex ); } diff --git a/Runtime/Tools/TestNode.cs b/Runtime/Tools/TestNode.cs new file mode 100644 index 0000000..1caa3ac --- /dev/null +++ b/Runtime/Tools/TestNode.cs @@ -0,0 +1,39 @@ +using System.Collections; +using System.Collections.Generic; + +using Godot; + +namespace Rokojori; + +[GlobalClass][Tool] +public partial class TestNode:Node +{ + /** + <summary> + The value of the other int + </summary> + */ + [Export] + public int otherValue = 1; + + /** + <summary> + The value of the int + </summary> + */ + [Export] + public int intValue = 0; + + /** + <summary> + The value of the float + </summary> + */ + [Export] + public float floatValue = 0; + + + [Export] + public TestResource testResource; + +} diff --git a/Runtime/Tools/TestNode.cs.uid b/Runtime/Tools/TestNode.cs.uid new file mode 100644 index 0000000..8d99ff2 --- /dev/null +++ b/Runtime/Tools/TestNode.cs.uid @@ -0,0 +1 @@ +uid://dhrut5oecuo3n diff --git a/Runtime/Tools/TestResource.cs b/Runtime/Tools/TestResource.cs new file mode 100644 index 0000000..9a8c930 --- /dev/null +++ b/Runtime/Tools/TestResource.cs @@ -0,0 +1,31 @@ +using System.Collections; +using System.Collections.Generic; + +using Godot; + +namespace Rokojori; + +[GlobalClass][Tool] +public partial class TestResource:Resource +{ + /** + <summary> + The value of the other int + </summary> + */ + [Export] + public int otherValue = 1; + + /** + <summary> + The value of the int + </summary> + */ + [Export] + public int intValue = 0; + + + + [Export] + public TestResource testResource; +} diff --git a/Runtime/Tools/TestResource.cs.uid b/Runtime/Tools/TestResource.cs.uid new file mode 100644 index 0000000..8af983b --- /dev/null +++ b/Runtime/Tools/TestResource.cs.uid @@ -0,0 +1 @@ +uid://c8y868kh2knwx diff --git a/Runtime/XML/Nodes/XMLAttributeNode.cs b/Runtime/XML/Nodes/XMLAttributeNode.cs index 3a7df07..40cbcd5 100644 --- a/Runtime/XML/Nodes/XMLAttributeNode.cs +++ b/Runtime/XML/Nodes/XMLAttributeNode.cs @@ -25,6 +25,7 @@ namespace Rokojori public string nameSpace => _nameSpace; public override string nodeValue => value; + public override string textContent => value; public string fullName { diff --git a/Runtime/XML/Nodes/XMLDocument.cs b/Runtime/XML/Nodes/XMLDocument.cs index ac51c66..c8f078a 100644 --- a/Runtime/XML/Nodes/XMLDocument.cs +++ b/Runtime/XML/Nodes/XMLDocument.cs @@ -55,6 +55,8 @@ namespace Rokojori } } + public override string textContent => documentElement?.textContent ?? ""; + public string Serialize() { var serializer = new XMLSerializer(); diff --git a/Runtime/XML/Nodes/XMLElementNode.cs b/Runtime/XML/Nodes/XMLElementNode.cs index 4074268..e3d03b1 100644 --- a/Runtime/XML/Nodes/XMLElementNode.cs +++ b/Runtime/XML/Nodes/XMLElementNode.cs @@ -1,5 +1,6 @@ using System.Collections; using System.Collections.Generic; +using System.Text; using System.Text.RegularExpressions; namespace Rokojori @@ -12,6 +13,21 @@ namespace Rokojori _nameSpace = nameSpace; } + public override string textContent + { + get + { + var sb = new StringBuilder(); + + for ( int i = 0; i < _children.Count; i++ ) + { + sb.Append( _children[ i ].textContent ); + } + + return sb.ToString(); + } + } + string _nodeName; public string nodeName => _nodeName; diff --git a/Runtime/XML/Nodes/XMLTextNode.cs b/Runtime/XML/Nodes/XMLTextNode.cs index a015ca8..bbe088c 100644 --- a/Runtime/XML/Nodes/XMLTextNode.cs +++ b/Runtime/XML/Nodes/XMLTextNode.cs @@ -14,5 +14,6 @@ namespace Rokojori string _textContent; public override string nodeValue => _textContent; + public override string textContent => _textContent; } } \ No newline at end of file diff --git a/Runtime/XML/XMLNode.cs b/Runtime/XML/XMLNode.cs index b637838..f75a657 100644 --- a/Runtime/XML/XMLNode.cs +++ b/Runtime/XML/XMLNode.cs @@ -1,5 +1,6 @@ using System.Collections; using System.Collections.Generic; +using System.Text; using System.Text.RegularExpressions; namespace Rokojori diff --git a/Runtime/XML/XMLReader.cs b/Runtime/XML/XMLReader.cs index b403a1f..fdad71d 100644 --- a/Runtime/XML/XMLReader.cs +++ b/Runtime/XML/XMLReader.cs @@ -43,7 +43,7 @@ errorLine += "~"; - RJLog.Error( line.GetContent( text ) + "\n" + errorLine ); + RJLog.Error( "Line " + line.lineIndex + " >> \n" + line.GetContent( text ) + "\n" + errorLine ); return null; diff --git a/Tools/analysis/ClassDocFromParser.cs b/Tools/analysis/ClassDocFromParser.cs new file mode 100644 index 0000000..cd77bc8 --- /dev/null +++ b/Tools/analysis/ClassDocFromParser.cs @@ -0,0 +1,113 @@ +using System.Collections; +using System.Collections.Generic; +using System.Text.RegularExpressions; +using System.Text; +using System.Reflection; + +namespace Rokojori.DocGenerator; + +public class ClassDocFromParser +{ + public ClassDocInfo objectInfo = new ClassDocInfo(); + + public static ClassDocInfo CreateFrom( CSObjectDeclaration csClass ) + { + var cd = new ClassDocFromParser(); + cd.Create( csClass ); + + return cd.objectInfo; + } + + public void Create( CSObjectDeclaration csClass ) + { + var walker = csClass.parser.root.walker; + + objectInfo.name = csClass.objectName.match; + objectInfo.csNameSpace = csClass.GetNamespace(); + objectInfo.doc = csClass.GetDocumentation(); + objectInfo.attributes = csClass.GetMemberAttributes(); + objectInfo.modifiers = csClass.GetMemberModifiers(); + + + if ( csClass.objectTail != null && csClass.objectTail.inheritanceDeclaration != null ) + { + objectInfo.extendingClasses = [ csClass.objectTail.GetExtendingObject() ]; + } + + objectInfo.attributes = CSModifierAttributesParser.GetAttributes( csClass.attributeBrackets ); + + + var members = new List<CSMemberDeclaration>(); + + walker.Iterate( csClass, + n => + { + // if ( n is CSEnumDeclaration en ) + // { + // var enumType = new GDScriptGeneratorEnum(); + // enumType.name = en.objectName.match; + + // var values = en.objectBody.children.FilterType<ASTNode,CSEnumValueDeclaration>( ); + // enumType.values =values.Map( v => v.GetEnumName() ); + + // gdClass.members.Add( enumType ); + + // return; + // } + + if ( ! ( n is CSMemberDeclaration ) ) + { + return; + } + + + var m = n as CSMemberDeclaration; + + MemberInfo member = new MemberInfo(); + member.name = m.GetMemberName(); + member.dataType = m.GetMemberType(); + member.doc = m.GetDocumentation(); + member.attributes = m.GetMemberAttributes(); + member.modifiers = m.GetMemberModifiers(); + + if ( m is CSFieldDeclaration f ) + { + member.memberType = MemberInfo.Field; + } + else if ( m is CSMethodMemberDeclaration me ) + { + member.memberType = me.isContructor ? MemberInfo.Constructor : MemberInfo.Method; + + if ( me.parametersContent != null ) + { + me.parametersContent.children.ForEach( + ( c ) => + { + var p = c as CSParameterDeclaration; + + var parameter = new ParameterType(); + parameter.name = p.GetParameterName(); + parameter.type = p.GetParameterType(); + + if ( p.parameterValue != null ) + { + parameter.value = p.GetParameterValue(); + } + + member.parameters.Add( parameter ); + + + } + ); + } + + } + + objectInfo.memberInfos.Add( member ); + + }, + false + ); + + } +} \ No newline at end of file diff --git a/Tools/analysis/ClassDocFromParser.cs.uid b/Tools/analysis/ClassDocFromParser.cs.uid new file mode 100644 index 0000000..b42cff5 --- /dev/null +++ b/Tools/analysis/ClassDocFromParser.cs.uid @@ -0,0 +1 @@ +uid://yos5dvjtt8xu diff --git a/Tools/analysis/LibraryDependencies.cs b/Tools/analysis/LibraryDependencies.cs new file mode 100644 index 0000000..66176d8 --- /dev/null +++ b/Tools/analysis/LibraryDependencies.cs @@ -0,0 +1,8 @@ +using System.Collections.Generic; + +namespace Rokojori.Analysis; + +public class LibraryDependencies +{ + +} diff --git a/Tools/analysis/LibraryDependencies.cs.uid b/Tools/analysis/LibraryDependencies.cs.uid new file mode 100644 index 0000000..2595199 --- /dev/null +++ b/Tools/analysis/LibraryDependencies.cs.uid @@ -0,0 +1 @@ +uid://cr2i2cr15uoyg diff --git a/Tools/core-generation/CoreCSGeneratorSettings.cs b/Tools/core-generation/CoreCSGeneratorSettings.cs new file mode 100644 index 0000000..550e35b --- /dev/null +++ b/Tools/core-generation/CoreCSGeneratorSettings.cs @@ -0,0 +1,21 @@ + +using Godot; + +using Rokojori; +using System.Collections.Generic; +using System; +using System.Reflection; +using System.Text.RegularExpressions; +using System.Linq; +using System.IO; + +namespace Rokojori.CoreGeneration; + +[Tool] +public partial class CoreCSGeneratorSettings:RokojoriActionCoreSettings +{ + public override void Generate( Node context ) + { + + } +} \ No newline at end of file diff --git a/Tools/core-generation/CoreCSGeneratorSettings.cs.uid b/Tools/core-generation/CoreCSGeneratorSettings.cs.uid new file mode 100644 index 0000000..90851b2 --- /dev/null +++ b/Tools/core-generation/CoreCSGeneratorSettings.cs.uid @@ -0,0 +1 @@ +uid://b2vox5o5e8wwy diff --git a/Tools/core-generation/RokojoriActionCoreExport.cs b/Tools/core-generation/RokojoriActionCoreExport.cs new file mode 100644 index 0000000..f888d95 --- /dev/null +++ b/Tools/core-generation/RokojoriActionCoreExport.cs @@ -0,0 +1,7 @@ +using System; +namespace Rokojori; + +public class RokojoriActionCoreExport : Attribute +{ + +} \ No newline at end of file diff --git a/Tools/core-generation/RokojoriActionCoreExport.cs.uid b/Tools/core-generation/RokojoriActionCoreExport.cs.uid new file mode 100644 index 0000000..4f78e0a --- /dev/null +++ b/Tools/core-generation/RokojoriActionCoreExport.cs.uid @@ -0,0 +1 @@ +uid://xyhglylgr8s2 diff --git a/Tools/core-generation/RokojoriActionCoreGenerator.cs b/Tools/core-generation/RokojoriActionCoreGenerator.cs new file mode 100644 index 0000000..d126dfa --- /dev/null +++ b/Tools/core-generation/RokojoriActionCoreGenerator.cs @@ -0,0 +1,31 @@ + +using Godot; + +using Rokojori; +using System.Collections.Generic; +using System; +using System.Reflection; +using System.Text.RegularExpressions; +using System.Linq; +using System.IO; + +namespace Rokojori.CoreGeneration; + +[Tool] +public partial class RokojoriActionCoreGenerator : Node +{ + [ExportToolButton( "Generate" )] + public Callable generateButton => Callable.From( + ()=> + { + settings.Generate( this ); + } + ); + + [Export] + public RokojoriActionCoreSettings settings; + + + + +} \ No newline at end of file diff --git a/Tools/core-generation/RokojoriActionCoreGenerator.cs.uid b/Tools/core-generation/RokojoriActionCoreGenerator.cs.uid new file mode 100644 index 0000000..7bd15a3 --- /dev/null +++ b/Tools/core-generation/RokojoriActionCoreGenerator.cs.uid @@ -0,0 +1 @@ +uid://86waecsiy8wg diff --git a/Tools/core-generation/RokojoriActionCoreSettings.cs b/Tools/core-generation/RokojoriActionCoreSettings.cs new file mode 100644 index 0000000..1173677 --- /dev/null +++ b/Tools/core-generation/RokojoriActionCoreSettings.cs @@ -0,0 +1,27 @@ + +using Godot; + +using Rokojori; +using System.Collections.Generic; +using System; +using System.Reflection; +using System.Text.RegularExpressions; +using System.Linq; +using System.IO; + +namespace Rokojori.CoreGeneration; + +[Tool] +public partial class RokojoriActionCoreSettings: Resource +{ + [Export] + public string outputProjectPath; + + [Export] + public string addonPath; + + public virtual void Generate( Node context ) + { + + } +} \ No newline at end of file diff --git a/Tools/core-generation/RokojoriActionCoreSettings.cs.uid b/Tools/core-generation/RokojoriActionCoreSettings.cs.uid new file mode 100644 index 0000000..cc3d8b7 --- /dev/null +++ b/Tools/core-generation/RokojoriActionCoreSettings.cs.uid @@ -0,0 +1 @@ +uid://bq4unyccjiqyn diff --git a/Tools/docs/ClassDocInfo.cs b/Tools/docs/ClassDocInfo.cs index 8ed86f6..522343a 100644 --- a/Tools/docs/ClassDocInfo.cs +++ b/Tools/docs/ClassDocInfo.cs @@ -8,6 +8,7 @@ namespace Rokojori.DocGenerator { public string name; public string type; + public string value; public string csNameSpace; public List<string> modifiers = []; public List<string> generics = []; @@ -86,7 +87,9 @@ namespace Rokojori.DocGenerator public string sourcePath; public string definitionType; public ISOTimeStamp modificationTime; - + + public List<string> modifiers = new List<string>(); + public List<string> attributes = new List<string>(); public List<string> generics = new List<string>(); public List<string> interfaces = new List<string>(); public List<string> extendingClasses = new List<string>(); diff --git a/Tools/gd-only-generator/GDLibraryGenerator.cs b/Tools/gd-only-generator/GDLibraryGenerator.cs new file mode 100644 index 0000000..5208b46 --- /dev/null +++ b/Tools/gd-only-generator/GDLibraryGenerator.cs @@ -0,0 +1,171 @@ + +using Godot; + +using Rokojori; +using System.Collections.Generic; +using System; +using System.Reflection; +using System.Text.RegularExpressions; +using System.Linq; +using System.IO; + +namespace Rokojori.GDLibraryGeneration +{ + [Tool][GlobalClass] + public partial class GDLibraryGenerator:Node + { + [Export] + public string path = "rokojori_action_library_gd"; + + [Export] + public bool scanForGDExport = true; + + [Export] + public string[] files = []; + + [ExportToolButton( "Generate" )] + public Callable generateButton => Callable.From( + ()=> + { + GenerateGDLibrary(); + } + ); + + HashSet<string> defines = new HashSet<string>(); + + void GenerateGDLibrary() + { + defines = new HashSet<string>(); + defines.Add( GDScriptGenerator.GD_SCRIPT_TRANSPILING ); + + var codeFilePaths = GetCodeFilePaths(); + + + + + var rokojoriProPath = FilePath.Absolute( ProjectSettings.GlobalizePath( RokojoriPlugin.path ) ); + var rokojoriGDPath = FilePath.Absolute( ProjectSettings.GlobalizePath( "res://addons/" + path ) ); + + + codeFilePaths.ForEach( + ( c )=> + { + var parser = new CSParser( c.absolutePath, defines ); + var root = parser.root as CSFileRoot; + + var originalPath = FilePath.Absolute( root.GetFilePath() ); + var relativePath = rokojoriProPath.MakeAbsolutePathRelative( originalPath.parentAbsolutePath ); + var gdPath = rokojoriGDPath.MakeRelative( relativePath.path ); + + var converter = new GDScriptFromCSAST(); + converter.Convert( root ); + var gdclass = converter.gdClass; + + var gdgenerator = new GDScriptGenerator(); + gdgenerator.gdClasses = [ gdclass ]; + + FilesSync.EnsureDirectoryExists( gdPath.absolutePath ); + gdgenerator.Generate( gdPath.absolutePath ); + } + ); + + + + + } + + List<FilePath> GetCodeFilePaths() + { + var codeFilePaths = new List<FilePath>(); + + var map = new HashSet<string>(); + + var combinedFiles = new List<string>(); + + combinedFiles.AddRange( files ); + + if ( scanForGDExport ) + { + var absPath = ProjectSettings.GlobalizePath( RokojoriPlugin.path ); + var scannedExportfiles = FilesSync.GetFilesRecursive( absPath, f => f.HasFileExtension( ".cs" ) ); + scannedExportfiles = scannedExportfiles.Filter( + ( f, i ) => + { + var text = f.LoadUTF8(); + + if ( ! text.Contains( "GDExport" ) ) + { + return false; + } + + var parser = new CSParser( f.absolutePath, defines ); + var csRoot = parser.root as CSFileRoot; + var cd = csRoot.GetObjectDeclarations().Find( c => c.objectName.match == f.fileName ); + + return cd?.GetMemberAttributes().Contains( "GDExport" ) ?? false; + } + ); + + + var scannedPaths = scannedExportfiles.Map( f => f.absolutePath ); + + RJLog.Log( "Found paths:", scannedPaths ); + combinedFiles.AddRange( scannedPaths ); + + } + + combinedFiles.ForEach( + ( fileString )=> + { + FilePath filePath; + + if ( fileString.StartsWith( "res://" ) ) + { + filePath = FilePath.Absolute( ProjectSettings.GlobalizePath( fileString ) ); + } + else if ( ! fileString.EndsWith( ".cs" ) ) + { + filePath = FindFilePathOf( fileString ); + } + else + { + filePath = FilePath.Absolute( fileString ); + } + + if ( filePath == null || ! filePath.Exists() ) + { + return; + } + + var absolutePath = filePath.absolutePath; + + if ( map.Contains( absolutePath ) ) + { + return; + } + + codeFilePaths.Add( filePath ); + map.Add( absolutePath ); + } + ); + + return codeFilePaths; + } + + + + List<FilePath> filePaths; + + FilePath FindFilePathOf( string type ) + { + if ( filePaths == null ) + { + var rokojoriPath = ProjectSettings.GlobalizePath( RokojoriPlugin.path ); + filePaths = FilesSync.GetFilesRecursive( rokojoriPath, fp => fp.HasFileExtension( ".cs" ) ); + } + + return filePaths.Find( fp => fp.fileName == type ); + } + + } +} \ No newline at end of file diff --git a/Tools/gd-only-generator/GDLibraryGenerator.cs.uid b/Tools/gd-only-generator/GDLibraryGenerator.cs.uid new file mode 100644 index 0000000..d81eaa9 --- /dev/null +++ b/Tools/gd-only-generator/GDLibraryGenerator.cs.uid @@ -0,0 +1 @@ +uid://bosqs73jx5m0m diff --git a/Tools/godot-editor-inspector-tools/CSInspectors/CSDocEditorInspector.cs b/Tools/godot-editor-inspector-tools/CSInspectors/CSDocEditorInspector.cs new file mode 100644 index 0000000..d026cb0 --- /dev/null +++ b/Tools/godot-editor-inspector-tools/CSInspectors/CSDocEditorInspector.cs @@ -0,0 +1,123 @@ +#if TOOLS +using System.Collections.Generic; +using Godot; + +namespace Rokojori.Tools; +using Rokojori.DocGenerator; + +public partial class CSDocEditorInspector : EditorInspectorPlugin +{ + public override bool _CanHandle( GodotObject obj ) + { + return obj is TestNode || obj is TestResource; + } + + + public static HashSet<string> godotBuiltInInts = new HashSet<string>() + { + "process_mode", + "process_priority", + "process_physics_priority", + "process_thread_group", + "physics_interpolation_mode", + "auto_translate_mode" + }; + + public MultiMap<string,string,string> objectComments = new MultiMap<string, string, string>(); + public List<FilePath> filePaths; + + string FindFilePathOf( string type ) + { + if ( filePaths == null ) + { + var rokojoriPath = ProjectSettings.GlobalizePath( RokojoriPlugin.path ); + filePaths = FilesSync.GetFilesRecursive( rokojoriPath, fp => fp.HasFileExtension( ".cs" ) ); + } + + return filePaths.Find( fp => fp.fileName == type )?.absolutePath; + } + + void ParseType( string type ) + { + if ( objectComments.ContainsKey( type ) ) + { + return; + } + + var filePath = FindFilePathOf( type ); + + if ( filePath == null ) + { + objectComments.Set( type, "", "" ); + return; + } + + RJLog.Log( "Parsing:", filePath ); + var defines = new HashSet<string>(); + + var parser = new CSParser( filePath, defines ); + + var root = parser.root as CSFileRoot; + + var objects = root.walker.FilterType<CSObjectDeclaration>( root ); + var objectDeclaration = objects.Find( obj => obj.objectName.match == type ); + + var doc = ClassDocFromParser.CreateFrom( objectDeclaration ); + + doc.memberInfos.ForEach( + ( mi )=> + { + RJLog.Log( mi.name, mi.doc ); + if ( ! mi.attributes.Contains( "Export" ) ) + { + return; + } + + var comment = mi.doc == null ? "" : XMLDocument.From( mi.doc ).textContent; + + RJLog.Log( mi.name, mi.doc, ">>", comment ); + objectComments.Set( type, mi.name, comment ); + } + ); + } + + string GetComment( string type, string name ) + { + ParseType( type ); + + + if ( ! objectComments.Has( type, name ) ) + { + return "(...)"; + } + + return objectComments[ type ][ name ]; + } + + public override bool _ParseProperty( + GodotObject obj, Variant.Type type, + string name, PropertyHint hintType, string hintString, + PropertyUsageFlags usageFlags, bool wide + ) + { + if ( type == Variant.Type.Int && ! godotBuiltInInts.Contains( name ) ) + { + var comment = GetComment( obj.GetType().Name, name ); + AddCustomControl( new CSIntInspectorProp( obj, name, comment ) ); + RJLog.Log( "Adding:", name ); + return true; + } + + if ( type == Variant.Type.Float && ! godotBuiltInInts.Contains( name ) ) + { + var comment = GetComment( obj.GetType().Name, name ); + AddCustomControl( new CSFloatInspectorProp( obj, name, comment ) ); + RJLog.Log( "Adding:", name ); + return true; + } + + return base._ParseProperty( obj, type, name, hintType, hintString, usageFlags, wide ); + + } +} +#endif \ No newline at end of file diff --git a/Tools/godot-editor-inspector-tools/CSInspectors/CSDocEditorInspector.cs.uid b/Tools/godot-editor-inspector-tools/CSInspectors/CSDocEditorInspector.cs.uid new file mode 100644 index 0000000..658dcbf --- /dev/null +++ b/Tools/godot-editor-inspector-tools/CSInspectors/CSDocEditorInspector.cs.uid @@ -0,0 +1 @@ +uid://bxsac7jh2i0go diff --git a/Tools/godot-editor-inspector-tools/CSInspectors/Types/Float/CSFloatInspectorProp.cs b/Tools/godot-editor-inspector-tools/CSInspectors/Types/Float/CSFloatInspectorProp.cs new file mode 100644 index 0000000..8004b04 --- /dev/null +++ b/Tools/godot-editor-inspector-tools/CSInspectors/Types/Float/CSFloatInspectorProp.cs @@ -0,0 +1,185 @@ +#if TOOLS +using System.Text; +using Godot; +namespace Rokojori.Tools; + +public partial class CSFloatInspectorProp : VBoxContainer +{ + SpinBox _spinBox; + Label label; + HBoxContainer hbox; + + bool _updating = false; + string toolTip; + + GodotObject godotObject; + StringName property; + + + public CSFloatInspectorProp( GodotObject godotObject, StringName property, string toolTip ) + { + this.godotObject = godotObject; + this.property = property; + + this.toolTip = toolTip; + + hbox = new HBoxContainer(); + + _spinBox = new SpinBox(); + + _spinBox.MinValue = -1024; + _spinBox.MaxValue = 1024; + _spinBox.Step = 0.0000001f; + _spinBox.AllowGreater = true; + _spinBox.AllowLesser = true; + _spinBox.SizeFlagsHorizontal = Control.SizeFlags.ExpandFill; + _spinBox.MouseFilter = Control.MouseFilterEnum.Ignore; + _spinBox.GetLineEdit().MouseFilter = Control.MouseFilterEnum.Ignore; + _spinBox.FocusMode = FocusModeEnum.Click; + + + _spinBox.GetLineEdit().FocusExited += ()=> + { + _spinBox.GetLineEdit().MouseFilter = Control.MouseFilterEnum.Ignore; + }; + + AddChild( hbox ); + + label = new Label(); + label.CustomMinimumSize = new Vector2( Size.X * 0.3f , 0 ); + label.Text = GodotEditorInspectorTools.ToEditorLabel( property ); + label.TooltipText = toolTip; + label.MouseFilter = Control.MouseFilterEnum.Stop; + + hbox.AddChild( label ); + hbox.AddChild( _spinBox ); + + // AddFocusable( _spinBox ); + + _spinBox.ValueChanged += _WriteProperty; + + Resized += ( )=> + { + label.CustomMinimumSize = new Vector2( Size.X * 0.3f , 0 ); + }; + + _ReadProperty(); + + } + + + + void _WriteProperty( double value ) + { + if ( _updating || godotObject == null ) + { + return; + } + + _updating = true; + + + var valueBefore = godotObject.Get( property ); + godotObject.Set( property, (float) value ); + RJLog.Log( "Changed:", value ); + + var undo = EditorInterface.Singleton.GetEditorUndoRedo(); + + undo.CreateAction( "Change " + property ); + + undo.AddDoProperty( godotObject, property, (float) value ); + undo.AddDoMethod( this, "_ReadProperty" ); + + undo.AddUndoProperty( godotObject, property, (float) valueBefore ); + undo.AddUndoMethod( this, "_ReadProperty" ); + + undo.CommitAction( false ); + + _updating = false; + + } + + public void _ReadProperty() + { + if ( _updating || godotObject == null ) + { + return; + } + + _updating = true; + + var value = (float)godotObject.Get( property ); + _spinBox.Value = value; + + RJLog.Log( "Updating prop:", value ); + + _updating = false; + } + + float minDragSensitivity = 0.005f; + float _dragSensitivity = 0.01f; + bool _dragging = false; + float _startMouseX; + double _startValue; + bool _wasDragged = false; + + public override void _GuiInput( InputEvent ev ) + { + if ( ev is InputEventMouseButton mouseButton ) + { + RJLog.Log( "Mouse Input", mouseButton.ButtonIndex ); + + if ( mouseButton.ButtonIndex == MouseButton.Left ) + { + if ( mouseButton.Pressed ) + { + _dragging = true; + _wasDragged = false; + _startMouseX = mouseButton.Position.X; + _startValue = _spinBox.Value; + _dragSensitivity = Mathf.Max( Mathf.Abs( (float)_startValue ) / 200f, minDragSensitivity ); + + + AcceptEvent(); + } + else + { + _dragging = false; + + if ( ! _wasDragged ) + { + // _spinBox.MouseFilter = Control.MouseFilterEnum.Stop; + // _spinBox.GetLineEdit().MouseFilter = Control.MouseFilterEnum.Stop; + _spinBox.GetLineEdit().MouseFilter = Control.MouseFilterEnum.Stop; + _spinBox.GetLineEdit().GrabFocus(); + _spinBox.GetLineEdit().SelectAll(); + + + + } + } + } + } + + if ( ev is InputEventMouseMotion motion && _dragging ) + { + var delta = motion.Position.X - _startMouseX; + + if ( Mathf.Abs( delta ) > 2 ) + { + _wasDragged = true; + } + + var newValue = _startValue + delta * _dragSensitivity; + + newValue = Mathf.Clamp( (float)newValue, (float)_spinBox.MinValue, (float)_spinBox.MaxValue); + + _spinBox.Value = newValue; + + AcceptEvent(); + } + } + +} + +#endif \ No newline at end of file diff --git a/Tools/godot-editor-inspector-tools/CSInspectors/Types/Float/CSFloatInspectorProp.cs.uid b/Tools/godot-editor-inspector-tools/CSInspectors/Types/Float/CSFloatInspectorProp.cs.uid new file mode 100644 index 0000000..5fcb116 --- /dev/null +++ b/Tools/godot-editor-inspector-tools/CSInspectors/Types/Float/CSFloatInspectorProp.cs.uid @@ -0,0 +1 @@ +uid://cwq13p0d8iebn diff --git a/Tools/godot-editor-inspector-tools/CSInspectors/Types/Int/CSIntInspectorProp.cs b/Tools/godot-editor-inspector-tools/CSInspectors/Types/Int/CSIntInspectorProp.cs new file mode 100644 index 0000000..c75f7db --- /dev/null +++ b/Tools/godot-editor-inspector-tools/CSInspectors/Types/Int/CSIntInspectorProp.cs @@ -0,0 +1,110 @@ +#if TOOLS +using System.Text; +using Godot; +namespace Rokojori.Tools; + +public partial class CSIntInspectorProp : VBoxContainer +{ + SpinBox _spinBox; + Label label; + HBoxContainer hbox; + + bool _updating = false; + string toolTip; + + GodotObject godotObject; + StringName property; + + + public CSIntInspectorProp( GodotObject godotObject, StringName property, string toolTip ) + { + this.godotObject = godotObject; + this.property = property; + + this.toolTip = toolTip; + + hbox = new HBoxContainer(); + + _spinBox = new SpinBox(); + + _spinBox.MinValue = -1024; + _spinBox.MaxValue = 1024; + _spinBox.Step = 1; + _spinBox.AllowGreater = true; + _spinBox.AllowLesser = true; + _spinBox.SizeFlagsHorizontal = Control.SizeFlags.ExpandFill; + + AddChild( hbox ); + + label = new Label(); + label.CustomMinimumSize = new Vector2( Size.X * 0.3f , 0 ); + label.Text = GodotEditorInspectorTools.ToEditorLabel( property ); + label.TooltipText = toolTip; + label.MouseFilter = Control.MouseFilterEnum.Stop; + + hbox.AddChild( label ); + hbox.AddChild( _spinBox ); + + // AddFocusable( _spinBox ); + + _spinBox.ValueChanged += _WriteProperty; + + Resized += ( )=> + { + label.CustomMinimumSize = new Vector2( Size.X * 0.3f , 0 ); + }; + + _ReadProperty(); + } + + void _WriteProperty( double value ) + { + if ( _updating || godotObject == null ) + { + return; + } + + _updating = true; + + + var valueBefore = godotObject.Get( property ); + godotObject.Set( property, (int) value ); + RJLog.Log( "Changed:", value ); + + var undo = EditorInterface.Singleton.GetEditorUndoRedo(); + + undo.CreateAction( "Change " + property ); + + undo.AddDoProperty( godotObject, property, (int) value ); + undo.AddDoMethod( this, "_ReadProperty" ); + + undo.AddUndoProperty( godotObject, property, (int) valueBefore ); + undo.AddUndoMethod( this, "_ReadProperty" ); + + undo.CommitAction( false ); + + _updating = false; + + } + + public void _ReadProperty() + { + if ( _updating || godotObject == null ) + { + return; + } + + _updating = true; + + var value = (int)godotObject.Get( property ); + _spinBox.Value = value; + + RJLog.Log( "Updating prop:", value ); + + _updating = false; + } + + +} + +#endif \ No newline at end of file diff --git a/Tools/godot-editor-inspector-tools/CSInspectors/Types/Int/CSIntInspectorProp.cs.uid b/Tools/godot-editor-inspector-tools/CSInspectors/Types/Int/CSIntInspectorProp.cs.uid new file mode 100644 index 0000000..64c4082 --- /dev/null +++ b/Tools/godot-editor-inspector-tools/CSInspectors/Types/Int/CSIntInspectorProp.cs.uid @@ -0,0 +1 @@ +uid://brepqtgp336ho diff --git a/Tools/godot-editor-inspector-tools/GodotEditorInspector.cs b/Tools/godot-editor-inspector-tools/GodotEditorInspector.cs index 5cfd8f8..2c08637 100644 --- a/Tools/godot-editor-inspector-tools/GodotEditorInspector.cs +++ b/Tools/godot-editor-inspector-tools/GodotEditorInspector.cs @@ -10,4 +10,6 @@ public abstract partial class GodotEditorInspector<T> : EditorInspectorPlugin wh { public override bool _CanHandle( GodotObject obj ) => obj is T t && CanHandle( t ); protected virtual bool CanHandle( T t ) => true; + + } \ No newline at end of file diff --git a/Tools/godot-editor-inspector-tools/GodotEditorInspectorTools.cs b/Tools/godot-editor-inspector-tools/GodotEditorInspectorTools.cs index 9780a27..dcbce14 100644 --- a/Tools/godot-editor-inspector-tools/GodotEditorInspectorTools.cs +++ b/Tools/godot-editor-inspector-tools/GodotEditorInspectorTools.cs @@ -4,6 +4,8 @@ using System.Collections.Generic; using System.Reflection; using Godot; using System.Linq; +using System.Text; +using System.Text.RegularExpressions; namespace Rokojori.Tools; @@ -12,6 +14,34 @@ public class GodotEditorInspectorTools List<EditorInspectorPlugin> registeredPlugins = []; public RokojoriPlugin rokojoriPlugin; + public static string ToEditorLabel( string label ) + { + if ( string.IsNullOrEmpty( label ) ) + { + return ""; + } + + label = label.Replace( "_", " " ); + + label = Regex.Replace( label, "([a-z])([A-Z])", "$1 $2" ); + + var words = label.Split( ' ' ); + + for ( int i = 0; i < words.Length; i++ ) + { + var word = words[ i ]; + + if ( word.Length > 0 ) + { + word = char.ToUpper( word[ 0 ] ) + word.Substring( 1 ); + } + + words[ i ] = word; + } + + return words.Join( " " ); + } + public void AddPlugins() { registeredPlugins = new List<EditorInspectorPlugin>(); @@ -20,10 +50,13 @@ public class GodotEditorInspectorTools List<EditorInspectorPlugin> plugins = [ + new InfoAttributeDrawer(), new ReadOnlyAttributeDrawer(), - new NamedArrayAttributeDrawer() + new NamedArrayAttributeDrawer(), + + new CSDocEditorInspector() ]; plugins.ForEach(