EditorHelp, makerst: Improve enum ref resolving and constant ref support

Enum reference resolving will now search in the @GlobalScope if no class is specified and the enum cannot be resolved in the current class.
Added support for constant references in EditorHelp, e.g.: [constant KEY_ENTER] or [constant Control.FOCUS_CLICK]. It supports enum constants (the enum name must not be included).
This commit is contained in:
Ignacio Etcheverry 2019-03-27 20:01:16 +01:00
parent e453934824
commit c8aa85189a
12 changed files with 178 additions and 33 deletions

View file

@ -48,7 +48,7 @@
</member>
<member name="button_mask" type="int" setter="set_button_mask" getter="get_button_mask">
Binary mask to choose which mouse buttons this button will respond to.
To allow both left-click and right-click, set this to 3, because it's BUTTON_MASK_LEFT | BUTTON_MASK_RIGHT.
To allow both left-click and right-click, use [code]BUTTON_MASK_LEFT | BUTTON_MASK_RIGHT[/code].
</member>
<member name="disabled" type="bool" setter="set_disabled" getter="is_disabled">
If [code]true[/code], the button is in disabled state and can't be clicked or toggled.

View file

@ -90,7 +90,7 @@
<argument index="1" name="axis" type="int">
</argument>
<description>
Returns the current value of the joypad axis at given index (see [code]JOY_*[/code] constants in [@GlobalScope])
Returns the current value of the joypad axis at given index (see [enum JoystickList]).
</description>
</method>
<method name="get_joy_axis_index_from_string">
@ -108,7 +108,7 @@
<argument index="0" name="axis_index" type="int">
</argument>
<description>
Receives a [code]JOY_AXIS_*[/code] Enum and returns its equivalent name as a string.
Receives a [enum JoystickList] axis and returns its equivalent name as a string.
</description>
</method>
<method name="get_joy_button_index_from_string">
@ -126,7 +126,7 @@
<argument index="0" name="button_index" type="int">
</argument>
<description>
Receives a [code]JOY_BUTTON_*[/code] Enum and returns its equivalent name as a string.
Receives a joy button from [enum JoystickList] and returns its equivalent name as a string.
</description>
</method>
<method name="get_joy_guid" qualifiers="const">
@ -229,7 +229,7 @@
<argument index="1" name="button" type="int">
</argument>
<description>
Returns [code]true[/code] if you are pressing the joypad button. (see [code]JOY_*[/code] constants in [@GlobalScope])
Returns [code]true[/code] if you are pressing the joypad button (see [enum JoystickList]).
</description>
</method>
<method name="is_joy_known">
@ -238,7 +238,7 @@
<argument index="0" name="device" type="int">
</argument>
<description>
Returns [code]true[/code] if the system knows the specified device. This means that it sets all button and axis indices exactly as defined in the [code]JOY_*[/code] constants (see [@GlobalScope]). Unknown joypads are not expected to match these constants, but you can still retrieve events from them.
Returns [code]true[/code] if the system knows the specified device. This means that it sets all button and axis indices exactly as defined in [enum JoystickList]. Unknown joypads are not expected to match these constants, but you can still retrieve events from them.
</description>
</method>
<method name="is_key_pressed" qualifiers="const">
@ -247,7 +247,7 @@
<argument index="0" name="scancode" type="int">
</argument>
<description>
Returns [code]true[/code] if you are pressing the key. You can pass [code]KEY_*[/code], which are pre-defined constants listed in [@GlobalScope].
Returns [code]true[/code] if you are pressing the key. You can pass a [enum KeyList] constant.
</description>
</method>
<method name="is_mouse_button_pressed" qualifiers="const">
@ -256,7 +256,7 @@
<argument index="0" name="button" type="int">
</argument>
<description>
Returns [code]true[/code] if you are pressing the mouse button. You can pass [code]BUTTON_*[/code], which are pre-defined constants listed in [@GlobalScope].
Returns [code]true[/code] if you are pressing the mouse button specified with [enum ButtonList].
</description>
</method>
<method name="joy_connection_changed">

View file

@ -15,7 +15,7 @@
</methods>
<members>
<member name="button_index" type="int" setter="set_button_index" getter="get_button_index">
Button identifier. One of the [code]JOY_BUTTON_*[/code] constants from [@GlobalScope].
Button identifier. One of the [enum JoystickList] button constants.
</member>
<member name="pressed" type="bool" setter="set_pressed" getter="is_pressed">
If [code]true[/code], the button's state is pressed. If [code]false[/code], the button's state is released.

View file

@ -15,7 +15,7 @@
</methods>
<members>
<member name="axis" type="int" setter="set_axis" getter="get_axis">
Axis identifier. Use one of the [code]JOY_AXIS_*[/code] constants in [@GlobalScope].
Axis identifier. Use one of the [enum JoystickList] axis constants.
</member>
<member name="axis_value" type="float" setter="set_axis_value" getter="get_axis_value">
Current position of the joystick on the given axis. The value ranges from [code]-1.0[/code] to [code]1.0[/code]. A value of [code]0[/code] means the axis is in its resting position.

View file

@ -28,7 +28,7 @@
If [code]true[/code], the key's state is pressed. If [code]false[/code], the key's state is released.
</member>
<member name="scancode" type="int" setter="set_scancode" getter="get_scancode">
Key scancode, one of the [code]KEY_*[/code] constants in [@GlobalScope].
Key scancode, one of the [enum KeyList] constants.
</member>
<member name="unicode" type="int" setter="set_unicode" getter="get_unicode">
Key unicode identifier when relevant.

View file

@ -15,7 +15,7 @@
</methods>
<members>
<member name="button_mask" type="int" setter="set_button_mask" getter="get_button_mask">
Mouse button mask identifier, one of or a bitwise combination of the BUTTON_MASK_* constants in [@GlobalScope].
Mouse button mask identifier, one of or a bitwise combination of the [enum ButtonList] button masks.
</member>
<member name="global_position" type="Vector2" setter="set_global_position" getter="get_global_position">
Mouse position relative to the current [Viewport] when used in [method Control._gui_input], otherwise is at 0,0.

View file

@ -15,7 +15,7 @@
</methods>
<members>
<member name="button_index" type="int" setter="set_button_index" getter="get_button_index">
Mouse button identifier, one of the BUTTON_* or BUTTON_WHEEL_* constants in [@GlobalScope].
Mouse button identifier, one of the [enum ButtonList] button or button wheel constants.
</member>
<member name="doubleclick" type="bool" setter="set_doubleclick" getter="is_doubleclick">
If [code]true[/code], the mouse button's state is a double-click.

View file

@ -101,7 +101,7 @@
If [code]true[/code], the [code]LineEdit[/code] width will increase to stay longer than the [member text]. It will [b]not[/b] compress if the [member text] is shortened.
</member>
<member name="focus_mode" type="int" setter="set_focus_mode" getter="get_focus_mode" enum="Control.FocusMode">
Defines how the [code]LineEdit[/code] can grab focus (Keyboard and mouse, only keyboard, or none). See [code]enum FocusMode[/code] in [Control] for details.
Defines how the [code]LineEdit[/code] can grab focus (Keyboard and mouse, only keyboard, or none). See [enum Control.FocusMode] in [Control] for details.
</member>
<member name="max_length" type="int" setter="set_max_length" getter="get_max_length">
Maximum amount of characters that can be entered inside the [code]LineEdit[/code]. If [code]0[/code], there is no limit.
@ -134,7 +134,7 @@
<argument index="0" name="new_text" type="String">
</argument>
<description>
Emitted when the user presses [code]KEY_ENTER[/code] on the [code]LineEdit[/code].
Emitted when the user presses [constant KEY_ENTER] on the [code]LineEdit[/code].
</description>
</signal>
</signals>

View file

@ -757,14 +757,25 @@ def rstize_text(text, state): # type: (str, State) -> str
elif cmd.startswith("constant"):
found = False
if method_param in class_def.constants:
found = True
else:
for enum in class_def.enums.values():
if method_param in enum.values:
found = True
break
# Search in the current class
search_class_defs = [class_def]
if param.find('.') == -1:
# Also search in @GlobalScope as a last resort if no class was specified
search_class_defs.append(state.classes["@GlobalScope"])
for search_class_def in search_class_defs:
if method_param in search_class_def.constants:
class_param = search_class_def.name
found = True
else:
for enum in search_class_def.enums.values():
if method_param in enum.values:
class_param = search_class_def.name
found = True
break
if not found:
print_error("Unresolved constant '{}', file: {}".format(param, state.current_class), state)
@ -917,6 +928,9 @@ def make_enum(t, state): # type: (str, State) -> str
if c in state.classes and e not in state.classes[c].enums:
c = "@GlobalScope"
if not c in state.classes and c.startswith("_"):
c = c[1:] # Remove the underscore prefix
if c in state.classes and e in state.classes[c].enums:
return ":ref:`{0}<enum_{1}_{0}>`".format(e, c)
print_error("Unresolved enum '{}', file: {}".format(t, state.current_class), state)

View file

@ -96,8 +96,8 @@ void EditorHelp::_class_desc_select(const String &p_select) {
emit_signal("go_to_help", "class_name:" + p_select.substr(1, p_select.length()));
return;
} else if (p_select.begins_with("@")) {
String tag = p_select.substr(1, 6);
String link = p_select.substr(7, p_select.length());
String tag = p_select.substr(1, 8).rstrip(" ");
String link = p_select.substr(9, p_select.length());
String topic;
Map<String, int> *table = NULL;
@ -108,24 +108,50 @@ void EditorHelp::_class_desc_select(const String &p_select) {
} else if (tag == "member") {
topic = "class_property";
table = &this->property_line;
} else if (tag == "enum ") {
} else if (tag == "enum") {
topic = "class_enum";
table = &this->enum_line;
} else if (tag == "signal") {
topic = "class_signal";
table = &this->signal_line;
} else if (tag == "constant") {
topic = "class_constant";
table = &this->constant_line;
} else {
return;
}
if (link.find(".") != -1) {
emit_signal("go_to_help", topic + ":" + link.get_slice(".", 0) + ":" + link.get_slice(".", 1));
} else {
if (table->has(link)) {
// Found in the current page
class_desc->scroll_to_line((*table)[link]);
} else {
if (topic == "class_enum") {
// Try to find the enum in @GlobalScope
const DocData::ClassDoc &cd = doc->class_list["@GlobalScope"];
if (!table->has(link))
return;
class_desc->scroll_to_line((*table)[link]);
for (int i = 0; i < cd.constants.size(); i++) {
if (cd.constants[i].enumeration == link) {
// Found in @GlobalScope
emit_signal("go_to_help", topic + ":@GlobalScope:" + link);
break;
}
}
} else if (topic == "class_constant") {
// Try to find the constant in @GlobalScope
const DocData::ClassDoc &cd = doc->class_list["@GlobalScope"];
for (int i = 0; i < cd.constants.size(); i++) {
if (cd.constants[i].name == link) {
// Found in @GlobalScope
emit_signal("go_to_help", topic + ":@GlobalScope:" + link);
break;
}
}
}
}
}
} else if (p_select.begins_with("http")) {
OS::get_singleton()->shell_open(p_select);
@ -733,6 +759,9 @@ void EditorHelp::_update_doc() {
if (cd.name == "@GlobalScope")
enumValuesContainer[enum_list[i].name] = enumStartingLine;
// Add the enum constant line to the constant_line map so we can locate it as a constant
constant_line[enum_list[i].name] = class_desc->get_line_count() - 2;
class_desc->push_font(doc_code_font);
class_desc->push_color(headline_color);
_add_text(enum_list[i].name);
@ -1160,10 +1189,10 @@ static void _add_text_to_rt(const String &p_bbcode, RichTextLabel *p_rt) {
p_rt->add_text("[");
pos = brk_pos + 1;
} else if (tag.begins_with("method ") || tag.begins_with("member ") || tag.begins_with("signal ") || tag.begins_with("enum ")) {
} else if (tag.begins_with("method ") || tag.begins_with("member ") || tag.begins_with("signal ") || tag.begins_with("enum ") || tag.begins_with("constant ")) {
String link_target = tag.substr(tag.find(" ") + 1, tag.length());
String link_tag = tag.substr(0, tag.find(" ")).rpad(6);
String link_tag = tag.substr(0, tag.find(" ")).rpad(8);
p_rt->push_color(link_color);
p_rt->push_meta("@" + link_tag + link_target);
p_rt->add_text(link_target + (tag.begins_with("method ") ? "()" : ""));

View file

@ -277,7 +277,7 @@ String BindingsGenerator::bbcode_to_xml(const String &p_bbcode, const TypeInterf
} else if (code_tag) {
xml_output.append("[");
pos = brk_pos + 1;
} else if (tag.begins_with("method ") || tag.begins_with("member ") || tag.begins_with("signal ") || tag.begins_with("enum ")) {
} else if (tag.begins_with("method ") || tag.begins_with("member ") || tag.begins_with("signal ") || tag.begins_with("enum ") || tag.begins_with("constant ")) {
String link_target = tag.substr(tag.find(" ") + 1, tag.length());
String link_tag = tag.substr(0, tag.find(" "));
@ -386,6 +386,97 @@ String BindingsGenerator::bbcode_to_xml(const String &p_bbcode, const TypeInterf
xml_output.append(link_target);
xml_output.append("</c>");
}
} else if (link_tag == "const") {
if (!target_itype || !target_itype->is_object_type) {
if (OS::get_singleton()->is_stdout_verbose()) {
if (target_itype) {
OS::get_singleton()->print("Cannot resolve constant reference for non-Godot.Object type in documentation: %s\n", link_target.utf8().get_data());
} else {
OS::get_singleton()->print("Cannot resolve type from constant reference in documentation: %s\n", link_target.utf8().get_data());
}
}
// TODO Map what we can
xml_output.append("<c>");
xml_output.append(link_target);
xml_output.append("</c>");
} else if (!target_itype && target_cname == name_cache.type_at_GlobalScope) {
String target_name = (String)target_cname;
// Try to find as a global constant
const ConstantInterface *target_iconst = find_constant_by_name(target_name, global_constants);
if (target_iconst) {
// Found global constant
xml_output.append("<see cref=\"" BINDINGS_NAMESPACE "." BINDINGS_GLOBAL_SCOPE_CLASS ".");
xml_output.append(target_iconst->proxy_name);
xml_output.append("\"/>");
} else {
// Try to find as global enum constant
const EnumInterface *target_ienum = NULL;
for (const List<EnumInterface>::Element *E = global_enums.front(); E; E = E->next()) {
target_ienum = &E->get();
target_iconst = find_constant_by_name(target_name, target_ienum->constants);
if (target_iconst)
break;
}
if (target_iconst) {
xml_output.append("<see cref=\"" BINDINGS_NAMESPACE ".");
xml_output.append(target_ienum->cname);
xml_output.append(".");
xml_output.append(target_iconst->proxy_name);
xml_output.append("\"/>");
} else {
ERR_PRINTS("Cannot resolve global constant reference in documentation: " + link_target);
xml_output.append("<c>");
xml_output.append(link_target);
xml_output.append("</c>");
}
}
} else {
String target_name = (String)target_cname;
// Try to find the constant in the current class
const ConstantInterface *target_iconst = find_constant_by_name(target_name, target_itype->constants);
if (target_iconst) {
// Found constant in current class
xml_output.append("<see cref=\"" BINDINGS_NAMESPACE ".");
xml_output.append(target_itype->proxy_name);
xml_output.append(".");
xml_output.append(target_iconst->proxy_name);
xml_output.append("\"/>");
} else {
// Try to find as enum constant in the current class
const EnumInterface *target_ienum = NULL;
for (const List<EnumInterface>::Element *E = target_itype->enums.front(); E; E = E->next()) {
target_ienum = &E->get();
target_iconst = find_constant_by_name(target_name, target_ienum->constants);
if (target_iconst)
break;
}
if (target_iconst) {
xml_output.append("<see cref=\"" BINDINGS_NAMESPACE ".");
xml_output.append(target_itype->proxy_name);
xml_output.append(".");
xml_output.append(target_ienum->cname);
xml_output.append(".");
xml_output.append(target_iconst->proxy_name);
xml_output.append("\"/>");
} else {
ERR_PRINTS("Cannot resolve constant reference in documentation: " + link_target);
xml_output.append("<c>");
xml_output.append(link_target);
xml_output.append("</c>");
}
}
}
}
pos = brk_end + 1;
@ -414,7 +505,7 @@ String BindingsGenerator::bbcode_to_xml(const String &p_bbcode, const TypeInterf
} else if (tag == "Nil") {
xml_output.append("<see langword=\"null\"/>");
} else if (tag.begins_with("@")) {
// @Global Scope, @GDScript, etc
// @GlobalScope, @GDScript, etc
xml_output.append("<c>");
xml_output.append(tag);
xml_output.append("</c>");

View file

@ -497,6 +497,7 @@ class BindingsGenerator {
StringName type_Object;
StringName type_Reference;
StringName type_String;
StringName type_at_GlobalScope;
StringName enum_Error;
NameCache() {
@ -509,6 +510,7 @@ class BindingsGenerator {
type_Object = StaticCString::create("Object");
type_Reference = StaticCString::create("Reference");
type_String = StaticCString::create("String");
type_at_GlobalScope = StaticCString::create("@GlobalScope");
enum_Error = StaticCString::create("Error");
}
@ -527,6 +529,15 @@ class BindingsGenerator {
return NULL;
}
const ConstantInterface *find_constant_by_name(const String &p_name, const List<ConstantInterface> &p_constants) const {
for (const List<ConstantInterface>::Element *E = p_constants.front(); E; E = E->next()) {
if (E->get().name == p_name)
return &E->get();
}
return NULL;
}
inline String get_unique_sig(const TypeInterface &p_type) {
if (p_type.is_reference)
return "Ref";