Merge pull request #78941 from dalexeev/gds-doc-comments-deprecated-and-experimental
GDScript: Add `@deprecated` and `@experimental` doc comment tags
This commit is contained in:
commit
41efc7cb86
5 changed files with 211 additions and 99 deletions
|
@ -532,6 +532,42 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct EnumDoc {
|
||||||
|
String description;
|
||||||
|
bool is_deprecated = false;
|
||||||
|
bool is_experimental = false;
|
||||||
|
static EnumDoc from_dict(const Dictionary &p_dict) {
|
||||||
|
EnumDoc doc;
|
||||||
|
|
||||||
|
if (p_dict.has("description")) {
|
||||||
|
doc.description = p_dict["description"];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p_dict.has("is_deprecated")) {
|
||||||
|
doc.is_deprecated = p_dict["is_deprecated"];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p_dict.has("is_experimental")) {
|
||||||
|
doc.is_experimental = p_dict["is_experimental"];
|
||||||
|
}
|
||||||
|
|
||||||
|
return doc;
|
||||||
|
}
|
||||||
|
static Dictionary to_dict(const EnumDoc &p_doc) {
|
||||||
|
Dictionary dict;
|
||||||
|
|
||||||
|
if (!p_doc.description.is_empty()) {
|
||||||
|
dict["description"] = p_doc.description;
|
||||||
|
}
|
||||||
|
|
||||||
|
dict["is_deprecated"] = p_doc.is_deprecated;
|
||||||
|
|
||||||
|
dict["is_experimental"] = p_doc.is_experimental;
|
||||||
|
|
||||||
|
return dict;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
struct ClassDoc {
|
struct ClassDoc {
|
||||||
String name;
|
String name;
|
||||||
String inherits;
|
String inherits;
|
||||||
|
@ -543,7 +579,7 @@ public:
|
||||||
Vector<MethodDoc> operators;
|
Vector<MethodDoc> operators;
|
||||||
Vector<MethodDoc> signals;
|
Vector<MethodDoc> signals;
|
||||||
Vector<ConstantDoc> constants;
|
Vector<ConstantDoc> constants;
|
||||||
HashMap<String, String> enums;
|
HashMap<String, EnumDoc> enums;
|
||||||
Vector<PropertyDoc> properties;
|
Vector<PropertyDoc> properties;
|
||||||
Vector<MethodDoc> annotations;
|
Vector<MethodDoc> annotations;
|
||||||
Vector<ThemeItemDoc> theme_properties;
|
Vector<ThemeItemDoc> theme_properties;
|
||||||
|
@ -626,7 +662,7 @@ public:
|
||||||
enums = p_dict["enums"];
|
enums = p_dict["enums"];
|
||||||
}
|
}
|
||||||
for (int i = 0; i < enums.size(); i++) {
|
for (int i = 0; i < enums.size(); i++) {
|
||||||
doc.enums[enums.get_key_at_index(i)] = enums.get_value_at_index(i);
|
doc.enums[enums.get_key_at_index(i)] = EnumDoc::from_dict(enums.get_value_at_index(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
Array properties;
|
Array properties;
|
||||||
|
@ -740,8 +776,8 @@ public:
|
||||||
|
|
||||||
if (!p_doc.enums.is_empty()) {
|
if (!p_doc.enums.is_empty()) {
|
||||||
Dictionary enums;
|
Dictionary enums;
|
||||||
for (const KeyValue<String, String> &E : p_doc.enums) {
|
for (const KeyValue<String, EnumDoc> &E : p_doc.enums) {
|
||||||
enums[E.key] = E.value;
|
enums[E.key] = EnumDoc::to_dict(E.value);
|
||||||
}
|
}
|
||||||
dict["enums"] = enums;
|
dict["enums"] = enums;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1059,6 +1059,7 @@ void EditorHelp::_update_doc() {
|
||||||
if (cd.properties[i].is_deprecated) {
|
if (cd.properties[i].is_deprecated) {
|
||||||
DEPRECATED_DOC_TAG;
|
DEPRECATED_DOC_TAG;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cd.properties[i].is_experimental) {
|
if (cd.properties[i].is_experimental) {
|
||||||
EXPERIMENTAL_DOC_TAG;
|
EXPERIMENTAL_DOC_TAG;
|
||||||
}
|
}
|
||||||
|
@ -1303,6 +1304,7 @@ void EditorHelp::_update_doc() {
|
||||||
if (cd.signals[i].is_deprecated) {
|
if (cd.signals[i].is_deprecated) {
|
||||||
DEPRECATED_DOC_TAG;
|
DEPRECATED_DOC_TAG;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cd.signals[i].is_experimental) {
|
if (cd.signals[i].is_experimental) {
|
||||||
EXPERIMENTAL_DOC_TAG;
|
EXPERIMENTAL_DOC_TAG;
|
||||||
}
|
}
|
||||||
|
@ -1363,6 +1365,7 @@ void EditorHelp::_update_doc() {
|
||||||
enum_line[E.key] = class_desc->get_paragraph_count() - 2;
|
enum_line[E.key] = class_desc->get_paragraph_count() - 2;
|
||||||
|
|
||||||
_push_code_font();
|
_push_code_font();
|
||||||
|
|
||||||
class_desc->push_color(theme_cache.title_color);
|
class_desc->push_color(theme_cache.title_color);
|
||||||
if (E.value.size() && E.value[0].is_bitfield) {
|
if (E.value.size() && E.value[0].is_bitfield) {
|
||||||
class_desc->add_text("flags ");
|
class_desc->add_text("flags ");
|
||||||
|
@ -1379,21 +1382,32 @@ void EditorHelp::_update_doc() {
|
||||||
class_desc->push_color(theme_cache.headline_color);
|
class_desc->push_color(theme_cache.headline_color);
|
||||||
class_desc->add_text(e);
|
class_desc->add_text(e);
|
||||||
class_desc->pop();
|
class_desc->pop();
|
||||||
_pop_code_font();
|
|
||||||
|
|
||||||
class_desc->push_color(theme_cache.symbol_color);
|
class_desc->push_color(theme_cache.symbol_color);
|
||||||
class_desc->add_text(":");
|
class_desc->add_text(":");
|
||||||
class_desc->pop();
|
class_desc->pop();
|
||||||
|
|
||||||
|
if (cd.enums.has(e)) {
|
||||||
|
if (cd.enums[e].is_deprecated) {
|
||||||
|
DEPRECATED_DOC_TAG;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cd.enums[e].is_experimental) {
|
||||||
|
EXPERIMENTAL_DOC_TAG;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_pop_code_font();
|
||||||
|
|
||||||
class_desc->add_newline();
|
class_desc->add_newline();
|
||||||
class_desc->add_newline();
|
class_desc->add_newline();
|
||||||
|
|
||||||
// Enum description.
|
// Enum description.
|
||||||
if (e != "@unnamed_enums" && cd.enums.has(e) && !cd.enums[e].strip_edges().is_empty()) {
|
if (e != "@unnamed_enums" && cd.enums.has(e) && !cd.enums[e].description.strip_edges().is_empty()) {
|
||||||
class_desc->push_color(theme_cache.text_color);
|
class_desc->push_color(theme_cache.text_color);
|
||||||
_push_normal_font();
|
_push_normal_font();
|
||||||
class_desc->push_indent(1);
|
class_desc->push_indent(1);
|
||||||
_add_text(cd.enums[e]);
|
_add_text(cd.enums[e].description);
|
||||||
class_desc->pop();
|
class_desc->pop();
|
||||||
_pop_normal_font();
|
_pop_normal_font();
|
||||||
class_desc->pop();
|
class_desc->pop();
|
||||||
|
@ -1417,6 +1431,7 @@ void EditorHelp::_update_doc() {
|
||||||
constant_line[enum_list[i].name] = class_desc->get_paragraph_count() - 2;
|
constant_line[enum_list[i].name] = class_desc->get_paragraph_count() - 2;
|
||||||
|
|
||||||
_push_code_font();
|
_push_code_font();
|
||||||
|
|
||||||
_add_bulletpoint();
|
_add_bulletpoint();
|
||||||
class_desc->push_color(theme_cache.headline_color);
|
class_desc->push_color(theme_cache.headline_color);
|
||||||
_add_text(enum_list[i].name);
|
_add_text(enum_list[i].name);
|
||||||
|
@ -1427,7 +1442,6 @@ void EditorHelp::_update_doc() {
|
||||||
class_desc->push_color(theme_cache.value_color);
|
class_desc->push_color(theme_cache.value_color);
|
||||||
_add_text(_fix_constant(enum_list[i].value));
|
_add_text(_fix_constant(enum_list[i].value));
|
||||||
class_desc->pop();
|
class_desc->pop();
|
||||||
_pop_code_font();
|
|
||||||
|
|
||||||
if (enum_list[i].is_deprecated) {
|
if (enum_list[i].is_deprecated) {
|
||||||
DEPRECATED_DOC_TAG;
|
DEPRECATED_DOC_TAG;
|
||||||
|
@ -1437,6 +1451,8 @@ void EditorHelp::_update_doc() {
|
||||||
EXPERIMENTAL_DOC_TAG;
|
EXPERIMENTAL_DOC_TAG;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_pop_code_font();
|
||||||
|
|
||||||
class_desc->add_newline();
|
class_desc->add_newline();
|
||||||
|
|
||||||
if (!enum_list[i].description.strip_edges().is_empty()) {
|
if (!enum_list[i].description.strip_edges().is_empty()) {
|
||||||
|
@ -1503,8 +1519,6 @@ void EditorHelp::_update_doc() {
|
||||||
_add_text(_fix_constant(constants[i].value));
|
_add_text(_fix_constant(constants[i].value));
|
||||||
class_desc->pop();
|
class_desc->pop();
|
||||||
|
|
||||||
_pop_code_font();
|
|
||||||
|
|
||||||
if (constants[i].is_deprecated) {
|
if (constants[i].is_deprecated) {
|
||||||
DEPRECATED_DOC_TAG;
|
DEPRECATED_DOC_TAG;
|
||||||
}
|
}
|
||||||
|
@ -1513,6 +1527,8 @@ void EditorHelp::_update_doc() {
|
||||||
EXPERIMENTAL_DOC_TAG;
|
EXPERIMENTAL_DOC_TAG;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_pop_code_font();
|
||||||
|
|
||||||
class_desc->add_newline();
|
class_desc->add_newline();
|
||||||
|
|
||||||
if (!constants[i].description.strip_edges().is_empty()) {
|
if (!constants[i].description.strip_edges().is_empty()) {
|
||||||
|
@ -1692,6 +1708,7 @@ void EditorHelp::_update_doc() {
|
||||||
if (cd.properties[i].is_deprecated) {
|
if (cd.properties[i].is_deprecated) {
|
||||||
DEPRECATED_DOC_TAG;
|
DEPRECATED_DOC_TAG;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cd.properties[i].is_experimental) {
|
if (cd.properties[i].is_experimental) {
|
||||||
EXPERIMENTAL_DOC_TAG;
|
EXPERIMENTAL_DOC_TAG;
|
||||||
}
|
}
|
||||||
|
|
|
@ -101,14 +101,16 @@ void GDScriptDocGen::generate_docs(GDScript *p_script, const GDP::ClassNode *p_c
|
||||||
doc.inherits = p_script->native->get_name();
|
doc.inherits = p_script->native->get_name();
|
||||||
}
|
}
|
||||||
|
|
||||||
doc.brief_description = p_class->doc_brief_description;
|
doc.brief_description = p_class->doc_data.brief;
|
||||||
doc.description = p_class->doc_description;
|
doc.description = p_class->doc_data.description;
|
||||||
for (const Pair<String, String> &p : p_class->doc_tutorials) {
|
for (const Pair<String, String> &p : p_class->doc_data.tutorials) {
|
||||||
DocData::TutorialDoc td;
|
DocData::TutorialDoc td;
|
||||||
td.title = p.first;
|
td.title = p.first;
|
||||||
td.link = p.second;
|
td.link = p.second;
|
||||||
doc.tutorials.append(td);
|
doc.tutorials.append(td);
|
||||||
}
|
}
|
||||||
|
doc.is_deprecated = p_class->doc_data.is_deprecated;
|
||||||
|
doc.is_experimental = p_class->doc_data.is_experimental;
|
||||||
|
|
||||||
for (const GDP::ClassNode::Member &member : p_class->members) {
|
for (const GDP::ClassNode::Member &member : p_class->members) {
|
||||||
switch (member.type) {
|
switch (member.type) {
|
||||||
|
@ -130,7 +132,9 @@ void GDScriptDocGen::generate_docs(GDScript *p_script, const GDP::ClassNode *p_c
|
||||||
p_script->member_lines[const_name] = m_const->start_line;
|
p_script->member_lines[const_name] = m_const->start_line;
|
||||||
|
|
||||||
DocData::ConstantDoc const_doc;
|
DocData::ConstantDoc const_doc;
|
||||||
DocData::constant_doc_from_variant(const_doc, const_name, m_const->initializer->reduced_value, m_const->doc_description);
|
DocData::constant_doc_from_variant(const_doc, const_name, m_const->initializer->reduced_value, m_const->doc_data.description);
|
||||||
|
const_doc.is_deprecated = m_const->doc_data.is_deprecated;
|
||||||
|
const_doc.is_experimental = m_const->doc_data.is_experimental;
|
||||||
doc.constants.push_back(const_doc);
|
doc.constants.push_back(const_doc);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
@ -153,7 +157,9 @@ void GDScriptDocGen::generate_docs(GDScript *p_script, const GDP::ClassNode *p_c
|
||||||
}
|
}
|
||||||
|
|
||||||
DocData::MethodDoc method_doc;
|
DocData::MethodDoc method_doc;
|
||||||
DocData::method_doc_from_methodinfo(method_doc, mi, m_func->doc_description);
|
DocData::method_doc_from_methodinfo(method_doc, mi, m_func->doc_data.description);
|
||||||
|
method_doc.is_deprecated = m_func->doc_data.is_deprecated;
|
||||||
|
method_doc.is_experimental = m_func->doc_data.is_experimental;
|
||||||
doc.methods.push_back(method_doc);
|
doc.methods.push_back(method_doc);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
@ -172,7 +178,9 @@ void GDScriptDocGen::generate_docs(GDScript *p_script, const GDP::ClassNode *p_c
|
||||||
}
|
}
|
||||||
|
|
||||||
DocData::MethodDoc signal_doc;
|
DocData::MethodDoc signal_doc;
|
||||||
DocData::signal_doc_from_methodinfo(signal_doc, mi, m_signal->doc_description);
|
DocData::signal_doc_from_methodinfo(signal_doc, mi, m_signal->doc_data.description);
|
||||||
|
signal_doc.is_deprecated = m_signal->doc_data.is_deprecated;
|
||||||
|
signal_doc.is_experimental = m_signal->doc_data.is_experimental;
|
||||||
doc.signals.push_back(signal_doc);
|
doc.signals.push_back(signal_doc);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
@ -185,7 +193,9 @@ void GDScriptDocGen::generate_docs(GDScript *p_script, const GDP::ClassNode *p_c
|
||||||
DocData::PropertyDoc prop_doc;
|
DocData::PropertyDoc prop_doc;
|
||||||
|
|
||||||
prop_doc.name = var_name;
|
prop_doc.name = var_name;
|
||||||
prop_doc.description = m_var->doc_description;
|
prop_doc.description = m_var->doc_data.description;
|
||||||
|
prop_doc.is_deprecated = m_var->doc_data.is_deprecated;
|
||||||
|
prop_doc.is_experimental = m_var->doc_data.is_experimental;
|
||||||
|
|
||||||
GDType dt = m_var->get_datatype();
|
GDType dt = m_var->get_datatype();
|
||||||
switch (dt.kind) {
|
switch (dt.kind) {
|
||||||
|
@ -236,15 +246,21 @@ void GDScriptDocGen::generate_docs(GDScript *p_script, const GDP::ClassNode *p_c
|
||||||
|
|
||||||
p_script->member_lines[name] = m_enum->start_line;
|
p_script->member_lines[name] = m_enum->start_line;
|
||||||
|
|
||||||
doc.enums[name] = m_enum->doc_description;
|
DocData::EnumDoc enum_doc;
|
||||||
|
enum_doc.description = m_enum->doc_data.description;
|
||||||
|
enum_doc.is_deprecated = m_enum->doc_data.is_deprecated;
|
||||||
|
enum_doc.is_experimental = m_enum->doc_data.is_experimental;
|
||||||
|
doc.enums[name] = enum_doc;
|
||||||
|
|
||||||
for (const GDP::EnumNode::Value &val : m_enum->values) {
|
for (const GDP::EnumNode::Value &val : m_enum->values) {
|
||||||
DocData::ConstantDoc const_doc;
|
DocData::ConstantDoc const_doc;
|
||||||
const_doc.name = val.identifier->name;
|
const_doc.name = val.identifier->name;
|
||||||
const_doc.value = String(Variant(val.value));
|
const_doc.value = String(Variant(val.value));
|
||||||
const_doc.is_value_valid = true;
|
const_doc.is_value_valid = true;
|
||||||
const_doc.description = val.doc_description;
|
|
||||||
const_doc.enumeration = name;
|
const_doc.enumeration = name;
|
||||||
|
const_doc.description = val.doc_data.description;
|
||||||
|
const_doc.is_deprecated = val.doc_data.is_deprecated;
|
||||||
|
const_doc.is_experimental = val.doc_data.is_experimental;
|
||||||
|
|
||||||
doc.constants.push_back(const_doc);
|
doc.constants.push_back(const_doc);
|
||||||
}
|
}
|
||||||
|
@ -257,10 +273,12 @@ void GDScriptDocGen::generate_docs(GDScript *p_script, const GDP::ClassNode *p_c
|
||||||
|
|
||||||
p_script->member_lines[name] = m_enum_val.identifier->start_line;
|
p_script->member_lines[name] = m_enum_val.identifier->start_line;
|
||||||
|
|
||||||
DocData::ConstantDoc constant_doc;
|
DocData::ConstantDoc const_doc;
|
||||||
constant_doc.enumeration = "@unnamed_enums";
|
DocData::constant_doc_from_variant(const_doc, name, m_enum_val.value, m_enum_val.doc_data.description);
|
||||||
DocData::constant_doc_from_variant(constant_doc, name, m_enum_val.value, m_enum_val.doc_description);
|
const_doc.enumeration = "@unnamed_enums";
|
||||||
doc.constants.push_back(constant_doc);
|
const_doc.is_deprecated = m_enum_val.doc_data.is_deprecated;
|
||||||
|
const_doc.is_experimental = m_enum_val.doc_data.is_experimental;
|
||||||
|
doc.constants.push_back(const_doc);
|
||||||
} break;
|
} break;
|
||||||
case GDP::ClassNode::Member::GROUP:
|
case GDP::ClassNode::Member::GROUP:
|
||||||
case GDP::ClassNode::Member::UNDEFINED:
|
case GDP::ClassNode::Member::UNDEFINED:
|
||||||
|
|
|
@ -571,8 +571,8 @@ void GDScriptParser::parse_program() {
|
||||||
class_doc_line = MIN(class_doc_line, E.key);
|
class_doc_line = MIN(class_doc_line, E.key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (has_comment(class_doc_line)) {
|
if (has_comment(class_doc_line, true)) {
|
||||||
get_class_doc_comment(class_doc_line, head->doc_brief_description, head->doc_description, head->doc_tutorials, false);
|
head->doc_data = parse_class_doc_comment(class_doc_line, false);
|
||||||
}
|
}
|
||||||
#endif // TOOLS_ENABLED
|
#endif // TOOLS_ENABLED
|
||||||
|
|
||||||
|
@ -771,12 +771,16 @@ void GDScriptParser::parse_class_member(T *(GDScriptParser::*p_parse_function)(b
|
||||||
|
|
||||||
// Check whether current line has a doc comment
|
// Check whether current line has a doc comment
|
||||||
if (has_comment(previous.start_line, true)) {
|
if (has_comment(previous.start_line, true)) {
|
||||||
member->doc_description = get_doc_comment(previous.start_line, true);
|
if constexpr (std::is_same_v<T, ClassNode>) {
|
||||||
|
member->doc_data = parse_class_doc_comment(previous.start_line, true, true);
|
||||||
|
} else {
|
||||||
|
member->doc_data = parse_doc_comment(previous.start_line, true);
|
||||||
|
}
|
||||||
} else if (has_comment(doc_comment_line, true)) {
|
} else if (has_comment(doc_comment_line, true)) {
|
||||||
if constexpr (std::is_same_v<T, ClassNode>) {
|
if constexpr (std::is_same_v<T, ClassNode>) {
|
||||||
get_class_doc_comment(doc_comment_line, member->doc_brief_description, member->doc_description, member->doc_tutorials, true);
|
member->doc_data = parse_class_doc_comment(doc_comment_line, true);
|
||||||
} else {
|
} else {
|
||||||
member->doc_description = get_doc_comment(doc_comment_line);
|
member->doc_data = parse_doc_comment(doc_comment_line);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif // TOOLS_ENABLED
|
#endif // TOOLS_ENABLED
|
||||||
|
@ -1314,25 +1318,34 @@ GDScriptParser::EnumNode *GDScriptParser::parse_enum(bool p_is_static) {
|
||||||
#ifdef TOOLS_ENABLED
|
#ifdef TOOLS_ENABLED
|
||||||
// Enum values documentation.
|
// Enum values documentation.
|
||||||
for (int i = 0; i < enum_node->values.size(); i++) {
|
for (int i = 0; i < enum_node->values.size(); i++) {
|
||||||
|
int doc_comment_line = enum_node->values[i].line;
|
||||||
|
bool single_line = false;
|
||||||
|
|
||||||
|
if (has_comment(doc_comment_line, true)) {
|
||||||
|
single_line = true;
|
||||||
|
} else if (has_comment(doc_comment_line - 1, true)) {
|
||||||
|
doc_comment_line--;
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (i == enum_node->values.size() - 1) {
|
if (i == enum_node->values.size() - 1) {
|
||||||
// If close bracket is same line as last value.
|
// If close bracket is same line as last value.
|
||||||
if (enum_node->values[i].line != previous.start_line && has_comment(enum_node->values[i].line)) {
|
if (doc_comment_line == previous.start_line) {
|
||||||
if (named) {
|
break;
|
||||||
enum_node->values.write[i].doc_description = get_doc_comment(enum_node->values[i].line, true);
|
|
||||||
} else {
|
|
||||||
current_class->set_enum_value_doc(enum_node->values[i].identifier->name, get_doc_comment(enum_node->values[i].line, true));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// If two values are same line.
|
// If two values are same line.
|
||||||
if (enum_node->values[i].line != enum_node->values[i + 1].line && has_comment(enum_node->values[i].line)) {
|
if (doc_comment_line == enum_node->values[i + 1].line) {
|
||||||
if (named) {
|
continue;
|
||||||
enum_node->values.write[i].doc_description = get_doc_comment(enum_node->values[i].line, true);
|
|
||||||
} else {
|
|
||||||
current_class->set_enum_value_doc(enum_node->values[i].identifier->name, get_doc_comment(enum_node->values[i].line, true));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (named) {
|
||||||
|
enum_node->values.write[i].doc_data = parse_doc_comment(doc_comment_line, single_line);
|
||||||
|
} else {
|
||||||
|
current_class->set_enum_value_doc_data(enum_node->values[i].identifier->name, parse_doc_comment(doc_comment_line, single_line));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif // TOOLS_ENABLED
|
#endif // TOOLS_ENABLED
|
||||||
|
|
||||||
|
@ -3411,19 +3424,20 @@ bool GDScriptParser::has_comment(int p_line, bool p_must_be_doc) {
|
||||||
return tokenizer.get_comments()[p_line].comment.begins_with("##");
|
return tokenizer.get_comments()[p_line].comment.begins_with("##");
|
||||||
}
|
}
|
||||||
|
|
||||||
String GDScriptParser::get_doc_comment(int p_line, bool p_single_line) {
|
GDScriptParser::MemberDocData GDScriptParser::parse_doc_comment(int p_line, bool p_single_line) {
|
||||||
|
MemberDocData result;
|
||||||
|
|
||||||
const HashMap<int, GDScriptTokenizer::CommentData> &comments = tokenizer.get_comments();
|
const HashMap<int, GDScriptTokenizer::CommentData> &comments = tokenizer.get_comments();
|
||||||
ERR_FAIL_COND_V(!comments.has(p_line), String());
|
ERR_FAIL_COND_V(!comments.has(p_line), result);
|
||||||
|
|
||||||
if (p_single_line) {
|
if (p_single_line) {
|
||||||
if (comments[p_line].comment.begins_with("##")) {
|
if (comments[p_line].comment.begins_with("##")) {
|
||||||
return comments[p_line].comment.trim_prefix("##").strip_edges();
|
result.description = comments[p_line].comment.trim_prefix("##").strip_edges();
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
return "";
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
String doc;
|
|
||||||
|
|
||||||
int line = p_line;
|
int line = p_line;
|
||||||
DocLineState state = DOC_LINE_NORMAL;
|
DocLineState state = DOC_LINE_NORMAL;
|
||||||
|
|
||||||
|
@ -3451,29 +3465,42 @@ String GDScriptParser::get_doc_comment(int p_line, bool p_single_line) {
|
||||||
}
|
}
|
||||||
|
|
||||||
String doc_line = comments[line].comment.trim_prefix("##");
|
String doc_line = comments[line].comment.trim_prefix("##");
|
||||||
doc += _process_doc_line(doc_line, doc, space_prefix, state);
|
|
||||||
line++;
|
line++;
|
||||||
|
|
||||||
|
if (state == DOC_LINE_NORMAL) {
|
||||||
|
String stripped_line = doc_line.strip_edges();
|
||||||
|
if (stripped_line.begins_with("@deprecated")) {
|
||||||
|
result.is_deprecated = true;
|
||||||
|
continue;
|
||||||
|
} else if (stripped_line.begins_with("@experimental")) {
|
||||||
|
result.is_experimental = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result.description += _process_doc_line(doc_line, result.description, space_prefix, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
return doc;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GDScriptParser::get_class_doc_comment(int p_line, String &p_brief, String &p_desc, Vector<Pair<String, String>> &p_tutorials, bool p_inner_class) {
|
GDScriptParser::ClassDocData GDScriptParser::parse_class_doc_comment(int p_line, bool p_inner_class, bool p_single_line) {
|
||||||
|
ClassDocData result;
|
||||||
|
|
||||||
const HashMap<int, GDScriptTokenizer::CommentData> &comments = tokenizer.get_comments();
|
const HashMap<int, GDScriptTokenizer::CommentData> &comments = tokenizer.get_comments();
|
||||||
if (!comments.has(p_line)) {
|
ERR_FAIL_COND_V(!comments.has(p_line), result);
|
||||||
return;
|
|
||||||
|
if (p_single_line) {
|
||||||
|
if (comments[p_line].comment.begins_with("##")) {
|
||||||
|
result.brief = comments[p_line].comment.trim_prefix("##").strip_edges();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
ERR_FAIL_COND(!p_brief.is_empty() || !p_desc.is_empty() || p_tutorials.size() != 0);
|
|
||||||
|
|
||||||
int line = p_line;
|
int line = p_line;
|
||||||
DocLineState state = DOC_LINE_NORMAL;
|
DocLineState state = DOC_LINE_NORMAL;
|
||||||
enum Mode {
|
bool is_in_brief = true;
|
||||||
BRIEF,
|
|
||||||
DESC,
|
|
||||||
TUTORIALS,
|
|
||||||
DONE,
|
|
||||||
};
|
|
||||||
Mode mode = BRIEF;
|
|
||||||
|
|
||||||
if (p_inner_class) {
|
if (p_inner_class) {
|
||||||
while (comments.has(line - 1)) {
|
while (comments.has(line - 1)) {
|
||||||
|
@ -3500,18 +3527,21 @@ void GDScriptParser::get_class_doc_comment(int p_line, String &p_brief, String &
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
String doc_line = comments[line++].comment.trim_prefix("##");
|
String doc_line = comments[line].comment.trim_prefix("##");
|
||||||
String title, link; // For tutorials.
|
line++;
|
||||||
|
|
||||||
if (state == DOC_LINE_NORMAL) {
|
if (state == DOC_LINE_NORMAL) {
|
||||||
// Set the read mode.
|
|
||||||
String stripped_line = doc_line.strip_edges();
|
String stripped_line = doc_line.strip_edges();
|
||||||
if (stripped_line.is_empty()) {
|
|
||||||
if (mode == BRIEF && !p_brief.is_empty()) {
|
// A blank line separates the description from the brief.
|
||||||
mode = DESC;
|
if (is_in_brief && !result.brief.is_empty() && stripped_line.is_empty()) {
|
||||||
}
|
is_in_brief = false;
|
||||||
continue;
|
continue;
|
||||||
} else if (stripped_line.begins_with("@tutorial")) {
|
}
|
||||||
|
|
||||||
|
if (stripped_line.begins_with("@tutorial")) {
|
||||||
|
String title, link;
|
||||||
|
|
||||||
int begin_scan = String("@tutorial").length();
|
int begin_scan = String("@tutorial").length();
|
||||||
if (begin_scan >= stripped_line.length()) {
|
if (begin_scan >= stripped_line.length()) {
|
||||||
continue; // Invalid syntax.
|
continue; // Invalid syntax.
|
||||||
|
@ -3553,24 +3583,21 @@ void GDScriptParser::get_class_doc_comment(int p_line, String &p_brief, String &
|
||||||
link = stripped_line.substr(colon_pos).strip_edges();
|
link = stripped_line.substr(colon_pos).strip_edges();
|
||||||
}
|
}
|
||||||
|
|
||||||
mode = TUTORIALS;
|
result.tutorials.append(Pair<String, String>(title, link));
|
||||||
} else if (mode == TUTORIALS) { // Tutorial docs are single line, we need a @tag after it.
|
continue;
|
||||||
mode = DONE;
|
} else if (stripped_line.begins_with("@deprecated")) {
|
||||||
|
result.is_deprecated = true;
|
||||||
|
continue;
|
||||||
|
} else if (stripped_line.begins_with("@experimental")) {
|
||||||
|
result.is_experimental = true;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (mode) {
|
if (is_in_brief) {
|
||||||
case BRIEF:
|
result.brief += _process_doc_line(doc_line, result.brief, space_prefix, state);
|
||||||
p_brief += _process_doc_line(doc_line, p_brief, space_prefix, state);
|
} else {
|
||||||
break;
|
result.description += _process_doc_line(doc_line, result.description, space_prefix, state);
|
||||||
case DESC:
|
|
||||||
p_desc += _process_doc_line(doc_line, p_desc, space_prefix, state);
|
|
||||||
break;
|
|
||||||
case TUTORIALS:
|
|
||||||
p_tutorials.append(Pair<String, String>(title, link));
|
|
||||||
break;
|
|
||||||
case DONE:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3578,11 +3605,11 @@ void GDScriptParser::get_class_doc_comment(int p_line, String &p_brief, String &
|
||||||
const ClassNode::Member &m = current_class->members[0];
|
const ClassNode::Member &m = current_class->members[0];
|
||||||
int first_member_line = m.get_line();
|
int first_member_line = m.get_line();
|
||||||
if (first_member_line == line) {
|
if (first_member_line == line) {
|
||||||
p_brief = "";
|
result = ClassDocData(); // Clear result.
|
||||||
p_desc = "";
|
|
||||||
p_tutorials.clear();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
#endif // TOOLS_ENABLED
|
#endif // TOOLS_ENABLED
|
||||||
|
|
||||||
|
|
|
@ -257,6 +257,22 @@ public:
|
||||||
int line = 0, column = 0;
|
int line = 0, column = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef TOOLS_ENABLED
|
||||||
|
struct ClassDocData {
|
||||||
|
String brief;
|
||||||
|
String description;
|
||||||
|
Vector<Pair<String, String>> tutorials;
|
||||||
|
bool is_deprecated = false;
|
||||||
|
bool is_experimental = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MemberDocData {
|
||||||
|
String description;
|
||||||
|
bool is_deprecated = false;
|
||||||
|
bool is_experimental = false;
|
||||||
|
};
|
||||||
|
#endif // TOOLS_ENABLED
|
||||||
|
|
||||||
struct Node {
|
struct Node {
|
||||||
enum Type {
|
enum Type {
|
||||||
NONE,
|
NONE,
|
||||||
|
@ -505,7 +521,7 @@ public:
|
||||||
int leftmost_column = 0;
|
int leftmost_column = 0;
|
||||||
int rightmost_column = 0;
|
int rightmost_column = 0;
|
||||||
#ifdef TOOLS_ENABLED
|
#ifdef TOOLS_ENABLED
|
||||||
String doc_description;
|
MemberDocData doc_data;
|
||||||
#endif // TOOLS_ENABLED
|
#endif // TOOLS_ENABLED
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -513,7 +529,7 @@ public:
|
||||||
Vector<Value> values;
|
Vector<Value> values;
|
||||||
Variant dictionary;
|
Variant dictionary;
|
||||||
#ifdef TOOLS_ENABLED
|
#ifdef TOOLS_ENABLED
|
||||||
String doc_description;
|
MemberDocData doc_data;
|
||||||
#endif // TOOLS_ENABLED
|
#endif // TOOLS_ENABLED
|
||||||
|
|
||||||
EnumNode() {
|
EnumNode() {
|
||||||
|
@ -720,14 +736,12 @@ public:
|
||||||
DataType base_type;
|
DataType base_type;
|
||||||
String fqcn; // Fully-qualified class name. Identifies uniquely any class in the project.
|
String fqcn; // Fully-qualified class name. Identifies uniquely any class in the project.
|
||||||
#ifdef TOOLS_ENABLED
|
#ifdef TOOLS_ENABLED
|
||||||
String doc_description;
|
ClassDocData doc_data;
|
||||||
String doc_brief_description;
|
|
||||||
Vector<Pair<String, String>> doc_tutorials;
|
|
||||||
|
|
||||||
// EnumValue docs are parsed after itself, so we need a method to add/modify the doc property later.
|
// EnumValue docs are parsed after itself, so we need a method to add/modify the doc property later.
|
||||||
void set_enum_value_doc(const StringName &p_name, const String &p_doc_description) {
|
void set_enum_value_doc_data(const StringName &p_name, const MemberDocData &p_doc_data) {
|
||||||
ERR_FAIL_INDEX(members_indices[p_name], members.size());
|
ERR_FAIL_INDEX(members_indices[p_name], members.size());
|
||||||
members.write[members_indices[p_name]].enum_value.doc_description = p_doc_description;
|
members.write[members_indices[p_name]].enum_value.doc_data = p_doc_data;
|
||||||
}
|
}
|
||||||
#endif // TOOLS_ENABLED
|
#endif // TOOLS_ENABLED
|
||||||
|
|
||||||
|
@ -766,7 +780,7 @@ public:
|
||||||
|
|
||||||
struct ConstantNode : public AssignableNode {
|
struct ConstantNode : public AssignableNode {
|
||||||
#ifdef TOOLS_ENABLED
|
#ifdef TOOLS_ENABLED
|
||||||
String doc_description;
|
MemberDocData doc_data;
|
||||||
#endif // TOOLS_ENABLED
|
#endif // TOOLS_ENABLED
|
||||||
|
|
||||||
ConstantNode() {
|
ConstantNode() {
|
||||||
|
@ -821,7 +835,7 @@ public:
|
||||||
LambdaNode *source_lambda = nullptr;
|
LambdaNode *source_lambda = nullptr;
|
||||||
#ifdef TOOLS_ENABLED
|
#ifdef TOOLS_ENABLED
|
||||||
Vector<Variant> default_arg_values;
|
Vector<Variant> default_arg_values;
|
||||||
String doc_description;
|
MemberDocData doc_data;
|
||||||
#endif // TOOLS_ENABLED
|
#endif // TOOLS_ENABLED
|
||||||
|
|
||||||
bool resolved_signature = false;
|
bool resolved_signature = false;
|
||||||
|
@ -1008,7 +1022,7 @@ public:
|
||||||
Vector<ParameterNode *> parameters;
|
Vector<ParameterNode *> parameters;
|
||||||
HashMap<StringName, int> parameters_indices;
|
HashMap<StringName, int> parameters_indices;
|
||||||
#ifdef TOOLS_ENABLED
|
#ifdef TOOLS_ENABLED
|
||||||
String doc_description;
|
MemberDocData doc_data;
|
||||||
#endif // TOOLS_ENABLED
|
#endif // TOOLS_ENABLED
|
||||||
|
|
||||||
SignalNode() {
|
SignalNode() {
|
||||||
|
@ -1213,7 +1227,7 @@ public:
|
||||||
int assignments = 0;
|
int assignments = 0;
|
||||||
bool is_static = false;
|
bool is_static = false;
|
||||||
#ifdef TOOLS_ENABLED
|
#ifdef TOOLS_ENABLED
|
||||||
String doc_description;
|
MemberDocData doc_data;
|
||||||
#endif // TOOLS_ENABLED
|
#endif // TOOLS_ENABLED
|
||||||
|
|
||||||
VariableNode() {
|
VariableNode() {
|
||||||
|
@ -1488,12 +1502,12 @@ private:
|
||||||
ExpressionNode *parse_yield(ExpressionNode *p_previous_operand, bool p_can_assign);
|
ExpressionNode *parse_yield(ExpressionNode *p_previous_operand, bool p_can_assign);
|
||||||
ExpressionNode *parse_invalid_token(ExpressionNode *p_previous_operand, bool p_can_assign);
|
ExpressionNode *parse_invalid_token(ExpressionNode *p_previous_operand, bool p_can_assign);
|
||||||
TypeNode *parse_type(bool p_allow_void = false);
|
TypeNode *parse_type(bool p_allow_void = false);
|
||||||
|
|
||||||
#ifdef TOOLS_ENABLED
|
#ifdef TOOLS_ENABLED
|
||||||
// Doc comments.
|
|
||||||
int class_doc_line = 0x7FFFFFFF;
|
int class_doc_line = 0x7FFFFFFF;
|
||||||
bool has_comment(int p_line, bool p_must_be_doc = false);
|
bool has_comment(int p_line, bool p_must_be_doc = false);
|
||||||
String get_doc_comment(int p_line, bool p_single_line = false);
|
MemberDocData parse_doc_comment(int p_line, bool p_single_line = false);
|
||||||
void get_class_doc_comment(int p_line, String &p_brief, String &p_desc, Vector<Pair<String, String>> &p_tutorials, bool p_inner_class);
|
ClassDocData parse_class_doc_comment(int p_line, bool p_inner_class, bool p_single_line = false);
|
||||||
#endif // TOOLS_ENABLED
|
#endif // TOOLS_ENABLED
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
Loading…
Reference in a new issue