diff --git a/core/doc_data.cpp b/core/doc_data.cpp new file mode 100644 index 0000000000..d84ac6d05b --- /dev/null +++ b/core/doc_data.cpp @@ -0,0 +1,126 @@ +/*************************************************************************/ +/* doc_data.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "doc_data.h" + +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 + p_method.return_enum = p_method.return_enum.substr(1, p_method.return_enum.length()); + } + p_method.return_type = "int"; + } else if (p_retinfo.class_name != StringName()) { + p_method.return_type = p_retinfo.class_name; + } else if (p_retinfo.type == Variant::ARRAY && p_retinfo.hint == PROPERTY_HINT_ARRAY_TYPE) { + p_method.return_type = p_retinfo.hint_string + "[]"; + } else if (p_retinfo.hint == PROPERTY_HINT_RESOURCE_TYPE) { + p_method.return_type = p_retinfo.hint_string; + } else if (p_retinfo.type == Variant::NIL && p_retinfo.usage & PROPERTY_USAGE_NIL_IS_VARIANT) { + p_method.return_type = "Variant"; + } else if (p_retinfo.type == Variant::NIL) { + p_method.return_type = "void"; + } else { + p_method.return_type = Variant::get_type_name(p_retinfo.type); + } +} + +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) { + p_argument.enumeration = p_arginfo.class_name; + if (p_argument.enumeration.begins_with("_")) { //proxy class + p_argument.enumeration = p_argument.enumeration.substr(1, p_argument.enumeration.length()); + } + p_argument.type = "int"; + } else if (p_arginfo.class_name != StringName()) { + p_argument.type = p_arginfo.class_name; + } else if (p_arginfo.type == Variant::ARRAY && p_arginfo.hint == PROPERTY_HINT_ARRAY_TYPE) { + p_argument.type = p_arginfo.hint_string + "[]"; + } else if (p_arginfo.hint == PROPERTY_HINT_RESOURCE_TYPE) { + p_argument.type = p_arginfo.hint_string; + } else if (p_arginfo.type == Variant::NIL) { + // Parameters cannot be void, so PROPERTY_USAGE_NIL_IS_VARIANT is not necessary + p_argument.type = "Variant"; + } else { + p_argument.type = Variant::get_type_name(p_arginfo.type); + } +} + +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++) { + DocData::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); +} diff --git a/editor/doc_data.h b/core/doc_data.h similarity index 80% rename from editor/doc_data.h rename to core/doc_data.h index 2cb475d137..bf016792ea 100644 --- a/editor/doc_data.h +++ b/core/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 values; + }; + struct PropertyDoc { String name; String type; @@ -115,27 +131,22 @@ public: Vector methods; Vector signals; Vector constants; + Map enums; Vector properties; Vector theme_properties; + bool is_script_doc = false; + String script_path; bool operator<(const ClassDoc &p_class) const { return name < p_class.name; } }; - String version; - - Map class_list; - Error _load(Ref parser); - -public: - void merge_from(const DocData &p_data); - void remove_from(const DocData &p_data); - void generate(bool p_basic_types = false); - Error load_classes(const String &p_dir); - static Error erase_classes(const String &p_dir); - Error save_classes(const String &p_default_path, const Map &p_class_path); - - Error load_compressed(const uint8_t *p_data, int p_compressed_size, int p_uncompressed_size); + 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); }; #endif // DOC_DATA_H diff --git a/core/object/script_language.h b/core/object/script_language.h index 3fd56c2f15..72586780ae 100644 --- a/core/object/script_language.h +++ b/core/object/script_language.h @@ -31,6 +31,7 @@ #ifndef SCRIPT_LANGUAGE_H #define SCRIPT_LANGUAGE_H +#include "core/doc_data.h" #include "core/io/multiplayer_api.h" #include "core/io/resource.h" #include "core/templates/map.h" @@ -145,6 +146,10 @@ public: virtual void set_source_code(const String &p_code) = 0; virtual Error reload(bool p_keep_state = false) = 0; +#ifdef TOOLS_ENABLED + virtual const Vector &get_documentation() const = 0; +#endif // TOOLS_ENABLED + virtual bool has_method(const StringName &p_method) const = 0; virtual MethodInfo get_method_info(const StringName &p_method) const = 0; @@ -310,6 +315,7 @@ public: virtual Script *create_script() const = 0; virtual bool has_named_classes() const = 0; virtual bool supports_builtin_mode() const = 0; + virtual bool supports_documentation() const { return false; } virtual bool can_inherit_from_file() { return false; } virtual int find_function(const String &p_function, const String &p_code) const = 0; virtual String make_function(const String &p_class, const String &p_name, const PackedStringArray &p_args) const = 0; diff --git a/editor/connections_dialog.cpp b/editor/connections_dialog.cpp index a04065a463..2630589912 100644 --- a/editor/connections_dialog.cpp +++ b/editor/connections_dialog.cpp @@ -31,6 +31,7 @@ #include "connections_dialog.h" #include "core/string/print_string.h" +#include "editor/doc_tools.h" #include "editor_node.h" #include "editor_scale.h" #include "editor_settings.h" @@ -998,7 +999,7 @@ void ConnectionsDock::update_tree() { } if (!found) { - DocData *dd = EditorHelp::get_doc_data(); + DocTools *dd = EditorHelp::get_doc_data(); Map::Element *F = dd->class_list.find(base); while (F && descr == String()) { for (int i = 0; i < F->get().signals.size(); i++) { diff --git a/editor/doc_data.cpp b/editor/doc_tools.cpp similarity index 88% rename from editor/doc_data.cpp rename to editor/doc_tools.cpp index 165a5c8546..5ee9abb183 100644 --- a/editor/doc_data.cpp +++ b/editor/doc_tools.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* doc_data.cpp */ +/* doc_tools.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,7 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "doc_data.h" +#include "doc_tools.h" #include "core/config/engine.h" #include "core/config/project_settings.h" @@ -43,22 +43,22 @@ // Used for a hack preserving Mono properties on non-Mono builds. #include "modules/modules_enabled.gen.h" -void DocData::merge_from(const DocData &p_data) { - for (Map::Element *E = class_list.front(); E; E = E->next()) { - ClassDoc &c = E->get(); +void DocTools::merge_from(const DocTools &p_data) { + for (Map::Element *E = class_list.front(); E; E = E->next()) { + DocData::ClassDoc &c = E->get(); if (!p_data.class_list.has(c.name)) { continue; } - const ClassDoc &cf = p_data.class_list[c.name]; + const DocData::ClassDoc &cf = p_data.class_list[c.name]; c.description = cf.description; c.brief_description = cf.brief_description; c.tutorials = cf.tutorials; for (int i = 0; i < c.methods.size(); i++) { - MethodDoc &m = c.methods.write[i]; + DocData::MethodDoc &m = c.methods.write[i]; for (int j = 0; j < cf.methods.size(); j++) { if (cf.methods[j].name != m.name) { @@ -95,7 +95,7 @@ void DocData::merge_from(const DocData &p_data) { continue; } - const MethodDoc &mf = cf.methods[j]; + const DocData::MethodDoc &mf = cf.methods[j]; m.description = mf.description; break; @@ -103,13 +103,13 @@ void DocData::merge_from(const DocData &p_data) { } for (int i = 0; i < c.signals.size(); i++) { - MethodDoc &m = c.signals.write[i]; + DocData::MethodDoc &m = c.signals.write[i]; for (int j = 0; j < cf.signals.size(); j++) { if (cf.signals[j].name != m.name) { continue; } - const MethodDoc &mf = cf.signals[j]; + const DocData::MethodDoc &mf = cf.signals[j]; m.description = mf.description; break; @@ -117,13 +117,13 @@ void DocData::merge_from(const DocData &p_data) { } for (int i = 0; i < c.constants.size(); i++) { - ConstantDoc &m = c.constants.write[i]; + DocData::ConstantDoc &m = c.constants.write[i]; for (int j = 0; j < cf.constants.size(); j++) { if (cf.constants[j].name != m.name) { continue; } - const ConstantDoc &mf = cf.constants[j]; + const DocData::ConstantDoc &mf = cf.constants[j]; m.description = mf.description; break; @@ -131,13 +131,13 @@ void DocData::merge_from(const DocData &p_data) { } for (int i = 0; i < c.properties.size(); i++) { - PropertyDoc &p = c.properties.write[i]; + DocData::PropertyDoc &p = c.properties.write[i]; for (int j = 0; j < cf.properties.size(); j++) { if (cf.properties[j].name != p.name) { continue; } - const PropertyDoc &pf = cf.properties[j]; + const DocData::PropertyDoc &pf = cf.properties[j]; p.description = pf.description; break; @@ -145,13 +145,13 @@ void DocData::merge_from(const DocData &p_data) { } for (int i = 0; i < c.theme_properties.size(); i++) { - PropertyDoc &p = c.theme_properties.write[i]; + DocData::PropertyDoc &p = c.theme_properties.write[i]; for (int j = 0; j < cf.theme_properties.size(); j++) { if (cf.theme_properties[j].name != p.name) { continue; } - const PropertyDoc &pf = cf.theme_properties[j]; + const DocData::PropertyDoc &pf = cf.theme_properties[j]; p.description = pf.description; break; @@ -177,57 +177,29 @@ void DocData::merge_from(const DocData &p_data) { } } -void DocData::remove_from(const DocData &p_data) { - for (Map::Element *E = p_data.class_list.front(); E; E = E->next()) { +void DocTools::remove_from(const DocTools &p_data) { + for (Map::Element *E = p_data.class_list.front(); E; E = E->next()) { if (class_list.has(E->key())) { class_list.erase(E->key()); } } } -static void 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 - p_method.return_enum = p_method.return_enum.substr(1, p_method.return_enum.length()); - } - p_method.return_type = "int"; - } else if (p_retinfo.class_name != StringName()) { - p_method.return_type = p_retinfo.class_name; - } else if (p_retinfo.type == Variant::ARRAY && p_retinfo.hint == PROPERTY_HINT_ARRAY_TYPE) { - p_method.return_type = p_retinfo.hint_string + "[]"; - } else if (p_retinfo.hint == PROPERTY_HINT_RESOURCE_TYPE) { - p_method.return_type = p_retinfo.hint_string; - } else if (p_retinfo.type == Variant::NIL && p_retinfo.usage & PROPERTY_USAGE_NIL_IS_VARIANT) { - p_method.return_type = "Variant"; - } else if (p_retinfo.type == Variant::NIL) { - p_method.return_type = "void"; - } else { - p_method.return_type = Variant::get_type_name(p_retinfo.type); - } +void DocTools::add_doc(const DocData::ClassDoc &p_class_doc) { + ERR_FAIL_COND(p_class_doc.name == ""); + class_list[p_class_doc.name] = p_class_doc; } -static void argument_doc_from_arginfo(DocData::ArgumentDoc &p_argument, const PropertyInfo &p_arginfo) { - p_argument.name = p_arginfo.name; +void DocTools::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); +} - if (p_arginfo.type == Variant::INT && p_arginfo.usage & PROPERTY_USAGE_CLASS_IS_ENUM) { - p_argument.enumeration = p_arginfo.class_name; - if (p_argument.enumeration.begins_with("_")) { //proxy class - p_argument.enumeration = p_argument.enumeration.substr(1, p_argument.enumeration.length()); - } - p_argument.type = "int"; - } else if (p_arginfo.class_name != StringName()) { - p_argument.type = p_arginfo.class_name; - } else if (p_arginfo.type == Variant::ARRAY && p_arginfo.hint == PROPERTY_HINT_ARRAY_TYPE) { - p_argument.type = p_arginfo.hint_string + "[]"; - } else if (p_arginfo.hint == PROPERTY_HINT_RESOURCE_TYPE) { - p_argument.type = p_arginfo.hint_string; - } else if (p_arginfo.type == Variant::NIL) { - // Parameters cannot be void, so PROPERTY_USAGE_NIL_IS_VARIANT is not necessary - p_argument.type = "Variant"; - } else { - p_argument.type = Variant::get_type_name(p_arginfo.type); +bool DocTools::has_doc(const String &p_class_name) { + if (p_class_name == "") { + return false; } + return class_list.has(p_class_name); } static Variant get_documentation_default_value(const StringName &p_class_name, const StringName &p_property_name, bool &r_default_value_valid) { @@ -253,7 +225,7 @@ static Variant get_documentation_default_value(const StringName &p_class_name, c return default_value; } -void DocData::generate(bool p_basic_types) { +void DocTools::generate(bool p_basic_types) { List classes; ClassDB::get_class_list(&classes); classes.sort_custom(); @@ -277,8 +249,8 @@ void DocData::generate(bool p_basic_types) { cname = cname.substr(1, name.length()); } - class_list[cname] = ClassDoc(); - ClassDoc &c = class_list[cname]; + class_list[cname] = DocData::ClassDoc(); + DocData::ClassDoc &c = class_list[cname]; c.name = cname; c.inherits = ClassDB::get_parent_class(name); @@ -305,7 +277,7 @@ void DocData::generate(bool p_basic_types) { continue; } - PropertyDoc prop; + DocData::PropertyDoc prop; prop.name = E->get().name; @@ -409,7 +381,7 @@ void DocData::generate(bool p_basic_types) { } } - MethodDoc method; + DocData::MethodDoc method; method.name = E->get().name; @@ -432,12 +404,12 @@ void DocData::generate(bool p_basic_types) { for (int i = -1; i < E->get().arguments.size(); i++) { if (i == -1) { #ifdef DEBUG_METHODS_ENABLED - return_doc_from_retinfo(method, E->get().return_val); + DocData::return_doc_from_retinfo(method, E->get().return_val); #endif } else { const PropertyInfo &arginfo = E->get().arguments[i]; - ArgumentDoc argument; - argument_doc_from_arginfo(argument, arginfo); + DocData::ArgumentDoc argument; + DocData::argument_doc_from_arginfo(argument, arginfo); int darg_idx = i - (E->get().arguments.size() - E->get().default_arguments.size()); if (darg_idx >= 0) { @@ -457,12 +429,12 @@ void DocData::generate(bool p_basic_types) { if (signal_list.size()) { for (List::Element *EV = signal_list.front(); EV; EV = EV->next()) { - MethodDoc signal; + DocData::MethodDoc signal; signal.name = EV->get().name; for (int i = 0; i < EV->get().arguments.size(); i++) { const PropertyInfo &arginfo = EV->get().arguments[i]; - ArgumentDoc argument; - argument_doc_from_arginfo(argument, arginfo); + DocData::ArgumentDoc argument; + DocData::argument_doc_from_arginfo(argument, arginfo); signal.arguments.push_back(argument); } @@ -475,7 +447,7 @@ void DocData::generate(bool p_basic_types) { ClassDB::get_integer_constant_list(name, &constant_list, true); for (List::Element *E = constant_list.front(); E; E = E->next()) { - ConstantDoc constant; + DocData::ConstantDoc constant; constant.name = E->get(); constant.value = itos(ClassDB::get_integer_constant(name, E->get())); constant.is_value_valid = true; @@ -489,7 +461,7 @@ void DocData::generate(bool p_basic_types) { List l; Theme::get_default()->get_constant_list(cname, &l); for (List::Element *E = l.front(); E; E = E->next()) { - PropertyDoc pd; + DocData::PropertyDoc pd; pd.name = E->get(); pd.type = "int"; pd.default_value = itos(Theme::get_default()->get_constant(E->get(), cname)); @@ -499,7 +471,7 @@ void DocData::generate(bool p_basic_types) { l.clear(); Theme::get_default()->get_color_list(cname, &l); for (List::Element *E = l.front(); E; E = E->next()) { - PropertyDoc pd; + DocData::PropertyDoc pd; pd.name = E->get(); pd.type = "Color"; pd.default_value = Variant(Theme::get_default()->get_color(E->get(), cname)).get_construct_string(); @@ -509,7 +481,7 @@ void DocData::generate(bool p_basic_types) { l.clear(); Theme::get_default()->get_icon_list(cname, &l); for (List::Element *E = l.front(); E; E = E->next()) { - PropertyDoc pd; + DocData::PropertyDoc pd; pd.name = E->get(); pd.type = "Texture2D"; c.theme_properties.push_back(pd); @@ -517,7 +489,7 @@ void DocData::generate(bool p_basic_types) { l.clear(); Theme::get_default()->get_font_list(cname, &l); for (List::Element *E = l.front(); E; E = E->next()) { - PropertyDoc pd; + DocData::PropertyDoc pd; pd.name = E->get(); pd.type = "Font"; c.theme_properties.push_back(pd); @@ -525,7 +497,7 @@ void DocData::generate(bool p_basic_types) { l.clear(); Theme::get_default()->get_font_size_list(cname, &l); for (List::Element *E = l.front(); E; E = E->next()) { - PropertyDoc pd; + DocData::PropertyDoc pd; pd.name = E->get(); pd.type = "int"; c.theme_properties.push_back(pd); @@ -533,7 +505,7 @@ void DocData::generate(bool p_basic_types) { l.clear(); Theme::get_default()->get_stylebox_list(cname, &l); for (List::Element *E = l.front(); E; E = E->next()) { - PropertyDoc pd; + DocData::PropertyDoc pd; pd.name = E->get(); pd.type = "StyleBox"; c.theme_properties.push_back(pd); @@ -545,7 +517,7 @@ void DocData::generate(bool p_basic_types) { { // So we can document the concept of Variant even if it's not a usable class per se. - class_list["Variant"] = ClassDoc(); + class_list["Variant"] = DocData::ClassDoc(); class_list["Variant"].name = "Variant"; } @@ -564,8 +536,8 @@ void DocData::generate(bool p_basic_types) { String cname = Variant::get_type_name(Variant::Type(i)); - class_list[cname] = ClassDoc(); - ClassDoc &c = class_list[cname]; + class_list[cname] = DocData::ClassDoc(); + DocData::ClassDoc &c = class_list[cname]; c.name = cname; Callable::CallError cerror; @@ -642,7 +614,7 @@ void DocData::generate(bool p_basic_types) { for (List::Element *E = method_list.front(); E; E = E->next()) { MethodInfo &mi = E->get(); - MethodDoc method; + DocData::MethodDoc method; method.name = mi.name; if (method.name == cname) { @@ -653,8 +625,8 @@ void DocData::generate(bool p_basic_types) { for (int j = 0; j < mi.arguments.size(); j++) { PropertyInfo arginfo = mi.arguments[j]; - ArgumentDoc ad; - argument_doc_from_arginfo(ad, mi.arguments[j]); + DocData::ArgumentDoc ad; + DocData::argument_doc_from_arginfo(ad, mi.arguments[j]); ad.name = arginfo.name; int darg_idx = mi.default_arguments.size() - mi.arguments.size() + j; @@ -666,7 +638,7 @@ void DocData::generate(bool p_basic_types) { method.arguments.push_back(ad); } - return_doc_from_retinfo(method, mi.return_val); + DocData::return_doc_from_retinfo(method, mi.return_val); if (mi.flags & METHOD_FLAG_VARARG) { if (method.qualifiers != "") { @@ -682,7 +654,7 @@ void DocData::generate(bool p_basic_types) { v.get_property_list(&properties); for (List::Element *E = properties.front(); E; E = E->next()) { PropertyInfo pi = E->get(); - PropertyDoc property; + DocData::PropertyDoc property; property.name = pi.name; property.type = Variant::get_type_name(pi.type); property.default_value = v.get(pi.name).get_construct_string(); @@ -694,7 +666,7 @@ void DocData::generate(bool p_basic_types) { Variant::get_constants_for_type(Variant::Type(i), &constants); for (List::Element *E = constants.front(); E; E = E->next()) { - ConstantDoc constant; + DocData::ConstantDoc constant; constant.name = E->get(); Variant value = Variant::get_constant_value(Variant::Type(i), E->get()); constant.value = value.get_type() == Variant::INT ? itos(value) : value.get_construct_string(); @@ -707,12 +679,12 @@ void DocData::generate(bool p_basic_types) { { String cname = "@GlobalScope"; - class_list[cname] = ClassDoc(); - ClassDoc &c = class_list[cname]; + class_list[cname] = DocData::ClassDoc(); + DocData::ClassDoc &c = class_list[cname]; c.name = cname; for (int i = 0; i < CoreConstants::get_global_constant_count(); i++) { - ConstantDoc cd; + DocData::ConstantDoc cd; cd.name = CoreConstants::get_global_constant_name(i); if (!CoreConstants::get_ignore_value_in_docs(i)) { cd.value = itos(CoreConstants::get_global_constant_value(i)); @@ -729,7 +701,7 @@ void DocData::generate(bool p_basic_types) { //servers (this is kind of hackish) for (List::Element *E = singletons.front(); E; E = E->next()) { - PropertyDoc pd; + DocData::PropertyDoc pd; Engine::Singleton &s = E->get(); if (!s.ptr) { continue; @@ -749,7 +721,7 @@ void DocData::generate(bool p_basic_types) { Variant::get_utility_function_list(&utility_functions); utility_functions.sort_custom(); for (List::Element *E = utility_functions.front(); E; E = E->next()) { - MethodDoc md; + DocData::MethodDoc md; md.name = E->get(); //return if (Variant::has_utility_function_return_value(E->get())) { @@ -759,7 +731,7 @@ void DocData::generate(bool p_basic_types) { pi.usage = PROPERTY_USAGE_NIL_IS_VARIANT; } DocData::ArgumentDoc ad; - argument_doc_from_arginfo(ad, pi); + DocData::argument_doc_from_arginfo(ad, pi); md.return_type = ad.type; } @@ -774,7 +746,7 @@ void DocData::generate(bool p_basic_types) { pi.usage = PROPERTY_USAGE_NIL_IS_VARIANT; } DocData::ArgumentDoc ad; - argument_doc_from_arginfo(ad, pi); + DocData::argument_doc_from_arginfo(ad, pi); md.arguments.push_back(ad); } } @@ -791,7 +763,7 @@ void DocData::generate(bool p_basic_types) { for (int i = 0; i < ScriptServer::get_language_count(); i++) { ScriptLanguage *lang = ScriptServer::get_language(i); String cname = "@" + lang->get_name(); - ClassDoc c; + DocData::ClassDoc c; c.name = cname; // Get functions. @@ -800,7 +772,7 @@ void DocData::generate(bool p_basic_types) { for (List::Element *E = minfo.front(); E; E = E->next()) { MethodInfo &mi = E->get(); - MethodDoc md; + DocData::MethodDoc md; md.name = mi.name; if (mi.flags & METHOD_FLAG_VARARG) { @@ -810,11 +782,11 @@ void DocData::generate(bool p_basic_types) { md.qualifiers += "vararg"; } - return_doc_from_retinfo(md, mi.return_val); + DocData::return_doc_from_retinfo(md, mi.return_val); for (int j = 0; j < mi.arguments.size(); j++) { - ArgumentDoc ad; - argument_doc_from_arginfo(ad, mi.arguments[j]); + DocData::ArgumentDoc ad; + DocData::argument_doc_from_arginfo(ad, mi.arguments[j]); int darg_idx = j - (mi.arguments.size() - mi.default_arguments.size()); if (darg_idx >= 0) { @@ -833,7 +805,7 @@ void DocData::generate(bool p_basic_types) { lang->get_public_constants(&cinfo); for (List>::Element *E = cinfo.front(); E; E = E->next()) { - ConstantDoc cd; + DocData::ConstantDoc cd; cd.name = E->get().first; cd.value = E->get().second; cd.is_value_valid = true; @@ -911,7 +883,7 @@ static Error _parse_methods(Ref &parser, Vector & return OK; } -Error DocData::load_classes(const String &p_dir) { +Error DocTools::load_classes(const String &p_dir) { Error err; DirAccessRef da = DirAccess::open(p_dir, &err); if (!da) { @@ -939,7 +911,7 @@ Error DocData::load_classes(const String &p_dir) { return OK; } -Error DocData::erase_classes(const String &p_dir) { +Error DocTools::erase_classes(const String &p_dir) { Error err; DirAccessRef da = DirAccess::open(p_dir, &err); if (!da) { @@ -967,7 +939,7 @@ Error DocData::erase_classes(const String &p_dir) { return OK; } -Error DocData::_load(Ref parser) { +Error DocTools::_load(Ref parser) { Error err = OK; while ((err = parser->read()) == OK) { @@ -983,8 +955,8 @@ Error DocData::_load(Ref parser) { ERR_FAIL_COND_V(!parser->has_attribute("name"), ERR_FILE_CORRUPT); String name = parser->get_attribute_value("name"); - class_list[name] = ClassDoc(); - ClassDoc &c = class_list[name]; + class_list[name] = DocData::ClassDoc(); + DocData::ClassDoc &c = class_list[name]; c.name = name; if (parser->has_attribute("inherits")) { @@ -1012,7 +984,7 @@ Error DocData::_load(Ref parser) { String name3 = parser->get_node_name(); if (name3 == "link") { - TutorialDoc tutorial; + DocData::TutorialDoc tutorial; if (parser->has_attribute("title")) { tutorial.title = parser->get_attribute_value("title"); } @@ -1041,7 +1013,7 @@ Error DocData::_load(Ref parser) { String name3 = parser->get_node_name(); if (name3 == "member") { - PropertyDoc prop2; + DocData::PropertyDoc prop2; ERR_FAIL_COND_V(!parser->has_attribute("name"), ERR_FILE_CORRUPT); prop2.name = parser->get_attribute_value("name"); @@ -1078,7 +1050,7 @@ Error DocData::_load(Ref parser) { String name3 = parser->get_node_name(); if (name3 == "theme_item") { - PropertyDoc prop2; + DocData::PropertyDoc prop2; ERR_FAIL_COND_V(!parser->has_attribute("name"), ERR_FILE_CORRUPT); prop2.name = parser->get_attribute_value("name"); @@ -1106,7 +1078,7 @@ Error DocData::_load(Ref parser) { String name3 = parser->get_node_name(); if (name3 == "constant") { - ConstantDoc constant2; + DocData::ConstantDoc constant2; ERR_FAIL_COND_V(!parser->has_attribute("name"), ERR_FILE_CORRUPT); constant2.name = parser->get_attribute_value("name"); ERR_FAIL_COND_V(!parser->has_attribute("value"), ERR_FILE_CORRUPT); @@ -1155,9 +1127,9 @@ static void _write_string(FileAccess *f, int p_tablevel, const String &p_string) f->store_string(tab + p_string + "\n"); } -Error DocData::save_classes(const String &p_default_path, const Map &p_class_path) { - for (Map::Element *E = class_list.front(); E; E = E->next()) { - ClassDoc &c = E->get(); +Error DocTools::save_classes(const String &p_default_path, const Map &p_class_path) { + for (Map::Element *E = class_list.front(); E; E = E->next()) { + DocData::ClassDoc &c = E->get(); String save_path; if (p_class_path.has(c.name)) { @@ -1192,7 +1164,7 @@ Error DocData::save_classes(const String &p_default_path, const Map"); for (int i = 0; i < c.tutorials.size(); i++) { - TutorialDoc tutorial = c.tutorials.get(i); + DocData::TutorialDoc tutorial = c.tutorials.get(i); String title_attribute = (!tutorial.title.empty()) ? " title=\"" + tutorial.title.xml_escape() + "\"" : ""; _write_string(f, 2, "" + tutorial.link.xml_escape() + ""); } @@ -1203,7 +1175,7 @@ Error DocData::save_classes(const String &p_default_path, const Map"); @@ -1279,10 +1251,10 @@ Error DocData::save_classes(const String &p_default_path, const Map"); for (int i = 0; i < c.signals.size(); i++) { - const MethodDoc &m = c.signals[i]; + const DocData::MethodDoc &m = c.signals[i]; _write_string(f, 2, ""); for (int j = 0; j < m.arguments.size(); j++) { - const ArgumentDoc &a = m.arguments[j]; + const DocData::ArgumentDoc &a = m.arguments[j]; _write_string(f, 3, ""); _write_string(f, 3, ""); } @@ -1300,7 +1272,7 @@ Error DocData::save_classes(const String &p_default_path, const Map"); for (int i = 0; i < c.constants.size(); i++) { - const ConstantDoc &k = c.constants[i]; + const DocData::ConstantDoc &k = c.constants[i]; if (k.is_value_valid) { if (k.enumeration != String()) { _write_string(f, 2, ""); @@ -1325,7 +1297,7 @@ Error DocData::save_classes(const String &p_default_path, const Map"); for (int i = 0; i < c.theme_properties.size(); i++) { - const PropertyDoc &p = c.theme_properties[i]; + const DocData::PropertyDoc &p = c.theme_properties[i]; if (p.default_value != "") { _write_string(f, 2, ""); @@ -1346,7 +1318,7 @@ Error DocData::save_classes(const String &p_default_path, const Map data; data.resize(p_uncompressed_size); Compression::decompress(data.ptrw(), p_uncompressed_size, p_data, p_compressed_size, Compression::MODE_DEFLATE); diff --git a/editor/doc_tools.h b/editor/doc_tools.h new file mode 100644 index 0000000000..db27e38c8b --- /dev/null +++ b/editor/doc_tools.h @@ -0,0 +1,56 @@ +/*************************************************************************/ +/* doc_tools.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef DOC_TOOLS_H +#define DOC_TOOLS_H + +#include "core/doc_data.h" + +class DocTools { +public: + String version; + Map class_list; + + static Error erase_classes(const String &p_dir); + + void merge_from(const DocTools &p_data); + void remove_from(const DocTools &p_data); + void add_doc(const DocData::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); + Error save_classes(const String &p_default_path, const Map &p_class_path); + + Error _load(Ref parser); + Error load_compressed(const uint8_t *p_data, int p_compressed_size, int p_uncompressed_size); +}; + +#endif // DOC_DATA_H diff --git a/editor/editor_file_system.cpp b/editor/editor_file_system.cpp index c66bc9b3fa..6dcc505a11 100644 --- a/editor/editor_file_system.cpp +++ b/editor/editor_file_system.cpp @@ -799,6 +799,20 @@ void EditorFileSystem::_scan_new_dir(EditorFileSystemDirectory *p_dir, DirAccess } } + for (int i = 0; i < ScriptServer::get_language_count(); i++) { + ScriptLanguage *lang = ScriptServer::get_language(i); + if (lang->supports_documentation() && fi->type == lang->get_type()) { + Ref