|
@@ -2909,9 +2909,10 @@ static void _find_enumeration_candidates(GDScriptParser::CompletionContext &p_co
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, const GDScriptCompletionIdentifier &p_base, const StringName &p_method, int p_argidx, bool p_static, HashMap<String, ScriptLanguage::CodeCompletionOption> &r_result, String &r_arghint) {
|
|
|
+static void _list_call_arguments(GDScriptParser::CompletionContext &p_context, const GDScriptCompletionIdentifier &p_base, const GDScriptParser::CallNode *p_call, int p_argidx, bool p_static, HashMap<String, ScriptLanguage::CodeCompletionOption> &r_result, String &r_arghint) {
|
|
|
Variant base = p_base.value;
|
|
|
GDScriptParser::DataType base_type = p_base.type;
|
|
|
+ const StringName &method = p_call->function_name;
|
|
|
|
|
|
const String quote_style = EDITOR_GET("text_editor/completion/use_single_quotes") ? "'" : "\"";
|
|
|
const bool use_string_names = EDITOR_GET("text_editor/completion/add_string_name_literals");
|
|
@@ -2920,7 +2921,7 @@ static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, c
|
|
|
while (base_type.is_set() && !base_type.is_variant()) {
|
|
|
switch (base_type.kind) {
|
|
|
case GDScriptParser::DataType::CLASS: {
|
|
|
- if (base_type.is_meta_type && p_method == SNAME("new")) {
|
|
|
+ if (base_type.is_meta_type && method == SNAME("new")) {
|
|
|
const GDScriptParser::ClassNode *current = base_type.class_type;
|
|
|
|
|
|
do {
|
|
@@ -2939,8 +2940,8 @@ static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, c
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- if (base_type.class_type->has_member(p_method)) {
|
|
|
- const GDScriptParser::ClassNode::Member &member = base_type.class_type->get_member(p_method);
|
|
|
+ if (base_type.class_type->has_member(method)) {
|
|
|
+ const GDScriptParser::ClassNode::Member &member = base_type.class_type->get_member(method);
|
|
|
|
|
|
if (member.type == GDScriptParser::ClassNode::Member::FUNCTION) {
|
|
|
r_arghint = _make_arguments_hint(member.function, p_argidx);
|
|
@@ -2951,8 +2952,8 @@ static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, c
|
|
|
base_type = base_type.class_type->base_type;
|
|
|
} break;
|
|
|
case GDScriptParser::DataType::SCRIPT: {
|
|
|
- if (base_type.script_type->is_valid() && base_type.script_type->has_method(p_method)) {
|
|
|
- r_arghint = _make_arguments_hint(base_type.script_type->get_method_info(p_method), p_argidx);
|
|
|
+ if (base_type.script_type->is_valid() && base_type.script_type->has_method(method)) {
|
|
|
+ r_arghint = _make_arguments_hint(base_type.script_type->get_method_info(method), p_argidx);
|
|
|
return;
|
|
|
}
|
|
|
Ref<Script> base_script = base_type.script_type->get_base_script();
|
|
@@ -2974,21 +2975,35 @@ static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, c
|
|
|
MethodInfo info;
|
|
|
int method_args = 0;
|
|
|
|
|
|
- if (ClassDB::get_method_info(class_name, p_method, &info)) {
|
|
|
+ if (ClassDB::get_method_info(class_name, method, &info)) {
|
|
|
method_args = info.arguments.size();
|
|
|
if (base.get_type() == Variant::OBJECT) {
|
|
|
Object *obj = base.operator Object *();
|
|
|
if (obj) {
|
|
|
List<String> options;
|
|
|
- obj->get_argument_options(p_method, p_argidx, &options);
|
|
|
+ obj->get_argument_options(method, p_argidx, &options);
|
|
|
for (String &opt : options) {
|
|
|
// Handle user preference.
|
|
|
if (opt.is_quoted()) {
|
|
|
opt = opt.unquote().quote(quote_style);
|
|
|
if (use_string_names && info.arguments[p_argidx].type == Variant::STRING_NAME) {
|
|
|
- opt = "&" + opt;
|
|
|
+ if (p_call->arguments.size() > p_argidx && p_call->arguments[p_argidx] && p_call->arguments[p_argidx]->type == GDScriptParser::Node::LITERAL) {
|
|
|
+ GDScriptParser::LiteralNode *literal = static_cast<GDScriptParser::LiteralNode *>(p_call->arguments[p_argidx]);
|
|
|
+ if (literal->value.get_type() == Variant::STRING) {
|
|
|
+ opt = "&" + opt;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ opt = "&" + opt;
|
|
|
+ }
|
|
|
} else if (use_node_paths && info.arguments[p_argidx].type == Variant::NODE_PATH) {
|
|
|
- opt = "^" + opt;
|
|
|
+ if (p_call->arguments.size() > p_argidx && p_call->arguments[p_argidx] && p_call->arguments[p_argidx]->type == GDScriptParser::Node::LITERAL) {
|
|
|
+ GDScriptParser::LiteralNode *literal = static_cast<GDScriptParser::LiteralNode *>(p_call->arguments[p_argidx]);
|
|
|
+ if (literal->value.get_type() == Variant::STRING) {
|
|
|
+ opt = "^" + opt;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ opt = "^" + opt;
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
ScriptLanguage::CodeCompletionOption option(opt, ScriptLanguage::CODE_COMPLETION_KIND_FUNCTION);
|
|
@@ -3007,13 +3022,13 @@ static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, c
|
|
|
r_arghint = _make_arguments_hint(info, p_argidx);
|
|
|
}
|
|
|
|
|
|
- if (p_argidx == 1 && p_context.node && p_context.node->type == GDScriptParser::Node::CALL && ClassDB::is_parent_class(class_name, SNAME("Tween")) && p_method == SNAME("tween_property")) {
|
|
|
+ if (p_argidx == 1 && p_call && ClassDB::is_parent_class(class_name, SNAME("Tween")) && method == SNAME("tween_property")) {
|
|
|
// Get tweened objects properties.
|
|
|
- if (static_cast<GDScriptParser::CallNode *>(p_context.node)->arguments.is_empty()) {
|
|
|
+ if (p_call->arguments.is_empty()) {
|
|
|
base_type.kind = GDScriptParser::DataType::UNRESOLVED;
|
|
|
break;
|
|
|
}
|
|
|
- GDScriptParser::ExpressionNode *tweened_object = static_cast<GDScriptParser::CallNode *>(p_context.node)->arguments[0];
|
|
|
+ GDScriptParser::ExpressionNode *tweened_object = p_call->arguments[0];
|
|
|
if (!tweened_object) {
|
|
|
base_type.kind = GDScriptParser::DataType::UNRESOLVED;
|
|
|
break;
|
|
@@ -3033,7 +3048,14 @@ static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, c
|
|
|
}
|
|
|
String name = E.name.quote(quote_style);
|
|
|
if (use_node_paths) {
|
|
|
- name = "^" + name;
|
|
|
+ if (p_call->arguments.size() > p_argidx && p_call->arguments[p_argidx] && p_call->arguments[p_argidx]->type == GDScriptParser::Node::LITERAL) {
|
|
|
+ GDScriptParser::LiteralNode *literal = static_cast<GDScriptParser::LiteralNode *>(p_call->arguments[p_argidx]);
|
|
|
+ if (literal->value.get_type() == Variant::STRING) {
|
|
|
+ name = "^" + name;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ name = "^" + name;
|
|
|
+ }
|
|
|
}
|
|
|
ScriptLanguage::CodeCompletionOption option(name, ScriptLanguage::CODE_COMPLETION_KIND_MEMBER, ScriptLanguage::CodeCompletionLocation::LOCATION_LOCAL + n);
|
|
|
r_result.insert(option.display, option);
|
|
@@ -3051,7 +3073,14 @@ static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, c
|
|
|
if (member.type == GDScriptParser::ClassNode::Member::VARIABLE) {
|
|
|
String name = member.get_name().quote(quote_style);
|
|
|
if (use_node_paths) {
|
|
|
- name = "^" + name;
|
|
|
+ if (p_call->arguments.size() > p_argidx && p_call->arguments[p_argidx] && p_call->arguments[p_argidx]->type == GDScriptParser::Node::LITERAL) {
|
|
|
+ GDScriptParser::LiteralNode *literal = static_cast<GDScriptParser::LiteralNode *>(p_call->arguments[p_argidx]);
|
|
|
+ if (literal->value.get_type() == Variant::STRING) {
|
|
|
+ name = "^" + name;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ name = "^" + name;
|
|
|
+ }
|
|
|
}
|
|
|
ScriptLanguage::CodeCompletionOption option(name, ScriptLanguage::CODE_COMPLETION_KIND_MEMBER, ScriptLanguage::CodeCompletionLocation::LOCATION_LOCAL + n);
|
|
|
r_result.insert(option.display, option);
|
|
@@ -3078,14 +3107,21 @@ static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, c
|
|
|
}
|
|
|
String name = E.name.quote(quote_style);
|
|
|
if (use_node_paths) {
|
|
|
- name = "^" + name;
|
|
|
+ if (p_call->arguments.size() > p_argidx && p_call->arguments[p_argidx] && p_call->arguments[p_argidx]->type == GDScriptParser::Node::LITERAL) {
|
|
|
+ GDScriptParser::LiteralNode *literal = static_cast<GDScriptParser::LiteralNode *>(p_call->arguments[p_argidx]);
|
|
|
+ if (literal->value.get_type() == Variant::STRING) {
|
|
|
+ name = "^" + name;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ name = "^" + name;
|
|
|
+ }
|
|
|
}
|
|
|
ScriptLanguage::CodeCompletionOption option(name, ScriptLanguage::CODE_COMPLETION_KIND_MEMBER);
|
|
|
r_result.insert(option.display, option);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- if (p_argidx == 0 && ClassDB::is_parent_class(class_name, SNAME("Node")) && (p_method == SNAME("get_node") || p_method == SNAME("has_node"))) {
|
|
|
+ if (p_argidx == 0 && ClassDB::is_parent_class(class_name, SNAME("Node")) && (method == SNAME("get_node") || method == SNAME("has_node"))) {
|
|
|
// Get autoloads
|
|
|
List<PropertyInfo> props;
|
|
|
ProjectSettings::get_singleton()->get_property_list(&props);
|
|
@@ -3098,14 +3134,21 @@ static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, c
|
|
|
String name = s.get_slicec('/', 1);
|
|
|
String path = ("/root/" + name).quote(quote_style);
|
|
|
if (use_node_paths) {
|
|
|
- path = "^" + path;
|
|
|
+ if (p_call->arguments.size() > p_argidx && p_call->arguments[p_argidx] && p_call->arguments[p_argidx]->type == GDScriptParser::Node::LITERAL) {
|
|
|
+ GDScriptParser::LiteralNode *literal = static_cast<GDScriptParser::LiteralNode *>(p_call->arguments[p_argidx]);
|
|
|
+ if (literal->value.get_type() == Variant::STRING) {
|
|
|
+ path = "^" + path;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ path = "^" + path;
|
|
|
+ }
|
|
|
}
|
|
|
ScriptLanguage::CodeCompletionOption option(path, ScriptLanguage::CODE_COMPLETION_KIND_NODE_PATH);
|
|
|
r_result.insert(option.display, option);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- if (p_argidx == 0 && method_args > 0 && ClassDB::is_parent_class(class_name, SNAME("InputEvent")) && p_method.operator String().contains("action")) {
|
|
|
+ if (p_argidx == 0 && method_args > 0 && ClassDB::is_parent_class(class_name, SNAME("InputEvent")) && method.operator String().contains("action")) {
|
|
|
// Get input actions
|
|
|
List<PropertyInfo> props;
|
|
|
ProjectSettings::get_singleton()->get_property_list(&props);
|
|
@@ -3116,14 +3159,21 @@ static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, c
|
|
|
}
|
|
|
String name = s.get_slicec('/', 1).quote(quote_style);
|
|
|
if (use_string_names) {
|
|
|
- name = "&" + name;
|
|
|
+ if (p_call->arguments.size() > p_argidx && p_call->arguments[p_argidx] && p_call->arguments[p_argidx]->type == GDScriptParser::Node::LITERAL) {
|
|
|
+ GDScriptParser::LiteralNode *literal = static_cast<GDScriptParser::LiteralNode *>(p_call->arguments[p_argidx]);
|
|
|
+ if (literal->value.get_type() == Variant::STRING) {
|
|
|
+ name = "&" + name;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ name = "&" + name;
|
|
|
+ }
|
|
|
}
|
|
|
ScriptLanguage::CodeCompletionOption option(name, ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT);
|
|
|
r_result.insert(option.display, option);
|
|
|
}
|
|
|
}
|
|
|
if (EDITOR_GET("text_editor/completion/complete_file_paths")) {
|
|
|
- if (p_argidx == 0 && p_method == SNAME("change_scene_to_file") && ClassDB::is_parent_class(class_name, SNAME("SceneTree"))) {
|
|
|
+ if (p_argidx == 0 && method == SNAME("change_scene_to_file") && ClassDB::is_parent_class(class_name, SNAME("SceneTree"))) {
|
|
|
HashMap<String, ScriptLanguage::CodeCompletionOption> list;
|
|
|
_get_directory_contents(EditorFileSystem::get_singleton()->get_filesystem(), list, SNAME("PackedScene"));
|
|
|
for (const KeyValue<String, ScriptLanguage::CodeCompletionOption> &key_value_pair : list) {
|
|
@@ -3147,7 +3197,7 @@ static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, c
|
|
|
List<MethodInfo> methods;
|
|
|
base.get_method_list(&methods);
|
|
|
for (const MethodInfo &E : methods) {
|
|
|
- if (E.name == p_method) {
|
|
|
+ if (E.name == method) {
|
|
|
r_arghint = _make_arguments_hint(E, p_argidx);
|
|
|
return;
|
|
|
}
|
|
@@ -3358,7 +3408,7 @@ static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, c
|
|
|
GDScriptCompletionIdentifier ci;
|
|
|
ci.type = base_type;
|
|
|
ci.value = base;
|
|
|
- _find_call_arguments(p_context, ci, call->function_name, p_argidx, _static, r_result, r_arghint);
|
|
|
+ _list_call_arguments(p_context, ci, call, p_argidx, _static, r_result, r_arghint);
|
|
|
|
|
|
r_forced = r_result.size() > 0;
|
|
|
}
|