Просмотр исходного кода

Fix completion popup for the variables created with `get_node` call

Yuri Rubinsky 2 лет назад
Родитель
Сommit
65d14679e7
1 измененных файлов с 63 добавлено и 61 удалено
  1. 63 61
      modules/gdscript/gdscript_editor.cpp

+ 63 - 61
modules/gdscript/gdscript_editor.cpp

@@ -2511,6 +2511,57 @@ static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, c
 	}
 }
 
+static bool _get_subscript_type(GDScriptParser::CompletionContext &p_context, const GDScriptParser::SubscriptNode *p_subscript, GDScriptParser::DataType &r_base_type, Variant *r_base = nullptr) {
+	if (p_subscript->base->type == GDScriptParser::Node::IDENTIFIER) {
+		const GDScriptParser::GetNodeNode *get_node = nullptr;
+		const GDScriptParser::IdentifierNode *identifier_node = static_cast<GDScriptParser::IdentifierNode *>(p_subscript->base);
+
+		switch (identifier_node->source) {
+			case GDScriptParser::IdentifierNode::Source::MEMBER_VARIABLE: {
+				if (p_context.current_class != nullptr) {
+					const StringName &member_name = identifier_node->name;
+					const GDScriptParser::ClassNode *current_class = p_context.current_class;
+
+					if (current_class->has_member(member_name)) {
+						const GDScriptParser::ClassNode::Member &member = current_class->get_member(member_name);
+
+						if (member.type == GDScriptParser::ClassNode::Member::VARIABLE) {
+							const GDScriptParser::VariableNode *variable = static_cast<GDScriptParser::VariableNode *>(member.variable);
+
+							if (variable->initializer && variable->initializer->type == GDScriptParser::Node::GET_NODE) {
+								get_node = static_cast<GDScriptParser::GetNodeNode *>(variable->initializer);
+							}
+						}
+					}
+				}
+			} break;
+			case GDScriptParser::IdentifierNode::Source::LOCAL_VARIABLE: {
+				if (identifier_node->next != nullptr && identifier_node->next->type == GDScriptParser::ClassNode::Node::GET_NODE) {
+					get_node = static_cast<GDScriptParser::GetNodeNode *>(identifier_node->next);
+				}
+			} break;
+			default:
+				break;
+		}
+
+		if (get_node != nullptr) {
+			const Object *node = p_context.base->call("get_node_or_null", NodePath(get_node->full_path));
+			if (node != nullptr) {
+				if (r_base != nullptr) {
+					*r_base = node;
+				}
+				r_base_type.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT;
+				r_base_type.kind = GDScriptParser::DataType::NATIVE;
+				r_base_type.native_type = node->get_class_name();
+				r_base_type.builtin_type = Variant::OBJECT;
+				return true;
+			}
+		}
+	}
+
+	return false;
+}
+
 static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, const GDScriptParser::Node *p_call, int p_argidx, HashMap<String, ScriptLanguage::CodeCompletionOption> &r_result, bool &r_forced, String &r_arghint) {
 	if (p_call->type == GDScriptParser::Node::PRELOAD) {
 		if (p_argidx == 0 && bool(EDITOR_GET("text_editor/completion/complete_file_paths"))) {
@@ -2561,13 +2612,17 @@ static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, c
 			}
 		}
 
-		if (subscript->is_attribute) {
-			GDScriptCompletionIdentifier ci;
-			if (_guess_expression_type(p_context, subscript->base, ci)) {
-				base_type = ci.type;
-				base = ci.value;
-			} else {
-				return;
+		if (p_context.base != nullptr && subscript->is_attribute) {
+			bool found_type = _get_subscript_type(p_context, subscript, base_type, &base);
+
+			if (!found_type) {
+				GDScriptCompletionIdentifier ci;
+				if (_guess_expression_type(p_context, subscript->base, ci)) {
+					base_type = ci.type;
+					base = ci.value;
+				} else {
+					return;
+				}
 			}
 
 			_static = base_type.is_meta_type;
@@ -2765,60 +2820,7 @@ static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, c
 			const GDScriptParser::SubscriptNode *attr = static_cast<const GDScriptParser::SubscriptNode *>(completion_context.node);
 			if (attr->base) {
 				GDScriptCompletionIdentifier base;
-				bool found_type = false;
-
-				if (p_owner != nullptr && attr->base->type == GDScriptParser::Node::IDENTIFIER) {
-					const GDScriptParser::GetNodeNode *get_node = nullptr;
-					const GDScriptParser::IdentifierNode *identifier_node = static_cast<GDScriptParser::IdentifierNode *>(attr->base);
-
-					switch (identifier_node->source) {
-						case GDScriptParser::IdentifierNode::Source::MEMBER_VARIABLE: {
-							if (completion_context.current_class != nullptr) {
-								const StringName &member_name = identifier_node->name;
-								const GDScriptParser::ClassNode *current_class = completion_context.current_class;
-
-								if (current_class->has_member(member_name)) {
-									const GDScriptParser::ClassNode::Member &member = current_class->get_member(member_name);
-
-									if (member.type == GDScriptParser::ClassNode::Member::VARIABLE) {
-										const GDScriptParser::VariableNode *variable = static_cast<GDScriptParser::VariableNode *>(member.variable);
-
-										if (variable->initializer && variable->initializer->type == GDScriptParser::Node::GET_NODE) {
-											get_node = static_cast<GDScriptParser::GetNodeNode *>(variable->initializer);
-										}
-									}
-								}
-							}
-						} break;
-						case GDScriptParser::IdentifierNode::Source::LOCAL_VARIABLE: {
-							if (identifier_node->next != nullptr && identifier_node->next->type == GDScriptParser::ClassNode::Node::GET_NODE) {
-								get_node = static_cast<GDScriptParser::GetNodeNode *>(identifier_node->next);
-							}
-						} break;
-						default:
-							break;
-					}
-
-					if (get_node != nullptr) {
-						const Object *node = p_owner->call("get_node_or_null", NodePath(get_node->full_path));
-						if (node != nullptr) {
-							found_type = true;
-
-							GDScriptParser::DataType type;
-							type.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT;
-							type.kind = GDScriptParser::DataType::NATIVE;
-							type.native_type = node->get_class_name();
-							type.builtin_type = Variant::OBJECT;
-
-							base.type = type;
-						}
-
-						if (!found_type) {
-							break;
-						}
-					}
-				}
-
+				bool found_type = _get_subscript_type(completion_context, attr, base.type);
 				if (!found_type && !_guess_expression_type(completion_context, attr->base, base)) {
 					break;
 				}