summaryrefslogtreecommitdiffstats
path: root/editor
diff options
context:
space:
mode:
authorThakee Nathees <thakeenathees@gmail.com>2020-11-29 08:07:57 +0530
committerThakee Nathees <thakeenathees@gmail.com>2020-11-29 19:45:36 +0530
commitd0e7d9b62f0bcc2ba438b12c8bfbf68d82fff0ea (patch)
treee2798248857411a781ac192cb847baed59ceb9f2 /editor
parentef2d1f6d19f861f0f4d9cf7c581795bc7f4016d8 (diff)
downloadredot-engine-d0e7d9b62f0bcc2ba438b12c8bfbf68d82fff0ea.tar.gz
Documentation generation for GDScript
- ClassDoc added to GDScript and property reflection data were extracted from parse tree - GDScript comments are collected from tokenizer for documentation and applied to the ClassDoc by the GDScript compiler - private docs were excluded (name with underscore prefix and doesn't have any doc comments) - default values (of non exported vars), arguments are extraced from the parser - Integrated with GDScript 2.0 and new enums were added. - merge conflicts fixed
Diffstat (limited to 'editor')
-rw-r--r--editor/doc_data.cpp71
-rw-r--r--editor/doc_data.h29
-rw-r--r--editor/editor_file_system.cpp9
-rw-r--r--editor/editor_help.cpp210
-rw-r--r--editor/editor_help.h1
-rw-r--r--editor/plugins/script_editor_plugin.cpp12
-rw-r--r--editor/plugins/script_editor_plugin.h1
7 files changed, 279 insertions, 54 deletions
diff --git a/editor/doc_data.cpp b/editor/doc_data.cpp
index 165a5c8546..d786806ffa 100644
--- a/editor/doc_data.cpp
+++ b/editor/doc_data.cpp
@@ -185,7 +185,24 @@ void DocData::remove_from(const DocData &p_data) {
}
}
-static void return_doc_from_retinfo(DocData::MethodDoc &p_method, const PropertyInfo &p_retinfo) {
+void DocData::add_doc(const ClassDoc &p_class_doc) {
+ ERR_FAIL_COND(p_class_doc.name == "");
+ class_list[p_class_doc.name] = p_class_doc;
+}
+
+void DocData::remove_doc(const String &p_class_name) {
+ ERR_FAIL_COND(p_class_name == "" || !class_list.has(p_class_name));
+ class_list.erase(p_class_name);
+}
+
+bool DocData::has_doc(const String &p_class_name) {
+ if (p_class_name == "") {
+ return false;
+ }
+ return class_list.has(p_class_name);
+}
+
+void DocData::return_doc_from_retinfo(DocData::MethodDoc &p_method, const PropertyInfo &p_retinfo) {
if (p_retinfo.type == Variant::INT && p_retinfo.usage & PROPERTY_USAGE_CLASS_IS_ENUM) {
p_method.return_enum = p_retinfo.class_name;
if (p_method.return_enum.begins_with("_")) { //proxy class
@@ -207,7 +224,7 @@ static void return_doc_from_retinfo(DocData::MethodDoc &p_method, const Property
}
}
-static void argument_doc_from_arginfo(DocData::ArgumentDoc &p_argument, const PropertyInfo &p_arginfo) {
+void DocData::argument_doc_from_arginfo(DocData::ArgumentDoc &p_argument, const PropertyInfo &p_arginfo) {
p_argument.name = p_arginfo.name;
if (p_arginfo.type == Variant::INT && p_arginfo.usage & PROPERTY_USAGE_CLASS_IS_ENUM) {
@@ -230,6 +247,56 @@ static void argument_doc_from_arginfo(DocData::ArgumentDoc &p_argument, const Pr
}
}
+void DocData::property_doc_from_scriptmemberinfo(DocData::PropertyDoc &p_property, const ScriptMemberInfo &p_memberinfo) {
+ p_property.name = p_memberinfo.propinfo.name;
+ p_property.description = p_memberinfo.doc_string;
+
+ if (p_memberinfo.propinfo.type == Variant::OBJECT) {
+ p_property.type = p_memberinfo.propinfo.class_name;
+ } else if (p_memberinfo.propinfo.type == Variant::NIL && p_memberinfo.propinfo.usage & PROPERTY_USAGE_NIL_IS_VARIANT) {
+ p_property.type = "Variant";
+ } else {
+ p_property.type = Variant::get_type_name(p_memberinfo.propinfo.type);
+ }
+
+ p_property.setter = p_memberinfo.setter;
+ p_property.getter = p_memberinfo.getter;
+
+ if (p_memberinfo.has_default_value && p_memberinfo.default_value.get_type() != Variant::OBJECT) {
+ p_property.default_value = p_memberinfo.default_value.get_construct_string().replace("\n", "");
+ }
+
+ p_property.overridden = false;
+}
+
+void DocData::method_doc_from_methodinfo(DocData::MethodDoc &p_method, const MethodInfo &p_methodinfo, const String &p_desc) {
+ p_method.name = p_methodinfo.name;
+ p_method.description = p_desc;
+
+ return_doc_from_retinfo(p_method, p_methodinfo.return_val);
+
+ for (int i = 0; i < p_methodinfo.arguments.size(); i++) {
+ ArgumentDoc argument;
+ argument_doc_from_arginfo(argument, p_methodinfo.arguments[i]);
+ int default_arg_index = i - (p_methodinfo.arguments.size() - p_methodinfo.default_arguments.size());
+ if (default_arg_index >= 0) {
+ Variant default_arg = p_methodinfo.default_arguments[default_arg_index];
+ argument.default_value = default_arg.get_construct_string();
+ }
+ p_method.arguments.push_back(argument);
+ }
+}
+
+void DocData::constant_doc_from_variant(DocData::ConstantDoc &p_const, const StringName &p_name, const Variant &p_value, const String &p_desc) {
+ p_const.name = p_name;
+ p_const.value = p_value;
+ p_const.description = p_desc;
+}
+
+void DocData::signal_doc_from_methodinfo(DocData::MethodDoc &p_signal, const MethodInfo &p_methodinfo, const String &p_desc) {
+ return method_doc_from_methodinfo(p_signal, p_methodinfo, p_desc);
+}
+
static Variant get_documentation_default_value(const StringName &p_class_name, const StringName &p_property_name, bool &r_default_value_valid) {
Variant default_value = Variant();
r_default_value_valid = false;
diff --git a/editor/doc_data.h b/editor/doc_data.h
index 2cb475d137..0090a97c93 100644
--- a/editor/doc_data.h
+++ b/editor/doc_data.h
@@ -35,6 +35,16 @@
#include "core/templates/map.h"
#include "core/variant/variant.h"
+struct ScriptMemberInfo {
+ PropertyInfo propinfo;
+ String doc_string;
+ StringName setter;
+ StringName getter;
+
+ bool has_default_value = false;
+ Variant default_value;
+};
+
class DocData {
public:
struct ArgumentDoc {
@@ -87,6 +97,12 @@ public:
}
};
+ struct EnumDoc {
+ String name = "@unnamed_enum";
+ String description;
+ Vector<DocData::ConstantDoc> values;
+ };
+
struct PropertyDoc {
String name;
String type;
@@ -115,8 +131,11 @@ public:
Vector<MethodDoc> methods;
Vector<MethodDoc> signals;
Vector<ConstantDoc> constants;
+ Map<String, String> enums;
Vector<PropertyDoc> properties;
Vector<PropertyDoc> theme_properties;
+ bool is_script_doc = false;
+ String script_path;
bool operator<(const ClassDoc &p_class) const {
return name < p_class.name;
}
@@ -128,8 +147,18 @@ public:
Error _load(Ref<XMLParser> parser);
public:
+ static void return_doc_from_retinfo(DocData::MethodDoc &p_method, const PropertyInfo &p_retinfo);
+ static void argument_doc_from_arginfo(DocData::ArgumentDoc &p_argument, const PropertyInfo &p_arginfo);
+ static void property_doc_from_scriptmemberinfo(DocData::PropertyDoc &p_property, const ScriptMemberInfo &p_memberinfo);
+ static void method_doc_from_methodinfo(DocData::MethodDoc &p_method, const MethodInfo &p_methodinfo, const String &p_desc);
+ static void constant_doc_from_variant(DocData::ConstantDoc &p_const, const StringName &p_name, const Variant &p_value, const String &p_desc);
+ static void signal_doc_from_methodinfo(DocData::MethodDoc &p_signal, const MethodInfo &p_methodinfo, const String &p_desc);
+
void merge_from(const DocData &p_data);
void remove_from(const DocData &p_data);
+ void add_doc(const ClassDoc &p_class_doc);
+ void remove_doc(const String &p_class_name);
+ bool has_doc(const String &p_class_name);
void generate(bool p_basic_types = false);
Error load_classes(const String &p_dir);
static Error erase_classes(const String &p_dir);
diff --git a/editor/editor_file_system.cpp b/editor/editor_file_system.cpp
index c66bc9b3fa..44c29ab81f 100644
--- a/editor/editor_file_system.cpp
+++ b/editor/editor_file_system.cpp
@@ -799,6 +799,15 @@ void EditorFileSystem::_scan_new_dir(EditorFileSystemDirectory *p_dir, DirAccess
}
}
+ if (fc) {
+ for (int i = 0; i < ScriptServer::get_language_count(); i++) {
+ ScriptLanguage *lang = ScriptServer::get_language(i);
+ if (lang->has_documentation() && fc->type == lang->get_type()) {
+ ResourceLoader::load(path);
+ }
+ }
+ }
+
p_dir->files.push_back(fi);
p_progress.update(idx, total);
}
diff --git a/editor/editor_help.cpp b/editor/editor_help.cpp
index 2c49782fd2..e9f6b16b88 100644
--- a/editor/editor_help.cpp
+++ b/editor/editor_help.cpp
@@ -388,7 +388,7 @@ void EditorHelp::_update_doc() {
}
// Descendents
- if (ClassDB::class_exists(cd.name)) {
+ if (cd.is_script_doc || ClassDB::class_exists(cd.name)) {
bool found = false;
bool prev = false;
@@ -494,7 +494,19 @@ void EditorHelp::_update_doc() {
Set<String> skip_methods;
bool property_descr = false;
- if (cd.properties.size()) {
+ bool has_properties = cd.properties.size() != 0;
+ if (cd.is_script_doc) {
+ has_properties = false;
+ for (int i = 0; i < cd.properties.size(); i++) {
+ if (cd.properties[i].name.begins_with("_") && cd.properties[i].description.empty()) {
+ continue;
+ }
+ has_properties = true;
+ break;
+ }
+ }
+
+ if (has_properties) {
section_line.push_back(Pair<String, int>(TTR("Properties"), class_desc->get_line_count() - 2));
class_desc->push_color(title_color);
class_desc->push_font(doc_title_font);
@@ -509,6 +521,10 @@ void EditorHelp::_update_doc() {
class_desc->set_table_column_expand(1, true);
for (int i = 0; i < cd.properties.size(); i++) {
+ // Ignore undocumented private.
+ if (cd.properties[i].name.begins_with("_") && cd.properties[i].description.empty()) {
+ continue;
+ }
property_line[cd.properties[i].name] = class_desc->get_line_count() - 2; //gets overridden if description
class_desc->push_cell();
@@ -565,6 +581,32 @@ void EditorHelp::_update_doc() {
class_desc->pop();
}
+ if (cd.is_script_doc && (cd.properties[i].setter != "" || cd.properties[i].getter != "")) {
+ class_desc->push_color(symbol_color);
+ class_desc->add_text(" [" + TTR("property:") + " ");
+ class_desc->pop(); // color
+
+ if (cd.properties[i].setter != "") {
+ class_desc->push_color(value_color);
+ class_desc->add_text("setter");
+ class_desc->pop(); // color
+ }
+ if (cd.properties[i].getter != "") {
+ if (cd.properties[i].setter != "") {
+ class_desc->push_color(symbol_color);
+ class_desc->add_text(", ");
+ class_desc->pop(); // color
+ }
+ class_desc->push_color(value_color);
+ class_desc->add_text("getter");
+ class_desc->pop(); // color
+ }
+
+ class_desc->push_color(symbol_color);
+ class_desc->add_text("]");
+ class_desc->pop(); // color
+ }
+
class_desc->pop();
class_desc->pop();
@@ -590,6 +632,10 @@ void EditorHelp::_update_doc() {
continue;
}
}
+ // Ignore undocumented private.
+ if (cd.methods[i].name.begins_with("_") && cd.methods[i].description.empty()) {
+ continue;
+ }
methods.push_back(cd.methods[i]);
}
@@ -802,13 +848,17 @@ void EditorHelp::_update_doc() {
Vector<DocData::ConstantDoc> constants;
for (int i = 0; i < cd.constants.size(); i++) {
- if (cd.constants[i].enumeration != String()) {
+ if (!cd.constants[i].enumeration.empty()) {
if (!enums.has(cd.constants[i].enumeration)) {
enums[cd.constants[i].enumeration] = Vector<DocData::ConstantDoc>();
}
enums[cd.constants[i].enumeration].push_back(cd.constants[i]);
} else {
+ // Ignore undocumented private.
+ if (cd.constants[i].name.begins_with("_") && cd.constants[i].description.empty()) {
+ continue;
+ }
constants.push_back(cd.constants[i]);
}
}
@@ -848,6 +898,19 @@ void EditorHelp::_update_doc() {
class_desc->add_newline();
class_desc->add_newline();
+ // Enum description.
+ if (e != "@unnamed_enums" && cd.enums.has(e)) {
+ class_desc->push_color(text_color);
+ class_desc->push_font(doc_font);
+ class_desc->push_indent(1);
+ _add_text(cd.enums[e]);
+ class_desc->pop();
+ class_desc->pop();
+ class_desc->pop();
+ class_desc->add_newline();
+ class_desc->add_newline();
+ }
+
class_desc->push_indent(1);
Vector<DocData::ConstantDoc> enum_list = E->get();
@@ -1018,60 +1081,89 @@ void EditorHelp::_update_doc() {
class_desc->pop(); // color
}
+ if (cd.is_script_doc && (cd.properties[i].setter != "" || cd.properties[i].getter != "")) {
+ class_desc->push_color(symbol_color);
+ class_desc->add_text(" [" + TTR("property:") + " ");
+ class_desc->pop(); // color
+
+ if (cd.properties[i].setter != "") {
+ class_desc->push_color(value_color);
+ class_desc->add_text("setter");
+ class_desc->pop(); // color
+ }
+ if (cd.properties[i].getter != "") {
+ if (cd.properties[i].setter != "") {
+ class_desc->push_color(symbol_color);
+ class_desc->add_text(", ");
+ class_desc->pop(); // color
+ }
+ class_desc->push_color(value_color);
+ class_desc->add_text("getter");
+ class_desc->pop(); // color
+ }
+
+ class_desc->push_color(symbol_color);
+ class_desc->add_text("]");
+ class_desc->pop(); // color
+ }
+
class_desc->pop(); // font
class_desc->pop(); // cell
- Map<String, DocData::MethodDoc> method_map;
- for (int j = 0; j < methods.size(); j++) {
- method_map[methods[j].name] = methods[j];
- }
+ // Script doc doesn't have setter, getter.
+ if (!cd.is_script_doc) {
+ Map<String, DocData::MethodDoc> method_map;
+ for (int j = 0; j < methods.size(); j++) {
+ method_map[methods[j].name] = methods[j];
+ }
- if (cd.properties[i].setter != "") {
- class_desc->push_cell();
- class_desc->pop(); // cell
+ if (cd.properties[i].setter != "") {
+ class_desc->push_cell();
+ class_desc->pop(); // cell
- class_desc->push_cell();
- class_desc->push_font(doc_code_font);
- class_desc->push_color(text_color);
- if (method_map[cd.properties[i].setter].arguments.size() > 1) {
- // Setters with additional arguments are exposed in the method list, so we link them here for quick access.
- class_desc->push_meta("@method " + cd.properties[i].setter);
- class_desc->add_text(cd.properties[i].setter + TTR("(value)"));
- class_desc->pop();
- } else {
- class_desc->add_text(cd.properties[i].setter + TTR("(value)"));
+ class_desc->push_cell();
+ class_desc->push_font(doc_code_font);
+ class_desc->push_color(text_color);
+ if (method_map[cd.properties[i].setter].arguments.size() > 1) {
+ // Setters with additional arguments are exposed in the method list, so we link them here for quick access.
+ class_desc->push_meta("@method " + cd.properties[i].setter);
+ class_desc->add_text(cd.properties[i].setter + TTR("(value)"));
+ class_desc->pop();
+ } else {
+ class_desc->add_text(cd.properties[i].setter + TTR("(value)"));
+ }
+ class_desc->pop(); // color
+ class_desc->push_color(comment_color);
+ class_desc->add_text(" setter");
+ class_desc->pop(); // color
+ class_desc->pop(); // font
+ class_desc->pop(); // cell
+ method_line[cd.properties[i].setter] = property_line[cd.properties[i].name];
}
- class_desc->pop(); // color
- class_desc->push_color(comment_color);
- class_desc->add_text(" setter");
- class_desc->pop(); // color
- class_desc->pop(); // font
- class_desc->pop(); // cell
- method_line[cd.properties[i].setter] = property_line[cd.properties[i].name];
- }
- if (cd.properties[i].getter != "") {
- class_desc->push_cell();
- class_desc->pop(); // cell
+ if (cd.properties[i].getter != "") {
+ class_desc->push_cell();
+ class_desc->pop(); // cell
- class_desc->push_cell();
- class_desc->push_font(doc_code_font);
- class_desc->push_color(text_color);
- if (method_map[cd.properties[i].getter].arguments.size() > 0) {
- // Getters with additional arguments are exposed in the method list, so we link them here for quick access.
- class_desc->push_meta("@method " + cd.properties[i].getter);
- class_desc->add_text(cd.properties[i].getter + "()");
- class_desc->pop();
- } else {
- class_desc->add_text(cd.properties[i].getter + "()");
+ class_desc->push_cell();
+ class_desc->push_font(doc_code_font);
+ class_desc->push_color(text_color);
+ if (method_map[cd.properties[i].getter].arguments.size() > 0) {
+ // Getters with additional arguments are exposed in the method list, so we link them here for quick access.
+ class_desc->push_meta("@method " + cd.properties[i].getter);
+ class_desc->add_text(cd.properties[i].getter + "()");
+ class_desc->pop();
+ } else {
+ class_desc->add_text(cd.properties[i].getter + "()");
+ }
+ class_desc->pop(); //color
+ class_desc->push_color(comment_color);
+ class_desc->add_text(" getter");
+ class_desc->pop(); //color
+ class_desc->pop(); //font
+ class_desc->pop(); //cell
+ method_line[cd.properties[i].getter] = property_line[cd.properties[i].name];
}
- class_desc->pop(); //color
- class_desc->push_color(comment_color);
- class_desc->add_text(" getter");
- class_desc->pop(); //color
- class_desc->pop(); //font
- class_desc->pop(); //cell
- method_line[cd.properties[i].getter] = property_line[cd.properties[i].name];
}
class_desc->pop(); // table
@@ -1082,13 +1174,17 @@ void EditorHelp::_update_doc() {
class_desc->push_color(text_color);
class_desc->push_font(doc_font);
class_desc->push_indent(1);
- if (cd.properties[i].description.strip_edges() != String()) {
+ if (!cd.properties[i].description.strip_edges().empty()) {
_add_text(DTR(cd.properties[i].description));
} else {
class_desc->add_image(get_theme_icon("Error", "EditorIcons"));
class_desc->add_text(" ");
class_desc->push_color(comment_color);
- class_desc->append_bbcode(TTR("There is currently no description for this property. Please help us by [color=$color][url=$url]contributing one[/url][/color]!").replace("$url", CONTRIBUTE_URL).replace("$color", link_color_text));
+ if (cd.is_script_doc) {
+ class_desc->append_bbcode(TTR("There is currently no description for this property."));
+ } else {
+ class_desc->append_bbcode(TTR("There is currently no description for this property. Please help us by [color=$color][url=$url]contributing one[/url][/color]!").replace("$url", CONTRIBUTE_URL).replace("$color", link_color_text));
+ }
class_desc->pop();
}
class_desc->pop();
@@ -1133,13 +1229,17 @@ void EditorHelp::_update_doc() {
class_desc->push_color(text_color);
class_desc->push_font(doc_font);
class_desc->push_indent(1);
- if (methods_filtered[i].description.strip_edges() != String()) {
+ if (!methods_filtered[i].description.strip_edges().empty()) {
_add_text(DTR(methods_filtered[i].description));
} else {
class_desc->add_image(get_theme_icon("Error", "EditorIcons"));
class_desc->add_text(" ");
class_desc->push_color(comment_color);
- class_desc->append_bbcode(TTR("There is currently no description for this method. Please help us by [color=$color][url=$url]contributing one[/url][/color]!").replace("$url", CONTRIBUTE_URL).replace("$color", link_color_text));
+ if (cd.is_script_doc) {
+ class_desc->append_bbcode(TTR("There is currently no description for this method."));
+ } else {
+ class_desc->append_bbcode(TTR("There is currently no description for this method. Please help us by [color=$color][url=$url]contributing one[/url][/color]!").replace("$url", CONTRIBUTE_URL).replace("$color", link_color_text));
+ }
class_desc->pop();
}
@@ -1549,6 +1649,12 @@ void EditorHelp::go_to_class(const String &p_class, int p_scroll) {
_goto_desc(p_class, p_scroll);
}
+void EditorHelp::update_doc() {
+ ERR_FAIL_COND(!doc->class_list.has(edited_class));
+ ERR_FAIL_COND(!doc->class_list[edited_class].is_script_doc);
+ _update_doc();
+}
+
Vector<Pair<String, int>> EditorHelp::get_sections() {
Vector<Pair<String, int>> sections;
diff --git a/editor/editor_help.h b/editor/editor_help.h
index cdb674cffd..545147f6f5 100644
--- a/editor/editor_help.h
+++ b/editor/editor_help.h
@@ -170,6 +170,7 @@ public:
void go_to_help(const String &p_help);
void go_to_class(const String &p_class, int p_scroll = 0);
+ void update_doc();
Vector<Pair<String, int>> get_sections();
void scroll_to_section(int p_section_index);
diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp
index 6ee8193291..fa70415210 100644
--- a/editor/plugins/script_editor_plugin.cpp
+++ b/editor/plugins/script_editor_plugin.cpp
@@ -2900,6 +2900,18 @@ void ScriptEditor::_help_class_goto(const String &p_desc) {
_save_layout();
}
+void ScriptEditor::update_doc(const String &p_name) {
+ ERR_FAIL_COND(!EditorHelp::get_doc_data()->has_doc(p_name));
+
+ for (int i = 0; i < tab_container->get_child_count(); i++) {
+ EditorHelp *eh = Object::cast_to<EditorHelp>(tab_container->get_child(i));
+ if (eh && eh->get_class() == p_name) {
+ eh->update_doc();
+ return;
+ }
+ }
+}
+
void ScriptEditor::_update_selected_editor_menu() {
for (int i = 0; i < tab_container->get_child_count(); i++) {
bool current = tab_container->get_current_tab() == i;
diff --git a/editor/plugins/script_editor_plugin.h b/editor/plugins/script_editor_plugin.h
index f1453c3d20..cc02a1ccbe 100644
--- a/editor/plugins/script_editor_plugin.h
+++ b/editor/plugins/script_editor_plugin.h
@@ -482,6 +482,7 @@ public:
void close_builtin_scripts_from_scene(const String &p_scene);
void goto_help(const String &p_desc) { _help_class_goto(p_desc); }
+ void update_doc(const String &p_name);
bool can_take_away_focus() const;