summaryrefslogtreecommitdiff
path: root/modules/gdscript
diff options
context:
space:
mode:
Diffstat (limited to 'modules/gdscript')
-rw-r--r--modules/gdscript/doc_classes/@GDScript.xml47
-rw-r--r--modules/gdscript/gdscript.cpp24
-rw-r--r--modules/gdscript/gdscript_compiler.cpp2
-rw-r--r--modules/gdscript/gdscript_editor.cpp11
-rw-r--r--modules/gdscript/gdscript_function.cpp6
-rw-r--r--modules/gdscript/gdscript_functions.cpp22
-rw-r--r--modules/gdscript/gdscript_parser.cpp41
-rw-r--r--modules/gdscript/language_server/gdscript_extend_parser.cpp2
-rw-r--r--modules/gdscript/language_server/gdscript_text_document.cpp2
9 files changed, 92 insertions, 65 deletions
diff --git a/modules/gdscript/doc_classes/@GDScript.xml b/modules/gdscript/doc_classes/@GDScript.xml
index d1f52d2422..c4b7e4887e 100644
--- a/modules/gdscript/doc_classes/@GDScript.xml
+++ b/modules/gdscript/doc_classes/@GDScript.xml
@@ -168,14 +168,16 @@
<method name="char">
<return type="String">
</return>
- <argument index="0" name="ascii" type="int">
+ <argument index="0" name="code" type="int">
</argument>
<description>
- Returns a character as a String of the given ASCII code.
+ Returns a character as a String of the given Unicode code point (which is compatible with ASCII code).
[codeblock]
a = char(65) # a is "A"
a = char(65 + 32) # a is "a"
+ a = char(8364) # a is "€"
[/codeblock]
+ This is the inverse of [method ord].
</description>
</method>
<method name="clamp">
@@ -616,9 +618,10 @@
Loads a resource from the filesystem located at [code]path[/code].
[b]Note:[/b] Resource paths can be obtained by right-clicking on a resource in the FileSystem dock and choosing [b]Copy Path[/b].
[codeblock]
- # Load a scene called main located in the root of the project directory
+ # Load a scene called main located in the root of the project directory.
var main = load("res://main.tscn")
[/codeblock]
+ [b]Important:[/b] The path must be absolute, a local path will just return [code]null[/code].
</description>
</method>
<method name="log">
@@ -701,6 +704,13 @@
<argument index="0" name="char" type="String">
</argument>
<description>
+ Returns an integer representing the Unicode code point of the given Unicode character [code]char[/code].
+ [codeblock]
+ a = ord("A") # a is 65
+ a = ord("a") # a is 97
+ a = ord("€") # a is 8364
+ [/codeblock]
+ This is the inverse of [method char].
</description>
</method>
<method name="parse_json">
@@ -786,7 +796,7 @@
Returns a resource from the filesystem that is loaded during script parsing.
[b]Note:[/b] Resource paths can be obtained by right clicking on a resource in the Assets Panel and choosing "Copy Path".
[codeblock]
- # Load a scene called main located in the root of the project directory
+ # Load a scene called main located in the root of the project directory.
var main = preload("res://main.tscn")
[/codeblock]
</description>
@@ -936,7 +946,7 @@
<return type="int">
</return>
<description>
- Returns a random unsigned 32 bit integer. Use remainder to obtain a random value in the interval [code][0, N][/code] (where N is smaller than 2^32 -1).
+ Returns a random unsigned 32 bit integer. Use remainder to obtain a random value in the interval [code][0, N - 1][/code] (where N is smaller than 2^32).
[codeblock]
randi() # Returns random integer between 0 and 2^32 - 1
randi() % 20 # Returns random integer between 0 and 19
@@ -1367,23 +1377,26 @@
You can also use [code]yield[/code] to wait for a function to finish:
[codeblock]
func _ready():
- yield(do_something(), "completed")
- yield(do_something_else(), "completed")
- print("All functions are done!")
-
- func do_something():
- print("Something is done!")
+ yield(countdown(), "completed") # waiting for the countdown() function to complete
+ print('Ready')
- func do_something_else():
- print("Something else is done!")
+ func countdown():
+ yield(get_tree(), "idle_frame") # returns a GDScriptFunctionState object to _ready()
+ print(3)
+ yield(get_tree().create_timer(1.0), "timeout")
+ print(2)
+ yield(get_tree().create_timer(1.0), "timeout")
+ print(1)
+ yield(get_tree().create_timer(1.0), "timeout")
# prints:
- # Something is done!
- # Something else is done!
- # All functions are done!
+ # 3
+ # 2
+ # 1
+ # Ready
[/codeblock]
When yielding on a function, the [code]completed[/code] signal will be emitted automatically when the function returns. It can, therefore, be used as the [code]signal[/code] parameter of the [code]yield[/code] method to resume.
- If you are planning on calling the same function within a loop, you should consider using [code]yield(get_tree(), "idle_frame")[/code] also.
+ In order to yield on a function, the resulting function should also return a [code]GDScriptFunctionState[/code]. Notice [code]yield(get_tree(), "idle_frame")[/code] from the above example.
</description>
</method>
</methods>
diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp
index 563f7e2471..03b51be27f 100644
--- a/modules/gdscript/gdscript.cpp
+++ b/modules/gdscript/gdscript.cpp
@@ -946,18 +946,29 @@ bool GDScriptInstance::set(const StringName &p_name, const Variant &p_value) {
{
const Map<StringName, GDScript::MemberInfo>::Element *E = script->member_indices.find(p_name);
if (E) {
- if (E->get().setter) {
+ const GDScript::MemberInfo *member = &E->get();
+ if (member->setter) {
const Variant *val = &p_value;
Variant::CallError err;
- call(E->get().setter, &val, 1, err);
+ call(member->setter, &val, 1, err);
if (err.error == Variant::CallError::CALL_OK) {
return true; //function exists, call was successful
}
} else {
- if (!E->get().data_type.is_type(p_value)) {
- return false; // Type mismatch
+ if (!member->data_type.is_type(p_value)) {
+ // Try conversion
+ Variant::CallError ce;
+ const Variant *value = &p_value;
+ Variant converted = Variant::construct(member->data_type.builtin_type, &value, 1, ce);
+ if (ce.error == Variant::CallError::CALL_OK) {
+ members.write[member->index] = converted;
+ return true;
+ } else {
+ return false;
+ }
+ } else {
+ members.write[member->index] = p_value;
}
- members.write[E->get().index] = p_value;
}
return true;
}
@@ -2143,7 +2154,8 @@ GDScriptLanguage::GDScriptLanguage() {
GLOBAL_DEF("debug/gdscript/completion/autocomplete_setters_and_getters", false);
for (int i = 0; i < (int)GDScriptWarning::WARNING_MAX; i++) {
String warning = GDScriptWarning::get_name_from_code((GDScriptWarning::Code)i).to_lower();
- GLOBAL_DEF("debug/gdscript/warnings/" + warning, !warning.begins_with("unsafe_"));
+ bool default_enabled = !warning.begins_with("unsafe_") && i != GDScriptWarning::UNUSED_CLASS_VARIABLE;
+ GLOBAL_DEF("debug/gdscript/warnings/" + warning, default_enabled);
}
#endif // DEBUG_ENABLED
}
diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp
index dea2225e91..7ce19f5adc 100644
--- a/modules/gdscript/gdscript_compiler.cpp
+++ b/modules/gdscript/gdscript_compiler.cpp
@@ -1144,7 +1144,7 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser::
GDScriptDataType assign_type = _gdtype_from_datatype(on->arguments[0]->get_datatype());
- if (assign_type.has_type && !on->arguments[1]->get_datatype().has_type) {
+ if (assign_type.has_type && !on->datatype.has_type) {
// Typed assignment
switch (assign_type.kind) {
case GDScriptDataType::BUILTIN: {
diff --git a/modules/gdscript/gdscript_editor.cpp b/modules/gdscript/gdscript_editor.cpp
index 280bc37dc0..97b8dda6d0 100644
--- a/modules/gdscript/gdscript_editor.cpp
+++ b/modules/gdscript/gdscript_editor.cpp
@@ -744,6 +744,14 @@ static bool _guess_expression_type(GDScriptCompletionContext &p_context, const G
r_type.type.kind = GDScriptParser::DataType::BUILTIN;
r_type.type.builtin_type = Variant::ARRAY;
} break;
+ case GDScriptParser::Node::TYPE_CAST: {
+ const GDScriptParser::CastNode *cn = static_cast<const GDScriptParser::CastNode *>(p_expression);
+ GDScriptCompletionIdentifier value;
+ if (_guess_expression_type(p_context, cn->source_node, r_type)) {
+ r_type.type = cn->get_datatype();
+ found = true;
+ }
+ } break;
case GDScriptParser::Node::TYPE_OPERATOR: {
const GDScriptParser::OperatorNode *op = static_cast<const GDScriptParser::OperatorNode *>(p_expression);
switch (op->op) {
@@ -1232,6 +1240,9 @@ static bool _guess_identifier_type(GDScriptCompletionContext &p_context, const S
c.line = last_assign_line;
r_type.assigned_expression = last_assigned_expression;
if (_guess_expression_type(c, last_assigned_expression, r_type)) {
+ if (var_type.has_type) {
+ r_type.type = var_type;
+ }
return true;
}
}
diff --git a/modules/gdscript/gdscript_function.cpp b/modules/gdscript/gdscript_function.cpp
index 0a01321851..4518a5be4b 100644
--- a/modules/gdscript/gdscript_function.cpp
+++ b/modules/gdscript/gdscript_function.cpp
@@ -764,15 +764,17 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
GET_VARIANT_PTR(dst, 2);
GET_VARIANT_PTR(src, 3);
-#ifdef DEBUG_ENABLED
Variant::Type var_type = (Variant::Type)_code_ptr[ip + 1];
GD_ERR_BREAK(var_type < 0 || var_type >= Variant::VARIANT_MAX);
if (src->get_type() != var_type) {
+#ifdef DEBUG_ENABLED
if (Variant::can_convert_strict(src->get_type(), var_type)) {
+#endif // DEBUG_ENABLED
Variant::CallError ce;
*dst = Variant::construct(var_type, const_cast<const Variant **>(&src), 1, ce);
} else {
+#ifdef DEBUG_ENABLED
err_text = "Trying to assign value of type '" + Variant::get_type_name(src->get_type()) +
"' to a variable of type '" + Variant::get_type_name(var_type) + "'.";
OPCODE_BREAK;
@@ -780,9 +782,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
} else {
#endif // DEBUG_ENABLED
*dst = *src;
-#ifdef DEBUG_ENABLED
}
-#endif // DEBUG_ENABLED
ip += 4;
}
diff --git a/modules/gdscript/gdscript_functions.cpp b/modules/gdscript/gdscript_functions.cpp
index bbafef68ed..5c0573be3f 100644
--- a/modules/gdscript/gdscript_functions.cpp
+++ b/modules/gdscript/gdscript_functions.cpp
@@ -1128,25 +1128,11 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_
d["@subpath"] = cp;
d["@path"] = p->get_path();
- p = base.ptr();
-
- while (p) {
-
- for (Set<StringName>::Element *E = p->members.front(); E; E = E->next()) {
-
- Variant value;
- if (ins->get(E->get(), value)) {
-
- String k = E->get();
- if (!d.has(k)) {
- d[k] = value;
- }
- }
+ for (Map<StringName, GDScript::MemberInfo>::Element *E = base->member_indices.front(); E; E = E->next()) {
+ if (!d.has(E->key())) {
+ d[E->key()] = ins->members[E->get().index];
}
-
- p = p->_base;
}
-
r_ret = d;
}
}
@@ -1869,7 +1855,7 @@ MethodInfo GDScriptFunctions::get_info(Function p_func) {
} break;
case TEXT_CHAR: {
- MethodInfo mi("char", PropertyInfo(Variant::INT, "ascii"));
+ MethodInfo mi("char", PropertyInfo(Variant::INT, "code"));
mi.return_val.type = Variant::STRING;
return mi;
diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp
index ef1a282e51..4405393b96 100644
--- a/modules/gdscript/gdscript_parser.cpp
+++ b/modules/gdscript/gdscript_parser.cpp
@@ -8185,7 +8185,9 @@ void GDScriptParser::_check_block_types(BlockNode *p_block) {
}
#endif // DEBUG_ENABLED
+ bool type_match = check_types;
if (check_types && !_is_type_compatible(lh_type, rh_type)) {
+ type_match = false;
// Try supertype test
if (_is_type_compatible(rh_type, lh_type)) {
_mark_line_as_unsafe(op->line);
@@ -8197,23 +8199,27 @@ void GDScriptParser::_check_block_types(BlockNode *p_block) {
op->line);
return;
}
- // Replace assignment with implicit conversion
- BuiltInFunctionNode *convert = alloc_node<BuiltInFunctionNode>();
- convert->line = op->line;
- convert->function = GDScriptFunctions::TYPE_CONVERT;
-
- ConstantNode *tgt_type = alloc_node<ConstantNode>();
- tgt_type->line = op->line;
- tgt_type->value = (int)lh_type.builtin_type;
-
- OperatorNode *convert_call = alloc_node<OperatorNode>();
- convert_call->line = op->line;
- convert_call->op = OperatorNode::OP_CALL;
- convert_call->arguments.push_back(convert);
- convert_call->arguments.push_back(op->arguments[1]);
- convert_call->arguments.push_back(tgt_type);
-
- op->arguments.write[1] = convert_call;
+ if (op->op == OperatorNode::OP_ASSIGN) {
+ // Replace assignment with implicit conversion
+ BuiltInFunctionNode *convert = alloc_node<BuiltInFunctionNode>();
+ convert->line = op->line;
+ convert->function = GDScriptFunctions::TYPE_CONVERT;
+
+ ConstantNode *tgt_type = alloc_node<ConstantNode>();
+ tgt_type->line = op->line;
+ tgt_type->value = (int)lh_type.builtin_type;
+
+ OperatorNode *convert_call = alloc_node<OperatorNode>();
+ convert_call->line = op->line;
+ convert_call->op = OperatorNode::OP_CALL;
+ convert_call->arguments.push_back(convert);
+ convert_call->arguments.push_back(op->arguments[1]);
+ convert_call->arguments.push_back(tgt_type);
+
+ op->arguments.write[1] = convert_call;
+
+ type_match = true; // Since we are converting, the type is matching
+ }
#ifdef DEBUG_ENABLED
if (lh_type.builtin_type == Variant::INT && rh_type.builtin_type == Variant::REAL) {
_add_warning(GDScriptWarning::NARROWING_CONVERSION, op->line);
@@ -8226,6 +8232,7 @@ void GDScriptParser::_check_block_types(BlockNode *p_block) {
_mark_line_as_unsafe(op->line);
}
#endif // DEBUG_ENABLED
+ op->datatype.has_type = type_match;
} break;
case OperatorNode::OP_CALL:
case OperatorNode::OP_PARENT_CALL: {
diff --git a/modules/gdscript/language_server/gdscript_extend_parser.cpp b/modules/gdscript/language_server/gdscript_extend_parser.cpp
index 6b5c26ec81..d63f786fcb 100644
--- a/modules/gdscript/language_server/gdscript_extend_parser.cpp
+++ b/modules/gdscript/language_server/gdscript_extend_parser.cpp
@@ -115,7 +115,7 @@ void ExtendGDScriptParser::update_document_links(const String &p_code) {
if (tokenizer.get_token() == GDScriptTokenizer::TK_EOF) {
break;
} else if (tokenizer.get_token() == GDScriptTokenizer::TK_CONSTANT) {
- Variant const_val = tokenizer.get_token_constant();
+ const Variant &const_val = tokenizer.get_token_constant();
if (const_val.get_type() == Variant::STRING) {
String path = const_val;
bool exists = fs->file_exists(path);
diff --git a/modules/gdscript/language_server/gdscript_text_document.cpp b/modules/gdscript/language_server/gdscript_text_document.cpp
index b83db718b8..1ca2a50c21 100644
--- a/modules/gdscript/language_server/gdscript_text_document.cpp
+++ b/modules/gdscript/language_server/gdscript_text_document.cpp
@@ -281,8 +281,6 @@ Dictionary GDScriptTextDocument::resolve(const Dictionary &p_params) {
}
Array GDScriptTextDocument::foldingRange(const Dictionary &p_params) {
- Dictionary params = p_params["textDocument"];
- String path = params["uri"];
Array arr;
return arr;
}