瀏覽代碼

Merge pull request #91660 from AThousandShips/methodinfo_vec

[Core] Use `Vector` for `MethodInfo::arguments`
Thaddeus Crews 4 月之前
父節點
當前提交
b377562b52

+ 3 - 4
core/doc_data.cpp

@@ -136,11 +136,10 @@ void DocData::method_doc_from_methodinfo(DocData::MethodDoc &p_method, const Met
 
 	return_doc_from_retinfo(p_method, p_methodinfo.return_val);
 
-	int i = 0;
-	for (List<PropertyInfo>::ConstIterator itr = p_methodinfo.arguments.begin(); itr != p_methodinfo.arguments.end(); ++itr, ++i) {
+	for (int64_t i = 0; i < p_methodinfo.arguments.size(); ++i) {
 		DocData::ArgumentDoc argument;
-		argument_doc_from_arginfo(argument, *itr);
-		int default_arg_index = i - (p_methodinfo.arguments.size() - p_methodinfo.default_arguments.size());
+		argument_doc_from_arginfo(argument, p_methodinfo.arguments[i]);
+		int64_t default_arg_index = i - (p_methodinfo.arguments.size() - p_methodinfo.default_arguments.size());
 		if (default_arg_index >= 0) {
 			Variant default_arg = p_methodinfo.default_arguments[default_arg_index];
 			argument.default_value = get_default_value_string(default_arg);

+ 5 - 7
core/extension/extension_api_dump.cpp

@@ -1053,9 +1053,8 @@ Dictionary GDExtensionAPIDump::generate_extension_api(bool p_include_docs) {
 						}
 
 						Array arguments;
-						int i = 0;
-						for (List<PropertyInfo>::ConstIterator itr = mi.arguments.begin(); itr != mi.arguments.end(); ++itr, ++i) {
-							const PropertyInfo &pinfo = *itr;
+						for (int64_t i = 0; i < mi.arguments.size(); ++i) {
+							const PropertyInfo &pinfo = mi.arguments[i];
 							Dictionary d3;
 
 							d3["name"] = pinfo.name;
@@ -1180,11 +1179,10 @@ Dictionary GDExtensionAPIDump::generate_extension_api(bool p_include_docs) {
 
 					Array arguments;
 
-					int i = 0;
-					for (List<PropertyInfo>::ConstIterator itr = F.arguments.begin(); itr != F.arguments.end(); ++itr, ++i) {
+					for (int64_t i = 0; i < F.arguments.size(); ++i) {
 						Dictionary d3;
-						d3["name"] = itr->name;
-						d3["type"] = get_property_info_type_name(*itr);
+						d3["name"] = F.arguments[i].name;
+						d3["type"] = get_property_info_type_name(F.arguments[i]);
 						if (F.get_argument_meta(i) > 0) {
 							d3["meta"] = get_type_meta_name((GodotTypeInfo::Metadata)F.get_argument_meta(i));
 						}

+ 2 - 3
core/object/class_db.cpp

@@ -2011,9 +2011,8 @@ void ClassDB::add_virtual_method(const StringName &p_class, const MethodInfo &p_
 		if (p_arg_names.size() != mi.arguments.size()) {
 			WARN_PRINT(vformat("Mismatch argument name count for virtual method: '%s::%s'.", String(p_class), p_method.name));
 		} else {
-			List<PropertyInfo>::Iterator itr = mi.arguments.begin();
-			for (int i = 0; i < p_arg_names.size(); ++itr, ++i) {
-				itr->name = p_arg_names[i];
+			for (int64_t i = 0; i < p_arg_names.size(); ++i) {
+				mi.arguments.write[i].name = p_arg_names[i];
 			}
 		}
 	}

+ 4 - 5
core/object/method_bind.h

@@ -151,7 +151,7 @@ public:
 		if (p_arg < 0) {
 			return _gen_return_type_info();
 		} else if (p_arg < method_info.arguments.size()) {
-			return method_info.arguments.get(p_arg);
+			return method_info.arguments[p_arg];
 		} else {
 			return PropertyInfo(Variant::NIL, "arg_" + itos(p_arg), PROPERTY_HINT_NONE, String(), PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_NIL_IS_VARIANT);
 		}
@@ -192,11 +192,10 @@ public:
 			Vector<StringName> names;
 			names.resize(method_info.arguments.size());
 #endif
-			int i = 0;
-			for (List<PropertyInfo>::ConstIterator itr = method_info.arguments.begin(); itr != method_info.arguments.end(); ++itr, ++i) {
-				at[i + 1] = itr->type;
+			for (int64_t i = 0; i < method_info.arguments.size(); ++i) {
+				at[i + 1] = method_info.arguments[i].type;
 #ifdef DEBUG_METHODS_ENABLED
-				names.write[i] = itr->name;
+				names.write[i] = method_info.arguments[i].name;
 #endif
 			}
 

+ 10 - 1
core/object/object.cpp

@@ -115,10 +115,19 @@ TypedArray<Dictionary> convert_property_list(const List<PropertyInfo> *p_list) {
 	return va;
 }
 
+TypedArray<Dictionary> convert_property_list(const Vector<PropertyInfo> &p_vector) {
+	TypedArray<Dictionary> va;
+	for (const PropertyInfo &E : p_vector) {
+		va.push_back(Dictionary(E));
+	}
+
+	return va;
+}
+
 MethodInfo::operator Dictionary() const {
 	Dictionary d;
 	d["name"] = name;
-	d["args"] = convert_property_list(&arguments);
+	d["args"] = convert_property_list(arguments);
 	Array da;
 	for (int i = 0; i < default_arguments.size(); i++) {
 		da.push_back(default_arguments[i]);

+ 7 - 16
core/object/object.h

@@ -208,6 +208,7 @@ struct PropertyInfo {
 };
 
 TypedArray<Dictionary> convert_property_list(const List<PropertyInfo> *p_list);
+TypedArray<Dictionary> convert_property_list(const Vector<PropertyInfo> &p_vector);
 
 enum MethodFlags {
 	METHOD_FLAG_NORMAL = 1,
@@ -226,7 +227,7 @@ struct MethodInfo {
 	PropertyInfo return_val;
 	uint32_t flags = METHOD_FLAGS_DEFAULT;
 	int id = 0;
-	List<PropertyInfo> arguments;
+	Vector<PropertyInfo> arguments;
 	Vector<Variant> default_arguments;
 	int return_val_metadata = 0;
 	Vector<int> arguments_metadata;
@@ -255,8 +256,8 @@ struct MethodInfo {
 			return_val(PropertyInfo(pinfo.return_value)),
 			flags(pinfo.flags),
 			id(pinfo.id) {
-		for (uint32_t j = 0; j < pinfo.argument_count; j++) {
-			arguments.push_back(PropertyInfo(pinfo.arguments[j]));
+		for (uint32_t i = 0; i < pinfo.argument_count; i++) {
+			arguments.push_back(PropertyInfo(pinfo.arguments[i]));
 		}
 		const Variant *def_values = (const Variant *)pinfo.default_arguments;
 		for (uint32_t j = 0; j < pinfo.default_argument_count; j++) {
@@ -264,22 +265,12 @@ struct MethodInfo {
 		}
 	}
 
-	void _push_params(const PropertyInfo &p_param) {
-		arguments.push_back(p_param);
-	}
-
-	template <typename... VarArgs>
-	void _push_params(const PropertyInfo &p_param, VarArgs... p_params) {
-		arguments.push_back(p_param);
-		_push_params(p_params...);
-	}
-
 	MethodInfo(const String &p_name) { name = p_name; }
 
 	template <typename... VarArgs>
 	MethodInfo(const String &p_name, VarArgs... p_params) {
 		name = p_name;
-		_push_params(p_params...);
+		arguments = Vector<PropertyInfo>{ p_params... };
 	}
 
 	MethodInfo(Variant::Type ret) { return_val.type = ret; }
@@ -292,7 +283,7 @@ struct MethodInfo {
 	MethodInfo(Variant::Type ret, const String &p_name, VarArgs... p_params) {
 		name = p_name;
 		return_val.type = ret;
-		_push_params(p_params...);
+		arguments = Vector<PropertyInfo>{ p_params... };
 	}
 
 	MethodInfo(const PropertyInfo &p_ret, const String &p_name) {
@@ -304,7 +295,7 @@ struct MethodInfo {
 	MethodInfo(const PropertyInfo &p_ret, const String &p_name, VarArgs... p_params) {
 		return_val = p_ret;
 		name = p_name;
-		_push_params(p_params...);
+		arguments = Vector<PropertyInfo>{ p_params... };
 	}
 };
 

+ 3 - 4
editor/animation_track_editor.cpp

@@ -5636,17 +5636,16 @@ void AnimationTrackEditor::_add_method_key(const String &p_method) {
 			Dictionary d;
 			d["method"] = p_method;
 			Array params;
-			int first_defarg = E.arguments.size() - E.default_arguments.size();
+			int64_t first_defarg = E.arguments.size() - E.default_arguments.size();
 
-			int i = 0;
-			for (List<PropertyInfo>::ConstIterator itr = E.arguments.begin(); itr != E.arguments.end(); ++itr, ++i) {
+			for (int64_t i = 0; i < E.arguments.size(); ++i) {
 				if (i >= first_defarg) {
 					Variant arg = E.default_arguments[i - first_defarg];
 					params.push_back(arg);
 				} else {
 					Callable::CallError ce;
 					Variant arg;
-					Variant::construct(itr->type, arg, nullptr, 0, ce);
+					Variant::construct(E.arguments[i].type, arg, nullptr, 0, ce);
 					params.push_back(arg);
 				}
 			}

+ 11 - 12
editor/connections_dialog.cpp

@@ -282,10 +282,11 @@ List<MethodInfo> ConnectDialog::_filter_method_list(const List<MethodInfo> &p_me
 	bool check_signal = compatible_methods_only->is_pressed();
 	List<MethodInfo> ret;
 
-	List<Pair<Variant::Type, StringName>> effective_args;
+	LocalVector<Pair<Variant::Type, StringName>> effective_args;
 	int unbind = get_unbinds();
-	for (int i = 0; i < p_signal.arguments.size() - unbind; i++) {
-		PropertyInfo pi = p_signal.arguments.get(i);
+	effective_args.reserve(p_signal.arguments.size() - unbind);
+	for (int64_t i = 0; i < p_signal.arguments.size() - unbind; i++) {
+		PropertyInfo pi = p_signal.arguments[i];
 		effective_args.push_back(Pair(pi.type, pi.class_name));
 	}
 	if (unbind == 0) {
@@ -312,17 +313,16 @@ List<MethodInfo> ConnectDialog::_filter_method_list(const List<MethodInfo> &p_me
 			}
 
 			bool type_mismatch = false;
-			const List<Pair<Variant::Type, StringName>>::Element *E = effective_args.front();
-			for (const List<PropertyInfo>::Element *F = mi.arguments.front(); F; F = F->next(), E = E->next()) {
-				Variant::Type stype = E->get().first;
-				Variant::Type mtype = F->get().type;
+			for (int64_t i = 0; i < mi.arguments.size(); ++i) {
+				Variant::Type stype = effective_args[i].first;
+				Variant::Type mtype = mi.arguments[i].type;
 
 				if (stype != Variant::NIL && mtype != Variant::NIL && stype != mtype) {
 					type_mismatch = true;
 					break;
 				}
 
-				if (stype == Variant::OBJECT && mtype == Variant::OBJECT && !ClassDB::is_parent_class(E->get().second, F->get().class_name)) {
+				if (stype == Variant::OBJECT && mtype == Variant::OBJECT && !ClassDB::is_parent_class(effective_args[i].second, mi.arguments[i].class_name)) {
 					type_mismatch = true;
 					break;
 				}
@@ -552,13 +552,12 @@ String ConnectDialog::get_signature(const MethodInfo &p_method, PackedStringArra
 	signature.append(p_method.name);
 	signature.append("(");
 
-	int i = 0;
-	for (List<PropertyInfo>::ConstIterator itr = p_method.arguments.begin(); itr != p_method.arguments.end(); ++itr, ++i) {
-		if (itr != p_method.arguments.begin()) {
+	for (int64_t i = 0; i < p_method.arguments.size(); ++i) {
+		if (i > 0) {
 			signature.append(", ");
 		}
 
-		const PropertyInfo &pi = *itr;
+		const PropertyInfo &pi = p_method.arguments[i];
 		String type_name;
 		switch (pi.type) {
 			case Variant::NIL:

+ 8 - 12
editor/doc_tools.cpp

@@ -660,8 +660,7 @@ void DocTools::generate(BitField<GenerateFlags> p_flags) {
 				for (List<MethodInfo>::Element *EV = signal_list.front(); EV; EV = EV->next()) {
 					DocData::MethodDoc signal;
 					signal.name = EV->get().name;
-					for (List<PropertyInfo>::Element *EA = EV->get().arguments.front(); EA; EA = EA->next()) {
-						const PropertyInfo &arginfo = EA->get();
+					for (const PropertyInfo &arginfo : EV->get().arguments) {
 						DocData::ArgumentDoc argument;
 						DocData::argument_doc_from_arginfo(argument, arginfo);
 
@@ -853,9 +852,8 @@ void DocTools::generate(BitField<GenerateFlags> p_flags) {
 
 			method.name = mi.name;
 
-			int j = 0;
-			for (List<PropertyInfo>::ConstIterator itr = mi.arguments.begin(); itr != mi.arguments.end(); ++itr, ++j) {
-				PropertyInfo arginfo = *itr;
+			for (int64_t j = 0; j < mi.arguments.size(); ++j) {
+				const PropertyInfo &arginfo = mi.arguments[j];
 				DocData::ArgumentDoc ad;
 				DocData::argument_doc_from_arginfo(ad, arginfo);
 				ad.name = arginfo.name;
@@ -1066,10 +1064,9 @@ void DocTools::generate(BitField<GenerateFlags> p_flags) {
 
 				DocData::return_doc_from_retinfo(md, mi.return_val);
 
-				int j = 0;
-				for (List<PropertyInfo>::ConstIterator itr = mi.arguments.begin(); itr != mi.arguments.end(); ++itr, ++j) {
+				for (int64_t j = 0; j < mi.arguments.size(); ++j) {
 					DocData::ArgumentDoc ad;
-					DocData::argument_doc_from_arginfo(ad, *itr);
+					DocData::argument_doc_from_arginfo(ad, mi.arguments[j]);
 
 					int darg_idx = j - (mi.arguments.size() - mi.default_arguments.size());
 					if (darg_idx >= 0) {
@@ -1112,12 +1109,11 @@ void DocTools::generate(BitField<GenerateFlags> p_flags) {
 
 				DocData::return_doc_from_retinfo(atd, ai.return_val);
 
-				int j = 0;
-				for (List<PropertyInfo>::ConstIterator itr = ai.arguments.begin(); itr != ai.arguments.end(); ++itr, ++j) {
+				for (int64_t j = 0; j < ai.arguments.size(); ++j) {
 					DocData::ArgumentDoc ad;
-					DocData::argument_doc_from_arginfo(ad, *itr);
+					DocData::argument_doc_from_arginfo(ad, ai.arguments[j]);
 
-					int darg_idx = j - (ai.arguments.size() - ai.default_arguments.size());
+					int64_t darg_idx = j - (ai.arguments.size() - ai.default_arguments.size());
 					if (darg_idx >= 0) {
 						ad.default_value = DocData::get_default_value_string(ai.default_arguments[darg_idx]);
 					}

+ 9 - 8
editor/property_selector.cpp

@@ -269,20 +269,21 @@ void PropertySelector::_update_search() {
 
 			desc += vformat(" %s(", mi.name);
 
-			for (List<PropertyInfo>::Iterator arg_itr = mi.arguments.begin(); arg_itr != mi.arguments.end(); ++arg_itr) {
-				if (arg_itr != mi.arguments.begin()) {
+			for (int64_t i = 0; i < mi.arguments.size(); ++i) {
+				PropertyInfo &arg = mi.arguments.write[i];
+				if (i > 0) {
 					desc += ", ";
 				}
 
-				desc += arg_itr->name;
+				desc += arg.name;
 
-				if (arg_itr->type == Variant::NIL) {
+				if (arg.type == Variant::NIL) {
 					desc += ": Variant";
-				} else if (arg_itr->name.contains_char(':')) {
-					desc += vformat(": %s", arg_itr->name.get_slicec(':', 1));
-					arg_itr->name = arg_itr->name.get_slicec(':', 0);
+				} else if (arg.name.contains_char(':')) {
+					desc += vformat(": %s", arg.name.get_slicec(':', 1));
+					arg.name = arg.name.get_slicec(':', 0);
 				} else {
-					desc += vformat(": %s", Variant::get_type_name(arg_itr->type));
+					desc += vformat(": %s", Variant::get_type_name(arg.type));
 				}
 			}
 

+ 16 - 21
modules/gdscript/gdscript_analyzer.cpp

@@ -1640,13 +1640,12 @@ void GDScriptAnalyzer::resolve_annotation(GDScriptParser::AnnotationNode *p_anno
 
 	const MethodInfo &annotation_info = parser->valid_annotations[p_annotation->name].info;
 
-	const List<PropertyInfo>::Element *E = annotation_info.arguments.front();
-	for (int i = 0; i < p_annotation->arguments.size(); i++) {
+	for (int64_t i = 0, j = 0; i < p_annotation->arguments.size(); i++) {
 		GDScriptParser::ExpressionNode *argument = p_annotation->arguments[i];
-		const PropertyInfo &argument_info = E->get();
+		const PropertyInfo &argument_info = annotation_info.arguments[j];
 
-		if (E->next() != nullptr) {
-			E = E->next();
+		if (j + 1 < annotation_info.arguments.size()) {
+			++j;
 		}
 
 		reduce_expression(argument);
@@ -3323,28 +3322,24 @@ void GDScriptAnalyzer::reduce_call(GDScriptParser::CallNode *p_call, bool p_is_a
 
 					bool types_match = true;
 
-					{
-						List<PropertyInfo>::ConstIterator arg_itr = info.arguments.begin();
-						for (int i = 0; i < p_call->arguments.size(); ++arg_itr, ++i) {
-							GDScriptParser::DataType par_type = type_from_property(*arg_itr, true);
-							GDScriptParser::DataType arg_type = p_call->arguments[i]->get_datatype();
-							if (!is_type_compatible(par_type, arg_type, true)) {
-								types_match = false;
-								break;
+					for (int64_t i = 0; i < p_call->arguments.size(); ++i) {
+						GDScriptParser::DataType par_type = type_from_property(info.arguments[i], true);
+						GDScriptParser::DataType arg_type = p_call->arguments[i]->get_datatype();
+						if (!is_type_compatible(par_type, arg_type, true)) {
+							types_match = false;
+							break;
 #ifdef DEBUG_ENABLED
-							} else {
-								if (par_type.builtin_type == Variant::INT && arg_type.builtin_type == Variant::FLOAT && builtin_type != Variant::INT) {
-									parser->push_warning(p_call, GDScriptWarning::NARROWING_CONVERSION, function_name);
-								}
-#endif
+						} else {
+							if (par_type.builtin_type == Variant::INT && arg_type.builtin_type == Variant::FLOAT && builtin_type != Variant::INT) {
+								parser->push_warning(p_call, GDScriptWarning::NARROWING_CONVERSION, function_name);
 							}
+#endif
 						}
 					}
 
 					if (types_match) {
-						List<PropertyInfo>::ConstIterator arg_itr = info.arguments.begin();
-						for (int i = 0; i < p_call->arguments.size(); ++arg_itr, ++i) {
-							GDScriptParser::DataType par_type = type_from_property(*arg_itr, true);
+						for (int64_t i = 0; i < p_call->arguments.size(); ++i) {
+							GDScriptParser::DataType par_type = type_from_property(info.arguments[i], true);
 							if (p_call->arguments[i]->is_constant) {
 								update_const_expression_builtin_type(p_call->arguments[i], par_type, "pass");
 							}

+ 2 - 3
modules/gdscript/gdscript_compiler.cpp

@@ -243,9 +243,8 @@ static bool _can_use_validate_call(const MethodBind *p_method, const Vector<GDSc
 	}
 	MethodInfo info;
 	ClassDB::get_method_info(p_method->get_instance_class(), p_method->get_name(), &info);
-	int i = 0;
-	for (List<PropertyInfo>::ConstIterator itr = info.arguments.begin(); itr != info.arguments.end(); ++itr, ++i) {
-		if (!_is_exact_type(*itr, p_arguments[i].type)) {
+	for (int64_t i = 0; i < info.arguments.size(); ++i) {
+		if (!_is_exact_type(info.arguments[i], p_arguments[i].type)) {
 			return false;
 		}
 	}

+ 7 - 7
modules/gdscript/gdscript_editor.cpp

@@ -2839,9 +2839,9 @@ static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, c
 								// Handle user preference.
 								if (opt.is_quoted()) {
 									opt = opt.unquote().quote(quote_style);
-									if (use_string_names && info.arguments.get(p_argidx).type == Variant::STRING_NAME) {
+									if (use_string_names && info.arguments[p_argidx].type == Variant::STRING_NAME) {
 										opt = "&" + opt;
-									} else if (use_node_paths && info.arguments.get(p_argidx).type == Variant::NODE_PATH) {
+									} else if (use_node_paths && info.arguments[p_argidx].type == Variant::NODE_PATH) {
 										opt = "^" + opt;
 									}
 								}
@@ -2852,7 +2852,7 @@ static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, c
 					}
 
 					if (p_argidx < method_args) {
-						const PropertyInfo &arg_info = info.arguments.get(p_argidx);
+						const PropertyInfo &arg_info = info.arguments[p_argidx];
 						if (arg_info.usage & (PROPERTY_USAGE_CLASS_IS_ENUM | PROPERTY_USAGE_CLASS_IS_BITFIELD)) {
 							_find_enumeration_candidates(p_context, arg_info.class_name, r_result);
 						}
@@ -3495,17 +3495,17 @@ static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, c
 				}
 				method_hint += "(";
 
-				for (List<PropertyInfo>::ConstIterator arg_itr = mi.arguments.begin(); arg_itr != mi.arguments.end(); ++arg_itr) {
-					if (arg_itr != mi.arguments.begin()) {
+				for (int64_t i = 0; i < mi.arguments.size(); ++i) {
+					if (i > 0) {
 						method_hint += ", ";
 					}
-					String arg = arg_itr->name;
+					String arg = mi.arguments[i].name;
 					if (arg.contains_char(':')) {
 						arg = arg.substr(0, arg.find_char(':'));
 					}
 					method_hint += arg;
 					if (use_type_hint) {
-						method_hint += ": " + _get_visual_datatype(*arg_itr, true, class_name);
+						method_hint += ": " + _get_visual_datatype(mi.arguments[i], true, class_name);
 					}
 				}
 				method_hint += ")";

+ 2 - 2
modules/gdscript/gdscript_utility_functions.cpp

@@ -624,8 +624,8 @@ StringName GDScriptUtilityFunctions::get_function_return_class(const StringName
 Variant::Type GDScriptUtilityFunctions::get_function_argument_type(const StringName &p_function, int p_arg) {
 	GDScriptUtilityFunctionInfo *info = utility_function_table.lookup_ptr(p_function);
 	ERR_FAIL_NULL_V(info, Variant::NIL);
-	ERR_FAIL_COND_V(p_arg >= info->info.arguments.size(), Variant::NIL);
-	return info->info.arguments.get(p_arg).type;
+	ERR_FAIL_INDEX_V(p_arg, info->info.arguments.size(), Variant::NIL);
+	return info->info.arguments[p_arg].type;
 }
 
 int GDScriptUtilityFunctions::get_function_argument_count(const StringName &p_function) {

+ 4 - 6
modules/gdscript/tests/gdscript_test_runner_suite.h

@@ -80,9 +80,8 @@ TEST_CASE("[Modules][GDScript] Validate built-in API") {
 
 	SUBCASE("[Modules][GDScript] Validate built-in methods") {
 		for (const MethodInfo &mi : builtin_methods) {
-			int i = 0;
-			for (List<PropertyInfo>::ConstIterator itr = mi.arguments.begin(); itr != mi.arguments.end(); ++itr, ++i) {
-				TEST_COND((itr->name.is_empty() || itr->name.begins_with("_unnamed_arg")),
+			for (int64_t i = 0; i < mi.arguments.size(); ++i) {
+				TEST_COND((mi.arguments[i].name.is_empty() || mi.arguments[i].name.begins_with("_unnamed_arg")),
 						vformat("Unnamed argument in position %d of built-in method '%s'.", i, mi.name));
 			}
 		}
@@ -94,9 +93,8 @@ TEST_CASE("[Modules][GDScript] Validate built-in API") {
 
 	SUBCASE("[Modules][GDScript] Validate built-in annotations") {
 		for (const MethodInfo &ai : builtin_annotations) {
-			int i = 0;
-			for (List<PropertyInfo>::ConstIterator itr = ai.arguments.begin(); itr != ai.arguments.end(); ++itr, ++i) {
-				TEST_COND((itr->name.is_empty() || itr->name.begins_with("_unnamed_arg")),
+			for (int64_t i = 0; i < ai.arguments.size(); ++i) {
+				TEST_COND((ai.arguments[i].name.is_empty() || ai.arguments[i].name.begins_with("_unnamed_arg")),
 						vformat("Unnamed argument in position %d of built-in annotation '%s'.", i, ai.name));
 			}
 		}

+ 4 - 6
modules/mono/editor/bindings_generator.cpp

@@ -4116,9 +4116,8 @@ bool BindingsGenerator::_populate_object_type_interfaces() {
 				imethod.return_type.cname = _get_type_name_from_meta(return_info.type, m ? m->get_argument_meta(-1) : (GodotTypeInfo::Metadata)method_info.return_val_metadata);
 			}
 
-			int idx = 0;
-			for (List<PropertyInfo>::ConstIterator itr = method_info.arguments.begin(); itr != method_info.arguments.end(); ++itr, ++idx) {
-				const PropertyInfo &arginfo = *itr;
+			for (int64_t idx = 0; idx < method_info.arguments.size(); ++idx) {
+				const PropertyInfo &arginfo = method_info.arguments[idx];
 
 				String orig_arg_name = arginfo.name;
 
@@ -4248,9 +4247,8 @@ bool BindingsGenerator::_populate_object_type_interfaces() {
 			isignal.name = method_info.name;
 			isignal.cname = method_info.name;
 
-			int idx = 0;
-			for (List<PropertyInfo>::ConstIterator itr = method_info.arguments.begin(); itr != method_info.arguments.end(); ++itr, ++idx) {
-				const PropertyInfo &arginfo = *itr;
+			for (int64_t idx = 0; idx < method_info.arguments.size(); ++idx) {
+				const PropertyInfo &arginfo = method_info.arguments[idx];
 
 				String orig_arg_name = arginfo.name;
 

+ 6 - 1
scene/main/node.cpp

@@ -3747,8 +3747,13 @@ void Node::_bind_methods() {
 
 		mi.name = "rpc";
 		ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "rpc", &Node::_rpc_bind, mi);
+	}
 
-		mi.arguments.push_front(PropertyInfo(Variant::INT, "peer_id"));
+	{
+		MethodInfo mi;
+
+		mi.arguments.push_back(PropertyInfo(Variant::INT, "peer_id"));
+		mi.arguments.push_back(PropertyInfo(Variant::STRING_NAME, "method"));
 
 		mi.name = "rpc_id";
 		ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "rpc_id", &Node::_rpc_id_bind, mi);

+ 4 - 6
tests/core/object/test_class_db.h

@@ -660,9 +660,8 @@ void add_exposed_classes(Context &r_context) {
 				method.return_type.name = Variant::get_type_name(return_info.type);
 			}
 
-			int i = 0;
-			for (List<PropertyInfo>::ConstIterator itr = method_info.arguments.begin(); itr != method_info.arguments.end(); ++itr, ++i) {
-				const PropertyInfo &arg_info = *itr;
+			for (int64_t i = 0; i < method_info.arguments.size(); ++i) {
+				const PropertyInfo &arg_info = method_info.arguments[i];
 
 				String orig_arg_name = arg_info.name;
 
@@ -734,9 +733,8 @@ void add_exposed_classes(Context &r_context) {
 			TEST_FAIL_COND(!String(signal.name).is_valid_ascii_identifier(),
 					"Signal name is not a valid identifier: '", exposed_class.name, ".", signal.name, "'.");
 
-			int i = 0;
-			for (List<PropertyInfo>::ConstIterator itr = method_info.arguments.begin(); itr != method_info.arguments.end(); ++itr, ++i) {
-				const PropertyInfo &arg_info = *itr;
+			for (int64_t i = 0; i < method_info.arguments.size(); ++i) {
+				const PropertyInfo &arg_info = method_info.arguments[i];
 
 				String orig_arg_name = arg_info.name;