Browse Source

String: Add contains().

Anilforextra 3 years ago
parent
commit
adbe948bda
57 changed files with 142 additions and 119 deletions
  1. 1 1
      core/debugger/remote_debugger_peer.cpp
  2. 1 1
      core/io/dir_access.cpp
  3. 1 1
      core/io/file_access.cpp
  4. 1 1
      core/io/file_access_pack.cpp
  5. 1 1
      core/io/resource.h
  6. 2 2
      core/io/resource_format_binary.cpp
  7. 1 1
      core/io/translation_loader_po.cpp
  8. 1 1
      core/object/class_db.cpp
  9. 2 0
      core/string/ustring.h
  10. 1 0
      core/variant/variant_call.cpp
  11. 1 1
      core/variant/variant_parser.cpp
  12. 7 0
      doc/classes/String.xml
  13. 2 2
      editor/array_property_edit.cpp
  14. 1 1
      editor/connections_dialog.cpp
  15. 1 1
      editor/debugger/editor_debugger_inspector.cpp
  16. 1 1
      editor/dependency_editor.cpp
  17. 1 1
      editor/editor_feature_profile.cpp
  18. 9 9
      editor/editor_help.cpp
  19. 4 4
      editor/editor_inspector.cpp
  20. 3 3
      editor/editor_properties.cpp
  21. 2 2
      editor/editor_sectioned_inspector.cpp
  22. 5 5
      editor/filesystem_dock.cpp
  23. 4 4
      editor/import/collada.cpp
  24. 1 1
      editor/plugins/animation_blend_tree_editor_plugin.cpp
  25. 2 2
      editor/plugins/animation_player_editor_plugin.cpp
  26. 1 1
      editor/plugins/animation_state_machine_editor.cpp
  27. 1 1
      editor/plugins/resource_preloader_editor_plugin.cpp
  28. 3 3
      editor/plugins/script_editor_plugin.cpp
  29. 1 1
      editor/plugins/script_text_editor.cpp
  30. 1 1
      editor/project_manager.cpp
  31. 1 1
      editor/project_settings_editor.cpp
  32. 1 1
      editor/property_editor.cpp
  33. 2 2
      editor/property_selector.cpp
  34. 2 2
      editor/script_create_dialog.cpp
  35. 1 1
      editor/shader_create_dialog.cpp
  36. 5 5
      main/main.cpp
  37. 1 1
      modules/fbx/editor_scene_importer_fbx.cpp
  38. 4 4
      modules/gdnative/nativescript/api_generator.cpp
  39. 1 1
      modules/gdscript/editor/gdscript_highlighter.cpp
  40. 1 1
      modules/gdscript/gdscript.cpp
  41. 7 7
      modules/gdscript/gdscript_editor.cpp
  42. 2 2
      modules/gdscript/language_server/gdscript_workspace.cpp
  43. 1 1
      modules/gdscript/language_server/lsp.hpp
  44. 18 18
      modules/gltf/gltf_document.cpp
  45. 1 1
      modules/visual_script/editor/visual_script_editor.cpp
  46. 1 1
      scene/3d/skeleton_3d.cpp
  47. 1 1
      scene/animation/animation_blend_tree.cpp
  48. 3 3
      scene/animation/animation_node_state_machine.cpp
  49. 2 2
      scene/animation/animation_player.cpp
  50. 2 2
      scene/animation/animation_tree.cpp
  51. 1 1
      scene/gui/code_edit.cpp
  52. 2 2
      scene/resources/resource_format_text.cpp
  53. 2 2
      scene/resources/theme.cpp
  54. 1 1
      scene/resources/visual_shader.cpp
  55. 2 2
      servers/rendering/rendering_device_binds.cpp
  56. 1 1
      servers/rendering/shader_compiler.cpp
  57. 13 0
      tests/core/string/test_string.h

+ 1 - 1
core/debugger/remote_debugger_peer.cpp

@@ -226,7 +226,7 @@ RemoteDebuggerPeer *RemoteDebuggerPeerTCP::create(const String &p_uri) {
 	String debug_host = p_uri.replace("tcp://", "");
 	uint16_t debug_port = 6007;
 
-	if (debug_host.find(":") != -1) {
+	if (debug_host.contains(":")) {
 		int sep_pos = debug_host.rfind(":");
 		debug_port = debug_host.substr(sep_pos + 1).to_int();
 		debug_host = debug_host.substr(0, sep_pos);

+ 1 - 1
core/io/dir_access.cpp

@@ -159,7 +159,7 @@ Error DirAccess::make_dir_recursive(String p_dir) {
 		base = full_dir.substr(0, pos + 1);
 	} else if (full_dir.begins_with("/")) {
 		base = "/";
-	} else if (full_dir.find(":/") != -1) {
+	} else if (full_dir.contains(":/")) {
 		base = full_dir.substr(0, full_dir.find(":/") + 2);
 	} else {
 		ERR_FAIL_V(ERR_INVALID_PARAMETER);

+ 1 - 1
core/io/file_access.cpp

@@ -538,7 +538,7 @@ void FileAccess::store_csv_line(const Vector<String> &p_values, const String &p_
 	for (int i = 0; i < size; ++i) {
 		String value = p_values[i];
 
-		if (value.find("\"") != -1 || value.find(p_delim) != -1 || value.find("\n") != -1) {
+		if (value.contains("\"") || value.contains(p_delim) || value.contains("\n")) {
 			value = "\"" + value.replace("\"", "\"\"") + "\"";
 		}
 		if (i < size - 1) {

+ 1 - 1
core/io/file_access_pack.cpp

@@ -70,7 +70,7 @@ void PackedData::add_path(const String &p_pkg_path, const String &p_path, uint64
 		String p = p_path.replace_first("res://", "");
 		PackedDir *cd = root;
 
-		if (p.find("/") != -1) { //in a subdir
+		if (p.contains("/")) { //in a subdir
 
 			Vector<String> ds = p.get_base_dir().split("/");
 

+ 1 - 1
core/io/resource.h

@@ -105,7 +105,7 @@ public:
 
 	virtual void set_path(const String &p_path, bool p_take_over = false);
 	String get_path() const;
-	_FORCE_INLINE_ bool is_built_in() const { return path_cache.is_empty() || path_cache.find("::") != -1 || path_cache.begins_with("local://"); }
+	_FORCE_INLINE_ bool is_built_in() const { return path_cache.is_empty() || path_cache.contains("::") || path_cache.begins_with("local://"); }
 
 	static String generate_scene_unique_id();
 	void set_scene_unique_id(const String &p_id);

+ 2 - 2
core/io/resource_format_binary.cpp

@@ -335,7 +335,7 @@ Error ResourceLoaderBinary::parse_variant(Variant &r_v) {
 					String exttype = get_unicode_string();
 					String path = get_unicode_string();
 
-					if (path.find("://") == -1 && path.is_relative_path()) {
+					if (!path.contains("://") && path.is_relative_path()) {
 						// path is relative to file being loaded, so convert to a resource path
 						path = ProjectSettings::get_singleton()->localize_path(res_path.get_base_dir().plus_file(path));
 					}
@@ -626,7 +626,7 @@ Error ResourceLoaderBinary::load() {
 			path = remaps[path];
 		}
 
-		if (path.find("://") == -1 && path.is_relative_path()) {
+		if (!path.contains("://") && path.is_relative_path()) {
 			// path is relative to file being loaded, so convert to a resource path
 			path = ProjectSettings::get_singleton()->localize_path(path.get_base_dir().plus_file(external_resources[i].path));
 		}

+ 1 - 1
core/io/translation_loader_po.cpp

@@ -179,7 +179,7 @@ RES TranslationLoaderPO::load_translation(FileAccess *f, Error *r_error) {
 		}
 
 		if (l.is_empty() || l.begins_with("#")) {
-			if (l.find("fuzzy") != -1) {
+			if (l.contains("fuzzy")) {
 				skip_next = true;
 			}
 			line++;

+ 1 - 1
core/object/class_db.cpp

@@ -732,7 +732,7 @@ void ClassDB::bind_integer_constant(const StringName &p_class, const StringName
 
 	String enum_name = p_enum;
 	if (!enum_name.is_empty()) {
-		if (enum_name.find(".") != -1) {
+		if (enum_name.contains(".")) {
 			enum_name = enum_name.get_slicec('.', 1);
 		}
 

+ 2 - 0
core/string/ustring.h

@@ -394,6 +394,8 @@ public:
 	Vector<uint8_t> sha256_buffer() const;
 
 	_FORCE_INLINE_ bool is_empty() const { return length() == 0; }
+	_FORCE_INLINE_ bool contains(const char *p_str) const { return find(p_str) != -1; }
+	_FORCE_INLINE_ bool contains(const String &p_str) const { return find(p_str) != -1; }
 
 	// path functions
 	bool is_absolute_path() const;

+ 1 - 0
core/variant/variant_call.cpp

@@ -1421,6 +1421,7 @@ static void _register_variant_builtin_methods() {
 	bind_method(String, sha1_buffer, sarray(), varray());
 	bind_method(String, sha256_buffer, sarray(), varray());
 	bind_method(String, is_empty, sarray(), varray());
+	bind_methodv(String, contains, static_cast<bool (String::*)(const String &) const>(&String::contains), sarray("what"), varray());
 
 	bind_method(String, is_absolute_path, sarray(), varray());
 	bind_method(String, is_relative_path, sarray(), varray());

+ 1 - 1
core/variant/variant_parser.cpp

@@ -1495,7 +1495,7 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str
 		case Variant::FLOAT: {
 			String s = rtos_fix(p_variant.operator double());
 			if (s != "inf" && s != "inf_neg" && s != "nan") {
-				if (s.find(".") == -1 && s.find("e") == -1) {
+				if (!s.contains(".") && !s.contains("e")) {
 					s += ".0";
 				}
 			}

+ 7 - 0
doc/classes/String.xml

@@ -103,6 +103,13 @@
 			<description>
 			</description>
 		</method>
+		<method name="contains" qualifiers="const">
+			<return type="bool" />
+			<argument index="0" name="what" type="String" />
+			<description>
+				Returns [code]true[/code] if the string contains the given string.
+			</description>
+		</method>
 		<method name="count" qualifiers="const">
 			<return type="int" />
 			<argument index="0" name="what" type="String" />

+ 2 - 2
editor/array_property_edit.cpp

@@ -121,7 +121,7 @@ bool ArrayPropertyEdit::_set(const StringName &p_name, const Variant &p_value) {
 		}
 
 	} else if (pn.begins_with("indices")) {
-		if (pn.find("_") != -1) {
+		if (pn.contains("_")) {
 			//type
 			int idx = pn.get_slicec('/', 1).get_slicec('_', 0).to_int();
 
@@ -178,7 +178,7 @@ bool ArrayPropertyEdit::_get(const StringName &p_name, Variant &r_ret) const {
 			return true;
 		}
 	} else if (pn.begins_with("indices")) {
-		if (pn.find("_") != -1) {
+		if (pn.contains("_")) {
 			//type
 			int idx = pn.get_slicec('/', 1).get_slicec('_', 0).to_int();
 			bool valid;

+ 1 - 1
editor/connections_dialog.cpp

@@ -310,7 +310,7 @@ void ConnectDialog::set_dst_node(Node *p_node) {
 
 StringName ConnectDialog::get_dst_method_name() const {
 	String txt = dst_method->get_text();
-	if (txt.find("(") != -1) {
+	if (txt.contains("(")) {
 		txt = txt.left(txt.find("(")).strip_edges();
 	}
 	return txt;

+ 1 - 1
editor/debugger/editor_debugger_inspector.cpp

@@ -155,7 +155,7 @@ ObjectID EditorDebuggerInspector::add_object(const Array &p_arr) {
 		if (pinfo.type == Variant::OBJECT) {
 			if (var.get_type() == Variant::STRING) {
 				String path = var;
-				if (path.find("::") != -1) {
+				if (path.contains("::")) {
 					// built-in resource
 					String base_path = path.get_slice("::", 0);
 					RES dependency = ResourceLoader::load(base_path);

+ 1 - 1
editor/dependency_editor.cpp

@@ -171,7 +171,7 @@ void DependencyEditor::_update_list() {
 		String path;
 		String type;
 
-		if (n.find("::") != -1) {
+		if (n.contains("::")) {
 			path = n.get_slice("::", 0);
 			type = n.get_slice("::", 1);
 		} else {

+ 1 - 1
editor/editor_feature_profile.cpp

@@ -462,7 +462,7 @@ void EditorFeatureProfileManager::_erase_selected_profile() {
 
 void EditorFeatureProfileManager::_create_new_profile() {
 	String name = new_profile_name->get_text().strip_edges();
-	if (!name.is_valid_filename() || name.find(".") != -1) {
+	if (!name.is_valid_filename() || name.contains(".")) {
 		EditorNode::get_singleton()->show_warning(TTR("Profile must be a valid filename and must not contain '.'"));
 		return;
 	}

+ 9 - 9
editor/editor_help.cpp

@@ -81,7 +81,7 @@ void EditorHelp::_class_desc_select(const String &p_select) {
 	if (p_select.begins_with("$")) { //enum
 		String select = p_select.substr(1, p_select.length());
 		String class_name;
-		if (select.find(".") != -1) {
+		if (select.contains(".")) {
 			class_name = select.get_slice(".", 0);
 			select = select.get_slice(".", 1);
 		} else {
@@ -123,7 +123,7 @@ void EditorHelp::_class_desc_select(const String &p_select) {
 			return;
 		}
 
-		if (link.find(".") != -1) {
+		if (link.contains(".")) {
 			emit_signal(SNAME("go_to_help"), topic + ":" + link.get_slice(".", 0) + ":" + link.get_slice(".", 1));
 		} else {
 			if (table->has(link)) {
@@ -185,7 +185,7 @@ void EditorHelp::_add_type(const String &p_type, const String &p_enum) {
 	if (t.is_empty()) {
 		t = "void";
 	}
-	bool can_ref = (t != "void" && t.find("*") == -1) || !p_enum.is_empty();
+	bool can_ref = (t != "void" && !t.contains("*")) || !p_enum.is_empty();
 
 	if (!p_enum.is_empty()) {
 		if (p_enum.get_slice_count(".") > 1) {
@@ -240,7 +240,7 @@ String EditorHelp::_fix_constant(const String &p_constant) const {
 void EditorHelp::_add_method(const DocData::MethodDoc &p_method, bool p_overview) {
 	method_line[p_method.name] = class_desc->get_line_count() - 2; //gets overridden if description
 
-	const bool is_vararg = p_method.qualifiers.find("vararg") != -1;
+	const bool is_vararg = p_method.qualifiers.contains("vararg");
 
 	if (p_overview) {
 		class_desc->push_cell();
@@ -364,7 +364,7 @@ void EditorHelp::_update_method_list(const Vector<DocData::MethodDoc> p_methods,
 
 		for (int i = 0; i < p_methods.size(); i++) {
 			const String &q = p_methods[i].qualifiers;
-			if ((pass == 0 && q.find("virtual") != -1) || (pass == 1 && q.find("virtual") == -1)) {
+			if ((pass == 0 && q.contains("virtual")) || (pass == 1 && !q.contains("virtual"))) {
 				m.push_back(p_methods[i]);
 			}
 		}
@@ -429,7 +429,7 @@ void EditorHelp::_update_method_descriptions(const DocData::ClassDoc p_classdoc,
 
 		for (int i = 0; i < p_methods.size(); i++) {
 			const String &q = p_methods[i].qualifiers;
-			if ((pass == 0 && q.find("virtual") != -1) || (pass == 1 && q.find("virtual") == -1)) {
+			if ((pass == 0 && q.contains("virtual")) || (pass == 1 && !q.contains("virtual"))) {
 				methods_filtered.push_back(p_methods[i]);
 			}
 		}
@@ -820,7 +820,7 @@ void EditorHelp::_update_doc() {
 			}
 		}
 		// Ignore undocumented non virtual private.
-		if (cd.methods[i].name.begins_with("_") && cd.methods[i].description.is_empty() && cd.methods[i].qualifiers.find("virtual") == -1) {
+		if (cd.methods[i].name.begins_with("_") && cd.methods[i].description.is_empty() && !cd.methods[i].qualifiers.contains("virtual")) {
 			continue;
 		}
 		methods.push_back(cd.methods[i]);
@@ -1921,7 +1921,7 @@ void EditorHelpBit::_meta_clicked(String p_select) {
 
 		String select = p_select.substr(1, p_select.length());
 		String class_name;
-		if (select.find(".") != -1) {
+		if (select.contains(".")) {
 			class_name = select.get_slice(".", 0);
 		} else {
 			class_name = "@Global";
@@ -1934,7 +1934,7 @@ void EditorHelpBit::_meta_clicked(String p_select) {
 	} else if (p_select.begins_with("@")) {
 		String m = p_select.substr(1, p_select.length());
 
-		if (m.find(".") != -1) {
+		if (m.contains(".")) {
 			_go_to_help("class_method:" + m.get_slice(".", 0) + ":" + m.get_slice(".", 0)); //must go somewhere else
 		}
 	}

+ 4 - 4
editor/editor_inspector.cpp

@@ -251,7 +251,7 @@ void EditorProperty::_notification(int p_what) {
 		} else {
 			color = get_theme_color(is_read_only() ? SNAME("readonly_color") : SNAME("property_color"));
 		}
-		if (label.find(".") != -1) {
+		if (label.contains(".")) {
 			// FIXME: Move this to the project settings editor, as this is only used
 			// for project settings feature tag overrides.
 			color.a = 0.5;
@@ -2572,7 +2572,7 @@ void EditorInspector::update_tree() {
 		}
 
 		// Get the property label's string.
-		String property_label_string = (path.find("/") != -1) ? path.substr(path.rfind("/") + 1) : path;
+		String property_label_string = (path.contains("/")) ? path.substr(path.rfind("/") + 1) : path;
 		if (capitalize_paths) {
 			// Capitalize paths.
 			int dot = property_label_string.find(".");
@@ -2596,7 +2596,7 @@ void EditorInspector::update_tree() {
 
 		// Ignore properties that do not fit the filter.
 		if (use_filter && !filter.is_empty()) {
-			if (!filter.is_subsequence_ofn(path) && !filter.is_subsequence_ofn(property_label_string) && property_prefix.to_lower().find(filter.to_lower()) == -1) {
+			if (!filter.is_subsequence_ofn(path) && !filter.is_subsequence_ofn(property_label_string) && !property_prefix.to_lower().contains(filter.to_lower())) {
 				continue;
 			}
 		}
@@ -2670,7 +2670,7 @@ void EditorInspector::update_tree() {
 				array_element_prefix = p.class_name;
 				editor_inspector_array = memnew(EditorInspectorArray);
 
-				String array_label = (path.find("/") != -1) ? path.substr(path.rfind("/") + 1) : path;
+				String array_label = path.contains("/") ? path.substr(path.rfind("/") + 1) : path;
 				array_label = property_label_string.capitalize();
 				int page = per_array_page.has(array_element_prefix) ? per_array_page[array_element_prefix] : 0;
 				editor_inspector_array->setup_with_move_element_function(object, array_label, array_element_prefix, page, c, use_folding);

+ 3 - 3
editor/editor_properties.cpp

@@ -592,7 +592,7 @@ void EditorPropertyMember::_property_select() {
 	} else if (hint == MEMBER_PROPERTY_OF_VARIANT_TYPE) {
 		Variant::Type type = Variant::NIL;
 		String tname = hint_text;
-		if (tname.find(".") != -1) {
+		if (tname.contains(".")) {
 			tname = tname.get_slice(".", 0);
 		}
 		for (int i = 0; i < Variant::VARIANT_MAX; i++) {
@@ -809,7 +809,7 @@ void EditorPropertyLayersGrid::_rename_operation_confirm() {
 	if (new_name.length() == 0) {
 		EditorNode::get_singleton()->show_warning(TTR("No name provided."));
 		return;
-	} else if (new_name.find("/") != -1 || new_name.find("\\") != -1 || new_name.find(":") != -1) {
+	} else if (new_name.contains("/") || new_name.contains("\\") || new_name.contains(":")) {
 		EditorNode::get_singleton()->show_warning(TTR("Name contains invalid characters."));
 		return;
 	}
@@ -2883,7 +2883,7 @@ void EditorPropertyNodePath::update_property() {
 	Node *target_node = base_node->get_node(p);
 	ERR_FAIL_COND(!target_node);
 
-	if (String(target_node->get_name()).find("@") != -1) {
+	if (String(target_node->get_name()).contains("@")) {
 		assign->set_icon(Ref<Texture2D>());
 		assign->set_text(p);
 		return;

+ 2 - 2
editor/editor_sectioned_inspector.cpp

@@ -89,7 +89,7 @@ class SectionedInspectorFilter : public Object {
 
 			if (pi.name.begins_with(section + "/")) {
 				pi.name = pi.name.replace_first(section + "/", "");
-				if (!allow_sub && pi.name.find("/") != -1) {
+				if (!allow_sub && pi.name.contains("/")) {
 					continue;
 				}
 				p_list->push_back(pi);
@@ -227,7 +227,7 @@ void SectionedInspector::update_category_list() {
 			continue;
 		}
 
-		if (pi.name.find(":") != -1 || pi.name == "script" || pi.name == "resource_name" || pi.name == "resource_path" || pi.name == "resource_local_to_scene" || pi.name.begins_with("_global_script")) {
+		if (pi.name.contains(":") || pi.name == "script" || pi.name == "resource_name" || pi.name == "resource_path" || pi.name == "resource_local_to_scene" || pi.name.begins_with("_global_script")) {
 			continue;
 		}
 

+ 5 - 5
editor/filesystem_dock.cpp

@@ -629,7 +629,7 @@ void FileSystemDock::_search(EditorFileSystemDirectory *p_path, List<FileInfo> *
 	for (int i = 0; i < p_path->get_file_count(); i++) {
 		String file = p_path->get_file(i);
 
-		if (file.to_lower().find(searched_string) != -1) {
+		if (file.to_lower().contains(searched_string)) {
 			FileInfo fi;
 			fi.name = file;
 			fi.type = p_path->get_file_type(i);
@@ -1373,8 +1373,8 @@ void FileSystemDock::_make_dir_confirm() {
 	if (dir_name.length() == 0) {
 		EditorNode::get_singleton()->show_warning(TTR("No name provided."));
 		return;
-	} else if (dir_name.find("/") != -1 || dir_name.find("\\") != -1 || dir_name.find(":") != -1 || dir_name.find("*") != -1 ||
-			dir_name.find("|") != -1 || dir_name.find(">") != -1 || dir_name.ends_with(".") || dir_name.ends_with(" ")) {
+	} else if (dir_name.contains("/") || dir_name.contains("\\") || dir_name.contains(":") || dir_name.contains("*") ||
+			dir_name.contains("|") || dir_name.contains(">") || dir_name.ends_with(".") || dir_name.ends_with(" ")) {
 		EditorNode::get_singleton()->show_warning(TTR("Provided name contains invalid characters."));
 		return;
 	}
@@ -1478,7 +1478,7 @@ void FileSystemDock::_rename_operation_confirm() {
 	if (new_name.length() == 0) {
 		EditorNode::get_singleton()->show_warning(TTR("No name provided."));
 		return;
-	} else if (new_name.find("/") != -1 || new_name.find("\\") != -1 || new_name.find(":") != -1) {
+	} else if (new_name.contains("/") || new_name.contains("\\") || new_name.contains(":")) {
 		EditorNode::get_singleton()->show_warning(TTR("Name contains invalid characters."));
 		return;
 	} else if (to_rename.is_file && old_name.get_extension() != new_name.get_extension()) {
@@ -1540,7 +1540,7 @@ void FileSystemDock::_duplicate_operation_confirm() {
 	if (new_name.length() == 0) {
 		EditorNode::get_singleton()->show_warning(TTR("No name provided."));
 		return;
-	} else if (new_name.find("/") != -1 || new_name.find("\\") != -1 || new_name.find(":") != -1) {
+	} else if (new_name.contains("/") || new_name.contains("\\") || new_name.contains(":")) {
 		EditorNode::get_singleton()->show_warning(TTR("Name contains invalid characters."));
 		return;
 	}

+ 4 - 4
editor/import/collada.cpp

@@ -287,7 +287,7 @@ void Collada::_parse_image(XMLParser &parser) {
 	if (state.version < State::Version(1, 4, 0)) {
 		/* <1.4 */
 		String path = parser.get_attribute_value("source").strip_edges();
-		if (path.find("://") == -1 && path.is_relative_path()) {
+		if (!path.contains("://") && path.is_relative_path()) {
 			// path is relative to file being loaded, so convert to a resource path
 			image.path = ProjectSettings::get_singleton()->localize_path(state.local_path.get_base_dir().plus_file(path.uri_decode()));
 		}
@@ -300,7 +300,7 @@ void Collada::_parse_image(XMLParser &parser) {
 					parser.read();
 					String path = parser.get_node_data().strip_edges().uri_decode();
 
-					if (path.find("://") == -1 && path.is_relative_path()) {
+					if (!path.contains("://") && path.is_relative_path()) {
 						// path is relative to file being loaded, so convert to a resource path
 						path = ProjectSettings::get_singleton()->localize_path(state.local_path.get_base_dir().plus_file(path));
 
@@ -1832,10 +1832,10 @@ void Collada::_parse_animation(XMLParser &parser) {
 				}
 			}
 
-			if (target.find("/") != -1) { //transform component
+			if (target.contains("/")) { //transform component
 				track.target = target.get_slicec('/', 0);
 				track.param = target.get_slicec('/', 1);
-				if (track.param.find(".") != -1) {
+				if (track.param.contains(".")) {
 					track.component = track.param.get_slice(".", 1).to_upper();
 				}
 				track.param = track.param.get_slice(".", 0);

+ 1 - 1
editor/plugins/animation_blend_tree_editor_plugin.cpp

@@ -833,7 +833,7 @@ void AnimationNodeBlendTreeEditor::_node_renamed(const String &p_text, Ref<Anima
 
 	const String &new_name = p_text;
 
-	ERR_FAIL_COND(new_name.is_empty() || new_name.find(".") != -1 || new_name.find("/") != -1);
+	ERR_FAIL_COND(new_name.is_empty() || new_name.contains(".") || new_name.contains("/"));
 
 	if (new_name == prev_name) {
 		return; //nothing to do

+ 2 - 2
editor/plugins/animation_player_editor_plugin.cpp

@@ -485,7 +485,7 @@ void AnimationPlayerEditor::_animation_name_edited() {
 	player->stop();
 
 	String new_name = name->get_text();
-	if (new_name.is_empty() || new_name.find(":") != -1 || new_name.find("/") != -1) {
+	if (new_name.is_empty() || new_name.contains(":") || new_name.contains("/")) {
 		error_dialog->set_text(TTR("Invalid animation name!"));
 		error_dialog->popup_centered();
 		return;
@@ -746,7 +746,7 @@ void AnimationPlayerEditor::_load_animations(Vector<String> p_files) {
 			file = file.substr(file.rfind("\\") + 1, file.length());
 		}
 
-		if (file.find(".") != -1) {
+		if (file.contains(".")) {
 			file = file.substr(0, file.find("."));
 		}
 

+ 1 - 1
editor/plugins/animation_state_machine_editor.cpp

@@ -1059,7 +1059,7 @@ void AnimationNodeStateMachineEditor::_removed_from_graph() {
 void AnimationNodeStateMachineEditor::_name_edited(const String &p_text) {
 	const String &new_name = p_text;
 
-	ERR_FAIL_COND(new_name.is_empty() || new_name.find(".") != -1 || new_name.find("/") != -1);
+	ERR_FAIL_COND(new_name.is_empty() || new_name.contains(".") || new_name.contains("/"));
 
 	if (new_name == prev_name) {
 		return; // Nothing to do.

+ 1 - 1
editor/plugins/resource_preloader_editor_plugin.cpp

@@ -110,7 +110,7 @@ void ResourcePreloaderEditor::_item_edited() {
 			return;
 		}
 
-		if (new_name.is_empty() || new_name.find("\\") != -1 || new_name.find("/") != -1 || preloader->has_resource(new_name)) {
+		if (new_name.is_empty() || new_name.contains("\\") || new_name.contains("/") || preloader->has_resource(new_name)) {
 			s->set_text(0, old_name);
 			return;
 		}

+ 3 - 3
editor/plugins/script_editor_plugin.cpp

@@ -159,7 +159,7 @@ void EditorStandardSyntaxHighlighter::_update_cache() {
 				if (E.usage & PROPERTY_USAGE_CATEGORY || E.usage & PROPERTY_USAGE_GROUP || E.usage & PROPERTY_USAGE_SUBGROUP) {
 					continue;
 				}
-				if (name.find("/") != -1) {
+				if (name.contains("/")) {
 					continue;
 				}
 				highlighter->add_member_keyword_color(name, member_variable_color);
@@ -714,7 +714,7 @@ void ScriptEditor::_open_recent_script(int p_idx) {
 			return;
 		}
 		// if it's a path then it's most likely a deleted file not help
-	} else if (path.find("::") != -1) {
+	} else if (path.contains("::")) {
 		// built-in script
 		String res_path = path.get_slice("::", 0);
 		if (ResourceLoader::get_resource_type(res_path) == "PackedScene") {
@@ -2292,7 +2292,7 @@ bool ScriptEditor::edit(const RES &p_resource, int p_line, int p_col, bool p_gra
 
 				} else if (flags[i] == '\0' || (!inside_quotes && flags[i] == ' ')) {
 					String arg = flags.substr(from, num_chars);
-					if (arg.find("{file}") != -1) {
+					if (arg.contains("{file}")) {
 						has_file_flag = true;
 					}
 

+ 1 - 1
editor/plugins/script_text_editor.cpp

@@ -1295,7 +1295,7 @@ void ScriptTextEditor::_edit_option_toggle_inline_comment() {
 	script->get_language()->get_comment_delimiters(&comment_delimiters);
 
 	for (const String &script_delimiter : comment_delimiters) {
-		if (script_delimiter.find(" ") == -1) {
+		if (!script_delimiter.contains(" ")) {
 			delimiter = script_delimiter;
 			break;
 		}

+ 1 - 1
editor/project_manager.cpp

@@ -1475,7 +1475,7 @@ void ProjectList::sort_projects() {
 		bool visible = true;
 		if (!_search_term.is_empty()) {
 			String search_path;
-			if (_search_term.find("/") != -1) {
+			if (_search_term.contains("/")) {
 				// Search path will match the whole path
 				search_path = item.path;
 			} else {

+ 1 - 1
editor/project_settings_editor.cpp

@@ -202,7 +202,7 @@ void ProjectSettingsEditor::_select_type(Variant::Type p_type) {
 
 String ProjectSettingsEditor::_get_setting_name() const {
 	String name = property_box->get_text().strip_edges();
-	if (name.find("/") == -1) {
+	if (!name.contains("/")) {
 		name = "global/" + name;
 	}
 	return name;

+ 1 - 1
editor/property_editor.cpp

@@ -623,7 +623,7 @@ bool CustomPropertyEditor::edit(Object *p_owner, const String &p_name, Variant::
 				MAKE_PROPSELECT
 				Variant::Type type = Variant::NIL;
 				String tname = hint_text;
-				if (tname.find(".") != -1) {
+				if (tname.contains(".")) {
 					tname = tname.get_slice(".", 0);
 				}
 				for (int i = 0; i < Variant::VARIANT_MAX; i++) {

+ 2 - 2
editor/property_selector.cpp

@@ -276,7 +276,7 @@ void PropertySelector::_update_search() {
 			TreeItem *item = search_options->create_item(category ? category : root);
 
 			String desc;
-			if (mi.name.find(":") != -1) {
+			if (mi.name.contains(":")) {
 				desc = mi.name.get_slice(":", 1) + " ";
 				mi.name = mi.name.get_slice(":", 0);
 			} else if (mi.return_val.type != Variant::NIL) {
@@ -296,7 +296,7 @@ void PropertySelector::_update_search() {
 
 				if (mi.arguments[i].type == Variant::NIL) {
 					desc += ": Variant";
-				} else if (mi.arguments[i].name.find(":") != -1) {
+				} else if (mi.arguments[i].name.contains(":")) {
 					desc += vformat(": %s", mi.arguments[i].name.get_slice(":", 1));
 					mi.arguments[i].name = mi.arguments[i].name.get_slice(":", 0);
 				} else {

+ 2 - 2
editor/script_create_dialog.cpp

@@ -378,7 +378,7 @@ void ScriptCreateDialog::_language_changed(int l) {
 	String path = file_path->get_text();
 	String extension = "";
 	if (!path.is_empty()) {
-		if (path.find(".") != -1) {
+		if (path.contains(".")) {
 			extension = path.get_extension();
 		}
 
@@ -811,7 +811,7 @@ ScriptLanguage::ScriptTemplate ScriptCreateDialog::_parse_template(const ScriptL
 	List<String> comment_delimiters;
 	language->get_comment_delimiters(&comment_delimiters);
 	for (const String &script_delimiter : comment_delimiters) {
-		if (script_delimiter.find(" ") == -1) {
+		if (!script_delimiter.contains(" ")) {
 			meta_delimiter = script_delimiter;
 			break;
 		}

+ 1 - 1
editor/shader_create_dialog.cpp

@@ -221,7 +221,7 @@ void ShaderCreateDialog::_language_changed(int p_language) {
 	String extension = "";
 
 	if (!path.is_empty()) {
-		if (path.find(".") != -1) {
+		if (path.contains(".")) {
 			extension = path.get_extension();
 		}
 		if (extension.length() == 0) {

+ 5 - 5
main/main.cpp

@@ -827,7 +827,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
 			if (I->next()) {
 				String vm = I->next()->get();
 
-				if (vm.find("x") == -1) { // invalid parameter format
+				if (!vm.contains("x")) { // invalid parameter format
 
 					OS::get_singleton()->print("Invalid resolution '%s', it should be e.g. '1280x720'.\n",
 							vm.utf8().get_data());
@@ -858,7 +858,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
 			if (I->next()) {
 				String vm = I->next()->get();
 
-				if (vm.find(",") == -1) { // invalid parameter format
+				if (!vm.contains(",")) { // invalid parameter format
 
 					OS::get_singleton()->print("Invalid position '%s', it should be e.g. '80,128'.\n",
 							vm.utf8().get_data());
@@ -940,7 +940,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
 		} else if (I->get() == "--debug-server") {
 			if (I->next()) {
 				debug_server_uri = I->next()->get();
-				if (debug_server_uri.find("://") == -1) { // wrong address
+				if (!debug_server_uri.contains("://")) { // wrong address
 					OS::get_singleton()->print("Invalid debug server uri. It should be of the form <protocol>://<bind_address>:<port>.\n");
 					goto error;
 				}
@@ -1073,7 +1073,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
 		} else if (I->get() == "--remote-debug") {
 			if (I->next()) {
 				debug_uri = I->next()->get();
-				if (debug_uri.find("://") == -1) { // wrong address
+				if (!debug_uri.contains("://")) { // wrong address
 					OS::get_singleton()->print(
 							"Invalid debug host address, it should be of the form <protocol>://<host/IP>:<port>.\n");
 					goto error;
@@ -1130,7 +1130,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
 	if (!remotefs.is_empty()) {
 		file_access_network_client = memnew(FileAccessNetworkClient);
 		int port;
-		if (remotefs.find(":") != -1) {
+		if (remotefs.contains(":")) {
 			port = remotefs.get_slicec(':', 1).to_int();
 			remotefs = remotefs.get_slicec(':', 0);
 		} else {

+ 1 - 1
modules/fbx/editor_scene_importer_fbx.cpp

@@ -123,7 +123,7 @@ Node3D *EditorSceneFormatImporterFBX::import_scene(const String &p_path, uint32_
 		bool corrupt = false;
 
 		// safer to check this way as there can be different formatted headers
-		if (fbx_header_string.find("Kaydara FBX Binary", 0) != -1) {
+		if (fbx_header_string.contains("Kaydara FBX Binary")) {
 			is_binary = true;
 			print_verbose("[doc] is binary");
 

+ 4 - 4
modules/gdnative/nativescript/api_generator.cpp

@@ -288,7 +288,7 @@ List<ClassAPI> generate_c_api_classes() {
 					String type;
 					String name = argument.name;
 
-					if (argument.name.find(":") != -1) {
+					if (argument.name.contains(":")) {
 						type = argument.name.get_slice(":", 1);
 						name = argument.name.get_slice(":", 0);
 					} else {
@@ -324,7 +324,7 @@ List<ClassAPI> generate_c_api_classes() {
 				property_api.getter = ClassDB::get_property_getter(class_name, p->get().name);
 				property_api.setter = ClassDB::get_property_setter(class_name, p->get().name);
 
-				if (p->get().name.find(":") != -1) {
+				if (p->get().name.contains(":")) {
 					property_api.type = p->get().name.get_slice(":", 1);
 					property_api.name = p->get().name.get_slice(":", 0);
 				} else {
@@ -355,7 +355,7 @@ List<ClassAPI> generate_c_api_classes() {
 				//method name
 				method_api.method_name = method_info.name;
 				//method return type
-				if (method_api.method_name.find(":") != -1) {
+				if (method_api.method_name.contains(":")) {
 					method_api.return_type = method_api.method_name.get_slice(":", 1);
 					method_api.method_name = method_api.method_name.get_slice(":", 0);
 				} else {
@@ -388,7 +388,7 @@ List<ClassAPI> generate_c_api_classes() {
 
 					arg_name = arg_info.name;
 
-					if (arg_info.name.find(":") != -1) {
+					if (arg_info.name.contains(":")) {
 						arg_type = arg_info.name.get_slice(":", 1);
 						arg_name = arg_info.name.get_slice(":", 0);
 					} else if (arg_info.hint == PROPERTY_HINT_RESOURCE_TYPE) {

+ 1 - 1
modules/gdscript/editor/gdscript_highlighter.cpp

@@ -585,7 +585,7 @@ void GDScriptSyntaxHighlighter::_update_cache() {
 				if (E.usage & PROPERTY_USAGE_CATEGORY || E.usage & PROPERTY_USAGE_GROUP || E.usage & PROPERTY_USAGE_SUBGROUP) {
 					continue;
 				}
-				if (name.find("/") != -1) {
+				if (name.contains("/")) {
 					continue;
 				}
 				member_keywords[name] = member_variable_color;

+ 1 - 1
modules/gdscript/gdscript.cpp

@@ -827,7 +827,7 @@ Error GDScript::reload(bool p_keep_state) {
 		return OK;
 	}
 #else
-	if (source.find("_BASE_") != -1) {
+	if (source.contains("_BASE_")) {
 		return OK;
 	}
 #endif

+ 7 - 7
modules/gdscript/gdscript_editor.cpp

@@ -486,7 +486,7 @@ struct GDScriptCompletionIdentifier {
 static String _get_visual_datatype(const PropertyInfo &p_info, bool p_is_arg = true) {
 	if (p_info.usage & PROPERTY_USAGE_CLASS_IS_ENUM) {
 		String enum_name = p_info.class_name;
-		if (enum_name.find(".") == -1) {
+		if (!enum_name.contains(".")) {
 			return enum_name;
 		}
 		return enum_name.get_slice(".", 1);
@@ -955,7 +955,7 @@ static void _find_identifiers_in_base(const GDScriptCompletionIdentifier &p_base
 							if (E.usage & (PROPERTY_USAGE_GROUP | PROPERTY_USAGE_CATEGORY)) {
 								continue;
 							}
-							if (E.name.find("/") != -1) {
+							if (E.name.contains("/")) {
 								continue;
 							}
 							ScriptCodeCompletionOption option(E.name, ScriptCodeCompletionOption::KIND_MEMBER);
@@ -1000,7 +1000,7 @@ static void _find_identifiers_in_base(const GDScriptCompletionIdentifier &p_base
 					}
 
 					for (const PropertyInfo &E : members) {
-						if (String(E.name).find("/") == -1) {
+						if (!String(E.name).contains("/")) {
 							ScriptCodeCompletionOption option(E.name, ScriptCodeCompletionOption::KIND_MEMBER);
 							r_result.insert(option.display, option);
 						}
@@ -2182,7 +2182,7 @@ static bool _guess_method_return_type_from_base(GDScriptParser::CompletionContex
 }
 
 static void _find_enumeration_candidates(GDScriptParser::CompletionContext &p_context, const String &p_enum_hint, Map<String, ScriptCodeCompletionOption> &r_result) {
-	if (p_enum_hint.find(".") == -1) {
+	if (!p_enum_hint.contains(".")) {
 		// Global constant or in the current class.
 		StringName current_enum = p_enum_hint;
 		if (p_context.current_class && p_context.current_class->has_member(current_enum) && p_context.current_class->get_member(current_enum).type == GDScriptParser::ClassNode::Member::ENUM) {
@@ -2291,7 +2291,7 @@ static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, c
 					}
 				}
 
-				if (p_argidx == 0 && method_args > 0 && ClassDB::is_parent_class(class_name, "InputEvent") && p_method.operator String().find("action") != -1) {
+				if (p_argidx == 0 && method_args > 0 && ClassDB::is_parent_class(class_name, "InputEvent") && p_method.operator String().contains("action")) {
 					// Get input actions
 					List<PropertyInfo> props;
 					ProjectSettings::get_singleton()->get_property_list(&props);
@@ -2639,7 +2639,7 @@ static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, c
 			ClassDB::get_virtual_methods(class_name, &virtual_methods);
 			for (const MethodInfo &mi : virtual_methods) {
 				String method_hint = mi.name;
-				if (method_hint.find(":") != -1) {
+				if (method_hint.contains(":")) {
 					method_hint = method_hint.get_slice(":", 0);
 				}
 				method_hint += "(";
@@ -2650,7 +2650,7 @@ static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, c
 							method_hint += ", ";
 						}
 						String arg = mi.arguments[i].name;
-						if (arg.find(":") != -1) {
+						if (arg.contains(":")) {
 							arg = arg.substr(0, arg.find(":"));
 						}
 						method_hint += arg;

+ 2 - 2
modules/gdscript/language_server/gdscript_workspace.cpp

@@ -63,7 +63,7 @@ void GDScriptWorkspace::apply_new_signal(Object *obj, String function, PackedStr
 	String function_signature = "func " + function;
 	String source = script->get_source_code();
 
-	if (source.find(function_signature) != -1) {
+	if (source.contains(function_signature)) {
 		return;
 	}
 
@@ -380,7 +380,7 @@ Error GDScriptWorkspace::initialize() {
 
 				symbol.children.push_back(symbol_arg);
 			}
-			if (data.qualifiers.find("vararg") != -1) {
+			if (data.qualifiers.contains("vararg")) {
 				params += params.is_empty() ? "..." : ", ...";
 			}
 

+ 1 - 1
modules/gdscript/language_server/lsp.hpp

@@ -1940,7 +1940,7 @@ static String marked_documentation(const String &p_bbcode) {
 			line = "\t" + line.substr(code_block_indent, line.length());
 		}
 
-		if (in_code_block && line.find("[/codeblock]") != -1) {
+		if (in_code_block && line.contains("[/codeblock]")) {
 			line = "\n";
 			in_code_block = false;
 		}

+ 18 - 18
modules/gltf/gltf_document.cpp

@@ -6277,7 +6277,7 @@ GLTFAnimation::Track GLTFDocument::_convert_animation_track(Ref<GLTFState> state
 			p_track.rotation_track.values.write[key_i] = rotation;
 		}
 	} else if (track_type == Animation::TYPE_VALUE) {
-		if (path.find(":position") != -1) {
+		if (path.contains(":position")) {
 			p_track.position_track.times = times;
 			p_track.position_track.interpolation = gltf_interpolation;
 
@@ -6288,7 +6288,7 @@ GLTFAnimation::Track GLTFDocument::_convert_animation_track(Ref<GLTFState> state
 				Vector3 position = p_animation->track_get_key_value(p_track_i, key_i);
 				p_track.position_track.values.write[key_i] = position;
 			}
-		} else if (path.find(":rotation") != -1) {
+		} else if (path.contains(":rotation")) {
 			p_track.rotation_track.times = times;
 			p_track.rotation_track.interpolation = gltf_interpolation;
 
@@ -6299,7 +6299,7 @@ GLTFAnimation::Track GLTFDocument::_convert_animation_track(Ref<GLTFState> state
 				Vector3 rotation_radian = p_animation->track_get_key_value(p_track_i, key_i);
 				p_track.rotation_track.values.write[key_i] = Quaternion(rotation_radian);
 			}
-		} else if (path.find(":scale") != -1) {
+		} else if (path.contains(":scale")) {
 			p_track.scale_track.times = times;
 			p_track.scale_track.interpolation = gltf_interpolation;
 
@@ -6312,7 +6312,7 @@ GLTFAnimation::Track GLTFDocument::_convert_animation_track(Ref<GLTFState> state
 			}
 		}
 	} else if (track_type == Animation::TYPE_BEZIER) {
-		if (path.find("/scale") != -1) {
+		if (path.contains("/scale")) {
 			const int32_t keys = p_animation->track_get_key_time(p_track_i, key_count - 1) * BAKE_FPS;
 			if (!p_track.scale_track.times.size()) {
 				Vector<real_t> new_times;
@@ -6333,16 +6333,16 @@ GLTFAnimation::Track GLTFDocument::_convert_animation_track(Ref<GLTFState> state
 
 			for (int32_t key_i = 0; key_i < keys; key_i++) {
 				Vector3 bezier_track = p_track.scale_track.values[key_i];
-				if (path.find("/scale:x") != -1) {
+				if (path.contains("/scale:x")) {
 					bezier_track.x = p_animation->bezier_track_interpolate(p_track_i, key_i / BAKE_FPS);
-				} else if (path.find("/scale:y") != -1) {
+				} else if (path.contains("/scale:y")) {
 					bezier_track.y = p_animation->bezier_track_interpolate(p_track_i, key_i / BAKE_FPS);
-				} else if (path.find("/scale:z") != -1) {
+				} else if (path.contains("/scale:z")) {
 					bezier_track.z = p_animation->bezier_track_interpolate(p_track_i, key_i / BAKE_FPS);
 				}
 				p_track.scale_track.values.write[key_i] = bezier_track;
 			}
-		} else if (path.find("/position") != -1) {
+		} else if (path.contains("/position")) {
 			const int32_t keys = p_animation->track_get_key_time(p_track_i, key_count - 1) * BAKE_FPS;
 			if (!p_track.position_track.times.size()) {
 				Vector<real_t> new_times;
@@ -6359,11 +6359,11 @@ GLTFAnimation::Track GLTFDocument::_convert_animation_track(Ref<GLTFState> state
 
 			for (int32_t key_i = 0; key_i < keys; key_i++) {
 				Vector3 bezier_track = p_track.position_track.values[key_i];
-				if (path.find("/position:x") != -1) {
+				if (path.contains("/position:x")) {
 					bezier_track.x = p_animation->bezier_track_interpolate(p_track_i, key_i / BAKE_FPS);
-				} else if (path.find("/position:y") != -1) {
+				} else if (path.contains("/position:y")) {
 					bezier_track.y = p_animation->bezier_track_interpolate(p_track_i, key_i / BAKE_FPS);
-				} else if (path.find("/position:z") != -1) {
+				} else if (path.contains("/position:z")) {
 					bezier_track.z = p_animation->bezier_track_interpolate(p_track_i, key_i / BAKE_FPS);
 				}
 				p_track.position_track.values.write[key_i] = bezier_track;
@@ -6384,7 +6384,7 @@ void GLTFDocument::_convert_animation(Ref<GLTFState> state, AnimationPlayer *ap,
 			continue;
 		}
 		String orig_track_path = animation->track_get_path(track_i);
-		if (String(orig_track_path).find(":position") != -1) {
+		if (String(orig_track_path).contains(":position")) {
 			const Vector<String> node_suffix = String(orig_track_path).split(":position");
 			const NodePath path = node_suffix[0];
 			const Node *node = ap->get_parent()->get_node_or_null(path);
@@ -6400,7 +6400,7 @@ void GLTFDocument::_convert_animation(Ref<GLTFState> state, AnimationPlayer *ap,
 					gltf_animation->get_tracks().insert(node_index, track);
 				}
 			}
-		} else if (String(orig_track_path).find(":rotation_degrees") != -1) {
+		} else if (String(orig_track_path).contains(":rotation_degrees")) {
 			const Vector<String> node_suffix = String(orig_track_path).split(":rotation_degrees");
 			const NodePath path = node_suffix[0];
 			const Node *node = ap->get_parent()->get_node_or_null(path);
@@ -6416,7 +6416,7 @@ void GLTFDocument::_convert_animation(Ref<GLTFState> state, AnimationPlayer *ap,
 					gltf_animation->get_tracks().insert(node_index, track);
 				}
 			}
-		} else if (String(orig_track_path).find(":scale") != -1) {
+		} else if (String(orig_track_path).contains(":scale")) {
 			const Vector<String> node_suffix = String(orig_track_path).split(":scale");
 			const NodePath path = node_suffix[0];
 			const Node *node = ap->get_parent()->get_node_or_null(path);
@@ -6432,7 +6432,7 @@ void GLTFDocument::_convert_animation(Ref<GLTFState> state, AnimationPlayer *ap,
 					gltf_animation->get_tracks().insert(node_index, track);
 				}
 			}
-		} else if (String(orig_track_path).find(":transform") != -1) {
+		} else if (String(orig_track_path).contains(":transform")) {
 			const Vector<String> node_suffix = String(orig_track_path).split(":transform");
 			const NodePath path = node_suffix[0];
 			const Node *node = ap->get_parent()->get_node_or_null(path);
@@ -6443,7 +6443,7 @@ void GLTFDocument::_convert_animation(Ref<GLTFState> state, AnimationPlayer *ap,
 					gltf_animation->get_tracks().insert(transform_track_i.key, track);
 				}
 			}
-		} else if (String(orig_track_path).find(":blend_shapes/") != -1) {
+		} else if (String(orig_track_path).contains(":blend_shapes/")) {
 			const Vector<String> node_suffix = String(orig_track_path).split(":blend_shapes/");
 			const NodePath path = node_suffix[0];
 			const String suffix = node_suffix[1];
@@ -6499,7 +6499,7 @@ void GLTFDocument::_convert_animation(Ref<GLTFState> state, AnimationPlayer *ap,
 				}
 				tracks[mesh_index] = track;
 			}
-		} else if (String(orig_track_path).find(":") != -1) {
+		} else if (String(orig_track_path).contains(":")) {
 			//Process skeleton
 			const Vector<String> node_suffix = String(orig_track_path).split(":");
 			const String node = node_suffix[0];
@@ -6529,7 +6529,7 @@ void GLTFDocument::_convert_animation(Ref<GLTFState> state, AnimationPlayer *ap,
 					gltf_animation->get_tracks()[node_i] = track;
 				}
 			}
-		} else if (String(orig_track_path).find(":") == -1) {
+		} else if (!String(orig_track_path).contains(":")) {
 			ERR_CONTINUE(!ap->get_parent());
 			Node *godot_node = ap->get_parent()->get_node_or_null(orig_track_path);
 			for (const KeyValue<GLTFNodeIndex, Node *> &scene_node_i : state->scene_nodes) {

+ 1 - 1
modules/visual_script/editor/visual_script_editor.cpp

@@ -2803,7 +2803,7 @@ void VisualScriptEditor::add_callback(const String &p_function, PackedStringArra
 		String name = p_args[i];
 		Variant::Type type = Variant::NIL;
 
-		if (name.find(":") != -1) {
+		if (name.contains(":")) {
 			String tt = name.get_slice(":", 1);
 			name = name.get_slice(":", 0);
 			for (int j = 0; j < Variant::VARIANT_MAX; j++) {

+ 1 - 1
scene/3d/skeleton_3d.cpp

@@ -506,7 +506,7 @@ int Skeleton3D::get_bone_axis_forward_enum(int p_bone) {
 // Skeleton creation api
 
 void Skeleton3D::add_bone(const String &p_name) {
-	ERR_FAIL_COND(p_name.is_empty() || p_name.find(":") != -1 || p_name.find("/") != -1);
+	ERR_FAIL_COND(p_name.is_empty() || p_name.contains(":") || p_name.contains("/"));
 
 	for (int i = 0; i < bones.size(); i++) {
 		ERR_FAIL_COND(bones[i].name == p_name);

+ 1 - 1
scene/animation/animation_blend_tree.cpp

@@ -857,7 +857,7 @@ void AnimationNodeBlendTree::add_node(const StringName &p_name, Ref<AnimationNod
 	ERR_FAIL_COND(nodes.has(p_name));
 	ERR_FAIL_COND(p_node.is_null());
 	ERR_FAIL_COND(p_name == SceneStringNames::get_singleton()->output);
-	ERR_FAIL_COND(String(p_name).find("/") != -1);
+	ERR_FAIL_COND(String(p_name).contains("/"));
 
 	Node n;
 	n.node = p_node;

+ 3 - 3
scene/animation/animation_node_state_machine.cpp

@@ -50,7 +50,7 @@ bool AnimationNodeStateMachineTransition::has_auto_advance() const {
 
 void AnimationNodeStateMachineTransition::set_advance_condition(const StringName &p_condition) {
 	String cs = p_condition;
-	ERR_FAIL_COND(cs.find("/") != -1 || cs.find(":") != -1);
+	ERR_FAIL_COND(cs.contains("/") || cs.contains(":"));
 	advance_condition = p_condition;
 	if (!cs.is_empty()) {
 		advance_condition_name = "conditions/" + cs;
@@ -536,7 +536,7 @@ Variant AnimationNodeStateMachine::get_parameter_default_value(const StringName
 void AnimationNodeStateMachine::add_node(const StringName &p_name, Ref<AnimationNode> p_node, const Vector2 &p_position) {
 	ERR_FAIL_COND(states.has(p_name));
 	ERR_FAIL_COND(p_node.is_null());
-	ERR_FAIL_COND(String(p_name).find("/") != -1);
+	ERR_FAIL_COND(String(p_name).contains("/"));
 
 	State state;
 	state.node = p_node;
@@ -553,7 +553,7 @@ void AnimationNodeStateMachine::add_node(const StringName &p_name, Ref<Animation
 void AnimationNodeStateMachine::replace_node(const StringName &p_name, Ref<AnimationNode> p_node) {
 	ERR_FAIL_COND(states.has(p_name) == false);
 	ERR_FAIL_COND(p_node.is_null());
-	ERR_FAIL_COND(String(p_name).find("/") != -1);
+	ERR_FAIL_COND(String(p_name).contains("/"));
 
 	{
 		Ref<AnimationNode> node = states[p_name].node;

+ 2 - 2
scene/animation/animation_player.cpp

@@ -1171,7 +1171,7 @@ void AnimationPlayer::_animation_process(double p_delta) {
 
 Error AnimationPlayer::add_animation(const StringName &p_name, const Ref<Animation> &p_animation) {
 #ifdef DEBUG_ENABLED
-	ERR_FAIL_COND_V_MSG(String(p_name).find("/") != -1 || String(p_name).find(":") != -1 || String(p_name).find(",") != -1 || String(p_name).find("[") != -1, ERR_INVALID_PARAMETER, "Invalid animation name: " + String(p_name) + ".");
+	ERR_FAIL_COND_V_MSG(String(p_name).contains("/") || String(p_name).contains(":") || String(p_name).contains(",") || String(p_name).contains("["), ERR_INVALID_PARAMETER, "Invalid animation name: " + String(p_name) + ".");
 #endif
 
 	ERR_FAIL_COND_V(p_animation.is_null(), ERR_INVALID_PARAMETER);
@@ -1213,7 +1213,7 @@ void AnimationPlayer::_unref_anim(const Ref<Animation> &p_anim) {
 
 void AnimationPlayer::rename_animation(const StringName &p_name, const StringName &p_new_name) {
 	ERR_FAIL_COND(!animation_set.has(p_name));
-	ERR_FAIL_COND(String(p_new_name).find("/") != -1 || String(p_new_name).find(":") != -1);
+	ERR_FAIL_COND(String(p_new_name).contains("/") || String(p_new_name).contains(":"));
 	ERR_FAIL_COND(animation_set.has(p_new_name));
 
 	stop();

+ 2 - 2
scene/animation/animation_tree.cpp

@@ -314,7 +314,7 @@ void AnimationNode::add_input(const String &p_name) {
 	//root nodes can't add inputs
 	ERR_FAIL_COND(Object::cast_to<AnimationRootNode>(this) != nullptr);
 	Input input;
-	ERR_FAIL_COND(p_name.find(".") != -1 || p_name.find("/") != -1);
+	ERR_FAIL_COND(p_name.contains(".") || p_name.contains("/"));
 	input.name = p_name;
 	inputs.push_back(input);
 	emit_changed();
@@ -322,7 +322,7 @@ void AnimationNode::add_input(const String &p_name) {
 
 void AnimationNode::set_input_name(int p_input, const String &p_name) {
 	ERR_FAIL_INDEX(p_input, inputs.size());
-	ERR_FAIL_COND(p_name.find(".") != -1 || p_name.find("/") != -1);
+	ERR_FAIL_COND(p_name.contains(".") || p_name.contains("/"));
 	inputs.write[p_input].name = p_name;
 	emit_changed();
 }

+ 1 - 1
scene/gui/code_edit.cpp

@@ -232,7 +232,7 @@ void CodeEdit::_notification(int p_what) {
 
 					int begin = 0;
 					int end = 0;
-					if (line.find(String::chr(0xFFFF)) != -1) {
+					if (line.contains(String::chr(0xFFFF))) {
 						begin = font->get_string_size(line.substr(0, line.find(String::chr(0xFFFF))), font_size).x;
 						end = font->get_string_size(line.substr(0, line.rfind(String::chr(0xFFFF))), font_size).x;
 					}

+ 2 - 2
scene/resources/resource_format_text.cpp

@@ -430,7 +430,7 @@ Error ResourceLoaderText::load() {
 			}
 		}
 
-		if (path.find("://") == -1 && path.is_relative_path()) {
+		if (!path.contains("://") && path.is_relative_path()) {
 			// path is relative to file being loaded, so convert to a resource path
 			path = ProjectSettings::get_singleton()->localize_path(local_path.get_base_dir().plus_file(path));
 		}
@@ -774,7 +774,7 @@ void ResourceLoaderText::get_dependencies(FileAccess *p_f, List<String> *p_depen
 			}
 		}
 
-		if (!using_uid && path.find("://") == -1 && path.is_relative_path()) {
+		if (!using_uid && !path.contains("://") && path.is_relative_path()) {
 			// path is relative to file being loaded, so convert to a resource path
 			path = ProjectSettings::get_singleton()->localize_path(local_path.get_base_dir().plus_file(path));
 		}

+ 2 - 2
scene/resources/theme.cpp

@@ -46,7 +46,7 @@ int Theme::fallback_font_size = 16;
 bool Theme::_set(const StringName &p_name, const Variant &p_value) {
 	String sname = p_name;
 
-	if (sname.find("/") != -1) {
+	if (sname.contains("/")) {
 		String type = sname.get_slicec('/', 1);
 		String theme_type = sname.get_slicec('/', 0);
 		String name = sname.get_slicec('/', 2);
@@ -78,7 +78,7 @@ bool Theme::_set(const StringName &p_name, const Variant &p_value) {
 bool Theme::_get(const StringName &p_name, Variant &r_ret) const {
 	String sname = p_name;
 
-	if (sname.find("/") != -1) {
+	if (sname.contains("/")) {
 		String type = sname.get_slicec('/', 1);
 		String theme_type = sname.get_slicec('/', 0);
 		String name = sname.get_slicec('/', 2);

+ 1 - 1
scene/resources/visual_shader.cpp

@@ -3044,7 +3044,7 @@ String VisualShaderNodeOutput::generate_code(Shader::Mode p_mode, VisualShader::
 		if (ports[idx].mode == shader_mode && ports[idx].shader_type == shader_type) {
 			if (!p_input_vars[count].is_empty()) {
 				String s = ports[idx].string;
-				if (s.find(":") != -1) {
+				if (s.contains(":")) {
 					code += "	" + s.get_slicec(':', 0) + " = " + p_input_vars[count] + "." + s.get_slicec(':', 1) + ";\n";
 				} else {
 					code += "	" + s + " = " + p_input_vars[count] + ";\n";

+ 2 - 2
servers/rendering/rendering_device_binds.cpp

@@ -99,11 +99,11 @@ Error RDShaderFile::parse_versions_from_text(const String &p_text, const String
 		if (reading_versions) {
 			String l = line.strip_edges();
 			if (!l.is_empty()) {
-				if (l.find("=") == -1) {
+				if (!l.contains("=")) {
 					base_error = "Missing `=` in '" + l + "'. Version syntax is `version = \"<defines with C escaping>\";`.";
 					break;
 				}
-				if (l.find(";") == -1) {
+				if (!l.contains(";")) {
 					// We don't require a semicolon per se, but it's needed for clang-format to handle things properly.
 					base_error = "Missing `;` in '" + l + "'. Version syntax is `version = \"<defines with C escaping>\";`.";
 					break;

+ 1 - 1
servers/rendering/shader_compiler.cpp

@@ -182,7 +182,7 @@ static String _mkid(const String &p_id) {
 
 static String f2sp0(float p_float) {
 	String num = rtoss(p_float);
-	if (num.find(".") == -1 && num.find("e") == -1) {
+	if (!num.contains(".") && !num.contains("e")) {
 		num += ".0";
 	}
 	return num;

+ 13 - 0
tests/core/string/test_string.h

@@ -245,6 +245,19 @@ TEST_CASE("[String] Testing for empty string") {
 	CHECK(String("").is_empty());
 }
 
+TEST_CASE("[String] Contains") {
+	String s = "C:\\Godot\\project\\string_test.tscn";
+	CHECK(s.contains(":\\"));
+	CHECK(s.contains("Godot"));
+	CHECK(s.contains(String("project\\string_test")));
+	CHECK(s.contains(String("\\string_test.tscn")));
+
+	CHECK(!s.contains("://"));
+	CHECK(!s.contains("Godoh"));
+	CHECK(!s.contains(String("project\\string test")));
+	CHECK(!s.contains(String("\\char_test.tscn")));
+}
+
 TEST_CASE("[String] Test chr") {
 	CHECK(String::chr('H') == "H");
 	CHECK(String::chr(0x3012)[0] == 0x3012);