mirror of
https://github.com/godotengine/godot
synced 2024-09-05 17:59:56 +00:00
Add support for documenting built-in annotations
This commit is contained in:
parent
b4644e2835
commit
a9098e6147
|
@ -163,6 +163,7 @@ public:
|
|||
Vector<ConstantDoc> constants;
|
||||
HashMap<String, String> enums;
|
||||
Vector<PropertyDoc> properties;
|
||||
Vector<MethodDoc> annotations;
|
||||
Vector<ThemeItemDoc> theme_properties;
|
||||
bool is_script_doc = false;
|
||||
String script_path;
|
||||
|
|
|
@ -350,6 +350,7 @@ public:
|
|||
LOOKUP_RESULT_CLASS_SIGNAL,
|
||||
LOOKUP_RESULT_CLASS_ENUM,
|
||||
LOOKUP_RESULT_CLASS_TBD_GLOBALSCOPE,
|
||||
LOOKUP_RESULT_CLASS_ANNOTATION,
|
||||
LOOKUP_RESULT_MAX
|
||||
};
|
||||
|
||||
|
@ -402,6 +403,7 @@ public:
|
|||
virtual void get_recognized_extensions(List<String> *p_extensions) const = 0;
|
||||
virtual void get_public_functions(List<MethodInfo> *p_functions) const = 0;
|
||||
virtual void get_public_constants(List<Pair<String, Variant>> *p_constants) const = 0;
|
||||
virtual void get_public_annotations(List<MethodInfo> *p_annotations) const = 0;
|
||||
|
||||
struct ProfilingInfo {
|
||||
StringName signature;
|
||||
|
|
|
@ -134,6 +134,7 @@ void ScriptLanguageExtension::_bind_methods() {
|
|||
GDVIRTUAL_BIND(_get_recognized_extensions);
|
||||
GDVIRTUAL_BIND(_get_public_functions);
|
||||
GDVIRTUAL_BIND(_get_public_constants);
|
||||
GDVIRTUAL_BIND(_get_public_annotations);
|
||||
|
||||
GDVIRTUAL_BIND(_profiling_start);
|
||||
GDVIRTUAL_BIND(_profiling_stop);
|
||||
|
@ -160,6 +161,7 @@ void ScriptLanguageExtension::_bind_methods() {
|
|||
BIND_ENUM_CONSTANT(LOOKUP_RESULT_CLASS_SIGNAL);
|
||||
BIND_ENUM_CONSTANT(LOOKUP_RESULT_CLASS_ENUM);
|
||||
BIND_ENUM_CONSTANT(LOOKUP_RESULT_CLASS_TBD_GLOBALSCOPE);
|
||||
BIND_ENUM_CONSTANT(LOOKUP_RESULT_CLASS_ANNOTATION);
|
||||
BIND_ENUM_CONSTANT(LOOKUP_RESULT_MAX);
|
||||
|
||||
BIND_ENUM_CONSTANT(LOCATION_LOCAL);
|
||||
|
|
|
@ -580,6 +580,15 @@ public:
|
|||
p_constants->push_back(Pair<String, Variant>(d["name"], d["value"]));
|
||||
}
|
||||
}
|
||||
GDVIRTUAL0RC(TypedArray<Dictionary>, _get_public_annotations)
|
||||
virtual void get_public_annotations(List<MethodInfo> *p_annotations) const override {
|
||||
TypedArray<Dictionary> ret;
|
||||
GDVIRTUAL_REQUIRED_CALL(_get_public_annotations, ret);
|
||||
for (int i = 0; i < ret.size(); i++) {
|
||||
MethodInfo mi = MethodInfo::from_dict(ret[i]);
|
||||
p_annotations->push_back(mi);
|
||||
}
|
||||
}
|
||||
|
||||
EXBIND0(profiling_start)
|
||||
EXBIND0(profiling_stop)
|
||||
|
|
|
@ -162,6 +162,42 @@
|
|||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="annotations" minOccurs="0">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="annotation" maxOccurs="unbounded" minOccurs="0">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="return" minOccurs="0">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:sequence />
|
||||
</xs:sequence>
|
||||
<xs:attribute type="xs:string" name="type" />
|
||||
<xs:attribute type="xs:string" name="enum" use="optional" />
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="argument" maxOccurs="unbounded" minOccurs="0">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:sequence />
|
||||
</xs:sequence>
|
||||
<xs:attribute type="xs:byte" name="index" />
|
||||
<xs:attribute type="xs:string" name="name" />
|
||||
<xs:attribute type="xs:string" name="type" />
|
||||
<xs:attribute type="xs:string" name="enum" use="optional" />
|
||||
<xs:attribute type="xs:string" name="default" use="optional" />
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element type="xs:string" name="description" />
|
||||
</xs:sequence>
|
||||
<xs:attribute type="xs:string" name="name" use="optional" />
|
||||
<xs:attribute type="xs:string" name="qualifiers" use="optional" />
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="theme_items" minOccurs="0">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
|
|
|
@ -174,6 +174,11 @@
|
|||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="_get_public_annotations" qualifiers="virtual const">
|
||||
<return type="Dictionary[]" />
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="_get_public_constants" qualifiers="virtual const">
|
||||
<return type="Dictionary" />
|
||||
<description>
|
||||
|
@ -378,7 +383,9 @@
|
|||
</constant>
|
||||
<constant name="LOOKUP_RESULT_CLASS_TBD_GLOBALSCOPE" value="7" enum="LookupResultType">
|
||||
</constant>
|
||||
<constant name="LOOKUP_RESULT_MAX" value="8" enum="LookupResultType">
|
||||
<constant name="LOOKUP_RESULT_CLASS_ANNOTATION" value="8" enum="LookupResultType">
|
||||
</constant>
|
||||
<constant name="LOOKUP_RESULT_MAX" value="9" enum="LookupResultType">
|
||||
</constant>
|
||||
<constant name="LOCATION_LOCAL" value="0" enum="CodeCompletionLocation">
|
||||
The option is local to the location of the code completion query - e.g. a local variable.
|
||||
|
|
|
@ -36,6 +36,7 @@ BASE_STRINGS = [
|
|||
"Signals",
|
||||
"Enumerations",
|
||||
"Constants",
|
||||
"Annotations",
|
||||
"Property Descriptions",
|
||||
"Constructor Descriptions",
|
||||
"Method Descriptions",
|
||||
|
@ -155,6 +156,7 @@ class ClassDef:
|
|||
self.methods = OrderedDict() # type: OrderedDict[str, List[MethodDef]]
|
||||
self.operators = OrderedDict() # type: OrderedDict[str, List[MethodDef]]
|
||||
self.signals = OrderedDict() # type: OrderedDict[str, SignalDef]
|
||||
self.annotations = OrderedDict() # type: OrderedDict[str, List[MethodDef]]
|
||||
self.theme_items = OrderedDict() # type: OrderedDict[str, ThemeItemDef]
|
||||
self.inherits = None # type: Optional[str]
|
||||
self.brief_description = None # type: Optional[str]
|
||||
|
@ -323,6 +325,27 @@ class State:
|
|||
|
||||
enum_def.values[constant_name] = constant_def
|
||||
|
||||
annotations = class_root.find("annotations")
|
||||
if annotations is not None:
|
||||
for annotation in annotations:
|
||||
assert annotation.tag == "annotation"
|
||||
|
||||
annotation_name = annotation.attrib["name"]
|
||||
qualifiers = annotation.get("qualifiers")
|
||||
|
||||
params = parse_arguments(annotation)
|
||||
|
||||
desc_element = annotation.find("description")
|
||||
annotation_desc = None
|
||||
if desc_element is not None:
|
||||
annotation_desc = desc_element.text
|
||||
|
||||
annotation_def = MethodDef(annotation_name, return_type, params, annotation_desc, qualifiers)
|
||||
if annotation_name not in class_def.annotations:
|
||||
class_def.annotations[annotation_name] = []
|
||||
|
||||
class_def.annotations[annotation_name].append(annotation_def)
|
||||
|
||||
signals = class_root.find("signals")
|
||||
if signals is not None:
|
||||
for signal in signals:
|
||||
|
@ -732,6 +755,26 @@ def make_rst_class(class_def, state, dry_run, output_dir): # type: (ClassDef, S
|
|||
|
||||
f.write("\n\n")
|
||||
|
||||
if len(class_def.annotations) > 0:
|
||||
f.write(make_heading("Annotations", "-"))
|
||||
index = 0
|
||||
|
||||
for method_list in class_def.annotations.values():
|
||||
for i, m in enumerate(method_list):
|
||||
if index != 0:
|
||||
f.write("----\n\n")
|
||||
|
||||
if i == 0:
|
||||
f.write(".. _class_{}_annotation_{}:\n\n".format(class_name, m.name.strip("@")))
|
||||
|
||||
ret_type, signature = make_method_signature(class_def, m, "", state)
|
||||
f.write("- {} {}\n\n".format(ret_type, signature))
|
||||
|
||||
if m.description is not None and m.description.strip() != "":
|
||||
f.write(rstize_text(m.description.strip(), state) + "\n\n")
|
||||
|
||||
index += 1
|
||||
|
||||
# Property descriptions
|
||||
if any(not p.overrides for p in class_def.properties.values()) > 0:
|
||||
f.write(make_heading("Property Descriptions", "-"))
|
||||
|
@ -1065,6 +1108,11 @@ def rstize_text(text, state): # type: (str, State) -> str
|
|||
print_error('{}.xml: Unresolved signal "{}".'.format(state.current_class, param), state)
|
||||
ref_type = "_signal"
|
||||
|
||||
elif cmd.startswith("annotation"):
|
||||
if method_param not in class_def.annotations:
|
||||
print_error('{}.xml: Unresolved annotation "{}".'.format(state.current_class, param), state)
|
||||
ref_type = "_annotation"
|
||||
|
||||
elif cmd.startswith("constant"):
|
||||
found = False
|
||||
|
||||
|
|
|
@ -178,6 +178,20 @@ void DocTools::merge_from(const DocTools &p_data) {
|
|||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < c.annotations.size(); i++) {
|
||||
DocData::MethodDoc &m = c.annotations.write[i];
|
||||
|
||||
for (int j = 0; j < cf.annotations.size(); j++) {
|
||||
if (cf.annotations[j].name != m.name) {
|
||||
continue;
|
||||
}
|
||||
const DocData::MethodDoc &mf = cf.annotations[j];
|
||||
|
||||
m.description = mf.description;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < c.properties.size(); i++) {
|
||||
DocData::PropertyDoc &p = c.properties.write[i];
|
||||
|
||||
|
@ -959,8 +973,41 @@ void DocTools::generate(bool p_basic_types) {
|
|||
c.constants.push_back(cd);
|
||||
}
|
||||
|
||||
// Get annotations.
|
||||
List<MethodInfo> ainfo;
|
||||
lang->get_public_annotations(&ainfo);
|
||||
|
||||
for (const MethodInfo &ai : ainfo) {
|
||||
DocData::MethodDoc atd;
|
||||
atd.name = ai.name;
|
||||
|
||||
if (ai.flags & METHOD_FLAG_VARARG) {
|
||||
if (!atd.qualifiers.is_empty()) {
|
||||
atd.qualifiers += " ";
|
||||
}
|
||||
atd.qualifiers += "vararg";
|
||||
}
|
||||
|
||||
DocData::return_doc_from_retinfo(atd, ai.return_val);
|
||||
|
||||
for (int j = 0; j < ai.arguments.size(); j++) {
|
||||
DocData::ArgumentDoc ad;
|
||||
DocData::argument_doc_from_arginfo(ad, ai.arguments[j]);
|
||||
|
||||
int darg_idx = j - (ai.arguments.size() - ai.default_arguments.size());
|
||||
if (darg_idx >= 0) {
|
||||
Variant default_arg = ai.default_arguments[darg_idx];
|
||||
ad.default_value = default_arg.get_construct_string().replace("\n", " ");
|
||||
}
|
||||
|
||||
atd.arguments.push_back(ad);
|
||||
}
|
||||
|
||||
c.annotations.push_back(atd);
|
||||
}
|
||||
|
||||
// Skip adding the lang if it doesn't expose anything (e.g. C#).
|
||||
if (c.methods.is_empty() && c.constants.is_empty()) {
|
||||
if (c.methods.is_empty() && c.constants.is_empty() && c.annotations.is_empty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -1162,6 +1209,9 @@ Error DocTools::_load(Ref<XMLParser> parser) {
|
|||
} else if (name2 == "signals") {
|
||||
Error err2 = _parse_methods(parser, c.signals);
|
||||
ERR_FAIL_COND_V(err2, err2);
|
||||
} else if (name2 == "annotations") {
|
||||
Error err2 = _parse_methods(parser, c.annotations);
|
||||
ERR_FAIL_COND_V(err2, err2);
|
||||
} else if (name2 == "members") {
|
||||
while (parser->read() == OK) {
|
||||
if (parser->get_node_type() == XMLParser::NODE_ELEMENT) {
|
||||
|
@ -1442,6 +1492,8 @@ Error DocTools::save_classes(const String &p_default_path, const HashMap<String,
|
|||
_write_string(f, 1, "</constants>");
|
||||
}
|
||||
|
||||
_write_method_doc(f, "annotation", c.annotations);
|
||||
|
||||
if (!c.theme_properties.is_empty()) {
|
||||
c.theme_properties.sort();
|
||||
|
||||
|
|
|
@ -125,6 +125,9 @@ void EditorHelp::_class_desc_select(const String &p_select) {
|
|||
} else if (tag == "constant") {
|
||||
topic = "class_constant";
|
||||
table = &this->constant_line;
|
||||
} else if (tag == "annotation") {
|
||||
topic = "class_annotation";
|
||||
table = &this->annotation_line;
|
||||
} else if (tag == "theme_item") {
|
||||
topic = "theme_item";
|
||||
table = &this->theme_property_line;
|
||||
|
@ -274,7 +277,7 @@ void EditorHelp::_add_method(const DocData::MethodDoc &p_method, bool p_overview
|
|||
class_desc->add_text(" ");
|
||||
}
|
||||
|
||||
if (p_overview && !p_method.description.is_empty()) {
|
||||
if (p_overview && !p_method.description.strip_edges().is_empty()) {
|
||||
class_desc->push_meta("@method " + p_method.name);
|
||||
}
|
||||
|
||||
|
@ -282,7 +285,7 @@ void EditorHelp::_add_method(const DocData::MethodDoc &p_method, bool p_overview
|
|||
_add_text(p_method.name);
|
||||
class_desc->pop();
|
||||
|
||||
if (p_overview && !p_method.description.is_empty()) {
|
||||
if (p_overview && !p_method.description.strip_edges().is_empty()) {
|
||||
class_desc->pop(); //meta
|
||||
}
|
||||
|
||||
|
@ -412,7 +415,7 @@ void EditorHelp::_update_method_list(const Vector<DocData::MethodDoc> p_methods,
|
|||
class_desc->pop(); //cell
|
||||
}
|
||||
|
||||
if (!m[i].description.is_empty() || m[i].errors_returned.size() > 0) {
|
||||
if (!m[i].description.strip_edges().is_empty() || m[i].errors_returned.size() > 0) {
|
||||
r_method_descrpitons = true;
|
||||
}
|
||||
|
||||
|
@ -611,7 +614,7 @@ void EditorHelp::_update_doc() {
|
|||
class_desc->add_newline();
|
||||
|
||||
// Brief description
|
||||
if (!cd.brief_description.is_empty()) {
|
||||
if (!cd.brief_description.strip_edges().is_empty()) {
|
||||
class_desc->push_color(text_color);
|
||||
class_desc->push_font(doc_bold_font);
|
||||
class_desc->push_indent(1);
|
||||
|
@ -625,7 +628,7 @@ void EditorHelp::_update_doc() {
|
|||
}
|
||||
|
||||
// Class description
|
||||
if (!cd.description.is_empty()) {
|
||||
if (!cd.description.strip_edges().is_empty()) {
|
||||
section_line.push_back(Pair<String, int>(TTR("Description"), class_desc->get_paragraph_count() - 2));
|
||||
description_line = class_desc->get_paragraph_count() - 2;
|
||||
class_desc->push_color(title_color);
|
||||
|
@ -692,7 +695,7 @@ void EditorHelp::_update_doc() {
|
|||
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.is_empty()) {
|
||||
if (cd.properties[i].name.begins_with("_") && cd.properties[i].description.strip_edges().is_empty()) {
|
||||
continue;
|
||||
}
|
||||
has_properties = true;
|
||||
|
@ -718,7 +721,7 @@ void EditorHelp::_update_doc() {
|
|||
|
||||
for (int i = 0; i < cd.properties.size(); i++) {
|
||||
// Ignore undocumented private.
|
||||
if (cd.properties[i].name.begins_with("_") && cd.properties[i].description.is_empty()) {
|
||||
if (cd.properties[i].name.begins_with("_") && cd.properties[i].description.strip_edges().is_empty()) {
|
||||
continue;
|
||||
}
|
||||
property_line[cd.properties[i].name] = class_desc->get_paragraph_count() - 2; //gets overridden if description
|
||||
|
@ -743,7 +746,7 @@ void EditorHelp::_update_doc() {
|
|||
describe = true;
|
||||
}
|
||||
|
||||
if (!cd.properties[i].description.is_empty()) {
|
||||
if (!cd.properties[i].description.strip_edges().is_empty()) {
|
||||
describe = true;
|
||||
}
|
||||
|
||||
|
@ -856,7 +859,7 @@ void EditorHelp::_update_doc() {
|
|||
}
|
||||
}
|
||||
// Ignore undocumented non virtual private.
|
||||
if (cd.methods[i].name.begins_with("_") && cd.methods[i].description.is_empty() && !cd.methods[i].qualifiers.contains("virtual")) {
|
||||
if (cd.methods[i].name.begins_with("_") && cd.methods[i].description.strip_edges().is_empty() && !cd.methods[i].qualifiers.contains("virtual")) {
|
||||
continue;
|
||||
}
|
||||
methods.push_back(cd.methods[i]);
|
||||
|
@ -976,7 +979,7 @@ void EditorHelp::_update_doc() {
|
|||
class_desc->pop(); // monofont
|
||||
|
||||
// Theme item description.
|
||||
if (!cd.theme_properties[i].description.is_empty()) {
|
||||
if (!cd.theme_properties[i].description.strip_edges().is_empty()) {
|
||||
class_desc->push_font(doc_font);
|
||||
class_desc->push_color(comment_color);
|
||||
class_desc->push_indent(1);
|
||||
|
@ -1018,8 +1021,8 @@ void EditorHelp::_update_doc() {
|
|||
signal_line[cd.signals[i].name] = class_desc->get_paragraph_count() - 2; // Gets overridden if description.
|
||||
|
||||
class_desc->push_font(doc_code_font); // monofont
|
||||
class_desc->push_color(headline_color);
|
||||
_add_bulletpoint();
|
||||
class_desc->push_color(headline_color);
|
||||
_add_text(cd.signals[i].name);
|
||||
class_desc->pop();
|
||||
class_desc->push_color(symbol_color);
|
||||
|
@ -1048,7 +1051,7 @@ void EditorHelp::_update_doc() {
|
|||
class_desc->add_text(")");
|
||||
class_desc->pop();
|
||||
class_desc->pop(); // end monofont
|
||||
if (!cd.signals[i].description.is_empty()) {
|
||||
if (!cd.signals[i].description.strip_edges().is_empty()) {
|
||||
class_desc->push_font(doc_font);
|
||||
class_desc->push_color(comment_color);
|
||||
class_desc->push_indent(1);
|
||||
|
@ -1079,7 +1082,7 @@ void EditorHelp::_update_doc() {
|
|||
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.is_empty()) {
|
||||
if (cd.constants[i].name.begins_with("_") && cd.constants[i].description.strip_edges().is_empty()) {
|
||||
continue;
|
||||
}
|
||||
constants.push_back(cd.constants[i]);
|
||||
|
@ -1151,8 +1154,8 @@ void EditorHelp::_update_doc() {
|
|||
constant_line[enum_list[i].name] = class_desc->get_paragraph_count() - 2;
|
||||
|
||||
class_desc->push_font(doc_code_font);
|
||||
class_desc->push_color(headline_color);
|
||||
_add_bulletpoint();
|
||||
class_desc->push_color(headline_color);
|
||||
_add_text(enum_list[i].name);
|
||||
class_desc->pop();
|
||||
class_desc->push_color(symbol_color);
|
||||
|
@ -1236,7 +1239,7 @@ void EditorHelp::_update_doc() {
|
|||
|
||||
class_desc->add_newline();
|
||||
|
||||
if (!constants[i].description.is_empty()) {
|
||||
if (!constants[i].description.strip_edges().is_empty()) {
|
||||
class_desc->push_font(doc_font);
|
||||
class_desc->push_color(comment_color);
|
||||
_add_text(DTR(constants[i].description));
|
||||
|
@ -1255,6 +1258,112 @@ void EditorHelp::_update_doc() {
|
|||
}
|
||||
}
|
||||
|
||||
// Annotations
|
||||
if (!cd.annotations.is_empty()) {
|
||||
if (sort_methods) {
|
||||
cd.annotations.sort();
|
||||
}
|
||||
|
||||
section_line.push_back(Pair<String, int>(TTR("Annotations"), class_desc->get_paragraph_count() - 2));
|
||||
class_desc->push_color(title_color);
|
||||
class_desc->push_font(doc_title_font);
|
||||
class_desc->push_font_size(doc_title_font_size);
|
||||
class_desc->add_text(TTR("Annotations"));
|
||||
class_desc->pop(); // font size
|
||||
class_desc->pop(); // font
|
||||
class_desc->pop(); // color
|
||||
|
||||
class_desc->add_newline();
|
||||
class_desc->add_newline();
|
||||
|
||||
class_desc->push_indent(1);
|
||||
|
||||
for (int i = 0; i < cd.annotations.size(); i++) {
|
||||
annotation_line[cd.annotations[i].name] = class_desc->get_paragraph_count() - 2; // Gets overridden if description.
|
||||
|
||||
class_desc->push_font(doc_code_font); // monofont
|
||||
_add_bulletpoint();
|
||||
class_desc->push_color(headline_color);
|
||||
_add_text(cd.annotations[i].name);
|
||||
class_desc->pop();
|
||||
|
||||
if (cd.annotations[i].arguments.size() > 0) {
|
||||
class_desc->push_color(symbol_color);
|
||||
class_desc->add_text("(");
|
||||
class_desc->pop();
|
||||
for (int j = 0; j < cd.annotations[i].arguments.size(); j++) {
|
||||
class_desc->push_color(text_color);
|
||||
if (j > 0) {
|
||||
class_desc->add_text(", ");
|
||||
}
|
||||
|
||||
_add_text(cd.annotations[i].arguments[j].name);
|
||||
class_desc->add_text(": ");
|
||||
_add_type(cd.annotations[i].arguments[j].type);
|
||||
if (!cd.annotations[i].arguments[j].default_value.is_empty()) {
|
||||
class_desc->push_color(symbol_color);
|
||||
class_desc->add_text(" = ");
|
||||
class_desc->pop();
|
||||
_add_text(cd.annotations[i].arguments[j].default_value);
|
||||
}
|
||||
|
||||
class_desc->pop();
|
||||
}
|
||||
|
||||
if (cd.annotations[i].qualifiers.contains("vararg")) {
|
||||
class_desc->push_color(text_color);
|
||||
if (cd.annotations[i].arguments.size()) {
|
||||
class_desc->add_text(", ");
|
||||
}
|
||||
class_desc->push_color(symbol_color);
|
||||
class_desc->add_text("...");
|
||||
class_desc->pop();
|
||||
class_desc->pop();
|
||||
}
|
||||
|
||||
class_desc->push_color(symbol_color);
|
||||
class_desc->add_text(")");
|
||||
class_desc->pop();
|
||||
}
|
||||
|
||||
if (!cd.annotations[i].qualifiers.is_empty()) {
|
||||
class_desc->push_color(qualifier_color);
|
||||
class_desc->add_text(" ");
|
||||
_add_text(cd.annotations[i].qualifiers);
|
||||
class_desc->pop();
|
||||
}
|
||||
|
||||
class_desc->pop(); // end monofont
|
||||
|
||||
if (!cd.annotations[i].description.strip_edges().is_empty()) {
|
||||
class_desc->push_font(doc_font);
|
||||
class_desc->push_color(comment_color);
|
||||
class_desc->push_indent(1);
|
||||
_add_text(DTR(cd.annotations[i].description));
|
||||
class_desc->pop(); // indent
|
||||
class_desc->pop();
|
||||
class_desc->pop(); // font
|
||||
} else {
|
||||
class_desc->push_indent(1);
|
||||
class_desc->add_image(get_theme_icon(SNAME("Error"), SNAME("EditorIcons")));
|
||||
class_desc->add_text(" ");
|
||||
class_desc->push_color(comment_color);
|
||||
if (cd.is_script_doc) {
|
||||
class_desc->append_text(TTR("There is currently no description for this annotation."));
|
||||
} else {
|
||||
class_desc->append_text(TTR("There is currently no description for this annotation. 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(); // indent
|
||||
}
|
||||
class_desc->add_newline();
|
||||
class_desc->add_newline();
|
||||
}
|
||||
|
||||
class_desc->pop();
|
||||
class_desc->add_newline();
|
||||
}
|
||||
|
||||
// Property descriptions
|
||||
if (property_descr) {
|
||||
section_line.push_back(Pair<String, int>(TTR("Property Descriptions"), class_desc->get_paragraph_count() - 2));
|
||||
|
@ -1501,6 +1610,10 @@ void EditorHelp::_help_callback(const String &p_topic) {
|
|||
if (constant_line.has(name)) {
|
||||
line = constant_line[name];
|
||||
}
|
||||
} else if (what == "class_annotation") {
|
||||
if (annotation_line.has(name)) {
|
||||
line = annotation_line[name];
|
||||
}
|
||||
} else if (what == "class_global") {
|
||||
if (constant_line.has(name)) {
|
||||
line = constant_line[name];
|
||||
|
|
|
@ -110,6 +110,7 @@ class EditorHelp : public VBoxContainer {
|
|||
HashMap<String, int> property_line;
|
||||
HashMap<String, int> theme_property_line;
|
||||
HashMap<String, int> constant_line;
|
||||
HashMap<String, int> annotation_line;
|
||||
HashMap<String, int> enum_line;
|
||||
HashMap<String, HashMap<String, int>> enum_values_line;
|
||||
int description_line = 0;
|
||||
|
|
|
@ -886,6 +886,9 @@ void ScriptTextEditor::_lookup_symbol(const String &p_symbol, int p_row, int p_c
|
|||
emit_signal(SNAME("go_to_help"), "class_enum:" + result.class_name + ":" + result.class_member);
|
||||
|
||||
} break;
|
||||
case ScriptLanguage::LOOKUP_RESULT_CLASS_ANNOTATION: {
|
||||
emit_signal(SNAME("go_to_help"), "class_annotation:" + result.class_name + ":" + result.class_member);
|
||||
} break;
|
||||
case ScriptLanguage::LOOKUP_RESULT_CLASS_TBD_GLOBALSCOPE: {
|
||||
emit_signal(SNAME("go_to_help"), "class_global:" + result.class_name + ":" + result.class_member);
|
||||
} break;
|
||||
|
|
|
@ -257,4 +257,145 @@
|
|||
[b]Note:[/b] "Not a Number" is only a concept with floating-point numbers, and has no equivalent for integers. Dividing an integer [code]0[/code] by [code]0[/code] will not result in [constant NAN] and will result in a run-time error instead.
|
||||
</constant>
|
||||
</constants>
|
||||
<annotations>
|
||||
<annotation name="@export">
|
||||
<return type="void" />
|
||||
<description>
|
||||
</description>
|
||||
</annotation>
|
||||
<annotation name="@export_color_no_alpha">
|
||||
<return type="void" />
|
||||
<description>
|
||||
</description>
|
||||
</annotation>
|
||||
<annotation name="@export_dir">
|
||||
<return type="void" />
|
||||
<description>
|
||||
</description>
|
||||
</annotation>
|
||||
<annotation name="@export_enum" qualifiers="vararg">
|
||||
<return type="void" />
|
||||
<argument index="0" name="names" type="String" />
|
||||
<description>
|
||||
</description>
|
||||
</annotation>
|
||||
<annotation name="@export_exp_easing">
|
||||
<return type="void" />
|
||||
<argument index="0" name="hint1" type="String" default="null" />
|
||||
<argument index="1" name="hint2" type="String" default="null" />
|
||||
<description>
|
||||
</description>
|
||||
</annotation>
|
||||
<annotation name="@export_file" qualifiers="vararg">
|
||||
<return type="void" />
|
||||
<argument index="0" name="filter" type="String" default="null" />
|
||||
<description>
|
||||
</description>
|
||||
</annotation>
|
||||
<annotation name="@export_flags" qualifiers="vararg">
|
||||
<return type="void" />
|
||||
<argument index="0" name="names" type="String" />
|
||||
<description>
|
||||
</description>
|
||||
</annotation>
|
||||
<annotation name="@export_flags_2d_navigation">
|
||||
<return type="void" />
|
||||
<description>
|
||||
</description>
|
||||
</annotation>
|
||||
<annotation name="@export_flags_2d_physics">
|
||||
<return type="void" />
|
||||
<description>
|
||||
</description>
|
||||
</annotation>
|
||||
<annotation name="@export_flags_2d_render">
|
||||
<return type="void" />
|
||||
<description>
|
||||
</description>
|
||||
</annotation>
|
||||
<annotation name="@export_flags_3d_navigation">
|
||||
<return type="void" />
|
||||
<description>
|
||||
</description>
|
||||
</annotation>
|
||||
<annotation name="@export_flags_3d_physics">
|
||||
<return type="void" />
|
||||
<description>
|
||||
</description>
|
||||
</annotation>
|
||||
<annotation name="@export_flags_3d_render">
|
||||
<return type="void" />
|
||||
<description>
|
||||
</description>
|
||||
</annotation>
|
||||
<annotation name="@export_global_dir">
|
||||
<return type="void" />
|
||||
<description>
|
||||
</description>
|
||||
</annotation>
|
||||
<annotation name="@export_global_file" qualifiers="vararg">
|
||||
<return type="void" />
|
||||
<argument index="0" name="filter" type="String" default="null" />
|
||||
<description>
|
||||
</description>
|
||||
</annotation>
|
||||
<annotation name="@export_multiline">
|
||||
<return type="void" />
|
||||
<description>
|
||||
</description>
|
||||
</annotation>
|
||||
<annotation name="@export_node_path" qualifiers="vararg">
|
||||
<return type="void" />
|
||||
<argument index="0" name="type" type="String" default="null" />
|
||||
<description>
|
||||
</description>
|
||||
</annotation>
|
||||
<annotation name="@export_placeholder">
|
||||
<return type="void" />
|
||||
<description>
|
||||
</description>
|
||||
</annotation>
|
||||
<annotation name="@export_range">
|
||||
<return type="void" />
|
||||
<argument index="0" name="min" type="float" />
|
||||
<argument index="1" name="max" type="float" />
|
||||
<argument index="2" name="step" type="float" default="null" />
|
||||
<argument index="3" name="slider1" type="String" default="null" />
|
||||
<argument index="4" name="slider2" type="String" default="null" />
|
||||
<argument index="5" name="slider3" type="String" default="null" />
|
||||
<description>
|
||||
</description>
|
||||
</annotation>
|
||||
<annotation name="@icon">
|
||||
<return type="void" />
|
||||
<argument index="0" name="icon_path" type="String" />
|
||||
<description>
|
||||
</description>
|
||||
</annotation>
|
||||
<annotation name="@onready">
|
||||
<return type="void" />
|
||||
<description>
|
||||
</description>
|
||||
</annotation>
|
||||
<annotation name="@rpc" qualifiers="vararg">
|
||||
<return type="void" />
|
||||
<argument index="0" name="mode" type="String" default="null" />
|
||||
<argument index="1" name="sync" type="String" default="null" />
|
||||
<argument index="2" name="transfer_mode" type="String" default="null" />
|
||||
<argument index="3" name="transfer_channel" type="int" default="null" />
|
||||
<description>
|
||||
</description>
|
||||
</annotation>
|
||||
<annotation name="@tool">
|
||||
<return type="void" />
|
||||
<description>
|
||||
</description>
|
||||
</annotation>
|
||||
<annotation name="@warning_ignore" qualifiers="vararg">
|
||||
<return type="void" />
|
||||
<argument index="0" name="warning" type="String" />
|
||||
<description>
|
||||
</description>
|
||||
</annotation>
|
||||
</annotations>
|
||||
</class>
|
||||
|
|
|
@ -489,6 +489,7 @@ public:
|
|||
|
||||
virtual void get_public_functions(List<MethodInfo> *p_functions) const override;
|
||||
virtual void get_public_constants(List<Pair<String, Variant>> *p_constants) const override;
|
||||
virtual void get_public_annotations(List<MethodInfo> *p_annotations) const override;
|
||||
|
||||
virtual void profiling_start() override;
|
||||
virtual void profiling_stop() override;
|
||||
|
|
|
@ -445,6 +445,16 @@ void GDScriptLanguage::get_public_constants(List<Pair<String, Variant>> *p_const
|
|||
p_constants->push_back(nan);
|
||||
}
|
||||
|
||||
void GDScriptLanguage::get_public_annotations(List<MethodInfo> *p_annotations) const {
|
||||
GDScriptParser parser;
|
||||
List<MethodInfo> annotations;
|
||||
parser.get_annotation_list(&annotations);
|
||||
|
||||
for (const MethodInfo &E : annotations) {
|
||||
p_annotations->push_back(E);
|
||||
}
|
||||
}
|
||||
|
||||
String GDScriptLanguage::make_function(const String &p_class, const String &p_name, const PackedStringArray &p_args) const {
|
||||
#ifdef TOOLS_ENABLED
|
||||
bool th = EditorSettings::get_singleton()->get_setting("text_editor/completion/add_type_hints");
|
||||
|
@ -3376,6 +3386,15 @@ static Error _lookup_symbol_from_base(const GDScriptParser::DataType &p_base, co
|
|||
return OK;
|
||||
}
|
||||
} break;
|
||||
case GDScriptParser::COMPLETION_ANNOTATION: {
|
||||
const String annotation_symbol = "@" + p_symbol;
|
||||
if (parser.annotation_exists(annotation_symbol)) {
|
||||
r_result.type = ScriptLanguage::LOOKUP_RESULT_CLASS_ANNOTATION;
|
||||
r_result.class_name = "@GDScript";
|
||||
r_result.class_member = annotation_symbol;
|
||||
return OK;
|
||||
}
|
||||
} break;
|
||||
default: {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -105,6 +105,10 @@ void GDScriptParser::get_annotation_list(List<MethodInfo> *r_annotations) const
|
|||
}
|
||||
}
|
||||
|
||||
bool GDScriptParser::annotation_exists(const String &p_annotation_name) const {
|
||||
return valid_annotations.has(p_annotation_name);
|
||||
}
|
||||
|
||||
GDScriptParser::GDScriptParser() {
|
||||
// Register valid annotations.
|
||||
// TODO: Should this be static?
|
||||
|
|
|
@ -1413,6 +1413,7 @@ public:
|
|||
CompletionContext get_completion_context() const { return completion_context; }
|
||||
CompletionCall get_completion_call() const { return completion_call; }
|
||||
void get_annotation_list(List<MethodInfo> *r_annotations) const;
|
||||
bool annotation_exists(const String &p_annotation_name) const;
|
||||
|
||||
const List<ParserError> &get_errors() const { return errors; }
|
||||
const List<String> get_dependencies() const {
|
||||
|
|
|
@ -502,6 +502,7 @@ public:
|
|||
|
||||
/* TODO? */ void get_public_functions(List<MethodInfo> *p_functions) const override {}
|
||||
/* TODO? */ void get_public_constants(List<Pair<String, Variant>> *p_constants) const override {}
|
||||
/* TODO? */ void get_public_annotations(List<MethodInfo> *p_annotations) const override {}
|
||||
|
||||
void reload_all_scripts() override;
|
||||
void reload_tool_script(const Ref<Script> &p_script, bool p_soft_reload) override;
|
||||
|
|
|
@ -2435,6 +2435,9 @@ void VisualScriptLanguage::get_public_functions(List<MethodInfo> *p_functions) c
|
|||
void VisualScriptLanguage::get_public_constants(List<Pair<String, Variant>> *p_constants) const {
|
||||
}
|
||||
|
||||
void VisualScriptLanguage::get_public_annotations(List<MethodInfo> *p_annotations) const {
|
||||
}
|
||||
|
||||
void VisualScriptLanguage::profiling_start() {
|
||||
}
|
||||
|
||||
|
|
|
@ -599,6 +599,7 @@ public:
|
|||
virtual void get_recognized_extensions(List<String> *p_extensions) const override;
|
||||
virtual void get_public_functions(List<MethodInfo> *p_functions) const override;
|
||||
virtual void get_public_constants(List<Pair<String, Variant>> *p_constants) const override;
|
||||
virtual void get_public_annotations(List<MethodInfo> *p_annotations) const override;
|
||||
|
||||
virtual void profiling_start() override;
|
||||
virtual void profiling_stop() override;
|
||||
|
|
Loading…
Reference in a new issue