Repository: godotengine/godot
File: editor/doc/doc_tools.cpp (C++)

Code before:
			if (ClassDB::can_instantiate(class_name)) {
				default_value = ClassDB::class_get_default_property_value(class_name, p_property_name, &r_default_value_valid);
				if (r_default_value_valid) {
					break;
				}
			}
		}
	}

	return default_value;
}

void DocTools::generate(BitField<GenerateFlags> p_flags) {
	// This may involve instantiating classes that are only usable from the main thread
	// (which is in fact the case of the core API).
	ERR_FAIL_COND(!Thread::is_main_thread());

	// Add ClassDB-exposed classes.
	{
		LocalVector<StringName> classes;
		if (p_flags.has_flag(GENERATE_FLAG_EXTENSION_CLASSES_ONLY)) {
			ClassDB::get_extensions_class_list(classes);
		} else {
			ClassDB::get_class_list(classes);
			// Move ProjectSettings, so that other classes can register properties there.
			SWAP(classes[classes.find("ProjectSettings")], classes[classes.size() - 1]);
		}

		bool skip_setter_getter_methods = true;

		// Populate documentation data for each exposed class.
		for (uint32_t classes_idx = 0; classes_idx < classes.size(); classes_idx++) {
			const String &name = classes[classes_idx];
			if (!ClassDB::is_class_exposed(name)) {
				print_verbose(vformat("Class '%s' is not exposed, skipping.", name));
				continue;
			}

			const String &cname = name;
			// Property setters and getters do not get exposed as individual methods.
			HashSet<StringName> setters_getters;

			class_list[cname] = DocData::ClassDoc();
			DocData::ClassDoc &c = class_list[cname];
			c.name = cname;
			c.inherits = ClassDB::get_parent_class(name);

			inheriting[c.inherits].insert(cname);

			List<PropertyInfo> properties;
			List<PropertyInfo> own_properties;

Review comment (suggestion):
I'm not sure why it has to be moved to back, but if it has an effect on which other classes can register properties on it, we probably shouldn't move the final element into its place. Instead, the element should be removed and then re-added to back (same as `move_to_back`).

Code after:
			if (ClassDB::can_instantiate(class_name)) {
				default_value = ClassDB::class_get_default_property_value(class_name, p_property_name, &r_default_value_valid);
				if (r_default_value_valid) {
					break;
				}
			}
		}
	}

	return default_value;
}

void DocTools::generate(BitField<GenerateFlags> p_flags) {
	// This may involve instantiating classes that are only usable from the main thread
	// (which is in fact the case of the core API).
	ERR_FAIL_COND(!Thread::is_main_thread());

	// Add ClassDB-exposed classes.
	{
		LocalVector<StringName> classes;
		if (p_flags.has_flag(GENERATE_FLAG_EXTENSION_CLASSES_ONLY)) {
			ClassDB::get_extensions_class_list(classes);
		} else {
			ClassDB::get_class_list(classes);
			// Move ProjectSettings, so that other classes can register properties there.
			classes.erase("ProjectSettings");
			classes.push_back("ProjectSettings");
		}

		bool skip_setter_getter_methods = true;

		// Populate documentation data for each exposed class.
		for (uint32_t classes_idx = 0; classes_idx < classes.size(); classes_idx++) {
			const String &name = classes[classes_idx];
			if (!ClassDB::is_class_exposed(name)) {
				print_verbose(vformat("Class '%s' is not exposed, skipping.", name));
				continue;
			}

			const String &cname = name;
			// Property setters and getters do not get exposed as individual methods.
			HashSet<StringName> setters_getters;

			class_list[cname] = DocData::ClassDoc();
			DocData::ClassDoc &c = class_list[cname];
			c.name = cname;
			c.inherits = ClassDB::get_parent_class(name);

			inheriting[c.inherits].insert(cname);

			List<PropertyInfo> properties;