GDScript: Add warnings that are set to error by default

- Adds a list of default levels for all warning so they can be set
  individually.
- Add warnings set by default to error for:
  - Using `get_node()` without `@onready`.
  - Using `@onready` together with `@export`.
  - Inferring a static type with a Variant value.
  - Overriding a native engine method.
- Adjust how annotations to ignore warnings are treated so they also
  apply to method parameters.
- Clean up a bit how ignored warnings are set. There were two sets but
  only one was actually being used.
- Set all warnings to the `WARN` level for tests, so they they can be
  properly tested.
- Fix enum types in native methods signatures being set to `int`.
- Fix native enums being treated as Dictionary by mistake.
- Make name of native enum types use the class they are defined in, not
  the direct super class of the script. This ensures they are always
  equal even when coming from different sources.
- Fix error for signature mismatch that was only showing the first
  default argument as having a default. Now it shows for all.
This commit is contained in:
George Marques
2023-02-02 11:57:22 -03:00
parent 315d3c4d21
commit 273bf7210f
22 changed files with 371 additions and 57 deletions

View File

@@ -1,2 +1,2 @@
GDTEST_ANALYZER_ERROR
The function signature doesn't match the parent. Parent signature is "my_function(int = default) -> int".
The function signature doesn't match the parent. Parent signature is "my_function(int = <default>) -> int".

View File

@@ -0,0 +1,18 @@
extends Node
@onready var shorthand = $Node
@onready var call = get_node(^"Node")
@onready var shorthand_with_cast = $Node as Node
@onready var call_with_cast = get_node(^"Node") as Node
func _init():
var node := Node.new()
node.name = "Node"
add_child(node)
func test():
# Those are expected to be `null` since `_ready()` is never called on tests.
prints("shorthand", shorthand)
prints("call", call)
prints("shorthand_with_cast", shorthand_with_cast)
prints("call_with_cast", call_with_cast)

View File

@@ -0,0 +1,5 @@
GDTEST_OK
shorthand <null>
call <null>
shorthand_with_cast <null>
call_with_cast <null>

View File

@@ -0,0 +1,13 @@
# https://github.com/godotengine/godot/issues/72501
extends Node
func test():
prints("before", process_mode)
process_mode = PROCESS_MODE_PAUSABLE
prints("after", process_mode)
var node := Node.new()
add_child(node)
prints("before", node.process_mode)
node.process_mode = PROCESS_MODE_PAUSABLE
prints("after", node.process_mode)

View File

@@ -0,0 +1,5 @@
GDTEST_OK
before 0
after 1
before 0
after 1

View File

@@ -2,16 +2,18 @@ func variant() -> Variant: return null
var member_weak = variant()
var member_typed: Variant = variant()
@warning_ignore("inference_on_variant")
var member_inferred := variant()
func param_weak(param = variant()) -> void: print(param)
func param_typed(param: Variant = variant()) -> void: print(param)
@warning_ignore("inference_on_variant")
func param_inferred(param := variant()) -> void: print(param)
func return_untyped(): return variant()
func return_typed() -> Variant: return variant()
@warning_ignore("unused_variable")
@warning_ignore("unused_variable", "inference_on_variant")
func test() -> void:
var weak = variant()
var typed: Variant = variant()

View File

@@ -0,0 +1,17 @@
extends Node
var add_node = do_add_node() # Hack to have one node on init and not fail at runtime.
var shorthand = $Node
var with_self = self.get_node(^"Node")
var without_self = get_node(^"Node")
var with_cast = get_node(^"Node") as Node
var shorthand_with_cast = $Node as Node
func test():
print("warn")
func do_add_node():
var node = Node.new()
node.name = "Node"
add_child(node)

View File

@@ -0,0 +1,22 @@
GDTEST_OK
>> WARNING
>> Line: 5
>> GET_NODE_DEFAULT_WITHOUT_ONREADY
>> The default value is using "$" which won't return nodes in the scene tree before "_ready()" is called. Use the "@onready" annotation to solve this.
>> WARNING
>> Line: 6
>> GET_NODE_DEFAULT_WITHOUT_ONREADY
>> The default value is using "get_node()" which won't return nodes in the scene tree before "_ready()" is called. Use the "@onready" annotation to solve this.
>> WARNING
>> Line: 7
>> GET_NODE_DEFAULT_WITHOUT_ONREADY
>> The default value is using "get_node()" which won't return nodes in the scene tree before "_ready()" is called. Use the "@onready" annotation to solve this.
>> WARNING
>> Line: 8
>> GET_NODE_DEFAULT_WITHOUT_ONREADY
>> The default value is using "get_node()" which won't return nodes in the scene tree before "_ready()" is called. Use the "@onready" annotation to solve this.
>> WARNING
>> Line: 9
>> GET_NODE_DEFAULT_WITHOUT_ONREADY
>> The default value is using "$" which won't return nodes in the scene tree before "_ready()" is called. Use the "@onready" annotation to solve this.
warn

View File

@@ -0,0 +1,6 @@
func test():
var inferred_with_variant := return_variant()
print(inferred_with_variant)
func return_variant() -> Variant:
return "warn"

View File

@@ -0,0 +1,6 @@
GDTEST_OK
>> WARNING
>> Line: 2
>> INFERENCE_ON_VARIANT
>> The variable type is being inferred from a Variant value, so it will be typed as Variant.
warn

View File

@@ -0,0 +1,6 @@
extends Node
@onready @export var conflict = ""
func test():
print("warn")

View File

@@ -0,0 +1,6 @@
GDTEST_OK
>> WARNING
>> Line: 3
>> ONREADY_WITH_EXPORT
>> The "@onready" annotation will make the default value to be set after the "@export" takes effect and will override it.
warn

View File

@@ -0,0 +1,5 @@
func test():
print("warn")
func get(_property: StringName) -> Variant:
return null

View File

@@ -0,0 +1,6 @@
GDTEST_OK
>> WARNING
>> Line: 4
>> NATIVE_METHOD_OVERRIDE
>> The method "get" overrides a method from native class "Object". This won't be called by the engine and may not work as expected.
warn