diff options
Diffstat (limited to 'modules/gdscript')
38 files changed, 478 insertions, 408 deletions
diff --git a/modules/gdscript/SCsub b/modules/gdscript/SCsub index 2f507db548..1dc4768186 100644 --- a/modules/gdscript/SCsub +++ b/modules/gdscript/SCsub @@ -7,7 +7,7 @@ env_gdscript = env_modules.Clone() env_gdscript.add_source_files(env.modules_sources, "*.cpp") -if env["tools"]: +if env.editor_build: env_gdscript.add_source_files(env.modules_sources, "./editor/*.cpp") SConscript("editor/script_templates/SCsub") diff --git a/modules/gdscript/doc_classes/@GDScript.xml b/modules/gdscript/doc_classes/@GDScript.xml index 6cf8c1a30e..c8eda53a2d 100644 --- a/modules/gdscript/doc_classes/@GDScript.xml +++ b/modules/gdscript/doc_classes/@GDScript.xml @@ -18,13 +18,11 @@ <param index="2" name="b8" type="int" /> <param index="3" name="a8" type="int" default="255" /> <description> - Returns a color constructed from integer red, green, blue, and alpha channels. Each channel should have 8 bits of information ranging from 0 to 255. - [code]r8[/code] red channel - [code]g8[/code] green channel - [code]b8[/code] blue channel - [code]a8[/code] alpha channel + Returns a [Color] constructed from red ([param r8]), green ([param g8]), blue ([param b8]), and optionally alpha ([param a8]) integer channels, each divided by [code]255.0[/code] for their final value. [codeblock] - red = Color8(255, 0, 0) + var red = Color8(255, 0, 0) # Same as Color(1, 0, 0) + var dark_blue = Color8(0, 0, 51) # Same as Color(0, 0, 0.2). + var my_color = Color8(306, 255, 0, 102) # Same as Color(1.2, 1, 0, 0.4). [/codeblock] </description> </method> @@ -33,9 +31,9 @@ <param index="0" name="condition" type="bool" /> <param index="1" name="message" type="String" default="""" /> <description> - Asserts that the [code]condition[/code] is [code]true[/code]. If the [code]condition[/code] is [code]false[/code], an error is generated. When running from the editor, the running project will also be paused until you resume it. This can be used as a stronger form of [method @GlobalScope.push_error] for reporting errors to project developers or add-on users. - [b]Note:[/b] For performance reasons, the code inside [method assert] is only executed in debug builds or when running the project from the editor. Don't include code that has side effects in an [method assert] call. Otherwise, the project will behave differently when exported in release mode. - The optional [code]message[/code] argument, if given, is shown in addition to the generic "Assertion failed" message. It must be a static string, so format strings can't be used. You can use this to provide additional details about why the assertion failed. + Asserts that the [param condition] is [code]true[/code]. If the [param condition] is [code]false[/code], an error is generated. When running from the editor, the running project will also be paused until you resume it. This can be used as a stronger form of [method @GlobalScope.push_error] for reporting errors to project developers or add-on users. + An optional [param message] can be shown in addition to the generic "Assertion failed" message. You can use this to provide additional details about why the assertion failed. + [b]Warning:[/b] For performance reasons, the code inside [method assert] is only executed in debug builds or when running the project from the editor. Don't include code that has side effects in an [method assert] call. Otherwise, the project will behave differently when exported in release mode. [codeblock] # Imagine we always want speed to be between 0 and 20. var speed = -10 @@ -50,7 +48,7 @@ <return type="String" /> <param index="0" name="char" type="int" /> <description> - Returns a character as a String of the given Unicode code point (which is compatible with ASCII code). + Returns a single 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" @@ -63,14 +61,14 @@ <param index="0" name="what" type="Variant" /> <param index="1" name="type" type="int" /> <description> - Converts from a type to another in the best way possible. The [code]type[/code] parameter uses the [enum Variant.Type] values. + Converts [param what] to [param type] in the best way possible. The [param type] uses the [enum Variant.Type] values. [codeblock] - a = Vector2(1, 0) - # Prints 1 - print(a.length()) - a = convert(a, TYPE_STRING) - # Prints 6 as "(1, 0)" is 6 characters - print(a.length()) + var a = [4, 2.5, 1.2] + print(a is Array) # Prints true + + var b = convert(a, TYPE_PACKED_BYTE_ARRAY) + print(b) # Prints [4, 2, 1] + print(b is Array) # Prints false [/codeblock] </description> </method> @@ -78,13 +76,13 @@ <return type="Object" /> <param index="0" name="dictionary" type="Dictionary" /> <description> - Converts a [param dictionary] (previously created with [method inst_to_dict]) back to an Object instance. Useful for deserializing. + Converts a [param dictionary] (created with [method inst_to_dict]) back to an Object instance. Can be useful for deserializing. </description> </method> <method name="get_stack"> <return type="Array" /> <description> - Returns an array of dictionaries representing the current call stack. + Returns an array of dictionaries representing the current call stack. See also [method print_stack]. [codeblock] func _ready(): foo() @@ -95,18 +93,19 @@ func bar(): print(get_stack()) [/codeblock] - would print + Starting from [code]_ready()[/code], [code]bar()[/code] would print: [codeblock] [{function:bar, line:12, source:res://script.gd}, {function:foo, line:9, source:res://script.gd}, {function:_ready, line:6, source:res://script.gd}] [/codeblock] - [b]Note:[/b] Not supported for calling from threads. Instead, this will return an empty array. + [b]Note:[/b] This function only works if the running instance is connected to a debugging server (i.e. an editor instance). [method get_stack] will not work in projects exported in release mode, or in projects exported in debug mode if not connected to a debugging server. + [b]Note:[/b] Calling this function from a [Thread] is not supported. Doing so will return an empty array. </description> </method> <method name="inst_to_dict"> <return type="Dictionary" /> <param index="0" name="instance" type="Object" /> <description> - Returns the passed [param instance] converted to a Dictionary (useful for serializing). + Returns the passed [param instance] converted to a Dictionary. Can be useful for serializing. [codeblock] var foo = "bar" func _ready(): @@ -125,11 +124,13 @@ <return type="int" /> <param index="0" name="var" type="Variant" /> <description> - Returns length of Variant [code]var[/code]. Length is the character count of String, element count of Array, size of Dictionary, etc. - [b]Note:[/b] Generates a fatal error if Variant can not provide a length. + Returns the length of the given Variant [param var]. The length can be the character count of a [String], the element count of any array type or the size of a [Dictionary]. For every other Variant type, a run-time error is generated and execution is stopped. [codeblock] a = [1, 2, 3, 4] len(a) # Returns 4 + + b = "Hello!" + len(b) # Returns 6 [/codeblock] </description> </method> @@ -137,25 +138,25 @@ <return type="Resource" /> <param index="0" name="path" type="String" /> <description> - Loads a resource from the filesystem located at [code]path[/code]. The resource is loaded on the method call (unless it's referenced already elsewhere, e.g. in another script or in the scene), which might cause slight delay, especially when loading scenes. To avoid unnecessary delays when loading something multiple times, either store the resource in a variable or use [method preload]. + Returns a [Resource] from the filesystem located at the absolute [param path]. Unless it's already referenced elsewhere (such as in another script or in the scene), the resource is loaded from disk on function call, which might cause a slight delay, especially when loading large scenes. To avoid unnecessary delays when loading something multiple times, either store the resource in a variable or use [method preload]. [b]Note:[/b] Resource paths can be obtained by right-clicking on a resource in the FileSystem dock and choosing "Copy Path" or by dragging the file from the FileSystem dock into the script. [codeblock] - # Load a scene called main located in the root of the project directory and cache it in a variable. + # Load a scene called "main" located in the root of the project directory and cache it in a variable. var main = load("res://main.tscn") # main will contain a PackedScene resource. [/codeblock] - [b]Important:[/b] The path must be absolute, a local path will just return [code]null[/code]. - This method is a simplified version of [method ResourceLoader.load], which can be used for more advanced scenarios. - [b]Note:[/b] You have to import the files into the engine first to load them using [method load]. If you want to load [Image]s at run-time, you may use [method Image.load]. If you want to import audio files, you can use the snippet described in [member AudioStreamMP3.data]. + [b]Important:[/b] The path must be absolute. A relative path will always return [code]null[/code]. + This function is a simplified version of [method ResourceLoader.load], which can be used for more advanced scenarios. + [b]Note:[/b] Files have to be imported into the engine first to load them using this function. If you want to load [Image]s at run-time, you may use [method Image.load]. If you want to import audio files, you can use the snippet described in [member AudioStreamMP3.data]. </description> </method> <method name="preload"> <return type="Resource" /> <param index="0" name="path" type="String" /> <description> - Returns a [Resource] from the filesystem located at [code]path[/code]. The resource is loaded during script parsing, i.e. is loaded with the script and [method preload] effectively acts as a reference to that resource. Note that the method requires a constant path. If you want to load a resource from a dynamic/variable path, use [method load]. + Returns a [Resource] from the filesystem located at [param path]. During run-time, the resource is loaded when the script is being parsed. This function effectively acts as a reference to that resource. Note that this function requires [param path] to be a constant [String]. If you want to load a resource from a dynamic/variable path, use [method load]. [b]Note:[/b] Resource paths can be obtained by right clicking on a resource in the Assets Panel and choosing "Copy Path" or by dragging the file from the FileSystem dock into the script. [codeblock] - # Instance a scene. + # Create instance of a scene. var diamond = preload("res://diamond.tscn").instantiate() [/codeblock] </description> @@ -164,23 +165,24 @@ <return type="void" /> <description> Like [method @GlobalScope.print], but includes the current stack frame when running with the debugger turned on. - Output in the console would look something like this: + The output in the console may look like the following: [codeblock] Test print - At: res://test.gd:15:_process() + At: res://test.gd:15:_process() [/codeblock] - [b]Note:[/b] Not supported for calling from threads. Instead of the stack frame, this will print the thread ID. + [b]Note:[/b] Calling this function from a [Thread] is not supported. Doing so will instead print the thread ID. </description> </method> <method name="print_stack"> <return type="void" /> <description> - Prints a stack trace at the current code location. Only works when running with debugger turned on. - Output in the console would look something like this: + Prints a stack trace at the current code location. See also [method get_stack]. + The output in the console may look like the following: [codeblock] Frame 0 - res://test.gd:16 in function '_process' [/codeblock] - [b]Note:[/b] Not supported for calling from threads. Instead of the stack trace, this will print the thread ID. + [b]Note:[/b] This function only works if the running instance is connected to a debugging server (i.e. an editor instance). [method print_stack] will not work in projects exported in release mode, or in projects exported in debug mode if not connected to a debugging server. + [b]Note:[/b] Calling this function from a [Thread] is not supported. Doing so will instead print the thread ID. </description> </method> <method name="range" qualifiers="vararg"> @@ -227,7 +229,7 @@ <method name="str" qualifiers="vararg"> <return type="String" /> <description> - Converts one or more arguments to string in the best way possible. + Converts one or more arguments to a [String] in the best way possible. [codeblock] var a = [10, 20, 30] var b = str(a); @@ -240,7 +242,7 @@ <return type="bool" /> <param index="0" name="type" type="StringName" /> <description> - Returns whether the given [Object]-derived class exists in [ClassDB]. Note that [Variant] data types are not registered in [ClassDB]. + Returns [code]true[/code] if the given [Object]-derived class exists in [ClassDB]. Note that [Variant] data types are not registered in [ClassDB]. [codeblock] type_exists("Sprite2D") # Returns true type_exists("NonExistentClass") # Returns false @@ -257,11 +259,11 @@ </constant> <constant name="INF" value="inf"> Positive floating-point infinity. This is the result of floating-point division when the divisor is [code]0.0[/code]. For negative infinity, use [code]-INF[/code]. Dividing by [code]-0.0[/code] will result in negative infinity if the numerator is positive, so dividing by [code]0.0[/code] is not the same as dividing by [code]-0.0[/code] (despite [code]0.0 == -0.0[/code] returning [code]true[/code]). - [b]Note:[/b] Numeric infinity is only a concept with floating-point numbers, and has no equivalent for integers. Dividing an integer number by [code]0[/code] will not result in [constant INF] and will result in a run-time error instead. + [b]Warning:[/b] Numeric infinity is only a concept with floating-point numbers, and has no equivalent for integers. Dividing an integer number by [code]0[/code] will not result in [constant INF] and will result in a run-time error instead. </constant> <constant name="NAN" value="nan"> "Not a Number", an invalid floating-point value. [constant NAN] has special properties, including that it is not equal to itself ([code]NAN == NAN[/code] returns [code]false[/code]). It is output by some invalid operations, such as dividing floating-point [code]0.0[/code] by [code]0.0[/code]. - [b]Note:[/b] "Not a Number" is only a concept with floating-point numbers, and has no equivalent for integers. Dividing an integer [code]0[/code] by [code]0[/code] will not result in [constant NAN] and will result in a run-time error instead. + [b]Warning:[/b] "Not a Number" is only a concept with floating-point numbers, and has no equivalent for integers. Dividing an integer [code]0[/code] by [code]0[/code] will not result in [constant NAN] and will result in a run-time error instead. </constant> </constants> <annotations> @@ -292,7 +294,7 @@ <annotation name="@export_color_no_alpha"> <return type="void" /> <description> - Export a [Color] property without an alpha (fixed as [code]1.0[/code]). + Export a [Color] property without transparency (its alpha fixed as [code]1.0[/code]). See also [constant PROPERTY_HINT_COLOR_NO_ALPHA]. [codeblock] @export_color_no_alpha var modulate_color: Color @@ -318,7 +320,7 @@ [codeblock] @export_enum("Rebecca", "Mary", "Leah") var character_name: String @export_enum("Warrior", "Magician", "Thief") var character_class: int - @export_enum("Walking:30", "Running:60", "Riding:200") var character_speed: int + @export_enum("Slow:30", "Average:60", "Very Fast:200") var character_speed: int [/codeblock] </description> </annotation> @@ -448,8 +450,8 @@ <param index="1" name="prefix" type="String" default="""" /> <description> Define a new group for the following exported properties. This helps to organize properties in the Inspector dock. Groups can be added with an optional [param prefix], which would make group to only consider properties that have this prefix. The grouping will break on the first property that doesn't have a prefix. The prefix is also removed from the property's name in the Inspector dock. - If no [param prefix] is provided, the every following property is added to the group. The group ends when then next group or category is defined. You can also force end a group by using this annotation with empty strings for paramters, [code]@export_group("", "")[/code]. - Groups cannot be nested, use [annotation @export_subgroup] to add subgroups to your groups. + If no [param prefix] is provided, the every following property is added to the group. The group ends when then next group or category is defined. You can also force end a group by using this annotation with empty strings for parameters, [code]@export_group("", "")[/code]. + Groups cannot be nested, use [annotation @export_subgroup] to add subgroups within groups. See also [constant PROPERTY_USAGE_GROUP]. [codeblock] @export_group("My Properties") @@ -471,7 +473,7 @@ Export a [String] property with a large [TextEdit] widget instead of a [LineEdit]. This adds support for multiline content and makes it easier to edit large amount of text stored in the property. See also [constant PROPERTY_HINT_MULTILINE_TEXT]. [codeblock] - @export_multiline var character_bio + @export_multiline var character_biography [/codeblock] </description> </annotation> @@ -505,7 +507,7 @@ <param index="3" name="extra_hints" type="String" default="""" /> <description> Export a numeric property as a range value. The range must be defined by [param min] and [param max], as well as an optional [param step] and a variety of extra hints. The [param step] defaults to [code]1[/code] for integer properties. For floating-point numbers this value depends on your [code]EditorSettings.interface/inspector/default_float_step[/code] setting. - If hints [code]"or_greater"[/code] and [code]"or_less"[/code] are provided, the editor widget will not cap the value at range boundaries. The [code]"exp"[/code] hint will make the edited values on range to change exponentially. The [code]"no_slider"[/code] hint will hide the slider element of the editor widget. + If hints [code]"or_greater"[/code] and [code]"or_less"[/code] are provided, the editor widget will not cap the value at range boundaries. The [code]"exp"[/code] hint will make the edited values on range to change exponentially. The [code]"hide_slider"[/code] hint will hide the slider element of the editor widget. Hints also allow to indicate the units for the edited value. Using [code]"radians"[/code] you can specify that the actual value is in radians, but should be displayed in degrees in the Inspector dock. [code]"degrees"[/code] allows to add a degree sign as a unit suffix. Finally, a custom suffix can be provided using [code]"suffix:unit"[/code], where "unit" can be any string. See also [constant PROPERTY_HINT_RANGE]. [codeblock] @@ -545,11 +547,11 @@ <return type="void" /> <param index="0" name="icon_path" type="String" /> <description> - Add a custom icon to the current script. The icon is displayed in the Scene dock for every node that the script is attached to. For named classes the icon is also displayed in various editor dialogs. + Add a custom icon to the current script. After loading an icon at [param icon_path], the icon is displayed in the Scene dock for every node that the script is attached to. For named classes, the icon is also displayed in various editor dialogs. [codeblock] @icon("res://path/to/class/icon.svg") [/codeblock] - [b]Note:[/b] Only the script can have a custom icon. Inner classes are not supported yet. + [b]Note:[/b] Only the script can have a custom icon. Inner classes are not supported. </description> </annotation> <annotation name="@onready"> @@ -588,7 +590,7 @@ <return type="void" /> <param index="0" name="warning" type="String" /> <description> - Mark the following statement to ignore the specified warning. See [url=$DOCS_URL/tutorials/scripting/gdscript/warning_system.html]GDScript warning system[/url]. + Mark the following statement to ignore the specified [param warning]. See [url=$DOCS_URL/tutorials/scripting/gdscript/warning_system.html]GDScript warning system[/url]. [codeblock] func test(): print("hello") diff --git a/modules/gdscript/editor/gdscript_highlighter.cpp b/modules/gdscript/editor/gdscript_highlighter.cpp index afb59b486c..996d323a7f 100644 --- a/modules/gdscript/editor/gdscript_highlighter.cpp +++ b/modules/gdscript/editor/gdscript_highlighter.cpp @@ -39,30 +39,32 @@ Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting_impl(int p_l Type next_type = NONE; Type current_type = NONE; - Type previous_type = NONE; - - String previous_text = ""; - int previous_column = 0; + Type prev_type = NONE; + String prev_text = ""; + int prev_column = 0; bool prev_is_char = false; bool prev_is_digit = false; bool prev_is_binary_op = false; + bool in_keyword = false; bool in_word = false; bool in_number = false; - bool in_function_name = false; - bool in_lambda = false; - bool in_variable_declaration = false; - bool in_signal_declaration = false; - bool in_function_args = false; - bool in_member_variable = false; bool in_node_path = false; bool in_node_ref = false; bool in_annotation = false; bool in_string_name = false; bool is_hex_notation = false; bool is_bin_notation = false; + bool in_member_variable = false; + bool in_lambda = false; + + bool in_function_name = false; + bool in_function_args = false; + bool in_variable_declaration = false; + bool in_signal_declaration = false; bool expect_type = false; + Color keyword_color; Color color; @@ -224,9 +226,9 @@ Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting_impl(int p_l } } - previous_type = REGION; - previous_text = ""; - previous_column = j; + prev_type = REGION; + prev_text = ""; + prev_column = j; j = from + (end_key_length - 1); if (region_end_index == -1) { color_region_cache[p_line] = in_region; @@ -241,19 +243,22 @@ Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting_impl(int p_l } } - // A bit of a hack, but couldn't come up with anything better. + // VERY hacky... but couldn't come up with anything better. if (j > 0 && (str[j] == '&' || str[j] == '^' || str[j] == '%' || str[j] == '+' || str[j] == '-' || str[j] == '~' || str[j] == '.')) { - if (!keywords.has(previous_text)) { - if (previous_text == "PI" || previous_text == "TAU" || previous_text == "INF" || previous_text == "NAN") { + int to = j - 1; + // Find what the last text was (prev_text won't work if there's no whitespace, so we need to do it manually). + while (to > 0 && is_whitespace(str[to])) { + to--; + } + int from = to; + while (from > 0 && !is_symbol(str[from])) { + from--; + } + String word = str.substr(from + 1, to - from); + // Keywords need to be exceptions, except for keywords that represent a value. + if (word == "true" || word == "false" || word == "null" || word == "PI" || word == "TAU" || word == "INF" || word == "NAN" || word == "self" || word == "super" || !reserved_keywords.has(word)) { + if (!is_symbol(str[to]) || str[to] == '"' || str[to] == '\'' || str[to] == ')' || str[to] == ']' || str[to] == '}') { is_binary_op = true; - } else { - int k = j - 1; - while (k > 0 && is_whitespace(str[k])) { - k--; - } - if (!is_symbol(str[k]) || str[k] == '"' || str[k] == '\'' || str[k] == ')' || str[k] == ']' || str[k] == '}') { - is_binary_op = true; - } } } } @@ -287,16 +292,18 @@ Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting_impl(int p_l is_hex_notation = true; } else if (!((str[j] == '-' || str[j] == '+') && str[j - 1] == 'e' && !prev_is_digit) && !(str[j] == '_' && (prev_is_digit || str[j - 1] == 'b' || str[j - 1] == 'x' || str[j - 1] == '.')) && - !((str[j] == 'e' || str[j] == '.') && (prev_is_digit || str[j - 1] == '_')) && + !(str[j] == 'e' && (prev_is_digit || str[j - 1] == '_')) && + !(str[j] == '.' && (prev_is_digit || (!prev_is_binary_op && (j > 0 && (str[j - 1] == '-' || str[j - 1] == '+' || str[j - 1] == '~'))))) && !((str[j] == '-' || str[j] == '+' || str[j] == '~') && !prev_is_binary_op && str[j - 1] != 'e')) { - /* 1st row of condition: '+' or '-' after scientific notation; - 2nd row of condition: '_' as a numeric separator; - 3rd row of condition: Scientific notation 'e' and floating points; - 4th row of condition: Multiple unary operators. */ + /* This condition continues Number highlighting in special cases. + 1st row: '+' or '-' after scientific notation; + 2nd row: '_' as a numeric separator; + 3rd row: Scientific notation 'e' and floating points; + 4th row: Floating points inside the number, or leading if after a unary mathematical operator; + 5th row: Multiple unary mathematical operators */ in_number = false; } - } else if ((str[j] == '-' || str[j] == '+' || str[j] == '~' || (str[j] == '.' && str[j + 1] != '.' && (j == 0 || (j > 0 && str[j - 1] != '.')))) && !is_binary_op) { - // Start a number from unary mathematical operators and floating points, except for '..' + } else if (!is_binary_op && (str[j] == '-' || str[j] == '+' || str[j] == '~' || (str[j] == '.' && str[j + 1] != '.' && (j == 0 || (j > 0 && str[j - 1] != '.'))))) { in_number = true; } @@ -318,7 +325,7 @@ Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting_impl(int p_l Color col = Color(); if (global_functions.has(word)) { // "assert" and "preload" are reserved, so highlight even if not followed by a bracket. - if (word == "assert" || word == "preload") { + if (word == GDScriptTokenizer::get_token_name(GDScriptTokenizer::Token::ASSERT) || word == GDScriptTokenizer::get_token_name(GDScriptTokenizer::Token::PRELOAD)) { col = global_function_color; } else { // For other global functions, check if followed by bracket. @@ -331,8 +338,10 @@ Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting_impl(int p_l col = global_function_color; } } - } else if (keywords.has(word)) { - col = keywords[word]; + } else if (class_names.has(word)) { + col = class_names[word]; + } else if (reserved_keywords.has(word)) { + col = reserved_keywords[word]; } else if (member_keywords.has(word)) { col = member_keywords[word]; } @@ -355,7 +364,7 @@ Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting_impl(int p_l } if (!in_function_name && in_word && !in_keyword) { - if (previous_text == GDScriptTokenizer::get_token_name(GDScriptTokenizer::Token::SIGNAL)) { + if (prev_text == GDScriptTokenizer::get_token_name(GDScriptTokenizer::Token::SIGNAL)) { in_signal_declaration = true; } else { int k = j; @@ -370,12 +379,12 @@ Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting_impl(int p_l if (str[k] == '(') { in_function_name = true; - } else if (previous_text == GDScriptTokenizer::get_token_name(GDScriptTokenizer::Token::VAR)) { + } else if (prev_text == GDScriptTokenizer::get_token_name(GDScriptTokenizer::Token::VAR)) { in_variable_declaration = true; } // Check for lambda. - if (in_function_name && previous_text == GDScriptTokenizer::get_token_name(GDScriptTokenizer::Token::FUNC)) { + if (in_function_name && prev_text == GDScriptTokenizer::get_token_name(GDScriptTokenizer::Token::FUNC)) { k = j - 1; while (k > 0 && is_whitespace(str[k])) { k--; @@ -408,11 +417,11 @@ Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting_impl(int p_l in_function_args = false; } - if (expect_type && (prev_is_char || str[j] == '=')) { + if (expect_type && (prev_is_char || str[j] == '=') && str[j] != '[') { expect_type = false; } - if (j > 0 && str[j] == '>' && str[j - 1] == '-') { + if (j > 0 && str[j - 1] == '-' && str[j] == '>') { expect_type = true; } @@ -491,7 +500,7 @@ Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting_impl(int p_l } else if (in_function_name) { next_type = FUNCTION; - if (!in_lambda && previous_text == GDScriptTokenizer::get_token_name(GDScriptTokenizer::Token::FUNC)) { + if (!in_lambda && prev_text == GDScriptTokenizer::get_token_name(GDScriptTokenizer::Token::FUNC)) { color = function_definition_color; } else { color = function_color; @@ -513,20 +522,20 @@ Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting_impl(int p_l if (current_type == NONE) { current_type = next_type; } else { - previous_type = current_type; + prev_type = current_type; current_type = next_type; // no need to store regions... - if (previous_type == REGION) { - previous_text = ""; - previous_column = j; + if (prev_type == REGION) { + prev_text = ""; + prev_column = j; } else { - String text = str.substr(previous_column, j - previous_column).strip_edges(); - previous_column = j; + String text = str.substr(prev_column, j - prev_column).strip_edges(); + prev_column = j; // ignore if just whitespace if (!text.is_empty()) { - previous_text = text; + prev_text = text; } } } @@ -556,7 +565,8 @@ PackedStringArray GDScriptSyntaxHighlighter::_get_supported_languages() const { } void GDScriptSyntaxHighlighter::_update_cache() { - keywords.clear(); + class_names.clear(); + reserved_keywords.clear(); member_keywords.clear(); global_functions.clear(); color_regions.clear(); @@ -573,7 +583,7 @@ void GDScriptSyntaxHighlighter::_update_cache() { List<StringName> types; ClassDB::get_class_list(&types); for (const StringName &E : types) { - keywords[E] = types_color; + class_names[E] = types_color; } /* User types. */ @@ -581,14 +591,14 @@ void GDScriptSyntaxHighlighter::_update_cache() { List<StringName> global_classes; ScriptServer::get_global_class_list(&global_classes); for (const StringName &E : global_classes) { - keywords[E] = usertype_color; + class_names[E] = usertype_color; } /* Autoloads. */ for (const KeyValue<StringName, ProjectSettings::AutoloadInfo> &E : ProjectSettings::get_singleton()->get_autoload_list()) { const ProjectSettings::AutoloadInfo &info = E.value; if (info.is_singleton) { - keywords[info.name] = usertype_color; + class_names[info.name] = usertype_color; } } @@ -599,7 +609,7 @@ void GDScriptSyntaxHighlighter::_update_cache() { List<String> core_types; gdscript->get_core_type_words(&core_types); for (const String &E : core_types) { - keywords[StringName(E)] = basetype_color; + class_names[StringName(E)] = basetype_color; } /* Reserved words. */ @@ -609,9 +619,9 @@ void GDScriptSyntaxHighlighter::_update_cache() { gdscript->get_reserved_words(&keyword_list); for (const String &E : keyword_list) { if (gdscript->is_control_flow_keyword(E)) { - keywords[StringName(E)] = control_flow_keyword_color; + reserved_keywords[StringName(E)] = control_flow_keyword_color; } else { - keywords[StringName(E)] = keyword_color; + reserved_keywords[StringName(E)] = keyword_color; } } @@ -646,23 +656,23 @@ void GDScriptSyntaxHighlighter::_update_cache() { add_color_region(beg, end, string_color, end.is_empty()); } - const Ref<Script> script = _get_edited_resource(); - if (script.is_valid()) { + const Ref<Script> scr = _get_edited_resource(); + if (scr.is_valid()) { /* Member types. */ const Color member_variable_color = EDITOR_GET("text_editor/theme/highlighting/member_variable_color"); - StringName instance_base = script->get_instance_base_type(); + StringName instance_base = scr->get_instance_base_type(); if (instance_base != StringName()) { List<PropertyInfo> plist; ClassDB::get_property_list(instance_base, &plist); for (const PropertyInfo &E : plist) { - String name = E.name; + String prop_name = E.name; if (E.usage & PROPERTY_USAGE_CATEGORY || E.usage & PROPERTY_USAGE_GROUP || E.usage & PROPERTY_USAGE_SUBGROUP) { continue; } - if (name.contains("/")) { + if (prop_name.contains("/")) { continue; } - member_keywords[name] = member_variable_color; + member_keywords[prop_name] = member_variable_color; } List<String> clist; diff --git a/modules/gdscript/editor/gdscript_highlighter.h b/modules/gdscript/editor/gdscript_highlighter.h index 60b5b092d4..7c22eb30b1 100644 --- a/modules/gdscript/editor/gdscript_highlighter.h +++ b/modules/gdscript/editor/gdscript_highlighter.h @@ -47,7 +47,8 @@ private: Vector<ColorRegion> color_regions; HashMap<int, int> color_region_cache; - HashMap<StringName, Color> keywords; + HashMap<StringName, Color> class_names; + HashMap<StringName, Color> reserved_keywords; HashMap<StringName, Color> member_keywords; HashSet<StringName> global_functions; diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp index 1cff2181af..0a9dad04c7 100644 --- a/modules/gdscript/gdscript.cpp +++ b/modules/gdscript/gdscript.cpp @@ -111,9 +111,9 @@ GDScriptFunction *GDScript::_super_constructor(GDScript *p_script) { if (p_script->initializer) { return p_script->initializer; } else { - GDScript *base = p_script->_base; - if (base != nullptr) { - return _super_constructor(base); + GDScript *base_src = p_script->_base; + if (base_src != nullptr) { + return _super_constructor(base_src); } else { return nullptr; } @@ -121,9 +121,9 @@ GDScriptFunction *GDScript::_super_constructor(GDScript *p_script) { } void GDScript::_super_implicit_constructor(GDScript *p_script, GDScriptInstance *p_instance, Callable::CallError &r_error) { - GDScript *base = p_script->_base; - if (base != nullptr) { - _super_implicit_constructor(base, p_instance, r_error); + GDScript *base_src = p_script->_base; + if (base_src != nullptr) { + _super_implicit_constructor(base_src, p_instance, r_error); if (r_error.error != Callable::CallError::CALL_OK) { return; } @@ -151,7 +151,7 @@ GDScriptInstance *GDScript::_create_instance(const Variant **p_args, int p_argco /* STEP 2, INITIALIZE AND CONSTRUCT */ { - MutexLock lock(GDScriptLanguage::singleton->lock); + MutexLock lock(GDScriptLanguage::singleton->mutex); instances.insert(instance->owner); } @@ -160,7 +160,7 @@ GDScriptInstance *GDScript::_create_instance(const Variant **p_args, int p_argco instance->script = Ref<GDScript>(); instance->owner->set_script_instance(nullptr); { - MutexLock lock(GDScriptLanguage::singleton->lock); + MutexLock lock(GDScriptLanguage::singleton->mutex); instances.erase(p_owner); } ERR_FAIL_V_MSG(nullptr, "Error constructing a GDScriptInstance."); @@ -177,7 +177,7 @@ GDScriptInstance *GDScript::_create_instance(const Variant **p_args, int p_argco instance->script = Ref<GDScript>(); instance->owner->set_script_instance(nullptr); { - MutexLock lock(GDScriptLanguage::singleton->lock); + MutexLock lock(GDScriptLanguage::singleton->mutex); instances.erase(p_owner); } ERR_FAIL_V_MSG(nullptr, "Error constructing a GDScriptInstance."); @@ -396,9 +396,9 @@ ScriptInstance *GDScript::instance_create(Object *p_this) { if (top->native.is_valid()) { if (!ClassDB::is_parent_class(p_this->get_class_name(), top->native->get_name())) { if (EngineDebugger::is_active()) { - GDScriptLanguage::get_singleton()->debug_break_parse(_get_debug_path(), 1, "Script inherits from native type '" + String(top->native->get_name()) + "', so it can't be instantiated in object of type: '" + p_this->get_class() + "'"); + GDScriptLanguage::get_singleton()->debug_break_parse(_get_debug_path(), 1, "Script inherits from native type '" + String(top->native->get_name()) + "', so it can't be assigned to an object of type: '" + p_this->get_class() + "'"); } - ERR_FAIL_V_MSG(nullptr, "Script inherits from native type '" + String(top->native->get_name()) + "', so it can't be instantiated in object of type '" + p_this->get_class() + "'" + "."); + ERR_FAIL_V_MSG(nullptr, "Script inherits from native type '" + String(top->native->get_name()) + "', so it can't be assigned to an object of type '" + p_this->get_class() + "'" + "."); } } @@ -418,7 +418,7 @@ PlaceHolderScriptInstance *GDScript::placeholder_instance_create(Object *p_this) } bool GDScript::instance_has(const Object *p_this) const { - MutexLock lock(GDScriptLanguage::singleton->lock); + MutexLock lock(GDScriptLanguage::singleton->mutex); return instances.has((Object *)p_this); } @@ -620,11 +620,11 @@ void GDScript::_update_doc() { } if (!is_enum) { DocData::ConstantDoc constant_doc; - String doc_description; + String const_description; if (doc_constants.has(E.key)) { - doc_description = doc_constants[E.key]; + const_description = doc_constants[E.key]; } - DocData::constant_doc_from_variant(constant_doc, E.key, E.value, doc_description); + DocData::constant_doc_from_variant(constant_doc, E.key, E.value, const_description); doc.constants.push_back(constant_doc); } } @@ -675,35 +675,35 @@ bool GDScript::_update_exports(bool *r_err, bool p_recursive_call, PlaceHolderSc } if (c->extends_used) { - String path = ""; + String ext_path = ""; if (String(c->extends_path) != "" && String(c->extends_path) != get_path()) { - path = c->extends_path; - if (path.is_relative_path()) { - String base = get_path(); - if (base.is_empty() || base.is_relative_path()) { - ERR_PRINT(("Could not resolve relative path for parent class: " + path).utf8().get_data()); + ext_path = c->extends_path; + if (ext_path.is_relative_path()) { + String base_path = get_path(); + if (base_path.is_empty() || base_path.is_relative_path()) { + ERR_PRINT(("Could not resolve relative path for parent class: " + ext_path).utf8().get_data()); } else { - path = base.get_base_dir().path_join(path); + ext_path = base_path.get_base_dir().path_join(ext_path); } } } else if (c->extends.size() != 0) { - const StringName &base = c->extends[0]; + const StringName &base_class = c->extends[0]; - if (ScriptServer::is_global_class(base)) { - path = ScriptServer::get_global_class_path(base); + if (ScriptServer::is_global_class(base_class)) { + ext_path = ScriptServer::get_global_class_path(base_class); } } - if (!path.is_empty()) { - if (path != get_path()) { - Ref<GDScript> bf = ResourceLoader::load(path); + if (!ext_path.is_empty()) { + if (ext_path != get_path()) { + Ref<GDScript> bf = ResourceLoader::load(ext_path); if (bf.is_valid()) { base_cache = bf; bf->inheriters_cache.insert(get_instance_id()); } } else { - ERR_PRINT(("Path extending itself in " + path).utf8().get_data()); + ERR_PRINT(("Path extending itself in " + ext_path).utf8().get_data()); } } } @@ -843,7 +843,7 @@ String GDScript::_get_debug_path() const { Error GDScript::reload(bool p_keep_state) { bool has_instances; { - MutexLock lock(GDScriptLanguage::singleton->lock); + MutexLock lock(GDScriptLanguage::singleton->mutex); has_instances = instances.size(); } @@ -1187,7 +1187,7 @@ GDScript::GDScript() : script_list(this) { #ifdef DEBUG_ENABLED { - MutexLock lock(GDScriptLanguage::get_singleton()->lock); + MutexLock lock(GDScriptLanguage::get_singleton()->mutex); GDScriptLanguage::get_singleton()->script_list.add(&script_list); } @@ -1258,7 +1258,7 @@ void GDScript::_init_rpc_methods_properties() { GDScript::~GDScript() { { - MutexLock lock(GDScriptLanguage::get_singleton()->lock); + MutexLock lock(GDScriptLanguage::get_singleton()->mutex); while (SelfList<GDScriptFunctionState> *E = pending_func_states.first()) { // Order matters since clearing the stack may already cause @@ -1295,7 +1295,7 @@ GDScript::~GDScript() { #ifdef DEBUG_ENABLED { - MutexLock lock(GDScriptLanguage::get_singleton()->lock); + MutexLock lock(GDScriptLanguage::get_singleton()->mutex); GDScriptLanguage::get_singleton()->script_list.remove(&script_list); } @@ -1722,7 +1722,7 @@ GDScriptInstance::GDScriptInstance() { } GDScriptInstance::~GDScriptInstance() { - MutexLock lock(GDScriptLanguage::get_singleton()->lock); + MutexLock lock(GDScriptLanguage::get_singleton()->mutex); while (SelfList<GDScriptFunctionState> *E = pending_func_states.first()) { // Order matters since clearing the stack may already cause @@ -1825,7 +1825,7 @@ void GDScriptLanguage::finish() { void GDScriptLanguage::profiling_start() { #ifdef DEBUG_ENABLED - MutexLock lock(this->lock); + MutexLock lock(this->mutex); SelfList<GDScriptFunction> *elem = function_list.first(); while (elem) { @@ -1847,7 +1847,7 @@ void GDScriptLanguage::profiling_start() { void GDScriptLanguage::profiling_stop() { #ifdef DEBUG_ENABLED - MutexLock lock(this->lock); + MutexLock lock(this->mutex); profiling = false; #endif @@ -1857,7 +1857,7 @@ int GDScriptLanguage::profiling_get_accumulated_data(ProfilingInfo *p_info_arr, int current = 0; #ifdef DEBUG_ENABLED - MutexLock lock(this->lock); + MutexLock lock(this->mutex); SelfList<GDScriptFunction> *elem = function_list.first(); while (elem) { @@ -1880,7 +1880,7 @@ int GDScriptLanguage::profiling_get_frame_data(ProfilingInfo *p_info_arr, int p_ int current = 0; #ifdef DEBUG_ENABLED - MutexLock lock(this->lock); + MutexLock lock(this->mutex); SelfList<GDScriptFunction> *elem = function_list.first(); while (elem) { @@ -1926,7 +1926,7 @@ void GDScriptLanguage::reload_all_scripts() { print_verbose("GDScript: Reloading all scripts"); List<Ref<GDScript>> scripts; { - MutexLock lock(this->lock); + MutexLock lock(this->mutex); SelfList<GDScript> *elem = script_list.first(); while (elem) { @@ -1942,10 +1942,10 @@ void GDScriptLanguage::reload_all_scripts() { scripts.sort_custom<GDScriptDepSort>(); //update in inheritance dependency order - for (Ref<GDScript> &script : scripts) { - print_verbose("GDScript: Reloading: " + script->get_path()); - script->load_source_code(script->get_path()); - script->reload(true); + for (Ref<GDScript> &scr : scripts) { + print_verbose("GDScript: Reloading: " + scr->get_path()); + scr->load_source_code(scr->get_path()); + scr->reload(true); } #endif } @@ -1955,7 +1955,7 @@ void GDScriptLanguage::reload_tool_script(const Ref<Script> &p_script, bool p_so List<Ref<GDScript>> scripts; { - MutexLock lock(this->lock); + MutexLock lock(this->mutex); SelfList<GDScript> *elem = script_list.first(); while (elem) { @@ -1974,21 +1974,21 @@ void GDScriptLanguage::reload_tool_script(const Ref<Script> &p_script, bool p_so scripts.sort_custom<GDScriptDepSort>(); //update in inheritance dependency order - for (Ref<GDScript> &script : scripts) { - bool reload = script == p_script || to_reload.has(script->get_base()); + for (Ref<GDScript> &scr : scripts) { + bool reload = scr == p_script || to_reload.has(scr->get_base()); if (!reload) { continue; } - to_reload.insert(script, HashMap<ObjectID, List<Pair<StringName, Variant>>>()); + to_reload.insert(scr, HashMap<ObjectID, List<Pair<StringName, Variant>>>()); if (!p_soft_reload) { //save state and remove script from instances - HashMap<ObjectID, List<Pair<StringName, Variant>>> &map = to_reload[script]; + HashMap<ObjectID, List<Pair<StringName, Variant>>> &map = to_reload[scr]; - while (script->instances.front()) { - Object *obj = script->instances.front()->get(); + while (scr->instances.front()) { + Object *obj = scr->instances.front()->get(); //save instance info List<Pair<StringName, Variant>> state; if (obj->get_script_instance()) { @@ -2001,8 +2001,8 @@ void GDScriptLanguage::reload_tool_script(const Ref<Script> &p_script, bool p_so //same thing for placeholders #ifdef TOOLS_ENABLED - while (script->placeholders.size()) { - Object *obj = (*script->placeholders.begin())->get_owner(); + while (scr->placeholders.size()) { + Object *obj = (*scr->placeholders.begin())->get_owner(); //save instance info if (obj->get_script_instance()) { @@ -2012,13 +2012,13 @@ void GDScriptLanguage::reload_tool_script(const Ref<Script> &p_script, bool p_so obj->set_script(Variant()); } else { // no instance found. Let's remove it so we don't loop forever - script->placeholders.erase(*script->placeholders.begin()); + scr->placeholders.erase(*scr->placeholders.begin()); } } #endif - for (const KeyValue<ObjectID, List<Pair<StringName, Variant>>> &F : script->pending_reload_state) { + for (const KeyValue<ObjectID, List<Pair<StringName, Variant>>> &F : scr->pending_reload_state) { map[F.key] = F.value; //pending to reload, use this one instead } } @@ -2043,9 +2043,9 @@ void GDScriptLanguage::reload_tool_script(const Ref<Script> &p_script, bool p_so } obj->set_script(scr); - ScriptInstance *script_instance = obj->get_script_instance(); + ScriptInstance *script_inst = obj->get_script_instance(); - if (!script_instance) { + if (!script_inst) { //failed, save reload state for next time if not saved if (!scr->pending_reload_state.has(obj->get_instance_id())) { scr->pending_reload_state[obj->get_instance_id()] = saved_state; @@ -2053,14 +2053,14 @@ void GDScriptLanguage::reload_tool_script(const Ref<Script> &p_script, bool p_so continue; } - if (script_instance->is_placeholder() && scr->is_placeholder_fallback_enabled()) { - PlaceHolderScriptInstance *placeholder = static_cast<PlaceHolderScriptInstance *>(script_instance); + if (script_inst->is_placeholder() && scr->is_placeholder_fallback_enabled()) { + PlaceHolderScriptInstance *placeholder = static_cast<PlaceHolderScriptInstance *>(script_inst); for (List<Pair<StringName, Variant>>::Element *G = saved_state.front(); G; G = G->next()) { placeholder->property_set_fallback(G->get().first, G->get().second); } } else { for (List<Pair<StringName, Variant>>::Element *G = saved_state.front(); G; G = G->next()) { - script_instance->set(G->get().first, G->get().second); + script_inst->set(G->get().first, G->get().second); } } @@ -2078,7 +2078,7 @@ void GDScriptLanguage::frame() { #ifdef DEBUG_ENABLED if (profiling) { - MutexLock lock(this->lock); + MutexLock lock(this->mutex); SelfList<GDScriptFunction> *elem = function_list.first(); while (elem) { @@ -2339,26 +2339,26 @@ GDScriptLanguage::~GDScriptLanguage() { // Clear dependencies between scripts, to ensure cyclic references are broken (to avoid leaks at exit). SelfList<GDScript> *s = script_list.first(); while (s) { - GDScript *script = s->self(); + GDScript *scr = s->self(); // This ensures the current script is not released before we can check what's the next one // in the list (we can't get the next upfront because we don't know if the reference breaking // will cause it -or any other after it, for that matter- to be released so the next one // is not the same as before). - script->reference(); + scr->reference(); - for (KeyValue<StringName, GDScriptFunction *> &E : script->member_functions) { + for (KeyValue<StringName, GDScriptFunction *> &E : scr->member_functions) { GDScriptFunction *func = E.value; for (int i = 0; i < func->argument_types.size(); i++) { func->argument_types.write[i].script_type_ref = Ref<Script>(); } func->return_type.script_type_ref = Ref<Script>(); } - for (KeyValue<StringName, GDScript::MemberInfo> &E : script->member_indices) { + for (KeyValue<StringName, GDScript::MemberInfo> &E : scr->member_indices) { E.value.data_type.script_type_ref = Ref<Script>(); } s = s->next(); - script->unreference(); + scr->unreference(); } singleton = nullptr; @@ -2390,20 +2390,20 @@ Ref<Resource> ResourceFormatLoaderGDScript::load(const String &p_path, const Str } Error err; - Ref<GDScript> script = GDScriptCache::get_full_script(p_path, err); + Ref<GDScript> scr = GDScriptCache::get_full_script(p_path, err, "", p_cache_mode == CACHE_MODE_IGNORE); // TODO: Reintroduce binary and encrypted scripts. - if (script.is_null()) { + if (scr.is_null()) { // Don't fail loading because of parsing error. - script.instantiate(); + scr.instantiate(); } if (r_error) { *r_error = OK; } - return script; + return scr; } void ResourceFormatLoaderGDScript::get_recognized_extensions(List<String> *p_extensions) const { diff --git a/modules/gdscript/gdscript.h b/modules/gdscript/gdscript.h index e4b12d4ddb..0a010e5ad0 100644 --- a/modules/gdscript/gdscript.h +++ b/modules/gdscript/gdscript.h @@ -342,7 +342,7 @@ class GDScriptLanguage : public ScriptLanguage { friend class GDScriptInstance; - Mutex lock; + Mutex mutex; friend class GDScript; diff --git a/modules/gdscript/gdscript_analyzer.cpp b/modules/gdscript/gdscript_analyzer.cpp index 32d9aec84f..898e4eb1a6 100644 --- a/modules/gdscript/gdscript_analyzer.cpp +++ b/modules/gdscript/gdscript_analyzer.cpp @@ -262,19 +262,19 @@ Error GDScriptAnalyzer::resolve_inheritance(GDScriptParser::ClassNode *p_class, if (p_class->extends_path.is_relative_path()) { p_class->extends_path = class_type.script_path.get_base_dir().path_join(p_class->extends_path).simplify_path(); } - Ref<GDScriptParserRef> parser = get_parser_for(p_class->extends_path); - if (parser.is_null()) { + Ref<GDScriptParserRef> ext_parser = get_parser_for(p_class->extends_path); + if (ext_parser.is_null()) { push_error(vformat(R"(Could not resolve super class path "%s".)", p_class->extends_path), p_class); return ERR_PARSE_ERROR; } - Error err = parser->raise_status(GDScriptParserRef::INTERFACE_SOLVED); + Error err = ext_parser->raise_status(GDScriptParserRef::INTERFACE_SOLVED); if (err != OK) { push_error(vformat(R"(Could not resolve super class inheritance from "%s".)", p_class->extends_path), p_class); return err; } - base = parser->get_parser()->head->get_datatype(); + base = ext_parser->get_parser()->head->get_datatype(); } else { if (p_class->extends.is_empty()) { push_error("Could not resolve an empty super class path.", p_class); @@ -289,18 +289,18 @@ Error GDScriptAnalyzer::resolve_inheritance(GDScriptParser::ClassNode *p_class, if (base_path == parser->script_path) { base = parser->head->get_datatype(); } else { - Ref<GDScriptParserRef> parser = get_parser_for(base_path); - if (parser.is_null()) { + Ref<GDScriptParserRef> base_parser = get_parser_for(base_path); + if (base_parser.is_null()) { push_error(vformat(R"(Could not resolve super class "%s".)", name), p_class); return ERR_PARSE_ERROR; } - Error err = parser->raise_status(GDScriptParserRef::INTERFACE_SOLVED); + Error err = base_parser->raise_status(GDScriptParserRef::INTERFACE_SOLVED); if (err != OK) { push_error(vformat(R"(Could not resolve super class inheritance from "%s".)", name), p_class); return err; } - base = parser->get_parser()->head->get_datatype(); + base = base_parser->get_parser()->head->get_datatype(); } } else if (ProjectSettings::get_singleton()->has_autoload(name) && ProjectSettings::get_singleton()->get_autoload(name).is_singleton) { const ProjectSettings::AutoloadInfo &info = ProjectSettings::get_singleton()->get_autoload(name); @@ -309,13 +309,13 @@ Error GDScriptAnalyzer::resolve_inheritance(GDScriptParser::ClassNode *p_class, return ERR_PARSE_ERROR; } - Ref<GDScriptParserRef> parser = get_parser_for(info.path); - if (parser.is_null()) { + Ref<GDScriptParserRef> info_parser = get_parser_for(info.path); + if (info_parser.is_null()) { push_error(vformat(R"(Could not parse singleton from "%s".)", info.path), p_class); return ERR_PARSE_ERROR; } - Error err = parser->raise_status(GDScriptParserRef::INTERFACE_SOLVED); + Error err = info_parser->raise_status(GDScriptParserRef::INTERFACE_SOLVED); if (err != OK) { push_error(vformat(R"(Could not resolve super class inheritance from "%s".)", name), p_class); return err; @@ -1041,7 +1041,7 @@ void GDScriptAnalyzer::resolve_class_body(GDScriptParser::ClassNode *p_class) { } } -void GDScriptAnalyzer::resolve_node(GDScriptParser::Node *p_node) { +void GDScriptAnalyzer::resolve_node(GDScriptParser::Node *p_node, bool p_is_root) { ERR_FAIL_COND_MSG(p_node == nullptr, "Trying to resolve type of a null node."); switch (p_node->type) { @@ -1114,7 +1114,7 @@ void GDScriptAnalyzer::resolve_node(GDScriptParser::Node *p_node) { case GDScriptParser::Node::SUBSCRIPT: case GDScriptParser::Node::TERNARY_OPERATOR: case GDScriptParser::Node::UNARY_OPERATOR: - reduce_expression(static_cast<GDScriptParser::ExpressionNode *>(p_node), true); + reduce_expression(static_cast<GDScriptParser::ExpressionNode *>(p_node), p_is_root); break; case GDScriptParser::Node::BREAK: case GDScriptParser::Node::BREAKPOINT: @@ -1411,7 +1411,7 @@ void GDScriptAnalyzer::resolve_for(GDScriptParser::ForNode *p_for) { variable_type.builtin_type = Variant::INT; // Can this ever be a float or something else? p_for->variable->set_datatype(variable_type); } else if (p_for->list) { - resolve_node(p_for->list); + resolve_node(p_for->list, false); if (p_for->list->datatype.has_container_element_type()) { variable_type = p_for->list->datatype.get_container_element_type(); variable_type.type_source = GDScriptParser::DataType::ANNOTATED_INFERRED; @@ -1439,7 +1439,7 @@ void GDScriptAnalyzer::resolve_for(GDScriptParser::ForNode *p_for) { } void GDScriptAnalyzer::resolve_while(GDScriptParser::WhileNode *p_while) { - resolve_node(p_while->condition); + resolve_node(p_while->condition, false); resolve_suite(p_while->loop); p_while->set_datatype(p_while->loop->get_datatype()); @@ -1824,7 +1824,7 @@ void GDScriptAnalyzer::reduce_expression(GDScriptParser::ExpressionNode *p_expre reduce_binary_op(static_cast<GDScriptParser::BinaryOpNode *>(p_expression)); break; case GDScriptParser::Node::CALL: - reduce_call(static_cast<GDScriptParser::CallNode *>(p_expression), p_is_root); + reduce_call(static_cast<GDScriptParser::CallNode *>(p_expression), false, p_is_root); break; case GDScriptParser::Node::CAST: reduce_cast(static_cast<GDScriptParser::CastNode *>(p_expression)); @@ -2548,6 +2548,16 @@ void GDScriptAnalyzer::reduce_call(GDScriptParser::CallNode *p_call, bool p_is_a mark_lambda_use_self(); } +#ifdef DEBUG_ENABLED + if (p_is_root && return_type.kind != GDScriptParser::DataType::UNRESOLVED && return_type.builtin_type != Variant::NIL) { + parser->push_warning(p_call, GDScriptWarning::RETURN_VALUE_DISCARDED, p_call->function_name); + } + + if (is_static && !base_type.is_meta_type && !(callee_type != GDScriptParser::Node::SUBSCRIPT && parser->current_function != nullptr && parser->current_function->is_static)) { + parser->push_warning(p_call, GDScriptWarning::STATIC_CALLED_ON_INSTANCE, p_call->function_name, base_type.to_string()); + } +#endif // DEBUG_ENABLED + call_type = return_type; } else { bool found = false; @@ -3093,11 +3103,11 @@ void GDScriptAnalyzer::reduce_identifier(GDScriptParser::IdentifierNode *p_ident result.kind = GDScriptParser::DataType::NATIVE; result.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT; if (autoload.path.to_lower().ends_with(GDScriptLanguage::get_singleton()->get_extension())) { - Ref<GDScriptParserRef> parser = get_parser_for(autoload.path); - if (parser.is_valid()) { - Error err = parser->raise_status(GDScriptParserRef::INTERFACE_SOLVED); + Ref<GDScriptParserRef> singl_parser = get_parser_for(autoload.path); + if (singl_parser.is_valid()) { + Error err = singl_parser->raise_status(GDScriptParserRef::INTERFACE_SOLVED); if (err == OK) { - result = type_from_metatype(parser->get_parser()->head->get_datatype()); + result = type_from_metatype(singl_parser->get_parser()->head->get_datatype()); } } } @@ -3216,7 +3226,13 @@ void GDScriptAnalyzer::reduce_preload(GDScriptParser::PreloadNode *p_preload) { } p_preload->resolved_path = p_preload->resolved_path.simplify_path(); if (!ResourceLoader::exists(p_preload->resolved_path)) { - push_error(vformat(R"(Preload file "%s" does not exist.)", p_preload->resolved_path), p_preload->path); + Ref<FileAccess> file_check = FileAccess::create(FileAccess::ACCESS_RESOURCES); + + if (file_check->file_exists(p_preload->resolved_path)) { + push_error(vformat(R"(Preload file "%s" has no resource loaders (unrecognized file extension).)", p_preload->resolved_path), p_preload->path); + } else { + push_error(vformat(R"(Preload file "%s" does not exist.)", p_preload->resolved_path), p_preload->path); + } } else { // TODO: Don't load if validating: use completion cache. p_preload->resource = ResourceLoader::load(p_preload->resolved_path); diff --git a/modules/gdscript/gdscript_analyzer.h b/modules/gdscript/gdscript_analyzer.h index 3966b81b6e..217a856ce0 100644 --- a/modules/gdscript/gdscript_analyzer.h +++ b/modules/gdscript/gdscript_analyzer.h @@ -63,7 +63,7 @@ class GDScriptAnalyzer { void resolve_class_body(GDScriptParser::ClassNode *p_class); void resolve_function_signature(GDScriptParser::FunctionNode *p_function); void resolve_function_body(GDScriptParser::FunctionNode *p_function); - void resolve_node(GDScriptParser::Node *p_node); + void resolve_node(GDScriptParser::Node *p_node, bool p_is_root = true); void resolve_suite(GDScriptParser::SuiteNode *p_suite); void resolve_if(GDScriptParser::IfNode *p_if); void resolve_for(GDScriptParser::ForNode *p_for); diff --git a/modules/gdscript/gdscript_cache.cpp b/modules/gdscript/gdscript_cache.cpp index c25f5b58d5..271296c2f9 100644 --- a/modules/gdscript/gdscript_cache.cpp +++ b/modules/gdscript/gdscript_cache.cpp @@ -183,20 +183,26 @@ Ref<GDScript> GDScriptCache::get_shallow_script(const String &p_path, const Stri return script; } -Ref<GDScript> GDScriptCache::get_full_script(const String &p_path, Error &r_error, const String &p_owner) { +Ref<GDScript> GDScriptCache::get_full_script(const String &p_path, Error &r_error, const String &p_owner, bool p_update_from_disk) { MutexLock lock(singleton->lock); if (!p_owner.is_empty()) { singleton->dependencies[p_owner].insert(p_path); } + Ref<GDScript> script; r_error = OK; if (singleton->full_gdscript_cache.has(p_path)) { - return singleton->full_gdscript_cache[p_path]; + script = Ref<GDScript>(singleton->full_gdscript_cache[p_path]); + if (!p_update_from_disk) { + return script; + } } - Ref<GDScript> script = get_shallow_script(p_path); - ERR_FAIL_COND_V(script.is_null(), Ref<GDScript>()); + if (script.is_null()) { + script = get_shallow_script(p_path); + ERR_FAIL_COND_V(script.is_null(), Ref<GDScript>()); + } r_error = script->load_source_code(p_path); diff --git a/modules/gdscript/gdscript_cache.h b/modules/gdscript/gdscript_cache.h index b971bdd984..3d111ea229 100644 --- a/modules/gdscript/gdscript_cache.h +++ b/modules/gdscript/gdscript_cache.h @@ -88,7 +88,7 @@ public: static Ref<GDScriptParserRef> get_parser(const String &p_path, GDScriptParserRef::Status status, Error &r_error, const String &p_owner = String()); static String get_source_code(const String &p_path); static Ref<GDScript> get_shallow_script(const String &p_path, const String &p_owner = String()); - static Ref<GDScript> get_full_script(const String &p_path, Error &r_error, const String &p_owner = String()); + static Ref<GDScript> get_full_script(const String &p_path, Error &r_error, const String &p_owner = String(), bool p_update_from_disk = false); static Error finish_compiling(const String &p_owner); GDScriptCache(); diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp index 00e8223b9a..7acd1cdb96 100644 --- a/modules/gdscript/gdscript_compiler.cpp +++ b/modules/gdscript/gdscript_compiler.cpp @@ -522,11 +522,11 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code // Create temporary for result first since it will be deleted last. GDScriptCodeGenerator::Address result = codegen.add_temporary(cast_type); - GDScriptCodeGenerator::Address source = _parse_expression(codegen, r_error, cn->operand); + GDScriptCodeGenerator::Address src = _parse_expression(codegen, r_error, cn->operand); - gen->write_cast(result, source, cast_type); + gen->write_cast(result, src, cast_type); - if (source.mode == GDScriptCodeGenerator::Address::TEMPORARY) { + if (src.mode == GDScriptCodeGenerator::Address::TEMPORARY) { gen->pop_temporary(); } @@ -1650,7 +1650,7 @@ void GDScriptCompiler::_add_locals_in_block(CodeGen &codegen, const GDScriptPars } Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::SuiteNode *p_block, bool p_add_locals) { - Error error = OK; + Error err = OK; GDScriptCodeGenerator *gen = codegen.generator; codegen.start_block(); @@ -1676,9 +1676,9 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Sui // Evaluate the match expression. GDScriptCodeGenerator::Address value = codegen.add_local("@match_value", _gdtype_from_datatype(match->test->get_datatype())); - GDScriptCodeGenerator::Address value_expr = _parse_expression(codegen, error, match->test); - if (error) { - return error; + GDScriptCodeGenerator::Address value_expr = _parse_expression(codegen, err, match->test); + if (err) { + return err; } // Assign to local. @@ -1723,9 +1723,9 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Sui // For each pattern in branch. GDScriptCodeGenerator::Address pattern_result = codegen.add_temporary(); for (int k = 0; k < branch->patterns.size(); k++) { - pattern_result = _parse_match_pattern(codegen, error, branch->patterns[k], value, type, pattern_result, k == 0, false); - if (error != OK) { - return error; + pattern_result = _parse_match_pattern(codegen, err, branch->patterns[k], value, type, pattern_result, k == 0, false); + if (err != OK) { + return err; } } @@ -1736,9 +1736,9 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Sui gen->pop_temporary(); // Parse the branch block. - error = _parse_block(codegen, branch->block, false); // Don't add locals again. - if (error) { - return error; + err = _parse_block(codegen, branch->block, false); // Don't add locals again. + if (err) { + return err; } codegen.end_block(); // Get out of extra block. @@ -1753,9 +1753,9 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Sui } break; case GDScriptParser::Node::IF: { const GDScriptParser::IfNode *if_n = static_cast<const GDScriptParser::IfNode *>(s); - GDScriptCodeGenerator::Address condition = _parse_expression(codegen, error, if_n->condition); - if (error) { - return error; + GDScriptCodeGenerator::Address condition = _parse_expression(codegen, err, if_n->condition); + if (err) { + return err; } gen->write_if(condition); @@ -1764,17 +1764,17 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Sui codegen.generator->pop_temporary(); } - error = _parse_block(codegen, if_n->true_block); - if (error) { - return error; + err = _parse_block(codegen, if_n->true_block); + if (err) { + return err; } if (if_n->false_block) { gen->write_else(); - error = _parse_block(codegen, if_n->false_block); - if (error) { - return error; + err = _parse_block(codegen, if_n->false_block); + if (err) { + return err; } } @@ -1788,9 +1788,9 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Sui gen->start_for(iterator.type, _gdtype_from_datatype(for_n->list->get_datatype())); - GDScriptCodeGenerator::Address list = _parse_expression(codegen, error, for_n->list); - if (error) { - return error; + GDScriptCodeGenerator::Address list = _parse_expression(codegen, err, for_n->list); + if (err) { + return err; } gen->write_for_assignment(iterator, list); @@ -1801,9 +1801,9 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Sui gen->write_for(); - error = _parse_block(codegen, for_n->loop); - if (error) { - return error; + err = _parse_block(codegen, for_n->loop); + if (err) { + return err; } gen->write_endfor(); @@ -1815,9 +1815,9 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Sui gen->start_while_condition(); - GDScriptCodeGenerator::Address condition = _parse_expression(codegen, error, while_n->condition); - if (error) { - return error; + GDScriptCodeGenerator::Address condition = _parse_expression(codegen, err, while_n->condition); + if (err) { + return err; } gen->write_while(condition); @@ -1826,9 +1826,9 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Sui codegen.generator->pop_temporary(); } - error = _parse_block(codegen, while_n->loop); - if (error) { - return error; + err = _parse_block(codegen, while_n->loop); + if (err) { + return err; } gen->write_endwhile(); @@ -1850,9 +1850,9 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Sui GDScriptCodeGenerator::Address return_value; if (return_n->return_value != nullptr) { - return_value = _parse_expression(codegen, error, return_n->return_value); - if (error) { - return error; + return_value = _parse_expression(codegen, err, return_n->return_value); + if (err) { + return err; } } @@ -1865,17 +1865,17 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Sui #ifdef DEBUG_ENABLED const GDScriptParser::AssertNode *as = static_cast<const GDScriptParser::AssertNode *>(s); - GDScriptCodeGenerator::Address condition = _parse_expression(codegen, error, as->condition); - if (error) { - return error; + GDScriptCodeGenerator::Address condition = _parse_expression(codegen, err, as->condition); + if (err) { + return err; } GDScriptCodeGenerator::Address message; if (as->message) { - message = _parse_expression(codegen, error, as->message); - if (error) { - return error; + message = _parse_expression(codegen, err, as->message); + if (err) { + return err; } } gen->write_assert(condition, message); @@ -1908,9 +1908,9 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Sui codegen.generator->write_construct_array(local, Vector<GDScriptCodeGenerator::Address>()); } } - GDScriptCodeGenerator::Address src_address = _parse_expression(codegen, error, lv->initializer); - if (error) { - return error; + GDScriptCodeGenerator::Address src_address = _parse_expression(codegen, err, lv->initializer); + if (err) { + return err; } if (lv->use_conversion_assign) { gen->write_assign_with_conversion(local, src_address); @@ -1946,9 +1946,9 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Sui default: { // Expression. if (s->is_expression()) { - GDScriptCodeGenerator::Address expr = _parse_expression(codegen, error, static_cast<const GDScriptParser::ExpressionNode *>(s), true); - if (error) { - return error; + GDScriptCodeGenerator::Address expr = _parse_expression(codegen, err, static_cast<const GDScriptParser::ExpressionNode *>(s), true); + if (err) { + return err; } if (expr.mode == GDScriptCodeGenerator::Address::TEMPORARY) { codegen.generator->pop_temporary(); @@ -2041,7 +2041,7 @@ GDScriptFunction *GDScriptCompiler::_parse_function(Error &r_error, GDScript *p_ codegen.generator->write_newline(field->initializer->start_line); // For typed arrays we need to make sure this is already initialized correctly so typed assignment work. - if (field_type.is_hard_type() && field_type.builtin_type == Variant::ARRAY && field_type.has_container_element_type()) { + if (field_type.is_hard_type() && field_type.builtin_type == Variant::ARRAY) { if (field_type.has_container_element_type()) { codegen.generator->write_construct_typed_array(dst_address, _gdtype_from_datatype(field_type.get_container_element_type(), codegen.script), Vector<GDScriptCodeGenerator::Address>()); } else { @@ -2180,7 +2180,7 @@ GDScriptFunction *GDScriptCompiler::_parse_function(Error &r_error, GDScript *p_ } Error GDScriptCompiler::_parse_setter_getter(GDScript *p_script, const GDScriptParser::ClassNode *p_class, const GDScriptParser::VariableNode *p_variable, bool p_is_setter) { - Error error = OK; + Error err = OK; GDScriptParser::FunctionNode *function; @@ -2190,9 +2190,9 @@ Error GDScriptCompiler::_parse_setter_getter(GDScript *p_script, const GDScriptP function = p_variable->getter; } - _parse_function(error, p_script, p_class, function); + _parse_function(err, p_script, p_class, function); - return error; + return err; } Error GDScriptCompiler::_parse_class_level(GDScript *p_script, const GDScriptParser::ClassNode *p_class, bool p_keep_state) { diff --git a/modules/gdscript/gdscript_compiler.h b/modules/gdscript/gdscript_compiler.h index 4841884e2d..e4264ea55b 100644 --- a/modules/gdscript/gdscript_compiler.h +++ b/modules/gdscript/gdscript_compiler.h @@ -81,10 +81,10 @@ class GDScriptCompiler { type.kind = GDScriptDataType::NATIVE; type.native_type = obj->get_class_name(); - Ref<Script> script = obj->get_script(); - if (script.is_valid()) { - type.script_type = script.ptr(); - Ref<GDScript> gdscript = script; + Ref<Script> scr = obj->get_script(); + if (scr.is_valid()) { + type.script_type = scr.ptr(); + Ref<GDScript> gdscript = scr; if (gdscript.is_valid()) { type.kind = GDScriptDataType::GDSCRIPT; } else { diff --git a/modules/gdscript/gdscript_disassembler.cpp b/modules/gdscript/gdscript_disassembler.cpp index b38c7c6699..b5a209c805 100644 --- a/modules/gdscript/gdscript_disassembler.cpp +++ b/modules/gdscript/gdscript_disassembler.cpp @@ -104,10 +104,10 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const { text += ": "; // This makes the compiler complain if some opcode is unchecked in the switch. - Opcode code = Opcode(_code_ptr[ip] & INSTR_MASK); + Opcode opcode = Opcode(_code_ptr[ip] & INSTR_MASK); int instr_var_args = (_code_ptr[ip] & INSTR_ARGS_MASK) >> INSTR_BITS; - switch (code) { + switch (opcode) { case OPCODE_OPERATOR: { int operation = _code_ptr[ip + 4]; diff --git a/modules/gdscript/gdscript_editor.cpp b/modules/gdscript/gdscript_editor.cpp index c00036c9f0..3c68993b36 100644 --- a/modules/gdscript/gdscript_editor.cpp +++ b/modules/gdscript/gdscript_editor.cpp @@ -61,8 +61,8 @@ bool GDScriptLanguage::is_using_templates() { } Ref<Script> GDScriptLanguage::make_template(const String &p_template, const String &p_class_name, const String &p_base_class_name) const { - Ref<GDScript> script; - script.instantiate(); + Ref<GDScript> scr; + scr.instantiate(); String processed_template = p_template; bool type_hints = false; #ifdef TOOLS_ENABLED @@ -82,8 +82,8 @@ Ref<Script> GDScriptLanguage::make_template(const String &p_template, const Stri processed_template = processed_template.replace("_BASE_", p_base_class_name) .replace("_CLASS_", p_class_name) .replace("_TS_", _get_indentation()); - script->set_source_code(processed_template); - return script; + scr->set_source_code(processed_template); + return scr; } Vector<ScriptLanguage::ScriptTemplate> GDScriptLanguage::get_built_in_templates(StringName p_object) { @@ -318,10 +318,10 @@ void GDScriptLanguage::debug_get_stack_level_members(int p_level, List<String> * return; } - Ref<GDScript> script = instance->get_script(); - ERR_FAIL_COND(script.is_null()); + Ref<GDScript> scr = instance->get_script(); + ERR_FAIL_COND(scr.is_null()); - const HashMap<StringName, GDScript::MemberInfo> &mi = script->debug_get_member_indices(); + const HashMap<StringName, GDScript::MemberInfo> &mi = scr->debug_get_member_indices(); for (const KeyValue<StringName, GDScript::MemberInfo> &E : mi) { p_members->push_back(E.key); @@ -344,7 +344,7 @@ ScriptInstance *GDScriptLanguage::debug_get_stack_level_instance(int p_level) { void GDScriptLanguage::debug_get_globals(List<String> *p_globals, List<Variant> *p_values, int p_max_subitems, int p_max_depth) { const HashMap<StringName, int> &name_idx = GDScriptLanguage::get_singleton()->get_global_map(); - const Variant *globals = GDScriptLanguage::get_singleton()->get_global_array(); + const Variant *gl_array = GDScriptLanguage::get_singleton()->get_global_array(); List<Pair<String, Variant>> cinfo; get_public_constants(&cinfo); @@ -365,7 +365,7 @@ void GDScriptLanguage::debug_get_globals(List<String> *p_globals, List<Variant> continue; } - const Variant &var = globals[E.value]; + const Variant &var = gl_array[E.value]; if (Object *obj = var) { if (Object::cast_to<GDScriptNativeClass>(obj)) { continue; @@ -766,7 +766,7 @@ static void _find_annotation_arguments(const GDScriptParser::AnnotationNode *p_a ScriptLanguage::CodeCompletionOption slider2("or_less", ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT); slider2.insert_text = slider2.display.quote(p_quote_style); r_result.insert(slider2.display, slider2); - ScriptLanguage::CodeCompletionOption slider3("no_slider", ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT); + ScriptLanguage::CodeCompletionOption slider3("hide_slider", ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT); slider3.insert_text = slider3.display.quote(p_quote_style); r_result.insert(slider3.display, slider3); } @@ -1205,8 +1205,8 @@ static void _find_identifiers(const GDScriptParser::CompletionContext &p_context _find_built_in_variants(r_result); static const char *_keywords[] = { - "false", "PI", "TAU", "INF", "NAN", "self", "true", "breakpoint", "tool", "super", - "break", "continue", "pass", "return", + "true", "false", "PI", "TAU", "INF", "NAN", "null", "self", "super", + "break", "breakpoint", "continue", "pass", "return", nullptr }; @@ -1218,7 +1218,7 @@ static void _find_identifiers(const GDScriptParser::CompletionContext &p_context } static const char *_keywords_with_space[] = { - "and", "in", "not", "or", "as", "class", "extends", "is", "func", "signal", "await", + "and", "not", "or", "in", "as", "class", "class_name", "extends", "is", "func", "signal", "await", "const", "enum", "static", "var", "if", "elif", "else", "for", "match", "while", nullptr }; @@ -3302,17 +3302,17 @@ static Error _lookup_symbol_from_base(const GDScriptParser::DataType &p_base, co if (ProjectSettings::get_singleton()->has_autoload(p_symbol)) { const ProjectSettings::AutoloadInfo &autoload = ProjectSettings::get_singleton()->get_autoload(p_symbol); if (autoload.is_singleton) { - String script = autoload.path; - if (!script.ends_with(".gd")) { + String scr_path = autoload.path; + if (!scr_path.ends_with(".gd")) { // Not a script, try find the script anyway, // may have some success. - script = script.get_basename() + ".gd"; + scr_path = scr_path.get_basename() + ".gd"; } - if (FileAccess::exists(script)) { + if (FileAccess::exists(scr_path)) { r_result.type = ScriptLanguage::LOOKUP_RESULT_SCRIPT_LOCATION; r_result.location = 0; - r_result.script = ResourceLoader::load(script); + r_result.script = ResourceLoader::load(scr_path); return OK; } } diff --git a/modules/gdscript/gdscript_function.cpp b/modules/gdscript/gdscript_function.cpp index cd3b7d69c5..98b3e40f1b 100644 --- a/modules/gdscript/gdscript_function.cpp +++ b/modules/gdscript/gdscript_function.cpp @@ -142,7 +142,7 @@ GDScriptFunction::GDScriptFunction() { name = "<anonymous>"; #ifdef DEBUG_ENABLED { - MutexLock lock(GDScriptLanguage::get_singleton()->lock); + MutexLock lock(GDScriptLanguage::get_singleton()->mutex); GDScriptLanguage::get_singleton()->function_list.add(&function_list); } #endif @@ -155,7 +155,7 @@ GDScriptFunction::~GDScriptFunction() { #ifdef DEBUG_ENABLED - MutexLock lock(GDScriptLanguage::get_singleton()->lock); + MutexLock lock(GDScriptLanguage::get_singleton()->mutex); GDScriptLanguage::get_singleton()->function_list.remove(&function_list); #endif @@ -201,7 +201,7 @@ bool GDScriptFunctionState::is_valid(bool p_extended_check) const { } if (p_extended_check) { - MutexLock lock(GDScriptLanguage::get_singleton()->lock); + MutexLock lock(GDScriptLanguage::get_singleton()->mutex); // Script gone? if (!scripts_list.in_list()) { @@ -219,7 +219,7 @@ bool GDScriptFunctionState::is_valid(bool p_extended_check) const { Variant GDScriptFunctionState::resume(const Variant &p_arg) { ERR_FAIL_COND_V(!function, Variant()); { - MutexLock lock(GDScriptLanguage::singleton->lock); + MutexLock lock(GDScriptLanguage::singleton->mutex); if (!scripts_list.in_list()) { #ifdef DEBUG_ENABLED @@ -304,7 +304,7 @@ GDScriptFunctionState::GDScriptFunctionState() : GDScriptFunctionState::~GDScriptFunctionState() { { - MutexLock lock(GDScriptLanguage::singleton->lock); + MutexLock lock(GDScriptLanguage::singleton->mutex); scripts_list.remove_from_list(); instances_list.remove_from_list(); } diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp index d8a06a8663..bdf6fb35b6 100644 --- a/modules/gdscript/gdscript_parser.cpp +++ b/modules/gdscript/gdscript_parser.cpp @@ -2932,11 +2932,16 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_call(ExpressionNode *p_pre // Allow for trailing comma. break; } + bool use_identifier_completion = current.cursor_place == GDScriptTokenizer::CURSOR_END || current.cursor_place == GDScriptTokenizer::CURSOR_MIDDLE; ExpressionNode *argument = parse_expression(false); if (argument == nullptr) { push_error(R"(Expected expression as the function argument.)"); } else { call->arguments.push_back(argument); + + if (argument->type == Node::IDENTIFIER && use_identifier_completion) { + completion_context.type = COMPLETION_IDENTIFIER; + } } ct = COMPLETION_CALL_ARGUMENTS; } while (match(GDScriptTokenizer::Token::COMMA)); @@ -3948,28 +3953,22 @@ GDScriptParser::DataType GDScriptParser::SuiteNode::Local::get_datatype() const } String GDScriptParser::SuiteNode::Local::get_name() const { - String name; switch (type) { case SuiteNode::Local::PARAMETER: - name = "parameter"; - break; + return "parameter"; case SuiteNode::Local::CONSTANT: - name = "constant"; - break; + return "constant"; case SuiteNode::Local::VARIABLE: - name = "variable"; - break; + return "variable"; case SuiteNode::Local::FOR_VARIABLE: - name = "for loop iterator"; - break; + return "for loop iterator"; case SuiteNode::Local::PATTERN_BIND: - name = "pattern_bind"; - break; + return "pattern_bind"; case SuiteNode::Local::UNDEFINED: - name = "<undefined>"; - break; + return "<undefined>"; + default: + return String(); } - return name; } String GDScriptParser::DataType::to_string() const { @@ -4001,7 +4000,7 @@ String GDScriptParser::DataType::to_string() const { if (is_meta_type) { return script_type->get_class_name().operator String(); } - String name = script_type->get_name(); + String name = script_type != nullptr ? script_type->get_name() : ""; if (!name.is_empty()) { return name; } diff --git a/modules/gdscript/gdscript_parser.h b/modules/gdscript/gdscript_parser.h index d4efab173b..1850a44678 100644 --- a/modules/gdscript/gdscript_parser.h +++ b/modules/gdscript/gdscript_parser.h @@ -578,19 +578,19 @@ public: return m_enum->get_datatype(); case ENUM_VALUE: { // Always integer. - DataType type; - type.type_source = DataType::ANNOTATED_EXPLICIT; - type.kind = DataType::BUILTIN; - type.builtin_type = Variant::INT; - return type; + DataType out_type; + out_type.type_source = DataType::ANNOTATED_EXPLICIT; + out_type.kind = DataType::BUILTIN; + out_type.builtin_type = Variant::INT; + return out_type; } case SIGNAL: { - DataType type; - type.type_source = DataType::ANNOTATED_EXPLICIT; - type.kind = DataType::BUILTIN; - type.builtin_type = Variant::SIGNAL; + DataType out_type; + out_type.type_source = DataType::ANNOTATED_EXPLICIT; + out_type.kind = DataType::BUILTIN; + out_type.builtin_type = Variant::SIGNAL; // TODO: Add parameter info. - return type; + return out_type; } case GROUP: { return DataType(); diff --git a/modules/gdscript/gdscript_tokenizer.cpp b/modules/gdscript/gdscript_tokenizer.cpp index 6c17afe939..9bbfd7aece 100644 --- a/modules/gdscript/gdscript_tokenizer.cpp +++ b/modules/gdscript/gdscript_tokenizer.cpp @@ -516,15 +516,15 @@ GDScriptTokenizer::Token GDScriptTokenizer::potential_identifier() { _advance(); } - int length = _current - _start; + int len = _current - _start; - if (length == 1 && _peek(-1) == '_') { + if (len == 1 && _peek(-1) == '_') { // Lone underscore. return make_token(Token::UNDERSCORE); } - String name(_start, length); - if (length < MIN_KEYWORD_LENGTH || length > MAX_KEYWORD_LENGTH) { + String name(_start, len); + if (len < MIN_KEYWORD_LENGTH || len > MAX_KEYWORD_LENGTH) { // Cannot be a keyword, as the length doesn't match any. return make_identifier(name); } @@ -538,7 +538,7 @@ GDScriptTokenizer::Token GDScriptTokenizer::potential_identifier() { const int keyword_length = sizeof(keyword) - 1; \ static_assert(keyword_length <= MAX_KEYWORD_LENGTH, "There's a keyword longer than the defined maximum length"); \ static_assert(keyword_length >= MIN_KEYWORD_LENGTH, "There's a keyword shorter than the defined minimum length"); \ - if (keyword_length == length && name == keyword) { \ + if (keyword_length == len && name == keyword) { \ return make_token(token_type); \ } \ } @@ -551,13 +551,13 @@ GDScriptTokenizer::Token GDScriptTokenizer::potential_identifier() { } // Check if it's a special literal - if (length == 4) { + if (len == 4) { if (name == "true") { return make_literal(true); } else if (name == "null") { return make_literal(Variant()); } - } else if (length == 5) { + } else if (len == 5) { if (name == "false") { return make_literal(false); } @@ -725,8 +725,8 @@ GDScriptTokenizer::Token GDScriptTokenizer::number() { } // Create a string with the whole number. - int length = _current - _start; - String number = String(_start, length).replace("_", ""); + int len = _current - _start; + String number = String(_start, len).replace("_", ""); // Convert to the appropriate literal type. if (base == 16) { diff --git a/modules/gdscript/gdscript_vm.cpp b/modules/gdscript/gdscript_vm.cpp index afebe3c149..c73ba798aa 100644 --- a/modules/gdscript/gdscript_vm.cpp +++ b/modules/gdscript/gdscript_vm.cpp @@ -2216,7 +2216,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a gdfs->state.line = line; gdfs->state.script = _script; { - MutexLock lock(GDScriptLanguage::get_singleton()->lock); + MutexLock lock(GDScriptLanguage::get_singleton()->mutex); _script->pending_func_states.add(&gdfs->scripts_list); if (p_instance) { gdfs->state.instance = p_instance; diff --git a/modules/gdscript/gdscript_warning.cpp b/modules/gdscript/gdscript_warning.cpp index 1cae7bdfac..a0c107aa53 100644 --- a/modules/gdscript/gdscript_warning.cpp +++ b/modules/gdscript/gdscript_warning.cpp @@ -155,6 +155,10 @@ String GDScriptWarning::get_message() const { case INT_ASSIGNED_TO_ENUM: { return "Integer used when an enum value is expected. If this is intended cast the integer to the enum type."; } + case STATIC_CALLED_ON_INSTANCE: { + CHECK_SYMBOLS(2); + return vformat(R"(The function '%s()' is a static function but was called from an instance. Instead, it should be directly called from the type: '%s.%s()'.)", symbols[0], symbols[1], symbols[0]); + } case WARNING_MAX: break; // Can't happen, but silences warning } @@ -215,6 +219,7 @@ String GDScriptWarning::get_name_from_code(Code p_code) { "EMPTY_FILE", "SHADOWED_GLOBAL_IDENTIFIER", "INT_ASSIGNED_TO_ENUM", + "STATIC_CALLED_ON_INSTANCE", }; static_assert((sizeof(names) / sizeof(*names)) == WARNING_MAX, "Amount of warning types don't match the amount of warning names."); diff --git a/modules/gdscript/gdscript_warning.h b/modules/gdscript/gdscript_warning.h index a639e7b44e..7e4e975510 100644 --- a/modules/gdscript/gdscript_warning.h +++ b/modules/gdscript/gdscript_warning.h @@ -78,6 +78,7 @@ public: EMPTY_FILE, // A script file is empty. SHADOWED_GLOBAL_IDENTIFIER, // A global class or function has the same name as variable. INT_ASSIGNED_TO_ENUM, // An integer value was assigned to an enum-typed variable without casting. + STATIC_CALLED_ON_INSTANCE, // A static method was called on an instance of a class instead of on the class itself. WARNING_MAX, }; diff --git a/modules/gdscript/language_server/gdscript_extend_parser.cpp b/modules/gdscript/language_server/gdscript_extend_parser.cpp index 46a9b33eb0..de3becbaf8 100644 --- a/modules/gdscript/language_server/gdscript_extend_parser.cpp +++ b/modules/gdscript/language_server/gdscript_extend_parser.cpp @@ -38,8 +38,8 @@ void ExtendGDScriptParser::update_diagnostics() { diagnostics.clear(); - const List<ParserError> &errors = get_errors(); - for (const ParserError &error : errors) { + const List<ParserError> &parser_errors = get_errors(); + for (const ParserError &error : parser_errors) { lsp::Diagnostic diagnostic; diagnostic.severity = lsp::DiagnosticSeverity::Error; diagnostic.message = error.message; @@ -47,9 +47,9 @@ void ExtendGDScriptParser::update_diagnostics() { diagnostic.code = -1; lsp::Range range; lsp::Position pos; - const PackedStringArray lines = get_lines(); - int line = CLAMP(LINE_NUMBER_TO_INDEX(error.line), 0, lines.size() - 1); - const String &line_text = lines[line]; + const PackedStringArray line_array = get_lines(); + int line = CLAMP(LINE_NUMBER_TO_INDEX(error.line), 0, line_array.size() - 1); + const String &line_text = line_array[line]; pos.line = line; pos.character = line_text.length() - line_text.strip_edges(true, false).length(); range.start = pos; @@ -59,8 +59,8 @@ void ExtendGDScriptParser::update_diagnostics() { diagnostics.push_back(diagnostic); } - const List<GDScriptWarning> &warnings = get_warnings(); - for (const GDScriptWarning &warning : warnings) { + const List<GDScriptWarning> &parser_warnings = get_warnings(); + for (const GDScriptWarning &warning : parser_warnings) { lsp::Diagnostic diagnostic; diagnostic.severity = lsp::DiagnosticSeverity::Warning; diagnostic.message = "(" + warning.get_name() + "): " + warning.get_message(); @@ -83,8 +83,7 @@ void ExtendGDScriptParser::update_diagnostics() { void ExtendGDScriptParser::update_symbols() { members.clear(); - const GDScriptParser::Node *head = get_tree(); - if (const GDScriptParser::ClassNode *gdclass = dynamic_cast<const GDScriptParser::ClassNode *>(head)) { + if (const GDScriptParser::ClassNode *gdclass = dynamic_cast<const GDScriptParser::ClassNode *>(get_tree())) { parse_class_symbol(gdclass, class_symbol); for (int i = 0; i < class_symbol.children.size(); i++) { @@ -107,26 +106,26 @@ void ExtendGDScriptParser::update_symbols() { void ExtendGDScriptParser::update_document_links(const String &p_code) { document_links.clear(); - GDScriptTokenizer tokenizer; + GDScriptTokenizer scr_tokenizer; Ref<FileAccess> fs = FileAccess::create(FileAccess::ACCESS_RESOURCES); - tokenizer.set_source_code(p_code); + scr_tokenizer.set_source_code(p_code); while (true) { - GDScriptTokenizer::Token token = tokenizer.scan(); + GDScriptTokenizer::Token token = scr_tokenizer.scan(); if (token.type == GDScriptTokenizer::Token::TK_EOF) { break; } else if (token.type == GDScriptTokenizer::Token::LITERAL) { const Variant &const_val = token.literal; if (const_val.get_type() == Variant::STRING) { - String path = const_val; - bool exists = fs->file_exists(path); + String scr_path = const_val; + bool exists = fs->file_exists(scr_path); if (!exists) { - path = get_path().get_base_dir() + "/" + path; - exists = fs->file_exists(path); + scr_path = get_path().get_base_dir() + "/" + scr_path; + exists = fs->file_exists(scr_path); } if (exists) { String value = const_val; lsp::DocumentLink link; - link.target = GDScriptLanguageProtocol::get_singleton()->get_workspace()->get_file_uri(path); + link.target = GDScriptLanguageProtocol::get_singleton()->get_workspace()->get_file_uri(scr_path); link.range.start.line = LINE_NUMBER_TO_INDEX(token.start_line); link.range.end.line = LINE_NUMBER_TO_INDEX(token.end_line); link.range.start.character = LINE_NUMBER_TO_INDEX(token.start_column); @@ -437,11 +436,11 @@ String ExtendGDScriptParser::parse_documentation(int p_line, bool p_docs_down) { if (!p_docs_down) { // inline comment String inline_comment = lines[p_line]; - int comment_start = inline_comment.find("#"); + int comment_start = inline_comment.find("##"); if (comment_start != -1) { inline_comment = inline_comment.substr(comment_start, inline_comment.length()).strip_edges(); if (inline_comment.length() > 1) { - doc_lines.push_back(inline_comment.substr(1, inline_comment.length())); + doc_lines.push_back(inline_comment.substr(2, inline_comment.length())); } } } @@ -454,8 +453,8 @@ String ExtendGDScriptParser::parse_documentation(int p_line, bool p_docs_down) { } String line_comment = lines[i].strip_edges(true, false); - if (line_comment.begins_with("#")) { - line_comment = line_comment.substr(1, line_comment.length()); + if (line_comment.begins_with("##")) { + line_comment = line_comment.substr(2, line_comment.length()); if (p_docs_down) { doc_lines.push_back(line_comment); } else { @@ -731,7 +730,7 @@ Dictionary ExtendGDScriptParser::dump_class_api(const GDScriptParser::ClassNode Array nested_classes; Array constants; - Array members; + Array class_members; Array signals; Array methods; Array static_functions; @@ -792,7 +791,7 @@ Dictionary ExtendGDScriptParser::dump_class_api(const GDScriptParser::ClassNode api["signature"] = symbol->detail; api["description"] = symbol->documentation; } - members.push_back(api); + class_members.push_back(api); } break; case ClassNode::Member::SIGNAL: { Dictionary api; @@ -824,7 +823,7 @@ Dictionary ExtendGDScriptParser::dump_class_api(const GDScriptParser::ClassNode class_api["sub_classes"] = nested_classes; class_api["constants"] = constants; - class_api["members"] = members; + class_api["members"] = class_members; class_api["signals"] = signals; class_api["methods"] = methods; class_api["static_functions"] = static_functions; @@ -834,8 +833,7 @@ Dictionary ExtendGDScriptParser::dump_class_api(const GDScriptParser::ClassNode Dictionary ExtendGDScriptParser::generate_api() const { Dictionary api; - const GDScriptParser::Node *head = get_tree(); - if (const GDScriptParser::ClassNode *gdclass = dynamic_cast<const GDScriptParser::ClassNode *>(head)) { + if (const GDScriptParser::ClassNode *gdclass = dynamic_cast<const GDScriptParser::ClassNode *>(get_tree())) { api = dump_class_api(gdclass); } return api; diff --git a/modules/gdscript/language_server/gdscript_language_server.cpp b/modules/gdscript/language_server/gdscript_language_server.cpp index ead4ef1987..38bea314a0 100644 --- a/modules/gdscript/language_server/gdscript_language_server.cpp +++ b/modules/gdscript/language_server/gdscript_language_server.cpp @@ -61,12 +61,12 @@ void GDScriptLanguageServer::_notification(int p_what) { } break; case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: { - String host = String(_EDITOR_GET("network/language_server/remote_host")); - int port = (int)_EDITOR_GET("network/language_server/remote_port"); - bool use_thread = (bool)_EDITOR_GET("network/language_server/use_thread"); - if (host != this->host || port != this->port || use_thread != this->use_thread) { - this->stop(); - this->start(); + String remote_host = String(_EDITOR_GET("network/language_server/remote_host")); + int remote_port = (int)_EDITOR_GET("network/language_server/remote_port"); + bool remote_use_thread = (bool)_EDITOR_GET("network/language_server/use_thread"); + if (remote_host != host || remote_port != port || remote_use_thread != use_thread) { + stop(); + start(); } } break; } diff --git a/modules/gdscript/language_server/gdscript_text_document.cpp b/modules/gdscript/language_server/gdscript_text_document.cpp index 5ad9680ea0..3905e28bcb 100644 --- a/modules/gdscript/language_server/gdscript_text_document.cpp +++ b/modules/gdscript/language_server/gdscript_text_document.cpp @@ -42,6 +42,7 @@ void GDScriptTextDocument::_bind_methods() { ClassDB::bind_method(D_METHOD("didOpen"), &GDScriptTextDocument::didOpen); ClassDB::bind_method(D_METHOD("didClose"), &GDScriptTextDocument::didClose); ClassDB::bind_method(D_METHOD("didChange"), &GDScriptTextDocument::didChange); + ClassDB::bind_method(D_METHOD("willSaveWaitUntil"), &GDScriptTextDocument::willSaveWaitUntil); ClassDB::bind_method(D_METHOD("didSave"), &GDScriptTextDocument::didSave); ClassDB::bind_method(D_METHOD("nativeSymbol"), &GDScriptTextDocument::nativeSymbol); ClassDB::bind_method(D_METHOD("documentSymbol"), &GDScriptTextDocument::documentSymbol); @@ -81,6 +82,16 @@ void GDScriptTextDocument::didChange(const Variant &p_param) { sync_script_content(doc.uri, doc.text); } +void GDScriptTextDocument::willSaveWaitUntil(const Variant &p_param) { + lsp::TextDocumentItem doc = load_document_item(p_param); + + String path = GDScriptLanguageProtocol::get_singleton()->get_workspace()->get_file_path(doc.uri); + Ref<Script> scr = ResourceLoader::load(path); + if (scr.is_valid()) { + ScriptEditor::get_singleton()->clear_docs_from_script(scr); + } +} + void GDScriptTextDocument::didSave(const Variant &p_param) { lsp::TextDocumentItem doc = load_document_item(p_param); Dictionary dict = p_param; @@ -88,11 +99,16 @@ void GDScriptTextDocument::didSave(const Variant &p_param) { sync_script_content(doc.uri, text); - /*String path = GDScriptLanguageProtocol::get_singleton()->get_workspace()->get_file_path(doc.uri); - - Ref<GDScript> script = ResourceLoader::load(path); - script->load_source_code(path); - script->reload(true);*/ + String path = GDScriptLanguageProtocol::get_singleton()->get_workspace()->get_file_path(doc.uri); + Ref<GDScript> scr = ResourceLoader::load(path); + if (scr.is_valid() && (scr->load_source_code(path) == OK)) { + if (scr->is_tool()) { + scr->get_language()->reload_tool_script(scr, true); + } else { + scr->reload(true); + } + ScriptEditor::get_singleton()->update_docs_from_script(scr); + } } lsp::TextDocumentItem GDScriptTextDocument::load_document_item(const Variant &p_param) { @@ -213,8 +229,8 @@ Array GDScriptTextDocument::completion(const Dictionary &p_params) { arr = native_member_completions.duplicate(); for (KeyValue<String, ExtendGDScriptParser *> &E : GDScriptLanguageProtocol::get_singleton()->get_workspace()->scripts) { - ExtendGDScriptParser *script = E.value; - const Array &items = script->get_member_completions(); + ExtendGDScriptParser *scr = E.value; + const Array &items = scr->get_member_completions(); const int start_size = arr.size(); arr.resize(start_size + items.size()); @@ -417,13 +433,6 @@ void GDScriptTextDocument::sync_script_content(const String &p_path, const Strin GDScriptLanguageProtocol::get_singleton()->get_workspace()->parse_script(path, p_content); EditorFileSystem::get_singleton()->update_file(path); - Error error; - Ref<GDScript> script = ResourceLoader::load(path, "", ResourceFormatLoader::CACHE_MODE_REUSE, &error); - if (error == OK) { - if (script->load_source_code(path) == OK) { - script->reload(true); - } - } } void GDScriptTextDocument::show_native_symbol_in_editor(const String &p_symbol_id) { diff --git a/modules/gdscript/language_server/gdscript_text_document.h b/modules/gdscript/language_server/gdscript_text_document.h index 87bc08a34e..456c7d71fe 100644 --- a/modules/gdscript/language_server/gdscript_text_document.h +++ b/modules/gdscript/language_server/gdscript_text_document.h @@ -45,6 +45,7 @@ protected: void didOpen(const Variant &p_param); void didClose(const Variant &p_param); void didChange(const Variant &p_param); + void willSaveWaitUntil(const Variant &p_param); void didSave(const Variant &p_param); void sync_script_content(const String &p_path, const String &p_content); diff --git a/modules/gdscript/language_server/gdscript_workspace.cpp b/modules/gdscript/language_server/gdscript_workspace.cpp index 16461b0a6c..390460bed9 100644 --- a/modules/gdscript/language_server/gdscript_workspace.cpp +++ b/modules/gdscript/language_server/gdscript_workspace.cpp @@ -55,14 +55,14 @@ void GDScriptWorkspace::_bind_methods() { } void GDScriptWorkspace::apply_new_signal(Object *obj, String function, PackedStringArray args) { - Ref<Script> script = obj->get_script(); + Ref<Script> scr = obj->get_script(); - if (script->get_language()->get_name() != "GDScript") { + if (scr->get_language()->get_name() != "GDScript") { return; } String function_signature = "func " + function; - String source = script->get_source_code(); + String source = scr->get_source_code(); if (source.contains(function_signature)) { return; @@ -98,7 +98,7 @@ void GDScriptWorkspace::apply_new_signal(Object *obj, String function, PackedStr text_edit.newText = function_body; - String uri = get_file_uri(script->get_path()); + String uri = get_file_uri(scr->get_path()); lsp::ApplyWorkspaceEditParams params; params.edit.add_edit(uri, text_edit); @@ -118,12 +118,12 @@ void GDScriptWorkspace::did_delete_files(const Dictionary &p_params) { void GDScriptWorkspace::remove_cache_parser(const String &p_path) { HashMap<String, ExtendGDScriptParser *>::Iterator parser = parse_results.find(p_path); - HashMap<String, ExtendGDScriptParser *>::Iterator script = scripts.find(p_path); - if (parser && script) { - if (script->value && script->value == parser->value) { - memdelete(script->value); + HashMap<String, ExtendGDScriptParser *>::Iterator scr = scripts.find(p_path); + if (parser && scr) { + if (scr->value && scr->value == parser->value) { + memdelete(scr->value); } else { - memdelete(script->value); + memdelete(scr->value); memdelete(parser->value); } parse_results.erase(p_path); @@ -131,8 +131,8 @@ void GDScriptWorkspace::remove_cache_parser(const String &p_path) { } else if (parser) { memdelete(parser->value); parse_results.erase(p_path); - } else if (script) { - memdelete(script->value); + } else if (scr) { + memdelete(scr->value); scripts.erase(p_path); } } @@ -587,8 +587,8 @@ void GDScriptWorkspace::completion(const lsp::CompletionParams &p_params, List<S while (!stack.is_empty()) { current = Object::cast_to<Node>(stack.pop_back()); - Ref<GDScript> script = current->get_script(); - if (script.is_valid() && script->get_path() == path) { + Ref<GDScript> scr = current->get_script(); + if (scr.is_valid() && scr->get_path() == path) { break; } for (int i = 0; i < current->get_child_count(); ++i) { @@ -596,8 +596,8 @@ void GDScriptWorkspace::completion(const lsp::CompletionParams &p_params, List<S } } - Ref<GDScript> script = current->get_script(); - if (!script.is_valid() || script->get_path() != path) { + Ref<GDScript> scr = current->get_script(); + if (!scr.is_valid() || scr->get_path() != path) { current = owner_scene_node; } } @@ -691,13 +691,13 @@ void GDScriptWorkspace::resolve_related_symbols(const lsp::TextDocumentPositionP } for (const KeyValue<String, ExtendGDScriptParser *> &E : scripts) { - const ExtendGDScriptParser *script = E.value; - const ClassMembers &members = script->get_members(); + const ExtendGDScriptParser *scr = E.value; + const ClassMembers &members = scr->get_members(); if (const lsp::DocumentSymbol *const *symbol = members.getptr(symbol_identifier)) { r_list.push_back(*symbol); } - for (const KeyValue<String, ClassMembers> &F : script->get_inner_classes()) { + for (const KeyValue<String, ClassMembers> &F : scr->get_inner_classes()) { const ClassMembers *inner_class = &F.value; if (const lsp::DocumentSymbol *const *symbol = inner_class->getptr(symbol_identifier)) { r_list.push_back(*symbol); diff --git a/modules/gdscript/language_server/godot_lsp.h b/modules/gdscript/language_server/godot_lsp.h index fbd40796c4..024da1cab7 100644 --- a/modules/gdscript/language_server/godot_lsp.h +++ b/modules/gdscript/language_server/godot_lsp.h @@ -546,7 +546,7 @@ struct TextDocumentSyncOptions { * If present will save wait until requests are sent to the server. If omitted the request should not be * sent. */ - bool willSaveWaitUntil = false; + bool willSaveWaitUntil = true; /** * If present save notifications are sent to the server. If omitted the notification should not be diff --git a/modules/gdscript/tests/gdscript_test_runner.cpp b/modules/gdscript/tests/gdscript_test_runner.cpp index 6c346acb7e..15131afde7 100644 --- a/modules/gdscript/tests/gdscript_test_runner.cpp +++ b/modules/gdscript/tests/gdscript_test_runner.cpp @@ -479,9 +479,9 @@ GDScriptTest::TestResult GDScriptTest::execute_test_code(bool p_is_generating) { result.output = get_text_for_status(result.status) + "\n"; const List<GDScriptParser::ParserError> &errors = parser.get_errors(); - for (const GDScriptParser::ParserError &E : errors) { - result.output += E.message + "\n"; // TODO: line, column? - break; // Only the first error since the following might be cascading. + if (!errors.is_empty()) { + // Only the first error since the following might be cascading. + result.output += errors[0].message + "\n"; // TODO: line, column? } if (!p_is_generating) { result.passed = check_output(result.output); @@ -498,9 +498,9 @@ GDScriptTest::TestResult GDScriptTest::execute_test_code(bool p_is_generating) { result.output = get_text_for_status(result.status) + "\n"; const List<GDScriptParser::ParserError> &errors = parser.get_errors(); - for (const GDScriptParser::ParserError &E : errors) { - result.output += E.message + "\n"; // TODO: line, column? - break; // Only the first error since the following might be cascading. + if (!errors.is_empty()) { + // Only the first error since the following might be cascading. + result.output += errors[0].message + "\n"; // TODO: line, column? } if (!p_is_generating) { result.passed = check_output(result.output); diff --git a/modules/gdscript/tests/scripts/parser/features/class.gd b/modules/gdscript/tests/scripts/parser/features/class.gd index 6652f85ad9..af24b32322 100644 --- a/modules/gdscript/tests/scripts/parser/features/class.gd +++ b/modules/gdscript/tests/scripts/parser/features/class.gd @@ -21,5 +21,5 @@ func test(): assert(test_sub.number == 25) # From Test. assert(test_sub.other_string == "bye") # From TestSub. - TestConstructor.new() - TestConstructor.new(500) + var _test_constructor = TestConstructor.new() + _test_constructor = TestConstructor.new(500) diff --git a/modules/gdscript/tests/scripts/parser/features/dictionary.out b/modules/gdscript/tests/scripts/parser/features/dictionary.out index 5f999f573a..e1eeb46f78 100644 --- a/modules/gdscript/tests/scripts/parser/features/dictionary.out +++ b/modules/gdscript/tests/scripts/parser/features/dictionary.out @@ -7,8 +7,8 @@ null false empty array zero Vector2i -{22:{4:["nesting", "arrays"]}} -{4:["nesting", "arrays"]} +{ 22: { 4: ["nesting", "arrays"] } } +{ 4: ["nesting", "arrays"] } ["nesting", "arrays"] nesting arrays diff --git a/modules/gdscript/tests/scripts/parser/features/dictionary_lua_style.out b/modules/gdscript/tests/scripts/parser/features/dictionary_lua_style.out index 5143d040a9..553d40d953 100644 --- a/modules/gdscript/tests/scripts/parser/features/dictionary_lua_style.out +++ b/modules/gdscript/tests/scripts/parser/features/dictionary_lua_style.out @@ -1,2 +1,2 @@ GDTEST_OK -{"a":1, "b":2, "with spaces":3, "2":4} +{ "a": 1, "b": 2, "with spaces": 3, "2": 4 } diff --git a/modules/gdscript/tests/scripts/parser/features/dictionary_mixed_syntax.out b/modules/gdscript/tests/scripts/parser/features/dictionary_mixed_syntax.out index dd28609850..cf79845f53 100644 --- a/modules/gdscript/tests/scripts/parser/features/dictionary_mixed_syntax.out +++ b/modules/gdscript/tests/scripts/parser/features/dictionary_mixed_syntax.out @@ -1,2 +1,2 @@ GDTEST_OK -{"hello":{"world":{"is":"beautiful"}}} +{ "hello": { "world": { "is": "beautiful" } } } diff --git a/modules/gdscript/tests/scripts/parser/features/nested_dictionary.out b/modules/gdscript/tests/scripts/parser/features/nested_dictionary.out index 8b8c33202f..508f0ff217 100644 --- a/modules/gdscript/tests/scripts/parser/features/nested_dictionary.out +++ b/modules/gdscript/tests/scripts/parser/features/nested_dictionary.out @@ -1,5 +1,5 @@ GDTEST_OK -{8:{"key":"value"}} -{"key":"value"} +{ 8: { "key": "value" } } +{ "key": "value" } value value diff --git a/modules/gdscript/tests/scripts/parser/warnings/return_value_discarded.out b/modules/gdscript/tests/scripts/parser/warnings/return_value_discarded.out index d73c5eb7cd..13f759dd46 100644 --- a/modules/gdscript/tests/scripts/parser/warnings/return_value_discarded.out +++ b/modules/gdscript/tests/scripts/parser/warnings/return_value_discarded.out @@ -1 +1,5 @@ GDTEST_OK +>> WARNING +>> Line: 6 +>> RETURN_VALUE_DISCARDED +>> The function 'i_return_int()' returns a value, but this value is never used. diff --git a/modules/gdscript/tests/scripts/parser/warnings/static_called_on_instance.gd b/modules/gdscript/tests/scripts/parser/warnings/static_called_on_instance.gd new file mode 100644 index 0000000000..29d8501b78 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/warnings/static_called_on_instance.gd @@ -0,0 +1,11 @@ +class Player: + var x = 3 + +func test(): + # These should not emit a warning. + var _player = Player.new() + print(String.num_uint64(8589934592)) # 2 ^ 33 + + # This should emit a warning. + var some_string = String() + print(some_string.num_uint64(8589934592)) # 2 ^ 33 diff --git a/modules/gdscript/tests/scripts/parser/warnings/static_called_on_instance.out b/modules/gdscript/tests/scripts/parser/warnings/static_called_on_instance.out new file mode 100644 index 0000000000..3933a35178 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/warnings/static_called_on_instance.out @@ -0,0 +1,7 @@ +GDTEST_OK +>> WARNING +>> Line: 11 +>> STATIC_CALLED_ON_INSTANCE +>> The function 'num_uint64()' is a static function but was called from an instance. Instead, it should be directly called from the type: 'String.num_uint64()'. +8589934592 +8589934592 diff --git a/modules/gdscript/tests/scripts/runtime/features/chain_assignment_works.out b/modules/gdscript/tests/scripts/runtime/features/chain_assignment_works.out index 5e7ccf534a..22929bf636 100644 --- a/modules/gdscript/tests/scripts/runtime/features/chain_assignment_works.out +++ b/modules/gdscript/tests/scripts/runtime/features/chain_assignment_works.out @@ -1,6 +1,6 @@ GDTEST_OK -{1:(2, 0)} -{3:(4, 0)} +{ 1: (2, 0) } +{ 3: (4, 0) } [[(5, 0)]] [[(6, 0)]] [[(7, 0)]] diff --git a/modules/gdscript/tests/scripts/runtime/features/stringify.out b/modules/gdscript/tests/scripts/runtime/features/stringify.out index d4468737a5..1f33de00cc 100644 --- a/modules/gdscript/tests/scripts/runtime/features/stringify.out +++ b/modules/gdscript/tests/scripts/runtime/features/stringify.out @@ -21,7 +21,7 @@ hello/world RID(0) Node::get_name Node::[signal]property_list_changed -{"hello":123} +{ "hello": 123 } ["hello", 123] [255, 0, 1] [-1, 0, 1] |