summaryrefslogtreecommitdiff
path: root/modules/gdscript
diff options
context:
space:
mode:
Diffstat (limited to 'modules/gdscript')
-rw-r--r--modules/gdscript/doc_classes/@GDScript.xml100
-rw-r--r--modules/gdscript/editor/gdscript_highlighter.cpp4
-rw-r--r--modules/gdscript/gdscript.h2
-rw-r--r--modules/gdscript/gdscript_editor.cpp227
-rw-r--r--modules/gdscript/gdscript_function.cpp50
-rw-r--r--modules/gdscript/gdscript_functions.cpp32
-rw-r--r--modules/gdscript/gdscript_functions.h2
-rw-r--r--modules/gdscript/gdscript_parser.cpp81
-rw-r--r--modules/gdscript/gdscript_parser.h4
9 files changed, 312 insertions, 190 deletions
diff --git a/modules/gdscript/doc_classes/@GDScript.xml b/modules/gdscript/doc_classes/@GDScript.xml
index 3870a5ea7d..f65f2a8935 100644
--- a/modules/gdscript/doc_classes/@GDScript.xml
+++ b/modules/gdscript/doc_classes/@GDScript.xml
@@ -345,45 +345,47 @@
<method name="fmod">
<return type="float">
</return>
- <argument index="0" name="x" type="float">
+ <argument index="0" name="a" type="float">
</argument>
- <argument index="1" name="y" type="float">
+ <argument index="1" name="b" type="float">
</argument>
<description>
- Returns the floating-point remainder of [code]x/y[/code].
+ Returns the floating-point remainder of [code]a/b[/code], keeping the sign of [code]a[/code].
[codeblock]
# Remainder is 1.5
var remainder = fmod(7, 5.5)
[/codeblock]
+ For the integer remainder operation, use the % operator.
</description>
</method>
<method name="fposmod">
<return type="float">
</return>
- <argument index="0" name="x" type="float">
+ <argument index="0" name="a" type="float">
</argument>
- <argument index="1" name="y" type="float">
+ <argument index="1" name="b" type="float">
</argument>
<description>
- Returns the floating-point remainder of [code]x/y[/code] that wraps equally in positive and negative.
+ Returns the floating-point modulus of [code]a/b[/code] that wraps equally in positive and negative.
[codeblock]
- var i = -10
- while i &lt; 0:
- prints(i, fposmod(i, 10))
+ var i = -6
+ while i &lt; 5:
+ prints(i, fposmod(i, 3))
i += 1
[/codeblock]
Produces:
[codeblock]
- -10 10
- -9 1
- -8 2
- -7 3
- -6 4
- -5 5
- -4 6
- -3 7
- -2 8
- -1 9
+ -6 0
+ -5 1
+ -4 2
+ -3 0
+ -2 1
+ -1 2
+ 0 0
+ 1 1
+ 2 2
+ 3 0
+ 4 1
[/codeblock]
</description>
</method>
@@ -571,6 +573,29 @@
[/codeblock]
</description>
</method>
+ <method name="lerp_angle">
+ <return type="float">
+ </return>
+ <argument index="0" name="from" type="float">
+ </argument>
+ <argument index="1" name="to" type="float">
+ </argument>
+ <argument index="2" name="weight" type="float">
+ </argument>
+ <description>
+ Linearly interpolates between two angles (in radians) by a normalized value.
+ Similar to [method lerp] but interpolate correctly when the angles wrap around [constant @GDScript.TAU].
+ [codeblock]
+ extends Sprite
+ var elapsed = 0.0
+ func _process(delta):
+ var min_angle = deg2rad(0.0)
+ var max_angle = deg2rad(90.0)
+ rotation = lerp_angle(min_angle, max_angle, elapsed)
+ elapsed += delta
+ [/codeblock]
+ </description>
+ </method>
<method name="linear2db">
<return type="float">
</return>
@@ -697,12 +722,43 @@
Converts a 2D point expressed in the polar coordinate system (a distance from the origin [code]r[/code] and an angle [code]th[/code]) to the cartesian coordinate system (X and Y axis).
</description>
</method>
+ <method name="posmod">
+ <return type="int">
+ </return>
+ <argument index="0" name="a" type="int">
+ </argument>
+ <argument index="1" name="b" type="int">
+ </argument>
+ <description>
+ Returns the integer modulus of [code]a/b[/code] that wraps equally in positive and negative.
+ [codeblock]
+ var i = -6
+ while i &lt; 5:
+ prints(i, posmod(i, 3))
+ i += 1
+ [/codeblock]
+ Produces:
+ [codeblock]
+ -6 0
+ -5 1
+ -4 2
+ -3 0
+ -2 1
+ -1 2
+ 0 0
+ 1 1
+ 2 2
+ 3 0
+ 4 1
+ [/codeblock]
+ </description>
+ </method>
<method name="pow">
<return type="float">
</return>
- <argument index="0" name="x" type="float">
+ <argument index="0" name="base" type="float">
</argument>
- <argument index="1" name="y" type="float">
+ <argument index="1" name="exp" type="float">
</argument>
<description>
Returns the result of [code]x[/code] raised to the power of [code]y[/code].
@@ -1039,7 +1095,7 @@
<argument index="0" name="step" type="float">
</argument>
<description>
- Returns the position of the first non-zero digit, after the decimal point.
+ Returns the position of the first non-zero digit, after the decimal point. Note that the maximum return value is 10, which is a design decision in the implementation.
[codeblock]
# n is 0
n = step_decimals(5)
diff --git a/modules/gdscript/editor/gdscript_highlighter.cpp b/modules/gdscript/editor/gdscript_highlighter.cpp
index 62b65fe96b..963b40529d 100644
--- a/modules/gdscript/editor/gdscript_highlighter.cpp
+++ b/modules/gdscript/editor/gdscript_highlighter.cpp
@@ -370,8 +370,8 @@ void GDScriptSyntaxHighlighter::_update_cache() {
bool default_theme = text_editor_color_theme == "Default";
bool dark_theme = settings->is_dark_theme();
- function_definition_color = Color::html(default_theme ? "#01e1ff" : dark_theme ? "#01e1ff" : "#00a5ba");
- node_path_color = Color::html(default_theme ? "#64c15a" : dark_theme ? "64c15a" : "#518b4b");
+ function_definition_color = default_theme ? Color(0.0, 0.88, 1.0) : dark_theme ? Color(0.0, 0.88, 1.0) : Color(0.0, 0.65, 0.73);
+ node_path_color = default_theme ? Color(0.39, 0.76, 0.35) : dark_theme ? Color(0.39, 0.76, 0.35) : Color(0.32, 0.55, 0.29);
EDITOR_DEF("text_editor/highlighting/gdscript/function_definition_color", function_definition_color);
EDITOR_DEF("text_editor/highlighting/gdscript/node_path_color", node_path_color);
diff --git a/modules/gdscript/gdscript.h b/modules/gdscript/gdscript.h
index 1756f6eabc..a5ad23c75d 100644
--- a/modules/gdscript/gdscript.h
+++ b/modules/gdscript/gdscript.h
@@ -458,7 +458,7 @@ public:
virtual bool can_inherit_from_file() { return true; }
virtual int find_function(const String &p_function, const String &p_code) const;
virtual String make_function(const String &p_class, const String &p_name, const PoolStringArray &p_args) const;
- virtual Error complete_code(const String &p_code, const String &p_path, Object *p_owner, List<String> *r_options, bool &r_forced, String &r_call_hint);
+ virtual Error complete_code(const String &p_code, const String &p_path, Object *p_owner, List<ScriptCodeCompletionOption> *r_options, bool &r_forced, String &r_call_hint);
#ifdef TOOLS_ENABLED
virtual Error lookup_code(const String &p_code, const String &p_symbol, const String &p_path, Object *p_owner, LookupResult &r_result);
#endif
diff --git a/modules/gdscript/gdscript_editor.cpp b/modules/gdscript/gdscript_editor.cpp
index 26b14a6148..9f65a9fff1 100644
--- a/modules/gdscript/gdscript_editor.cpp
+++ b/modules/gdscript/gdscript_editor.cpp
@@ -159,7 +159,11 @@ bool GDScriptLanguage::validate(const String &p_script, int &r_line_error, int &
for (int i = 0; i < cl->subclasses.size(); i++) {
for (int j = 0; j < cl->subclasses[i]->functions.size(); j++) {
- funcs[cl->subclasses[i]->functions[j]->line] = String(cl->subclasses[i]->name) + "." + String(cl->subclasses[i]->functions[j]->name);
+ funcs[cl->subclasses[i]->functions[j]->line] = String(cl->subclasses[i]->name) + "." + cl->subclasses[i]->functions[j]->name;
+ }
+ for (int j = 0; j < cl->subclasses[i]->static_functions.size(); j++) {
+
+ funcs[cl->subclasses[i]->static_functions[j]->line] = String(cl->subclasses[i]->name) + "." + cl->subclasses[i]->static_functions[j]->name;
}
}
@@ -382,8 +386,6 @@ void GDScriptLanguage::debug_get_globals(List<String> *p_globals, List<Variant>
String GDScriptLanguage::debug_parse_stack_level_expression(int p_level, const String &p_expression, int p_max_subitems, int p_max_depth) {
- if (_debug_parse_err_line >= 0)
- return "";
return "";
}
@@ -509,12 +511,14 @@ struct GDScriptCompletionIdentifier {
assigned_expression(NULL) {}
};
-static void _get_directory_contents(EditorFileSystemDirectory *p_dir, Set<String> &r_list) {
+static void _get_directory_contents(EditorFileSystemDirectory *p_dir, Map<String, ScriptCodeCompletionOption> &r_list) {
const String quote_style = EDITOR_DEF("text_editor/completion/use_single_quotes", false) ? "'" : "\"";
for (int i = 0; i < p_dir->get_file_count(); i++) {
- r_list.insert(quote_style + p_dir->get_file_path(i) + quote_style);
+ ScriptCodeCompletionOption option(p_dir->get_file_path(i), ScriptCodeCompletionOption::KIND_FILE_PATH);
+ option.insert_text = quote_style + option.display + quote_style;
+ r_list.insert(option.display, option);
}
for (int i = 0; i < p_dir->get_subdir_count(); i++) {
@@ -1807,14 +1811,15 @@ static String _make_arguments_hint(const GDScriptParser::FunctionNode *p_functio
return arghint;
}
-static void _find_enumeration_candidates(const String p_enum_hint, Set<String> &r_result) {
+static void _find_enumeration_candidates(const String p_enum_hint, Map<String, ScriptCodeCompletionOption> &r_result) {
if (p_enum_hint.find(".") == -1) {
// Global constant
StringName current_enum = p_enum_hint;
for (int i = 0; i < GlobalConstants::get_global_constant_count(); i++) {
if (GlobalConstants::get_global_constant_enum(i) == current_enum) {
- r_result.insert(GlobalConstants::get_global_constant_name(i));
+ ScriptCodeCompletionOption option(GlobalConstants::get_global_constant_name(i), ScriptCodeCompletionOption::KIND_ENUM);
+ r_result.insert(option.display, option);
}
}
} else {
@@ -1829,15 +1834,17 @@ static void _find_enumeration_candidates(const String p_enum_hint, Set<String> &
ClassDB::get_enum_constants(class_name, enum_name, &enum_constants);
for (List<StringName>::Element *E = enum_constants.front(); E; E = E->next()) {
String candidate = class_name + "." + E->get();
- r_result.insert(candidate);
+ ScriptCodeCompletionOption option(candidate, ScriptCodeCompletionOption::KIND_ENUM);
+ r_result.insert(option.display, option);
}
}
}
-static void _find_identifiers_in_block(const GDScriptCompletionContext &p_context, Set<String> &r_result) {
+static void _find_identifiers_in_block(const GDScriptCompletionContext &p_context, Map<String, ScriptCodeCompletionOption> &r_result) {
for (Map<StringName, GDScriptParser::LocalVarNode *>::Element *E = p_context.block->variables.front(); E; E = E->next()) {
if (E->get()->line < p_context.line) {
- r_result.insert(E->key().operator String());
+ ScriptCodeCompletionOption option(E->key().operator String(), ScriptCodeCompletionOption::KIND_VARIABLE);
+ r_result.insert(option.display, option);
}
}
if (p_context.block->parent_block) {
@@ -1847,40 +1854,47 @@ static void _find_identifiers_in_block(const GDScriptCompletionContext &p_contex
}
}
-static void _find_identifiers_in_base(const GDScriptCompletionContext &p_context, const GDScriptCompletionIdentifier &p_base, bool p_only_functions, Set<String> &r_result);
+static void _find_identifiers_in_base(const GDScriptCompletionContext &p_context, const GDScriptCompletionIdentifier &p_base, bool p_only_functions, Map<String, ScriptCodeCompletionOption> &r_result);
-static void _find_identifiers_in_class(const GDScriptCompletionContext &p_context, bool p_static, bool p_only_functions, bool p_parent_only, Set<String> &r_result) {
+static void _find_identifiers_in_class(const GDScriptCompletionContext &p_context, bool p_static, bool p_only_functions, bool p_parent_only, Map<String, ScriptCodeCompletionOption> &r_result) {
if (!p_parent_only) {
if (!p_static && !p_only_functions) {
for (int i = 0; i < p_context._class->variables.size(); i++) {
- r_result.insert(p_context._class->variables[i].identifier);
+ ScriptCodeCompletionOption option(p_context._class->variables[i].identifier, ScriptCodeCompletionOption::KIND_MEMBER);
+ r_result.insert(option.display, option);
}
}
if (!p_only_functions) {
for (Map<StringName, GDScriptParser::ClassNode::Constant>::Element *E = p_context._class->constant_expressions.front(); E; E = E->next()) {
- r_result.insert(E->key());
+ ScriptCodeCompletionOption option(E->key(), ScriptCodeCompletionOption::KIND_CONSTANT);
+ r_result.insert(option.display, option);
}
for (int i = 0; i < p_context._class->subclasses.size(); i++) {
- r_result.insert(p_context._class->subclasses[i]->name);
+ ScriptCodeCompletionOption option(p_context._class->subclasses[i]->name, ScriptCodeCompletionOption::KIND_CLASS);
+ r_result.insert(option.display, option);
}
}
for (int i = 0; i < p_context._class->static_functions.size(); i++) {
+ ScriptCodeCompletionOption option(p_context._class->static_functions[i]->name.operator String(), ScriptCodeCompletionOption::KIND_FUNCTION);
if (p_context._class->static_functions[i]->arguments.size()) {
- r_result.insert(p_context._class->static_functions[i]->name.operator String() + "(");
+ option.insert_text += "(";
} else {
- r_result.insert(p_context._class->static_functions[i]->name.operator String() + "()");
+ option.insert_text += "()";
}
+ r_result.insert(option.display, option);
}
if (!p_static) {
for (int i = 0; i < p_context._class->functions.size(); i++) {
+ ScriptCodeCompletionOption option(p_context._class->functions[i]->name.operator String(), ScriptCodeCompletionOption::KIND_FUNCTION);
if (p_context._class->functions[i]->arguments.size()) {
- r_result.insert(p_context._class->functions[i]->name.operator String() + "(");
+ option.insert_text += "(";
} else {
- r_result.insert(p_context._class->functions[i]->name.operator String() + "()");
+ option.insert_text += "()";
}
+ r_result.insert(option.display, option);
}
}
}
@@ -1898,12 +1912,14 @@ static void _find_identifiers_in_class(const GDScriptCompletionContext &p_contex
_find_identifiers_in_base(c, base_type, p_only_functions, r_result);
}
-static void _find_identifiers_in_base(const GDScriptCompletionContext &p_context, const GDScriptCompletionIdentifier &p_base, bool p_only_functions, Set<String> &r_result) {
+static void _find_identifiers_in_base(const GDScriptCompletionContext &p_context, const GDScriptCompletionIdentifier &p_base, bool p_only_functions, Map<String, ScriptCodeCompletionOption> &r_result) {
GDScriptParser::DataType base_type = p_base.type;
bool _static = base_type.is_meta_type;
if (_static && base_type.kind != GDScriptParser::DataType::BUILTIN) {
- r_result.insert("new(");
+ ScriptCodeCompletionOption option("new", ScriptCodeCompletionOption::KIND_FUNCTION);
+ option.insert_text += "(";
+ r_result.insert(option.display, option);
}
while (base_type.has_type) {
@@ -1921,26 +1937,31 @@ static void _find_identifiers_in_base(const GDScriptCompletionContext &p_context
if (script.is_valid()) {
if (!_static && !p_only_functions) {
for (const Set<StringName>::Element *E = script->get_members().front(); E; E = E->next()) {
- r_result.insert(E->get().operator String());
+ ScriptCodeCompletionOption option(E->get().operator String(), ScriptCodeCompletionOption::KIND_MEMBER);
+ r_result.insert(option.display, option);
}
}
if (!p_only_functions) {
for (const Map<StringName, Variant>::Element *E = script->get_constants().front(); E; E = E->next()) {
- r_result.insert(E->key().operator String());
+ ScriptCodeCompletionOption option(E->key().operator String(), ScriptCodeCompletionOption::KIND_CONSTANT);
+ r_result.insert(option.display, option);
}
}
for (const Map<StringName, GDScriptFunction *>::Element *E = script->get_member_functions().front(); E; E = E->next()) {
if (!_static || E->get()->is_static()) {
+ ScriptCodeCompletionOption option(E->key().operator String(), ScriptCodeCompletionOption::KIND_FUNCTION);
if (E->get()->get_argument_count()) {
- r_result.insert(E->key().operator String() + "(");
+ option.insert_text += "(";
} else {
- r_result.insert(E->key().operator String() + "()");
+ option.insert_text += "()";
}
+ r_result.insert(option.display, option);
}
}
if (!p_only_functions) {
for (const Map<StringName, Ref<GDScript> >::Element *E = script->get_subclasses().front(); E; E = E->next()) {
- r_result.insert(E->key().operator String());
+ ScriptCodeCompletionOption option(E->key().operator String(), ScriptCodeCompletionOption::KIND_CLASS);
+ r_result.insert(option.display, option);
}
}
base_type = GDScriptParser::DataType();
@@ -1964,25 +1985,29 @@ static void _find_identifiers_in_base(const GDScriptCompletionContext &p_context
List<PropertyInfo> members;
scr->get_script_property_list(&members);
for (List<PropertyInfo>::Element *E = members.front(); E; E = E->next()) {
- r_result.insert(E->get().name);
+ ScriptCodeCompletionOption option(E->get().name, ScriptCodeCompletionOption::KIND_MEMBER);
+ r_result.insert(option.display, option);
}
}
if (!p_only_functions) {
Map<StringName, Variant> constants;
scr->get_constants(&constants);
for (Map<StringName, Variant>::Element *E = constants.front(); E; E = E->next()) {
- r_result.insert(E->key().operator String());
+ ScriptCodeCompletionOption option(E->key().operator String(), ScriptCodeCompletionOption::KIND_CONSTANT);
+ r_result.insert(option.display, option);
}
}
List<MethodInfo> methods;
scr->get_script_method_list(&methods);
for (List<MethodInfo>::Element *E = methods.front(); E; E = E->next()) {
+ ScriptCodeCompletionOption option(E->get().name, ScriptCodeCompletionOption::KIND_FUNCTION);
if (E->get().arguments.size()) {
- r_result.insert(E->get().name + "(");
+ option.insert_text += "(";
} else {
- r_result.insert(E->get().name + "()");
+ option.insert_text += "()";
}
+ r_result.insert(option.display, option);
}
Ref<Script> base_script = scr->get_base_script();
@@ -2009,7 +2034,8 @@ static void _find_identifiers_in_base(const GDScriptCompletionContext &p_context
List<String> constants;
ClassDB::get_integer_constant_list(type, &constants);
for (List<String>::Element *E = constants.front(); E; E = E->next()) {
- r_result.insert(E->get());
+ ScriptCodeCompletionOption option(E->get(), ScriptCodeCompletionOption::KIND_CONSTANT);
+ r_result.insert(option.display, option);
}
if (!_static) {
@@ -2022,7 +2048,8 @@ static void _find_identifiers_in_base(const GDScriptCompletionContext &p_context
if (E->get().name.find("/") != -1) {
continue;
}
- r_result.insert(E->get().name);
+ ScriptCodeCompletionOption option(E->get().name, ScriptCodeCompletionOption::KIND_MEMBER);
+ r_result.insert(option.display, option);
}
}
}
@@ -2035,11 +2062,13 @@ static void _find_identifiers_in_base(const GDScriptCompletionContext &p_context
if (E->get().name.begins_with("_")) {
continue;
}
+ ScriptCodeCompletionOption option(E->get().name, ScriptCodeCompletionOption::KIND_FUNCTION);
if (E->get().arguments.size()) {
- r_result.insert(E->get().name + "(");
+ option.insert_text += "(";
} else {
- r_result.insert(E->get().name + "()");
+ option.insert_text += "()";
}
+ r_result.insert(option.display, option);
}
}
@@ -2058,7 +2087,8 @@ static void _find_identifiers_in_base(const GDScriptCompletionContext &p_context
for (List<PropertyInfo>::Element *E = members.front(); E; E = E->next()) {
if (String(E->get().name).find("/") == -1) {
- r_result.insert(E->get().name);
+ ScriptCodeCompletionOption option(E->get().name, ScriptCodeCompletionOption::KIND_MEMBER);
+ r_result.insert(option.display, option);
}
}
}
@@ -2066,11 +2096,13 @@ static void _find_identifiers_in_base(const GDScriptCompletionContext &p_context
List<MethodInfo> methods;
tmp.get_method_list(&methods);
for (List<MethodInfo>::Element *E = methods.front(); E; E = E->next()) {
+ ScriptCodeCompletionOption option(E->get().name, ScriptCodeCompletionOption::KIND_FUNCTION);
if (E->get().arguments.size()) {
- r_result.insert(E->get().name + "(");
+ option.insert_text += "(";
} else {
- r_result.insert(E->get().name + "()");
+ option.insert_text += "()";
}
+ r_result.insert(option.display, option);
}
return;
@@ -2082,7 +2114,7 @@ static void _find_identifiers_in_base(const GDScriptCompletionContext &p_context
}
}
-static void _find_identifiers(const GDScriptCompletionContext &p_context, bool p_only_functions, Set<String> &r_result) {
+static void _find_identifiers(const GDScriptCompletionContext &p_context, bool p_only_functions, Map<String, ScriptCodeCompletionOption> &r_result) {
const GDScriptParser::BlockNode *block = p_context.block;
@@ -2091,7 +2123,8 @@ static void _find_identifiers(const GDScriptCompletionContext &p_context, bool p
const GDScriptParser::FunctionNode *f = p_context.function;
for (int i = 0; i < f->arguments.size(); i++) {
- r_result.insert(f->arguments[i].operator String());
+ ScriptCodeCompletionOption option(f->arguments[i].operator String(), ScriptCodeCompletionOption::KIND_PLAIN_TEXT);
+ r_result.insert(option.display, option);
}
}
@@ -2116,11 +2149,13 @@ static void _find_identifiers(const GDScriptCompletionContext &p_context, bool p
for (int i = 0; i < GDScriptFunctions::FUNC_MAX; i++) {
MethodInfo mi = GDScriptFunctions::get_info(GDScriptFunctions::Function(i));
+ ScriptCodeCompletionOption option(String(GDScriptFunctions::get_func_name(GDScriptFunctions::Function(i))), ScriptCodeCompletionOption::KIND_FUNCTION);
if (mi.arguments.size() || (mi.flags & METHOD_FLAG_VARARG)) {
- r_result.insert(String(GDScriptFunctions::get_func_name(GDScriptFunctions::Function(i))) + "(");
+ option.insert_text += "(";
} else {
- r_result.insert(String(GDScriptFunctions::get_func_name(GDScriptFunctions::Function(i))) + "()");
+ option.insert_text += "()";
}
+ r_result.insert(option.display, option);
}
static const char *_type_names[Variant::VARIANT_MAX] = {
@@ -2130,7 +2165,8 @@ static void _find_identifiers(const GDScriptCompletionContext &p_context, bool p
};
for (int i = 0; i < Variant::VARIANT_MAX; i++) {
- r_result.insert(_type_names[i]);
+ ScriptCodeCompletionOption option(_type_names[i], ScriptCodeCompletionOption::KIND_CLASS);
+ r_result.insert(option.display, option);
}
static const char *_keywords[] = {
@@ -2144,7 +2180,8 @@ static void _find_identifiers(const GDScriptCompletionContext &p_context, bool p
const char **kw = _keywords;
while (*kw) {
- r_result.insert(*kw);
+ ScriptCodeCompletionOption option(*kw, ScriptCodeCompletionOption::KIND_PLAIN_TEXT);
+ r_result.insert(option.display, option);
kw++;
}
@@ -2158,7 +2195,8 @@ static void _find_identifiers(const GDScriptCompletionContext &p_context, bool p
}
String path = ProjectSettings::get_singleton()->get(s);
if (path.begins_with("*")) {
- r_result.insert(s.get_slice("/", 1));
+ ScriptCodeCompletionOption option(s.get_slice("/", 1), ScriptCodeCompletionOption::KIND_CONSTANT);
+ r_result.insert(option.display, option);
}
}
@@ -2166,16 +2204,18 @@ static void _find_identifiers(const GDScriptCompletionContext &p_context, bool p
List<StringName> named_scripts;
ScriptServer::get_global_class_list(&named_scripts);
for (List<StringName>::Element *E = named_scripts.front(); E; E = E->next()) {
- r_result.insert(E->get().operator String());
+ ScriptCodeCompletionOption option(E->get().operator String(), ScriptCodeCompletionOption::KIND_CLASS);
+ r_result.insert(option.display, option);
}
// Native classes
for (const Map<StringName, int>::Element *E = GDScriptLanguage::get_singleton()->get_global_map().front(); E; E = E->next()) {
- r_result.insert(E->key().operator String());
+ ScriptCodeCompletionOption option(E->key().operator String(), ScriptCodeCompletionOption::KIND_CLASS);
+ r_result.insert(option.display, option);
}
}
-static void _find_call_arguments(const GDScriptCompletionContext &p_context, const GDScriptCompletionIdentifier &p_base, const StringName &p_method, int p_argidx, bool p_static, Set<String> &r_result, String &r_arghint) {
+static void _find_call_arguments(const GDScriptCompletionContext &p_context, const GDScriptCompletionIdentifier &p_base, const StringName &p_method, int p_argidx, bool p_static, Map<String, ScriptCodeCompletionOption> &r_result, String &r_arghint) {
Variant base = p_base.value;
GDScriptParser::DataType base_type = p_base.type;
@@ -2199,7 +2239,9 @@ static void _find_call_arguments(const GDScriptCompletionContext &p_context, con
if ((p_method == "connect" || p_method == "emit_signal") && p_argidx == 0) {
for (int i = 0; i < base_type.class_type->_signals.size(); i++) {
- r_result.insert(quote_style + base_type.class_type->_signals[i].name.operator String() + quote_style);
+ ScriptCodeCompletionOption option(base_type.class_type->_signals[i].name.operator String(), ScriptCodeCompletionOption::KIND_SIGNAL);
+ option.insert_text = quote_style + option.display + quote_style;
+ r_result.insert(option.display, option);
}
}
@@ -2212,7 +2254,9 @@ static void _find_call_arguments(const GDScriptCompletionContext &p_context, con
List<MethodInfo> signals;
gds->get_script_signal_list(&signals);
for (List<MethodInfo>::Element *E = signals.front(); E; E = E->next()) {
- r_result.insert(quote_style + E->get().name + quote_style);
+ ScriptCodeCompletionOption option(E->get().name, ScriptCodeCompletionOption::KIND_SIGNAL);
+ option.insert_text = quote_style + option.display + quote_style;
+ r_result.insert(option.display, option);
}
}
Ref<GDScript> base_script = gds->get_base_script();
@@ -2250,7 +2294,8 @@ static void _find_call_arguments(const GDScriptCompletionContext &p_context, con
List<String> options;
obj->get_argument_options(p_method, p_argidx, &options);
for (List<String>::Element *F = options.front(); F; F = F->next()) {
- r_result.insert(F->get());
+ ScriptCodeCompletionOption option(F->get(), ScriptCodeCompletionOption::KIND_FUNCTION);
+ r_result.insert(option.display, option);
}
}
}
@@ -2271,7 +2316,9 @@ static void _find_call_arguments(const GDScriptCompletionContext &p_context, con
List<MethodInfo> signals;
ClassDB::get_signal_list(class_name, &signals);
for (List<MethodInfo>::Element *E = signals.front(); E; E = E->next()) {
- r_result.insert(quote_style + E->get().name + quote_style);
+ ScriptCodeCompletionOption option(E->get().name, ScriptCodeCompletionOption::KIND_SIGNAL);
+ option.insert_text = quote_style + option.display + quote_style;
+ r_result.insert(option.display, option);
}
}
@@ -2286,7 +2333,9 @@ static void _find_call_arguments(const GDScriptCompletionContext &p_context, con
continue;
}
String name = s.get_slice("/", 1);
- r_result.insert(quote_style + "/root/" + name + quote_style);
+ ScriptCodeCompletionOption option("/root/" + name, ScriptCodeCompletionOption::KIND_NODE_PATH);
+ option.insert_text = quote_style + option.display + quote_style;
+ r_result.insert(option.display, option);
}
}
@@ -2300,7 +2349,9 @@ static void _find_call_arguments(const GDScriptCompletionContext &p_context, con
continue;
}
String name = s.get_slice("/", 1);
- r_result.insert(quote_style + name + quote_style);
+ ScriptCodeCompletionOption option(name, ScriptCodeCompletionOption::KIND_CONSTANT);
+ option.insert_text = quote_style + option.display + quote_style;
+ r_result.insert(option.display, option);
}
}
@@ -2333,7 +2384,7 @@ static void _find_call_arguments(const GDScriptCompletionContext &p_context, con
}
}
-static void _find_call_arguments(GDScriptCompletionContext &p_context, const GDScriptParser::Node *p_node, int p_argidx, Set<String> &r_result, bool &r_forced, String &r_arghint) {
+static void _find_call_arguments(GDScriptCompletionContext &p_context, const GDScriptParser::Node *p_node, int p_argidx, Map<String, ScriptCodeCompletionOption> &r_result, bool &r_forced, String &r_arghint) {
const String quote_style = EDITOR_DEF("text_editor/completion/use_single_quotes", false) ? "'" : "\"";
@@ -2451,17 +2502,19 @@ static void _find_call_arguments(GDScriptCompletionContext &p_context, const GDS
_find_call_arguments(p_context, ci, function, p_argidx, _static, r_result, r_arghint);
if (function == "connect" && p_argidx == 2) {
- Set<String> methods;
+ Map<String, ScriptCodeCompletionOption> methods;
_find_identifiers_in_base(p_context, connect_base, true, methods);
- for (Set<String>::Element *E = methods.front(); E; E = E->next()) {
- r_result.insert(quote_style + E->get().replace("(", "").replace(")", "") + quote_style);
+ for (Map<String, ScriptCodeCompletionOption>::Element *E = methods.front(); E; E = E->next()) {
+ ScriptCodeCompletionOption &option = E->value();
+ option.insert_text = quote_style + option.display + quote_style;
+ r_result.insert(option.display, option);
}
}
r_forced = r_result.size() > 0;
}
-Error GDScriptLanguage::complete_code(const String &p_code, const String &p_path, Object *p_owner, List<String> *r_options, bool &r_forced, String &r_call_hint) {
+Error GDScriptLanguage::complete_code(const String &p_code, const String &p_path, Object *p_owner, List<ScriptCodeCompletionOption> *r_options, bool &r_forced, String &r_call_hint) {
const String quote_style = EDITOR_DEF("text_editor/completion/use_single_quotes", false) ? "'" : "\"";
@@ -2469,7 +2522,7 @@ Error GDScriptLanguage::complete_code(const String &p_code, const String &p_path
parser.parse(p_code, p_path.get_base_dir(), false, p_path, true);
r_forced = false;
- Set<String> options;
+ Map<String, ScriptCodeCompletionOption> options;
GDScriptCompletionContext context;
context._class = parser.get_completion_class();
context.block = parser.get_completion_block();
@@ -2490,7 +2543,8 @@ Error GDScriptLanguage::complete_code(const String &p_code, const String &p_path
List<StringName> constants;
Variant::get_constants_for_type(parser.get_completion_built_in_constant(), &constants);
for (List<StringName>::Element *E = constants.front(); E; E = E->next()) {
- options.insert(E->get().operator String());
+ ScriptCodeCompletionOption option(E->get().operator String(), ScriptCodeCompletionOption::KIND_CONSTANT);
+ options.insert(option.display, option);
}
} break;
case GDScriptParser::COMPLETION_PARENT_FUNCTION: {
@@ -2515,9 +2569,11 @@ Error GDScriptLanguage::complete_code(const String &p_code, const String &p_path
r_forced = true;
String idopt = opt.unquote();
if (idopt.replace("/", "_").is_valid_identifier()) {
- options.insert(idopt);
+ ScriptCodeCompletionOption option(idopt, ScriptCodeCompletionOption::KIND_NODE_PATH);
+ options.insert(option.display, option);
} else {
- options.insert(opt);
+ ScriptCodeCompletionOption option(opt, ScriptCodeCompletionOption::KIND_NODE_PATH);
+ options.insert(option.display, option);
}
}
}
@@ -2532,7 +2588,8 @@ Error GDScriptLanguage::complete_code(const String &p_code, const String &p_path
continue;
}
String name = s.get_slice("/", 1);
- options.insert(quote_style + "/root/" + name + quote_style);
+ ScriptCodeCompletionOption option(quote_style + "/root/" + name + quote_style, ScriptCodeCompletionOption::KIND_NODE_PATH);
+ options.insert(option.display, option);
}
}
} break;
@@ -2655,7 +2712,8 @@ Error GDScriptLanguage::complete_code(const String &p_code, const String &p_path
}
method_hint += ":";
- options.insert(method_hint);
+ ScriptCodeCompletionOption option(method_hint, ScriptCodeCompletionOption::KIND_FUNCTION);
+ options.insert(option.display, option);
}
} break;
case GDScriptParser::COMPLETION_YIELD: {
@@ -2673,7 +2731,9 @@ Error GDScriptLanguage::complete_code(const String &p_code, const String &p_path
switch (base_type.kind) {
case GDScriptParser::DataType::CLASS: {
for (int i = 0; i < base_type.class_type->_signals.size(); i++) {
- options.insert(quote_style + base_type.class_type->_signals[i].name.operator String() + quote_style);
+ ScriptCodeCompletionOption option(base_type.class_type->_signals[i].name.operator String(), ScriptCodeCompletionOption::KIND_SIGNAL);
+ option.insert_text = quote_style + option.display + quote_style;
+ options.insert(option.display, option);
}
base_type = base_type.class_type->base_type;
} break;
@@ -2684,7 +2744,8 @@ Error GDScriptLanguage::complete_code(const String &p_code, const String &p_path
List<MethodInfo> signals;
scr->get_script_signal_list(&signals);
for (List<MethodInfo>::Element *E = signals.front(); E; E = E->next()) {
- options.insert(quote_style + E->get().name + quote_style);
+ ScriptCodeCompletionOption option(quote_style + E->get().name + quote_style, ScriptCodeCompletionOption::KIND_SIGNAL);
+ options.insert(option.display, option);
}
Ref<Script> base_script = scr->get_base_script();
if (base_script.is_valid()) {
@@ -2711,7 +2772,8 @@ Error GDScriptLanguage::complete_code(const String &p_code, const String &p_path
List<MethodInfo> signals;
ClassDB::get_signal_list(class_name, &signals);
for (List<MethodInfo>::Element *E = signals.front(); E; E = E->next()) {
- options.insert(quote_style + E->get().name + quote_style);
+ ScriptCodeCompletionOption option(quote_style + E->get().name + quote_style, ScriptCodeCompletionOption::KIND_SIGNAL);
+ options.insert(option.display, option);
}
} break;
default: {
@@ -2748,18 +2810,21 @@ Error GDScriptLanguage::complete_code(const String &p_code, const String &p_path
c.line = E->value().expression->line;
if (_guess_expression_type(c, E->value().expression, constant)) {
if (constant.type.has_type && constant.type.is_meta_type) {
- options.insert(E->key().operator String());
+ ScriptCodeCompletionOption option(E->key().operator String(), ScriptCodeCompletionOption::KIND_CLASS);
+ options.insert(option.display, option);
}
}
}
for (int i = 0; i < clss->subclasses.size(); i++) {
if (clss->subclasses[i]->name != StringName()) {
- options.insert(clss->subclasses[i]->name.operator String());
+ ScriptCodeCompletionOption option(clss->subclasses[i]->name.operator String(), ScriptCodeCompletionOption::KIND_CLASS);
+ options.insert(option.display, option);
}
}
clss = clss->owner;
for (int i = 0; i < Variant::VARIANT_MAX; i++) {
- options.insert(Variant::get_type_name((Variant::Type)i));
+ ScriptCodeCompletionOption option(Variant::get_type_name((Variant::Type)i), ScriptCodeCompletionOption::KIND_CLASS);
+ options.insert(option.display, option);
}
}
@@ -2773,18 +2838,21 @@ Error GDScriptLanguage::complete_code(const String &p_code, const String &p_path
if (Engine::get_singleton()->has_singleton(class_name)) {
continue;
}
- options.insert(class_name);
+ ScriptCodeCompletionOption option(class_name, ScriptCodeCompletionOption::KIND_CLASS);
+ options.insert(option.display, option);
}
// Named scripts
List<StringName> named_scripts;
ScriptServer::get_global_class_list(&named_scripts);
for (List<StringName>::Element *E = named_scripts.front(); E; E = E->next()) {
- options.insert(E->get().operator String());
+ ScriptCodeCompletionOption option(E->get().operator String(), ScriptCodeCompletionOption::KIND_CLASS);
+ options.insert(option.display, option);
}
if (parser.get_completion_identifier_is_function()) {
- options.insert("void");
+ ScriptCodeCompletionOption option("void", ScriptCodeCompletionOption::KIND_PLAIN_TEXT);
+ options.insert(option.display, option);
}
r_forced = true;
} break;
@@ -2831,13 +2899,15 @@ Error GDScriptLanguage::complete_code(const String &p_code, const String &p_path
c2.line = E->value().expression->line;
if (_guess_expression_type(c2, E->value().expression, constant)) {
if (constant.type.has_type && constant.type.is_meta_type) {
- options.insert(E->key().operator String());
+ ScriptCodeCompletionOption option(E->key().operator String(), ScriptCodeCompletionOption::KIND_CLASS);
+ options.insert(option.display, option);
}
}
}
for (int i = 0; i < base_type.class_type->subclasses.size(); i++) {
if (base_type.class_type->subclasses[i]->name != StringName()) {
- options.insert(base_type.class_type->subclasses[i]->name.operator String());
+ ScriptCodeCompletionOption option(base_type.class_type->subclasses[i]->name.operator String(), ScriptCodeCompletionOption::KIND_CLASS);
+ options.insert(option.display, option);
}
}
@@ -2855,7 +2925,8 @@ Error GDScriptLanguage::complete_code(const String &p_code, const String &p_path
for (Map<StringName, Variant>::Element *E = constants.front(); E; E = E->next()) {
Ref<Script> const_scr = E->value();
if (const_scr.is_valid()) {
- options.insert(E->key().operator String());
+ ScriptCodeCompletionOption option(E->key().operator String(), ScriptCodeCompletionOption::KIND_CLASS);
+ options.insert(option.display, option);
}
}
Ref<Script> base_script = scr->get_base_script();
@@ -2877,7 +2948,7 @@ Error GDScriptLanguage::complete_code(const String &p_code, const String &p_path
} break;
}
- for (Set<String>::Element *E = options.front(); E; E = E->next()) {
+ for (Map<String, ScriptCodeCompletionOption>::Element *E = options.front(); E; E = E->next()) {
r_options->push_back(E->get());
}
@@ -2886,7 +2957,7 @@ Error GDScriptLanguage::complete_code(const String &p_code, const String &p_path
#else
-Error GDScriptLanguage::complete_code(const String &p_code, const String &p_path, Object *p_owner, List<String> *r_options, bool &r_forced, String &r_call_hint) {
+Error GDScriptLanguage::complete_code(const String &p_code, const String &p_path, Object *p_owner, List<ScriptCodeCompletionOption> *r_options, bool &r_forced, String &r_call_hint) {
return OK;
}
diff --git a/modules/gdscript/gdscript_function.cpp b/modules/gdscript/gdscript_function.cpp
index d5e74c07c9..42f349ffc0 100644
--- a/modules/gdscript/gdscript_function.cpp
+++ b/modules/gdscript/gdscript_function.cpp
@@ -1784,20 +1784,9 @@ GDScriptFunction::~GDScriptFunction() {
Variant GDScriptFunctionState::_signal_callback(const Variant **p_args, int p_argcount, Variant::CallError &r_error) {
- if (state.instance_id && !ObjectDB::get_instance(state.instance_id)) {
-#ifdef DEBUG_ENABLED
- ERR_EXPLAIN("Resumed function '" + String(function->get_name()) + "()' after yield, but class instance is gone. At script: " + state.script->get_path() + ":" + itos(state.line));
- ERR_FAIL_V(Variant());
-#else
- return Variant();
-#endif
- }
-
Variant arg;
r_error.error = Variant::CallError::CALL_OK;
- ERR_FAIL_COND_V(!function, Variant());
-
if (p_argcount == 0) {
r_error.error = Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
r_error.argument = 1;
@@ -1823,44 +1812,7 @@ Variant GDScriptFunctionState::_signal_callback(const Variant **p_args, int p_ar
return Variant();
}
- state.result = arg;
- Variant ret = function->call(NULL, NULL, 0, r_error, &state);
-
- bool completed = true;
-
- // If the return value is a GDScriptFunctionState reference,
- // then the function did yield again after resuming.
- if (ret.is_ref()) {
- GDScriptFunctionState *gdfs = Object::cast_to<GDScriptFunctionState>(ret);
- if (gdfs && gdfs->function == function) {
- completed = false;
- gdfs->first_state = first_state.is_valid() ? first_state : Ref<GDScriptFunctionState>(this);
- }
- }
-
- function = NULL; //cleaned up;
- state.result = Variant();
-
- if (completed) {
- if (first_state.is_valid()) {
- first_state->emit_signal("completed", ret);
- } else {
- emit_signal("completed", ret);
- }
- }
-
-#ifdef DEBUG_ENABLED
- if (ScriptDebugger::get_singleton())
- GDScriptLanguage::get_singleton()->exit_function();
- if (state.stack_size) {
- //free stack
- Variant *stack = (Variant *)state.stack.ptr();
- for (int i = 0; i < state.stack_size; i++)
- stack[i].~Variant();
- }
-#endif
-
- return ret;
+ return resume(arg);
}
bool GDScriptFunctionState::is_valid(bool p_extended_check) const {
diff --git a/modules/gdscript/gdscript_functions.cpp b/modules/gdscript/gdscript_functions.cpp
index 0736f3d010..f5f245b25f 100644
--- a/modules/gdscript/gdscript_functions.cpp
+++ b/modules/gdscript/gdscript_functions.cpp
@@ -58,6 +58,7 @@ const char *GDScriptFunctions::get_func_name(Function p_func) {
"sqrt",
"fmod",
"fposmod",
+ "posmod",
"floor",
"ceil",
"round",
@@ -75,6 +76,7 @@ const char *GDScriptFunctions::get_func_name(Function p_func) {
"step_decimals",
"stepify",
"lerp",
+ "lerp_angle",
"inverse_lerp",
"range_lerp",
"smoothstep",
@@ -243,6 +245,12 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_
VALIDATE_ARG_NUM(1);
r_ret = Math::fposmod((double)*p_args[0], (double)*p_args[1]);
} break;
+ case MATH_POSMOD: {
+ VALIDATE_ARG_COUNT(2);
+ VALIDATE_ARG_NUM(0);
+ VALIDATE_ARG_NUM(1);
+ r_ret = Math::posmod((int)*p_args[0], (int)*p_args[1]);
+ } break;
case MATH_FLOOR: {
VALIDATE_ARG_COUNT(1);
VALIDATE_ARG_NUM(0);
@@ -376,6 +384,13 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_
} break;
}
} break;
+ case MATH_LERP_ANGLE: {
+ VALIDATE_ARG_COUNT(3);
+ VALIDATE_ARG_NUM(0);
+ VALIDATE_ARG_NUM(1);
+ VALIDATE_ARG_NUM(2);
+ r_ret = Math::lerp_angle((double)*p_args[0], (double)*p_args[1], (double)*p_args[2]);
+ } break;
case MATH_INVERSE_LERP: {
VALIDATE_ARG_COUNT(3);
VALIDATE_ARG_NUM(0);
@@ -1456,6 +1471,7 @@ bool GDScriptFunctions::is_deterministic(Function p_func) {
case MATH_SQRT:
case MATH_FMOD:
case MATH_FPOSMOD:
+ case MATH_POSMOD:
case MATH_FLOOR:
case MATH_CEIL:
case MATH_ROUND:
@@ -1568,15 +1584,20 @@ MethodInfo GDScriptFunctions::get_info(Function p_func) {
return mi;
} break;
case MATH_FMOD: {
- MethodInfo mi("fmod", PropertyInfo(Variant::REAL, "x"), PropertyInfo(Variant::REAL, "y"));
+ MethodInfo mi("fmod", PropertyInfo(Variant::REAL, "a"), PropertyInfo(Variant::REAL, "b"));
mi.return_val.type = Variant::REAL;
return mi;
} break;
case MATH_FPOSMOD: {
- MethodInfo mi("fposmod", PropertyInfo(Variant::REAL, "x"), PropertyInfo(Variant::REAL, "y"));
+ MethodInfo mi("fposmod", PropertyInfo(Variant::REAL, "a"), PropertyInfo(Variant::REAL, "b"));
mi.return_val.type = Variant::REAL;
return mi;
} break;
+ case MATH_POSMOD: {
+ MethodInfo mi("posmod", PropertyInfo(Variant::INT, "a"), PropertyInfo(Variant::INT, "b"));
+ mi.return_val.type = Variant::INT;
+ return mi;
+ } break;
case MATH_FLOOR: {
MethodInfo mi("floor", PropertyInfo(Variant::REAL, "s"));
mi.return_val.type = Variant::REAL;
@@ -1603,7 +1624,7 @@ MethodInfo GDScriptFunctions::get_info(Function p_func) {
return mi;
} break;
case MATH_POW: {
- MethodInfo mi("pow", PropertyInfo(Variant::REAL, "x"), PropertyInfo(Variant::REAL, "y"));
+ MethodInfo mi("pow", PropertyInfo(Variant::REAL, "base"), PropertyInfo(Variant::REAL, "exp"));
mi.return_val.type = Variant::REAL;
return mi;
} break;
@@ -1663,6 +1684,11 @@ MethodInfo GDScriptFunctions::get_info(Function p_func) {
mi.return_val.usage |= PROPERTY_USAGE_NIL_IS_VARIANT;
return mi;
} break;
+ case MATH_LERP_ANGLE: {
+ MethodInfo mi("lerp_angle", PropertyInfo(Variant::REAL, "from"), PropertyInfo(Variant::REAL, "to"), PropertyInfo(Variant::REAL, "weight"));
+ mi.return_val.type = Variant::REAL;
+ return mi;
+ } break;
case MATH_INVERSE_LERP: {
MethodInfo mi("inverse_lerp", PropertyInfo(Variant::REAL, "from"), PropertyInfo(Variant::REAL, "to"), PropertyInfo(Variant::REAL, "weight"));
mi.return_val.type = Variant::REAL;
diff --git a/modules/gdscript/gdscript_functions.h b/modules/gdscript/gdscript_functions.h
index 6ad70f2eb4..8f7ba76d2c 100644
--- a/modules/gdscript/gdscript_functions.h
+++ b/modules/gdscript/gdscript_functions.h
@@ -49,6 +49,7 @@ public:
MATH_SQRT,
MATH_FMOD,
MATH_FPOSMOD,
+ MATH_POSMOD,
MATH_FLOOR,
MATH_CEIL,
MATH_ROUND,
@@ -66,6 +67,7 @@ public:
MATH_STEP_DECIMALS,
MATH_STEPIFY,
MATH_LERP,
+ MATH_LERP_ANGLE,
MATH_INVERSE_LERP,
MATH_RANGE_LERP,
MATH_SMOOTHSTEP,
diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp
index 9ab86a5459..f006d50a83 100644
--- a/modules/gdscript/gdscript_parser.cpp
+++ b/modules/gdscript/gdscript_parser.cpp
@@ -125,7 +125,7 @@ bool GDScriptParser::_enter_indent_block(BlockNode *p_block) {
}
}
-bool GDScriptParser::_parse_arguments(Node *p_parent, Vector<Node *> &p_args, bool p_static, bool p_can_codecomplete) {
+bool GDScriptParser::_parse_arguments(Node *p_parent, Vector<Node *> &p_args, bool p_static, bool p_can_codecomplete, bool p_parsing_constant) {
if (tokenizer->get_token() == GDScriptTokenizer::TK_PARENTHESIS_CLOSE) {
tokenizer->advance();
@@ -149,7 +149,7 @@ bool GDScriptParser::_parse_arguments(Node *p_parent, Vector<Node *> &p_args, bo
return false;
}
- Node *arg = _parse_expression(p_parent, p_static);
+ Node *arg = _parse_expression(p_parent, p_static, false, p_parsing_constant);
if (!arg) {
return false;
}
@@ -639,7 +639,7 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s
id->name = identifier;
op->arguments.push_back(id);
- if (!_parse_arguments(op, op->arguments, p_static, true))
+ if (!_parse_arguments(op, op->arguments, p_static, true, p_parsing_constant))
return NULL;
expr = op;
@@ -731,7 +731,7 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s
completion_node = op;
}
if (!replaced) {
- if (!_parse_arguments(op, op->arguments, p_static, true))
+ if (!_parse_arguments(op, op->arguments, p_static, true, p_parsing_constant))
return NULL;
expr = op;
}
@@ -826,11 +826,12 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s
}
// Check parents for the constant
- if (!bfn && cln->extends_file != StringName()) {
- Ref<GDScript> parent = ResourceLoader::load(cln->extends_file);
- if (parent.is_valid() && parent->is_valid()) {
+ if (!bfn) {
+ // Using current_class instead of cln here, since cln is const*
+ _determine_inheritance(current_class, false);
+ if (cln->base_type.has_type && cln->base_type.kind == DataType::GDSCRIPT && cln->base_type.script_type->is_valid()) {
Map<StringName, Variant> parent_constants;
- parent->get_constants(&parent_constants);
+ current_class->base_type.script_type->get_constants(&parent_constants);
if (parent_constants.has(identifier)) {
ConstantNode *constant = alloc_node<ConstantNode>();
constant->value = parent_constants[identifier];
@@ -1112,7 +1113,7 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s
}
} else {
tokenizer->advance();
- if (!_parse_arguments(op, op->arguments, p_static)) {
+ if (!_parse_arguments(op, op->arguments, p_static, false, p_parsing_constant)) {
return NULL;
}
}
@@ -1164,22 +1165,14 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s
tokenizer->advance();
IdentifierNode *id = alloc_node<IdentifierNode>();
- if (tokenizer->get_token() == GDScriptTokenizer::TK_BUILT_IN_FUNC) {
- //small hack so built in funcs don't obfuscate methods
-
- id->name = GDScriptFunctions::get_func_name(tokenizer->get_token_built_in_func());
- tokenizer->advance();
-
- } else {
- StringName identifier;
- if (_get_completable_identifier(COMPLETION_METHOD, identifier)) {
- completion_node = op;
- //indexing stuff
- }
-
- id->name = identifier;
+ StringName identifier;
+ if (_get_completable_identifier(COMPLETION_METHOD, identifier)) {
+ completion_node = op;
+ //indexing stuff
}
+ id->name = identifier;
+
op->arguments.push_back(expr); // call what
op->arguments.push_back(id); // call func
//get arguments
@@ -1188,7 +1181,7 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s
_make_completable_call(0);
completion_node = op;
}
- if (!_parse_arguments(op, op->arguments, p_static, true))
+ if (!_parse_arguments(op, op->arguments, p_static, true, p_parsing_constant))
return NULL;
expr = op;
@@ -1773,8 +1766,6 @@ GDScriptParser::Node *GDScriptParser::_reduce_expression(Node *p_node, bool p_to
cn->value = v;
cn->datatype = _type_from_variant(v);
return cn;
-
- } else if (op->arguments[0]->type == Node::TYPE_BUILT_IN_FUNCTION && last_not_constant == 0) {
}
return op; //don't reduce yet
@@ -2218,6 +2209,8 @@ void GDScriptParser::_parse_pattern_block(BlockNode *p_block, Vector<PatternBran
p_block->has_return = true;
+ bool catch_all_appeared = false;
+
while (true) {
while (tokenizer->get_token() == GDScriptTokenizer::TK_NEWLINE && _parse_newline())
@@ -2228,7 +2221,7 @@ void GDScriptParser::_parse_pattern_block(BlockNode *p_block, Vector<PatternBran
return;
if (indent_level > tab_level.back()->get()) {
- return; // go back a level
+ break; // go back a level
}
if (pending_newline != -1) {
@@ -2243,12 +2236,20 @@ void GDScriptParser::_parse_pattern_block(BlockNode *p_block, Vector<PatternBran
branch->patterns.push_back(_parse_pattern(p_static));
if (!branch->patterns[0]) {
- return;
+ break;
}
bool has_binding = branch->patterns[0]->pt_type == PatternNode::PT_BIND;
bool catch_all = has_binding || branch->patterns[0]->pt_type == PatternNode::PT_WILDCARD;
+#ifdef DEBUG_ENABLED
+ // Branches after a wildcard or binding are unreachable
+ if (catch_all_appeared && !current_function->has_unreachable_code) {
+ _add_warning(GDScriptWarning::UNREACHABLE_CODE, -1, current_function->name.operator String());
+ current_function->has_unreachable_code = true;
+ }
+#endif
+
while (tokenizer->get_token() == GDScriptTokenizer::TK_COMMA) {
tokenizer->advance();
branch->patterns.push_back(_parse_pattern(p_static));
@@ -2266,6 +2267,8 @@ void GDScriptParser::_parse_pattern_block(BlockNode *p_block, Vector<PatternBran
catch_all = catch_all || pt == PatternNode::PT_WILDCARD;
}
+ catch_all_appeared = catch_all_appeared || catch_all;
+
if (!_enter_indent_block()) {
_set_error("Expected block in pattern branch");
return;
@@ -2281,6 +2284,11 @@ void GDScriptParser::_parse_pattern_block(BlockNode *p_block, Vector<PatternBran
p_branches.push_back(branch);
}
+
+ // Even if all branches return, there is possibility of default fallthrough
+ if (!catch_all_appeared) {
+ p_block->has_return = false;
+ }
}
void GDScriptParser::_generate_pattern(PatternNode *p_pattern, Node *p_node_to_match, Node *&p_resulting_node, Map<StringName, Node *> &p_bindings) {
@@ -5084,6 +5092,9 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
if (tokenizer->get_token() == GDScriptTokenizer::TK_COMMA) {
tokenizer->advance();
+ } else if (tokenizer->is_token_literal(0, true)) {
+ _set_error("Unexpected identifier");
+ return;
}
if (enum_name != "") {
@@ -5158,9 +5169,11 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
}
}
-void GDScriptParser::_determine_inheritance(ClassNode *p_class) {
+void GDScriptParser::_determine_inheritance(ClassNode *p_class, bool p_recursive) {
- if (p_class->extends_used) {
+ if (p_class->base_type.has_type) {
+ // Already determined
+ } else if (p_class->extends_used) {
//do inheritance
String path = p_class->extends_file;
@@ -5355,9 +5368,11 @@ void GDScriptParser::_determine_inheritance(ClassNode *p_class) {
p_class->base_type.native_type = "Reference";
}
- // Recursively determine subclasses
- for (int i = 0; i < p_class->subclasses.size(); i++) {
- _determine_inheritance(p_class->subclasses[i]);
+ if (p_recursive) {
+ // Recursively determine subclasses
+ for (int i = 0; i < p_class->subclasses.size(); i++) {
+ _determine_inheritance(p_class->subclasses[i], p_recursive);
+ }
}
}
diff --git a/modules/gdscript/gdscript_parser.h b/modules/gdscript/gdscript_parser.h
index 5e4de11357..62d7bdb393 100644
--- a/modules/gdscript/gdscript_parser.h
+++ b/modules/gdscript/gdscript_parser.h
@@ -582,7 +582,7 @@ private:
#endif // DEBUG_ENABLED
bool _recover_from_completion();
- bool _parse_arguments(Node *p_parent, Vector<Node *> &p_args, bool p_static, bool p_can_codecomplete = false);
+ bool _parse_arguments(Node *p_parent, Vector<Node *> &p_args, bool p_static, bool p_can_codecomplete = false, bool p_parsing_constant = false);
bool _enter_indent_block(BlockNode *p_block = NULL);
bool _parse_newline();
Node *_parse_expression(Node *p_parent, bool p_static, bool p_allow_assign = false, bool p_parsing_constant = false);
@@ -599,7 +599,7 @@ private:
void _parse_class(ClassNode *p_class);
bool _end_statement();
- void _determine_inheritance(ClassNode *p_class);
+ void _determine_inheritance(ClassNode *p_class, bool p_recursive = true);
bool _parse_type(DataType &r_type, bool p_can_be_void = false);
DataType _resolve_type(const DataType &p_source, int p_line);
DataType _type_from_variant(const Variant &p_value) const;