Преглед на файлове

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).
Ignacio Etcheverry преди 6 години
родител
ревизия
c8aa85189a

+ 1 - 1
doc/classes/BaseButton.xml

@@ -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.

+ 7 - 7
doc/classes/Input.xml

@@ -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">

+ 1 - 1
doc/classes/InputEventJoypadButton.xml

@@ -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.

+ 1 - 1
doc/classes/InputEventJoypadMotion.xml

@@ -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.

+ 1 - 1
doc/classes/InputEventKey.xml

@@ -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.

+ 1 - 1
doc/classes/InputEventMouse.xml

@@ -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.

+ 1 - 1
doc/classes/InputEventMouseButton.xml

@@ -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.

+ 2 - 2
doc/classes/LineEdit.xml

@@ -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>

+ 21 - 7
doc/tools/makerst.py

@@ -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)

+ 39 - 10
editor/editor_help.cpp

@@ -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))
-				return;
-			class_desc->scroll_to_line((*table)[link]);
+			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"];
+
+					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 ") ? "()" : ""));

+ 93 - 2
modules/mono/editor/bindings_generator.cpp

@@ -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>");

+ 11 - 0
modules/mono/editor/bindings_generator.h

@@ -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";