Repository: godotengine/godot
File: modules/gdscript/gdscript_editor.cpp (C++)

Code before:
	} else if (GDScriptParser::get_builtin_type(call->function_name) < Variant::VARIANT_MAX) {
		// Complete constructor
		List<MethodInfo> constructors;
		Variant::get_constructor_list(GDScriptParser::get_builtin_type(call->function_name), &constructors);

		int i = 0;
		for (const MethodInfo &E : constructors) {
			if (p_argidx >= E.arguments.size()) {
				continue;
			}
			if (i > 0) {
				r_arghint += "\n";
			}
			r_arghint += _make_arguments_hint(E, p_argidx);
			i++;
		}
		return;
	} else if (call->is_super || callee_type == GDScriptParser::Node::IDENTIFIER) {
		base = p_context.base;

		if (p_context.current_class) {
			base_type = p_context.current_class->get_datatype();
			_static = !p_context.current_function || p_context.current_function->is_static;
		}
	} else if (callee_type == GDScriptParser::Node::SUBSCRIPT) {
		const GDScriptParser::SubscriptNode *subscript = static_cast<const GDScriptParser::SubscriptNode *>(call->callee);

		if (subscript->is_attribute) {
			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;
		}
	} else {
		return;
	}

	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);

	r_forced = r_result.size() > 0;
}

::Error GDScriptLanguage::complete_code(const String &p_code, const String &p_path, Object *p_owner, List<ScriptLanguage::CodeCompletionOption> *r_options, bool &r_forced, String &r_call_hint) {

Review comment (suggestion):
It's not guaranteed that the base will always be an `IdentifierNode`, so you need to check if it actually is (checking the node type) before casting.

Code after:
	} else if (GDScriptParser::get_builtin_type(call->function_name) < Variant::VARIANT_MAX) {
		// Complete constructor.
		List<MethodInfo> constructors;
		Variant::get_constructor_list(GDScriptParser::get_builtin_type(call->function_name), &constructors);

		int i = 0;
		for (const MethodInfo &E : constructors) {
			if (p_argidx >= E.arguments.size()) {
				continue;
			}
			if (i > 0) {
				r_arghint += "\n";
			}
			r_arghint += _make_arguments_hint(E, p_argidx);
			i++;
		}
		return;
	} else if (call->is_super || callee_type == GDScriptParser::Node::IDENTIFIER) {
		base = p_context.base;

		if (p_context.current_class) {
			base_type = p_context.current_class->get_datatype();
			_static = !p_context.current_function || p_context.current_function->is_static;
		}
	} else if (callee_type == GDScriptParser::Node::SUBSCRIPT) {
		const GDScriptParser::SubscriptNode *subscript = static_cast<const GDScriptParser::SubscriptNode *>(call->callee);

		if (subscript->base != nullptr && subscript->base->type == GDScriptParser::Node::IDENTIFIER) {
			const GDScriptParser::IdentifierNode *base_identifier = static_cast<const GDScriptParser::IdentifierNode *>(subscript->base);

			Variant::Type method_type = GDScriptParser::get_builtin_type(base_identifier->name);
			if (method_type < Variant::VARIANT_MAX) {
				Variant v;
				Callable::CallError err;
				Variant::construct(method_type, v, nullptr, 0, err);
				if (err.error != Callable::CallError::CALL_OK) {
					return;
				}
				List<MethodInfo> methods;
				v.get_method_list(&methods);

				for (MethodInfo &E : methods) {
					if (p_argidx >= E.arguments.size()) {
						continue;
					}
					if (E.name == call->function_name) {
						r_arghint += _make_arguments_hint(E, p_argidx);
						return;
					}
				}
			}