Skip to content

Commit 6761923

Browse files
committed
Merge pull request #90716 from dalexeev/gds-fix-export-annotation-issues
GDScript: Fix some export annotation issues
2 parents f58a96c + 76b2d85 commit 6761923

File tree

13 files changed

+249
-150
lines changed

13 files changed

+249
-150
lines changed

editor/editor_help.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1967,7 +1967,7 @@ void EditorHelp::_update_doc() {
19671967

19681968
class_desc->add_text(argument.name);
19691969
class_desc->add_text(": ");
1970-
_add_type(argument.type);
1970+
_add_type(argument.type, argument.enumeration, argument.is_bitfield);
19711971

19721972
if (!argument.default_value.is_empty()) {
19731973
class_desc->push_color(theme_cache.symbol_color);

modules/gdscript/doc_classes/@GDScript.xml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -349,10 +349,11 @@
349349
<param index="1" name="hint_string" type="String" />
350350
<param index="2" name="usage" type="int" enum="PropertyUsageFlags" is_bitfield="true" default="6" />
351351
<description>
352-
Allows you to set a custom hint, hint string, and usage flags for the exported property. Note that there's no validation done in GDScript, it will just pass the hint along to the editor.
352+
Allows you to set a custom hint, hint string, and usage flags for the exported property. Note that there's no validation done in GDScript, it will just pass the parameters to the editor.
353353
[codeblock]
354354
@export_custom(PROPERTY_HINT_NONE, "suffix:m") var suffix: Vector3
355355
[/codeblock]
356+
[b]Note:[/b] Regardless of the [param usage] value, the [constant PROPERTY_USAGE_SCRIPT_VARIABLE] flag is always added, as with any explicitly declared script variable.
356357
</description>
357358
</annotation>
358359
<annotation name="@export_dir">

modules/gdscript/gdscript_editor.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -911,6 +911,29 @@ static void _find_annotation_arguments(const GDScriptParser::AnnotationNode *p_a
911911
option.insert_text = option.display.quote(p_quote_style);
912912
r_result.insert(option.display, option);
913913
}
914+
} else if (p_annotation->name == SNAME("@export_custom")) {
915+
switch (p_argument) {
916+
case 0: {
917+
static HashMap<StringName, int64_t> items;
918+
if (unlikely(items.is_empty())) {
919+
CoreConstants::get_enum_values(SNAME("PropertyHint"), &items);
920+
}
921+
for (const KeyValue<StringName, int64_t> &item : items) {
922+
ScriptLanguage::CodeCompletionOption option(item.key, ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT);
923+
r_result.insert(option.display, option);
924+
}
925+
} break;
926+
case 2: {
927+
static HashMap<StringName, int64_t> items;
928+
if (unlikely(items.is_empty())) {
929+
CoreConstants::get_enum_values(SNAME("PropertyUsageFlags"), &items);
930+
}
931+
for (const KeyValue<StringName, int64_t> &item : items) {
932+
ScriptLanguage::CodeCompletionOption option(item.key, ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT);
933+
r_result.insert(option.display, option);
934+
}
935+
} break;
936+
}
914937
} else if (p_annotation->name == SNAME("@warning_ignore")) {
915938
for (int warning_code = 0; warning_code < GDScriptWarning::WARNING_MAX; warning_code++) {
916939
ScriptLanguage::CodeCompletionOption warning(GDScriptWarning::get_name_from_code((GDScriptWarning::Code)warning_code).to_lower(), ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT);

modules/gdscript/gdscript_parser.cpp

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,6 @@ GDScriptParser::GDScriptParser() {
101101
register_annotation(MethodInfo("@onready"), AnnotationInfo::VARIABLE, &GDScriptParser::onready_annotation);
102102
// Export annotations.
103103
register_annotation(MethodInfo("@export"), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_NONE, Variant::NIL>);
104-
register_annotation(MethodInfo("@export_storage"), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_NONE, Variant::NIL>);
105104
register_annotation(MethodInfo("@export_enum", PropertyInfo(Variant::STRING, "names")), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_ENUM, Variant::NIL>, varray(), true);
106105
register_annotation(MethodInfo("@export_file", PropertyInfo(Variant::STRING, "filter")), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_FILE, Variant::STRING>, varray(""), true);
107106
register_annotation(MethodInfo("@export_dir"), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_DIR, Variant::STRING>);
@@ -121,6 +120,7 @@ GDScriptParser::GDScriptParser() {
121120
register_annotation(MethodInfo("@export_flags_3d_physics"), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_LAYERS_3D_PHYSICS, Variant::INT>);
122121
register_annotation(MethodInfo("@export_flags_3d_navigation"), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_LAYERS_3D_NAVIGATION, Variant::INT>);
123122
register_annotation(MethodInfo("@export_flags_avoidance"), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_LAYERS_AVOIDANCE, Variant::INT>);
123+
register_annotation(MethodInfo("@export_storage"), AnnotationInfo::VARIABLE, &GDScriptParser::export_storage_annotation);
124124
register_annotation(MethodInfo("@export_custom", PropertyInfo(Variant::INT, "hint", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_CLASS_IS_ENUM, "PropertyHint"), PropertyInfo(Variant::STRING, "hint_string"), PropertyInfo(Variant::INT, "usage", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_CLASS_IS_BITFIELD, "PropertyUsageFlags")), AnnotationInfo::VARIABLE, &GDScriptParser::export_custom_annotation, varray(PROPERTY_USAGE_DEFAULT));
125125
// Export grouping annotations.
126126
register_annotation(MethodInfo("@export_category", PropertyInfo(Variant::STRING, "name")), AnnotationInfo::STANDALONE, &GDScriptParser::export_group_annotations<PROPERTY_USAGE_CATEGORY>);
@@ -4299,7 +4299,7 @@ bool GDScriptParser::export_annotations(const AnnotationNode *p_annotation, Node
42994299
case GDScriptParser::DataType::BUILTIN:
43004300
variable->export_info.type = export_type.builtin_type;
43014301
variable->export_info.hint = PROPERTY_HINT_NONE;
4302-
variable->export_info.hint_string = Variant::get_type_name(export_type.builtin_type);
4302+
variable->export_info.hint_string = String();
43034303
break;
43044304
case GDScriptParser::DataType::NATIVE:
43054305
if (ClassDB::is_parent_class(export_type.native_type, SNAME("Resource"))) {
@@ -4400,12 +4400,6 @@ bool GDScriptParser::export_annotations(const AnnotationNode *p_annotation, Node
44004400
push_error(_get_annotation_error_string(p_annotation->name, expected_types, variable->get_datatype()), p_annotation);
44014401
return false;
44024402
}
4403-
} else if (p_annotation->name == SNAME("@export_storage")) {
4404-
use_default_variable_type_check = false; // Can be applied to a variable of any type.
4405-
4406-
// Save the info because the compiler uses export info for overwriting member info.
4407-
variable->export_info = export_type.to_property_info(variable->identifier->name);
4408-
variable->export_info.usage |= PROPERTY_USAGE_STORAGE;
44094403
}
44104404

44114405
if (use_default_variable_type_check) {
@@ -4425,11 +4419,38 @@ bool GDScriptParser::export_annotations(const AnnotationNode *p_annotation, Node
44254419
if (variable->export_info.hint) {
44264420
hint_prefix += "/" + itos(variable->export_info.hint);
44274421
}
4422+
variable->export_info.type = original_export_type_builtin;
44284423
variable->export_info.hint = PROPERTY_HINT_TYPE_STRING;
44294424
variable->export_info.hint_string = hint_prefix + ":" + variable->export_info.hint_string;
4430-
variable->export_info.type = original_export_type_builtin;
4425+
variable->export_info.usage = PROPERTY_USAGE_DEFAULT;
4426+
variable->export_info.class_name = StringName();
4427+
}
4428+
4429+
return true;
4430+
}
4431+
4432+
// For `@export_storage` and `@export_custom`, there is no need to check the variable type, argument values,
4433+
// or handle array exports in a special way, so they are implemented as separate methods.
4434+
4435+
bool GDScriptParser::export_storage_annotation(const AnnotationNode *p_annotation, Node *p_node, ClassNode *p_class) {
4436+
ERR_FAIL_COND_V_MSG(p_node->type != Node::VARIABLE, false, vformat(R"("%s" annotation can only be applied to variables.)", p_annotation->name));
4437+
4438+
VariableNode *variable = static_cast<VariableNode *>(p_node);
4439+
if (variable->is_static) {
4440+
push_error(vformat(R"(Annotation "%s" cannot be applied to a static variable.)", p_annotation->name), p_annotation);
4441+
return false;
4442+
}
4443+
if (variable->exported) {
4444+
push_error(vformat(R"(Annotation "%s" cannot be used with another "@export" annotation.)", p_annotation->name), p_annotation);
4445+
return false;
44314446
}
44324447

4448+
variable->exported = true;
4449+
4450+
// Save the info because the compiler uses export info for overwriting member info.
4451+
variable->export_info = variable->get_datatype().to_property_info(variable->identifier->name);
4452+
variable->export_info.usage |= PROPERTY_USAGE_STORAGE;
4453+
44334454
return true;
44344455
}
44354456

@@ -4438,6 +4459,10 @@ bool GDScriptParser::export_custom_annotation(const AnnotationNode *p_annotation
44384459
ERR_FAIL_COND_V_MSG(p_annotation->resolved_arguments.size() < 2, false, R"(Annotation "@export_custom" requires 2 arguments.)");
44394460

44404461
VariableNode *variable = static_cast<VariableNode *>(p_node);
4462+
if (variable->is_static) {
4463+
push_error(vformat(R"(Annotation "%s" cannot be applied to a static variable.)", p_annotation->name), p_annotation);
4464+
return false;
4465+
}
44414466
if (variable->exported) {
44424467
push_error(vformat(R"(Annotation "%s" cannot be used with another "@export" annotation.)", p_annotation->name), p_annotation);
44434468
return false;

modules/gdscript/gdscript_parser.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1497,6 +1497,7 @@ class GDScriptParser {
14971497
bool onready_annotation(const AnnotationNode *p_annotation, Node *p_target, ClassNode *p_class);
14981498
template <PropertyHint t_hint, Variant::Type t_type>
14991499
bool export_annotations(const AnnotationNode *p_annotation, Node *p_target, ClassNode *p_class);
1500+
bool export_storage_annotation(const AnnotationNode *p_annotation, Node *p_target, ClassNode *p_class);
15001501
bool export_custom_annotation(const AnnotationNode *p_annotation, Node *p_target, ClassNode *p_class);
15011502
template <PropertyUsageFlags t_usage>
15021503
bool export_group_annotations(const AnnotationNode *p_annotation, Node *p_target, ClassNode *p_class);
Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
GDTEST_OK
22
var test_1: Dictionary
3-
hint=NONE hint_string="" usage=DEFAULT|SCRIPT_VARIABLE
3+
hint=NONE hint_string="" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
44
var test_2: TestExportEnumAsDictionary.MyEnum
5-
hint=ENUM hint_string="A:0,B:1,C:2" usage=DEFAULT|SCRIPT_VARIABLE|CLASS_IS_ENUM
5+
hint=ENUM hint_string="A:0,B:1,C:2" usage=DEFAULT|SCRIPT_VARIABLE|CLASS_IS_ENUM class_name=&"TestExportEnumAsDictionary.MyEnum"
66
var test_3: Dictionary
7-
hint=NONE hint_string="" usage=DEFAULT|SCRIPT_VARIABLE
7+
hint=NONE hint_string="" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
88
var test_4: TestExportEnumAsDictionary.MyEnum
9-
hint=ENUM hint_string="A:0,B:1,C:2" usage=DEFAULT|SCRIPT_VARIABLE|CLASS_IS_ENUM
9+
hint=ENUM hint_string="A:0,B:1,C:2" usage=DEFAULT|SCRIPT_VARIABLE|CLASS_IS_ENUM class_name=&"TestExportEnumAsDictionary.MyEnum"
1010
var test_5: TestExportEnumAsDictionary.MyEnum
11-
hint=ENUM hint_string="A:0,B:1,C:2" usage=DEFAULT|SCRIPT_VARIABLE|CLASS_IS_ENUM
11+
hint=ENUM hint_string="A:0,B:1,C:2" usage=DEFAULT|SCRIPT_VARIABLE|CLASS_IS_ENUM class_name=&"TestExportEnumAsDictionary.MyEnum"
Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,25 @@
11
GDTEST_OK
22
var test_1: int = null
3-
hint=ENUM hint_string="A,B,C" usage=DEFAULT|SCRIPT_VARIABLE
3+
hint=ENUM hint_string="A,B,C" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
44
var test_2: int = null
5-
hint=ENUM hint_string="A,B,C" usage=DEFAULT|SCRIPT_VARIABLE
5+
hint=ENUM hint_string="A,B,C" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
66
var test_3: int = null
7-
hint=ENUM hint_string="A,B,C" usage=DEFAULT|SCRIPT_VARIABLE
7+
hint=ENUM hint_string="A,B,C" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
88
var test_4: int = null
9-
hint=ENUM hint_string="A,B,C" usage=DEFAULT|SCRIPT_VARIABLE
9+
hint=ENUM hint_string="A,B,C" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
1010
var test_5: int = 0
11-
hint=NONE hint_string="int" usage=DEFAULT|SCRIPT_VARIABLE
11+
hint=NONE hint_string="" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
1212
var test_6: int = 0
13-
hint=NONE hint_string="int" usage=DEFAULT|SCRIPT_VARIABLE
13+
hint=NONE hint_string="" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
1414
var test_7: int = 42
15-
hint=NONE hint_string="int" usage=DEFAULT|SCRIPT_VARIABLE
15+
hint=NONE hint_string="" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
1616
var test_8: int = 0
17-
hint=NONE hint_string="int" usage=DEFAULT|SCRIPT_VARIABLE
17+
hint=NONE hint_string="" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
1818
var test_9: int = 0
19-
hint=NONE hint_string="int" usage=DEFAULT|SCRIPT_VARIABLE
19+
hint=NONE hint_string="" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
2020
var test_10: int = 0
21-
hint=NONE hint_string="int" usage=DEFAULT|SCRIPT_VARIABLE
21+
hint=NONE hint_string="" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
2222
var test_11: int = 0
23-
hint=NONE hint_string="int" usage=DEFAULT|SCRIPT_VARIABLE
23+
hint=NONE hint_string="" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""
2424
var test_12: int = 0
25-
hint=NONE hint_string="int" usage=DEFAULT|SCRIPT_VARIABLE
25+
hint=NONE hint_string="" usage=DEFAULT|SCRIPT_VARIABLE class_name=&""

0 commit comments

Comments
 (0)