Skip to content

Commit

Permalink
Add support for documenting built-in annotations
Browse files Browse the repository at this point in the history
  • Loading branch information
YuriSizov committed Jul 4, 2022
1 parent b4644e2 commit a9098e6
Show file tree
Hide file tree
Showing 19 changed files with 462 additions and 17 deletions.
1 change: 1 addition & 0 deletions core/doc_data.h
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ class DocData {
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;
Expand Down
2 changes: 2 additions & 0 deletions core/object/script_language.h
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,7 @@ class ScriptLanguage : public Object {
LOOKUP_RESULT_CLASS_SIGNAL,
LOOKUP_RESULT_CLASS_ENUM,
LOOKUP_RESULT_CLASS_TBD_GLOBALSCOPE,
LOOKUP_RESULT_CLASS_ANNOTATION,
LOOKUP_RESULT_MAX
};

Expand Down Expand Up @@ -402,6 +403,7 @@ class ScriptLanguage : public Object {
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;
Expand Down
2 changes: 2 additions & 0 deletions core/object/script_language_extension.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
Expand Down
9 changes: 9 additions & 0 deletions core/object/script_language_extension.h
Original file line number Diff line number Diff line change
Expand Up @@ -580,6 +580,15 @@ class ScriptLanguageExtension : public ScriptLanguage {
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)
Expand Down
36 changes: 36 additions & 0 deletions doc/class.xsd
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down
9 changes: 8 additions & 1 deletion doc/classes/ScriptLanguageExtension.xml
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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.
Expand Down
48 changes: 48 additions & 0 deletions doc/tools/make_rst.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
"Signals",
"Enumerations",
"Constants",
"Annotations",
"Property Descriptions",
"Constructor Descriptions",
"Method Descriptions",
Expand Down Expand Up @@ -155,6 +156,7 @@ def __init__(self, name): # type: (str) -> None
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]
Expand Down Expand Up @@ -323,6 +325,27 @@ def parse_class(self, class_root, filepath): # type: (ET.Element, str) -> None

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:
Expand Down Expand Up @@ -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", "-"))
Expand Down Expand Up @@ -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

Expand Down
54 changes: 53 additions & 1 deletion editor/doc_tools.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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];

Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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();

Expand Down
Loading

0 comments on commit a9098e6

Please sign in to comment.