From 4d4431817d8dbe16bb83e0b66d57430b932cc08d Mon Sep 17 00:00:00 2001 From: Allison Ghost Date: Sat, 20 Jan 2024 15:31:45 -0800 Subject: [PATCH] implement PR https://github.com/godotengine/godot/pull/35716 adds tooltips to exportd vars --- core/object.h | 3 + editor/editor_inspector.cpp | 2 +- modules/gdscript/gdscript_parser.cpp | 29 +++++++++ modules/gdscript/gdscript_tokenizer.cpp | 83 ++++++++++++++++++++++++- modules/gdscript/gdscript_tokenizer.h | 1 + 5 files changed, 116 insertions(+), 2 deletions(-) diff --git a/core/object.h b/core/object.h index a31f826e..5ec79090 100644 --- a/core/object.h +++ b/core/object.h @@ -149,6 +149,9 @@ struct PropertyInfo { PropertyHint hint; String hint_string; uint32_t usage; +#ifdef TOOLS_ENABLED + String tooltip; +#endif _FORCE_INLINE_ PropertyInfo added_usage(int p_fl) const { PropertyInfo pi = *this; diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp index 43ac8907..0b71b5c0 100644 --- a/editor/editor_inspector.cpp +++ b/editor/editor_inspector.cpp @@ -1788,7 +1788,7 @@ void EditorInspector::update_tree() { if (doc_hint != String()) { ep->set_tooltip(property_prefix + p.name + "::" + doc_hint); } else { - ep->set_tooltip(property_prefix + p.name); + ep->set_tooltip(property_prefix + p.name + "::" + p.tooltip); } ep->update_property(); ep->_update_pin_flags(); diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp index 0179e414..6f902aee 100644 --- a/modules/gdscript/gdscript_parser.cpp +++ b/modules/gdscript/gdscript_parser.cpp @@ -3716,6 +3716,28 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { case GDScriptTokenizer::TK_CURSOR: { tokenizer->advance(); } break; + case GDScriptTokenizer::TK_TOOLTIP: { + tokenizer->advance(); +#ifdef TOOLS_ENABLED + if (tokenizer->get_token() == GDScriptTokenizer::TK_CONSTANT && tokenizer->get_token_constant().get_type() == Variant::STRING) { + Variant constant = tokenizer->get_token_constant(); + current_export.tooltip = constant; + } + + // Handle multiline tooltips. + while (tokenizer->get_token(2) == GDScriptTokenizer::TK_TOOLTIP) { + tokenizer->advance(3); + if (tokenizer->get_token() == GDScriptTokenizer::TK_CONSTANT && tokenizer->get_token_constant().get_type() == Variant::STRING) { + Variant constant = tokenizer->get_token_constant(); + current_export.tooltip += constant.operator String(); + } + } +#else + if (tokenizer->get_token() == GDScriptTokenizer::TK_CONSTANT && tokenizer->get_token_constant().get_type() == Variant::STRING) { + tokenizer->advance(); + } +#endif + } break; case GDScriptTokenizer::TK_EOF: p_class->end_line = tokenizer->get_token_line(); case GDScriptTokenizer::TK_ERROR: { @@ -4936,6 +4958,13 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { current_export = PropertyInfo(); } +#ifdef TOOLS_ENABLED + if (autoexport) { + member._export.tooltip = current_export.tooltip; + current_export.tooltip = ""; + } +#endif + bool onready = tokenizer->get_token(-1) == GDScriptTokenizer::TK_PR_ONREADY; tokenizer->advance(); diff --git a/modules/gdscript/gdscript_tokenizer.cpp b/modules/gdscript/gdscript_tokenizer.cpp index ed9b2dd9..96a2c356 100644 --- a/modules/gdscript/gdscript_tokenizer.cpp +++ b/modules/gdscript/gdscript_tokenizer.cpp @@ -135,7 +135,8 @@ const char *GDScriptTokenizer::token_names[TK_MAX] = { "NAN", "Error", "EOF", - "Cursor" + "Cursor", + "##", // Tooltip comment for exported variables. }; struct _bit { @@ -258,6 +259,7 @@ bool GDScriptTokenizer::is_token_literal(int p_offset, bool variable_safe) const case TK_PR_REMOTESYNC: case TK_PR_MASTERSYNC: case TK_PR_PUPPETSYNC: + case TK_TOOLTIP: return true; // Literal for non-variables only: @@ -501,17 +503,96 @@ void GDScriptTokenizerText::_advance() { #ifdef DEBUG_ENABLED String comment; #endif // DEBUG_ENABLED + +#ifdef TOOLS_ENABLED + bool export_var = true; + + if (GETCHAR(1) == '#' || GETCHAR(-1) == '#') { + // Check if it's a tooltip comment + int tip_code_pos = code_pos + 1; + bool multiline = false; + do { + // Move to the end of the line + while (tip_code_pos < len && _code[tip_code_pos] != '\n') { + tip_code_pos++; + } + + // Skip '\n' + tip_code_pos++; + + // Skip whitespaces + while (tip_code_pos < len && (_code[tip_code_pos] == ' ' || _code[tip_code_pos] == '\t' || _code[tip_code_pos] == '\r')) { + tip_code_pos++; + } + + // Check if "##" -> possible multiline tooltip + if (tip_code_pos + 2 < len) { + if (_code[tip_code_pos] == '#' && _code[tip_code_pos + 1] == '#') { + multiline = true; + tip_code_pos += 2; + } else { + multiline = false; + } + } else { + multiline = false; + } + } while (multiline); + + // "export" - 6 CharType characters + const int export_size = 6; + + // Check if there is "export" keyword after "##" comments + if (tip_code_pos + export_size < len) { + const char *export_str = "export"; + for (int e = 0; e < export_size; e++) { + if (_code[tip_code_pos + e] != export_str[e]) { + export_var = false; + break; + } + } + } else { + export_var = false; + } + } else { + export_var = false; + } + + if (export_var) { + if (GETCHAR(1) == '#') { + _make_token(TK_TOOLTIP); + INCPOS(1); + return; + } + } + + String tooltip_text; +#endif while (GETCHAR(0) != '\n') { #ifdef DEBUG_ENABLED comment += GETCHAR(0); #endif // DEBUG_ENABLED code_pos++; +#ifdef TOOLS_ENABLED + if (export_var) { + tooltip_text += GETCHAR(0); + INCPOS(1); + } else +#endif + { + code_pos++; + } if (GETCHAR(0) == 0) { //end of file //_make_error("Unterminated Comment"); _make_token(TK_EOF); return; } } +#ifdef TOOLS_ENABLED + if (export_var) { + _make_constant(tooltip_text.trim_prefix("#").trim_prefix(" ")); + return; + } +#endif #ifdef DEBUG_ENABLED String comment_content = comment.trim_prefix("#").trim_prefix(" "); if (comment_content.begins_with("warning-ignore:")) { diff --git a/modules/gdscript/gdscript_tokenizer.h b/modules/gdscript/gdscript_tokenizer.h index 0ec3c160..1524b8a7 100644 --- a/modules/gdscript/gdscript_tokenizer.h +++ b/modules/gdscript/gdscript_tokenizer.h @@ -142,6 +142,7 @@ class GDScriptTokenizer { TK_ERROR, TK_EOF, TK_CURSOR, //used for code completion + TK_TOOLTIP, TK_MAX };