mirror of
https://github.com/godotengine/godot
synced 2024-09-04 22:18:28 +00:00
Completion Tests: Add script to owner
This commit is contained in:
parent
fe01776f05
commit
d2c2194937
|
@ -13,6 +13,12 @@ The `script/completion` folder contains test for the GDScript autocompletion.
|
|||
|
||||
Each test case consists of at least one `.gd` file, which contains the code, and one `.cfg` file, which contains expected results and configuration. Inside of the GDScript file the character `➡` represents the cursor position, at which autocompletion is invoked.
|
||||
|
||||
The script files won't be parsable GDScript since it contains an invalid char and and often the code is not complete during autocompletion. To allow for a valid base when used with a scene, the
|
||||
runner will remove the line which contains `➡`. Therefore the scripts need to be valid if this line is removed, otherwise the test might behave in unexpected ways. This may for example require
|
||||
adding an additional `pass` statement.
|
||||
|
||||
This also means, that the runner will add the script to its owner node, so the script should not be loaded through the scene file.
|
||||
|
||||
The config file contains two section:
|
||||
|
||||
`[input]` contains keys that configure the test environment. The following keys are possible:
|
||||
|
@ -20,6 +26,7 @@ The config file contains two section:
|
|||
- `cs: boolean = false`: If `true`, the test will be skipped when running a non C# build.
|
||||
- `use_single_quotes: boolean = false`: Configures the corresponding editor setting for the test.
|
||||
- `scene: String`: Allows to specify a scene which is opened while autocompletion is performed. If this is not set the test runner will search for a `.tscn` file with the same basename as the GDScript file. If that isn't found either, autocompletion will behave as if no scene was opened.
|
||||
- `node_path: String`: The node path of the node which holds the current script inside of the scene. Defaults to the scene root node.
|
||||
|
||||
`[output]` specifies the expected results for the test. The following key are supported:
|
||||
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
[gd_scene load_steps=1 format=3 uid="uid://dl28pdkxcjvym"]
|
||||
|
||||
[node name="GetNode" type="Node"]
|
|
@ -0,0 +1,8 @@
|
|||
[input]
|
||||
scene="res://completion/argument_options/argument_options.tscn"
|
||||
[output]
|
||||
include=[
|
||||
; Node
|
||||
{"display": "\"signal_a\""},
|
||||
{"display": "\"child_entered_tree\""},
|
||||
]
|
|
@ -0,0 +1,7 @@
|
|||
extends Node
|
||||
|
||||
signal signal_a()
|
||||
|
||||
func _ready():
|
||||
connect(➡)
|
||||
pass
|
|
@ -2,3 +2,4 @@ extends Node
|
|||
|
||||
func a():
|
||||
%AnimationPlayer.➡
|
||||
pass
|
||||
|
|
|
@ -2,3 +2,4 @@ extends Node
|
|||
|
||||
func a():
|
||||
$UniqueAnimationPlayer.➡
|
||||
pass
|
||||
|
|
|
@ -2,3 +2,4 @@ extends Node
|
|||
|
||||
func a():
|
||||
$A.➡
|
||||
pass
|
||||
|
|
|
@ -2,3 +2,4 @@ extends Node
|
|||
|
||||
func a():
|
||||
$AnimationPlayer.➡
|
||||
pass
|
||||
|
|
|
@ -2,3 +2,4 @@ extends Node
|
|||
|
||||
func a():
|
||||
%UniqueA.➡
|
||||
pass
|
||||
|
|
|
@ -2,3 +2,4 @@ extends Node
|
|||
|
||||
func a():
|
||||
%UniqueAnimationPlayer.➡
|
||||
pass
|
||||
|
|
|
@ -3,3 +3,4 @@ extends Node
|
|||
func a():
|
||||
var test = $AnimationPlayer
|
||||
test.➡
|
||||
pass
|
||||
|
|
|
@ -3,3 +3,4 @@ extends Node
|
|||
func a():
|
||||
var test := $AnimationPlayer
|
||||
test.➡
|
||||
pass
|
||||
|
|
|
@ -3,3 +3,4 @@ extends Node
|
|||
func a():
|
||||
var test := $A
|
||||
test.➡
|
||||
pass
|
||||
|
|
|
@ -3,3 +3,4 @@ extends Node
|
|||
func a():
|
||||
var test := $AnimationPlayer
|
||||
test.➡
|
||||
pass
|
||||
|
|
|
@ -3,3 +3,4 @@ extends Node
|
|||
func a():
|
||||
var test = $A
|
||||
test.➡
|
||||
pass
|
||||
|
|
|
@ -3,3 +3,4 @@ extends Node
|
|||
func a():
|
||||
var test = $AnimationPlayer
|
||||
test.➡
|
||||
pass
|
||||
|
|
|
@ -5,3 +5,4 @@ const A := preload("res://completion/class_a.notest.gd")
|
|||
func a():
|
||||
var test: A = $A
|
||||
test.➡
|
||||
pass
|
||||
|
|
|
@ -3,3 +3,4 @@ extends Node
|
|||
func a():
|
||||
var test: AnimationPlayer = $AnimationPlayer
|
||||
test.➡
|
||||
pass
|
||||
|
|
|
@ -5,3 +5,4 @@ const A := preload("res://completion/class_a.notest.gd")
|
|||
func a():
|
||||
var test: A = $A
|
||||
test.➡
|
||||
pass
|
||||
|
|
|
@ -3,3 +3,4 @@ extends Node
|
|||
func a():
|
||||
var test: AnimationPlayer = $AnimationPlayer
|
||||
test.➡
|
||||
pass
|
||||
|
|
|
@ -4,3 +4,4 @@ extends Node
|
|||
func a():
|
||||
var test: Node = $A
|
||||
test.➡
|
||||
pass
|
||||
|
|
|
@ -4,3 +4,4 @@ extends Node
|
|||
func a():
|
||||
var test: Node = $AnimationPlayer
|
||||
test.➡
|
||||
pass
|
||||
|
|
|
@ -3,3 +3,4 @@ extends Node
|
|||
func a():
|
||||
var test: Area2D = $A
|
||||
test.➡
|
||||
pass
|
||||
|
|
|
@ -3,3 +3,4 @@ extends Node
|
|||
func a():
|
||||
var test: Area2D = $AnimationPlayer
|
||||
test.➡
|
||||
pass
|
||||
|
|
|
@ -4,3 +4,4 @@ var test = $AnimationPlayer
|
|||
|
||||
func a():
|
||||
test.➡
|
||||
pass
|
||||
|
|
|
@ -4,3 +4,4 @@ var test := $AnimationPlayer
|
|||
|
||||
func a():
|
||||
test.➡
|
||||
pass
|
||||
|
|
|
@ -4,3 +4,4 @@ var test := $A
|
|||
|
||||
func a():
|
||||
test.➡
|
||||
pass
|
||||
|
|
|
@ -4,3 +4,4 @@ var test := $AnimationPlayer
|
|||
|
||||
func a():
|
||||
test.➡
|
||||
pass
|
||||
|
|
|
@ -4,3 +4,4 @@ var test = $A
|
|||
|
||||
func a():
|
||||
test.➡
|
||||
pass
|
||||
|
|
|
@ -4,3 +4,4 @@ var test = $AnimationPlayer
|
|||
|
||||
func a():
|
||||
test.➡
|
||||
pass
|
||||
|
|
|
@ -6,3 +6,4 @@ var test: A = $A
|
|||
|
||||
func a():
|
||||
test.➡
|
||||
pass
|
||||
|
|
|
@ -4,3 +4,4 @@ var test: AnimationPlayer = $AnimationPlayer
|
|||
|
||||
func a():
|
||||
test.➡
|
||||
pass
|
||||
|
|
|
@ -6,3 +6,4 @@ const A := preload("res://completion/class_a.notest.gd")
|
|||
|
||||
func a():
|
||||
test.➡
|
||||
pass
|
||||
|
|
|
@ -4,3 +4,4 @@ var test: AnimationPlayer = $AnimationPlayer
|
|||
|
||||
func a():
|
||||
test.➡
|
||||
pass
|
||||
|
|
|
@ -4,3 +4,4 @@ var test: Node = $A
|
|||
|
||||
func a():
|
||||
test.➡
|
||||
pass
|
||||
|
|
|
@ -4,3 +4,4 @@ var test: Node = $AnimationPlayer
|
|||
|
||||
func a():
|
||||
test.➡
|
||||
pass
|
||||
|
|
|
@ -4,3 +4,4 @@ var test: Area2D = $A
|
|||
|
||||
func a():
|
||||
test.➡
|
||||
pass
|
||||
|
|
|
@ -4,3 +4,4 @@ var test: Area2D = $AnimationPlayer
|
|||
|
||||
func a():
|
||||
test.➡
|
||||
pass
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
|
||||
#ifdef TOOLS_ENABLED
|
||||
|
||||
#include "core/config/project_settings.h"
|
||||
#include "core/io/config_file.h"
|
||||
#include "core/io/dir_access.h"
|
||||
#include "core/io/file_access.h"
|
||||
|
@ -111,7 +112,10 @@ static void test_directory(const String &p_dir) {
|
|||
// For ease of reading ➡ (0x27A1) acts as sentinel char instead of 0xFFFF in the files.
|
||||
code = code.replace_first(String::chr(0x27A1), String::chr(0xFFFF));
|
||||
// Require pointer sentinel char in scripts.
|
||||
CHECK(code.find_char(0xFFFF) != -1);
|
||||
int location = code.find_char(0xFFFF);
|
||||
CHECK(location != -1);
|
||||
|
||||
String res_path = ProjectSettings::get_singleton()->localize_path(path.path_join(next));
|
||||
|
||||
ConfigFile conf;
|
||||
if (conf.load(path.path_join(next.get_basename() + ".cfg")) != OK) {
|
||||
|
@ -137,20 +141,46 @@ static void test_directory(const String &p_dir) {
|
|||
String call_hint;
|
||||
bool forced;
|
||||
|
||||
Node *owner = nullptr;
|
||||
Node *scene = nullptr;
|
||||
if (conf.has_section_key("input", "scene")) {
|
||||
Ref<PackedScene> scene = ResourceLoader::load(conf.get_value("input", "scene"), "PackedScene", ResourceFormatLoader::CACHE_MODE_IGNORE_DEEP);
|
||||
if (scene.is_valid()) {
|
||||
owner = scene->instantiate();
|
||||
Ref<PackedScene> packed_scene = ResourceLoader::load(conf.get_value("input", "scene"), "PackedScene", ResourceFormatLoader::CACHE_MODE_IGNORE_DEEP);
|
||||
if (packed_scene.is_valid()) {
|
||||
scene = packed_scene->instantiate();
|
||||
}
|
||||
} else if (dir->file_exists(next.get_basename() + ".tscn")) {
|
||||
Ref<PackedScene> scene = ResourceLoader::load(path.path_join(next.get_basename() + ".tscn"), "PackedScene");
|
||||
if (scene.is_valid()) {
|
||||
owner = scene->instantiate();
|
||||
Ref<PackedScene> packed_scene = ResourceLoader::load(path.path_join(next.get_basename() + ".tscn"), "PackedScene");
|
||||
if (packed_scene.is_valid()) {
|
||||
scene = packed_scene->instantiate();
|
||||
}
|
||||
}
|
||||
Node *owner = nullptr;
|
||||
if (scene != nullptr) {
|
||||
owner = scene->get_node(conf.get_value("input", "node_path", "."));
|
||||
}
|
||||
|
||||
GDScriptLanguage::get_singleton()->complete_code(code, path.path_join(next), owner, &options, forced, call_hint);
|
||||
if (owner != nullptr) {
|
||||
// Remove the line which contains the sentinel char, to get a valid script.
|
||||
Ref<GDScript> scr;
|
||||
scr.instantiate();
|
||||
int start = location;
|
||||
int end = location;
|
||||
for (; start >= 0; --start) {
|
||||
if (code.get(start) == '\n') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (; end < code.size(); ++end) {
|
||||
if (code.get(end) == '\n') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
scr->set_source_code(code.erase(start, end - start));
|
||||
scr->reload();
|
||||
scr->set_path(res_path);
|
||||
owner->set_script(scr);
|
||||
}
|
||||
|
||||
GDScriptLanguage::get_singleton()->complete_code(code, res_path, owner, &options, forced, call_hint);
|
||||
String contains_excluded;
|
||||
for (ScriptLanguage::CodeCompletionOption &option : options) {
|
||||
for (const Dictionary &E : exclude) {
|
||||
|
@ -179,8 +209,8 @@ static void test_directory(const String &p_dir) {
|
|||
CHECK(expected_call_hint == call_hint);
|
||||
CHECK(expected_forced == forced);
|
||||
|
||||
if (owner) {
|
||||
memdelete(owner);
|
||||
if (scene) {
|
||||
memdelete(scene);
|
||||
}
|
||||
}
|
||||
next = dir->get_next();
|
||||
|
|
Loading…
Reference in a new issue