text:
/*************************************************************************/
/*  doc_tools.cpp                                                        */
/*************************************************************************/
/*                       This file is part of:                           */
/*                           GODOT ENGINE                                */
/*                      https://godotengine.org                          */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur.                 */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md).   */
/*                                                                       */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the       */
/* "Software"), to deal in the Software without restriction, including   */
/* without limitation the rights to use, copy, modify, merge, publish,   */
/* distribute, sublicense, and/or sell copies of the Software, and to    */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions:                                             */
/*                                                                       */
/* The above copyright notice and this permission notice shall be        */
/* included in all copies or substantial portions of the Software.       */
/*                                                                       */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
/*************************************************************************/

#include "doc_tools.h"

#include "core/config/engine.h"
#include "core/config/project_settings.h"
#include "core/core_constants.h"
#include "core/io/compression.h"
#include "core/io/dir_access.h"
#include "core/io/marshalls.h"
#include "core/object/script_language.h"
#include "core/string/translation.h"
#include "core/version.h"
#include "scene/resources/theme.h"

// Used for a hack preserving Mono properties on non-Mono builds.
#include "modules/modules_enabled.gen.h" // For mono.

static String _get_indent(const String &p_text) {
	String indent;
	bool has_text = false;
	int line_start = 0;

	for (int i = 0; i < p_text.length(); i++) {
		const char32_t c = p_text[i];
		if (c == '\n') {
			line_start = i + 1;
		} else if (c > 32) {
			has_text = true;
			indent = p_text.substr(line_start, i - line_start);
			break; // Indentation of the first line that has text.
		}
	}
	if (!has_text) {
		return p_text;
	}
	return indent;
}

static String _translate_doc_string(const String &p_text) {
	const String indent = _get_indent(p_text);
	const String message = p_text.dedent().strip_edges();
	const String translated = TranslationServer::get_singleton()->doc_translate(message, "");
	// No need to restore stripped edges because they'll be stripped again later.
	return translated.indent(indent);
}

void DocTools::merge_from(const DocTools &p_data) {
	for (KeyValue<String, DocData::ClassDoc> &E : class_list) {
		DocData::ClassDoc &c = E.value;

		if (!p_data.class_list.has(c.name)) {
			continue;
		}

		const DocData::ClassDoc &cf = p_data.class_list[c.name];

		c.description = cf.description;
		c.brief_description = cf.brief_description;
		c.tutorials = cf.tutorials;

		for (int i = 0; i < c.constructors.size(); i++) {
			DocData::MethodDoc &m = c.constructors.write[i];

			for (int j = 0; j < cf.constructors.size(); j++) {
				if (cf.constructors[j].name != m.name) {
					continue;
				}

				{
					// Since constructors can repeat, we need to check the type of
					// the arguments so we make sure they are different.
					if (cf.constructors[j].arguments.size() != m.arguments.size()) {
						continue;
					}
					int arg_count = cf.constructors[j].arguments.size();
					Vector<bool> arg_used;
					arg_used.resize(arg_count);
					for (int l = 0; l < arg_count; ++l) {
						arg_used.write[l] = false;
					}
					// also there is no guarantee that argument ordering will match, so we
					// have to check one by one so we make sure we have an exact match
					for (int k = 0; k < arg_count; ++k) {
						for (int l = 0; l < arg_count; ++l) {
							if (cf.constructors[j].arguments[k].type == m.arguments[l].type && !arg_used[l]) {
								arg_used.write[l] = true;
								break;
							}
						}
					}
					bool not_the_same = false;
					for (int l = 0; l < arg_count; ++l) {
						if (!arg_used[l]) { // at least one of the arguments was different
							not_the_same = true;
						}
					}
					if (not_the_same) {
						continue;
					}
				}

				const DocData::MethodDoc &mf = cf.constructors[j];

				m.description = mf.description;
				break;
			}
		}

		for (int i = 0; i < c.methods.size(); i++) {
			DocData::MethodDoc &m = c.methods.write[i];

			for (int j = 0; j < cf.methods.size(); j++) {
				if (cf.methods[j].name != m.name) {
					continue;
				}

				const DocData::MethodDoc &mf = cf.methods[j];

				m.description = mf.description;
				break;
			}
		}

		for (int i = 0; i < c.signals.size(); i++) {
			DocData::MethodDoc &m = c.signals.write[i];

			for (int j = 0; j < cf.signals.size(); j++) {
				if (cf.signals[j].name != m.name) {
					continue;
				}
				const DocData::MethodDoc &mf = cf.signals[j];

				m.description = mf.description;
				break;
			}
		}

		for (int i = 0; i < c.constants.size(); i++) {
			DocData::ConstantDoc &m = c.constants.write[i];

			for (int j = 0; j < cf.constants.size(); j++) {
				if (cf.constants[j].name != m.name) {
					continue;
				}
				const DocData::ConstantDoc &mf = cf.constants[j];

				m.description = mf.description;
				break;
			}
		}

		for (int i = 0; i < c.properties.size(); i++) {
			DocData::PropertyDoc &p = c.properties.write[i];

			for (int j = 0; j < cf.properties.size(); j++) {
				if (cf.properties[j].name != p.name) {
					continue;
				}
				const DocData::PropertyDoc &pf = cf.properties[j];

				p.description = pf.description;
				break;
			}
		}

		for (int i = 0; i < c.theme_properties.size(); i++) {
			DocData::ThemeItemDoc &ti = c.theme_properties.write[i];

			for (int j = 0; j < cf.theme_properties.size(); j++) {
				if (cf.theme_properties[j].name != ti.name || cf.theme_properties[j].data_type != ti.data_type) {
					continue;
				}
				const DocData::ThemeItemDoc &pf = cf.theme_properties[j];

				ti.description = pf.description;
				break;
			}
		}

		for (int i = 0; i < c.operators.size(); i++) {
			DocData::MethodDoc &m = c.operators.write[i];

			for (int j = 0; j < cf.operators.size(); j++) {
				if (cf.operators[j].name != m.name) {
					continue;
				}

				{
					// Since operators can repeat, we need to check the type of
					// the arguments so we make sure they are different.
					if (cf.operators[j].arguments.size() != m.arguments.size()) {
						continue;
					}
					int arg_count = cf.operators[j].arguments.size();
					Vector<bool> arg_used;
					arg_used.resize(arg_count);
					for (int l = 0; l < arg_count; ++l) {
						arg_used.write[l] = false;
					}
					// also there is no guarantee that argument ordering will match, so we
					// have to check one by one so we make sure we have an exact match
					for (int k = 0; k < arg_count; ++k) {
						for (int l = 0; l < arg_count; ++l) {
							if (cf.operators[j].arguments[k].type == m.arguments[l].type && !arg_used[l]) {
								arg_used.write[l] = true;
								break;
							}
						}
					}
					bool not_the_same = false;
					for (int l = 0; l < arg_count; ++l) {
						if (!arg_used[l]) { // at least one of the arguments was different
							not_the_same = true;
						}
					}
					if (not_the_same) {
						continue;
					}
				}

				const DocData::MethodDoc &mf = cf.operators[j];

				m.description = mf.description;
				break;
			}
		}

#ifndef MODULE_MONO_ENABLED
		// The Mono module defines some properties that we want to keep when
		// re-generating docs with a non-Mono build, to prevent pointless diffs
		// (and loss of descriptions) depending on the config of the doc writer.
		// We use a horrible hack to force keeping the relevant properties,
		// hardcoded below. At least it's an ad hoc hack... ¯\_(ツ)_/¯
		// Don't show this to your kids.
		if (c.name == "@GlobalScope") {
			// Retrieve GodotSharp singleton.
			for (int j = 0; j < cf.properties.size(); j++) {
				if (cf.properties[j].name == "GodotSharp") {
					c.properties.push_back(cf.properties[j]);
				}
			}
		}
#endif
	}
}

void DocTools::remove_from(const DocTools &p_data) {
	for (const KeyValue<String, DocData::ClassDoc> &E : p_data.class_list) {
		if (class_list.has(E.key)) {
			class_list.erase(E.key);
		}
	}
}

void DocTools::add_doc(const DocData::ClassDoc &p_class_doc) {
	ERR_FAIL_COND(p_class_doc.name.is_empty());
	class_list[p_class_doc.name] = p_class_doc;
}

void DocTools::remove_doc(const String &p_class_name) {
	ERR_FAIL_COND(p_class_name.is_empty() || !class_list.has(p_class_name));
	class_list.erase(p_class_name);
}

bool DocTools::has_doc(const String &p_class_name) {
	if (p_class_name.is_empty()) {
		return false;
	}
	return class_list.has(p_class_name);
}

static Variant get_documentation_default_value(const StringName &p_class_name, const StringName &p_property_name, bool &r_default_value_valid) {
	Variant default_value = Variant();
	r_default_value_valid = false;

	if (ClassDB::can_instantiate(p_class_name)) {
		default_value = ClassDB::class_get_default_property_value(p_class_name, p_property_name, &r_default_value_valid);
	} else {
		// Cannot get default value of classes that can't be instantiated
		List<StringName> inheriting_classes;
		ClassDB::get_direct_inheriters_from_class(p_class_name, &inheriting_classes);
		for (List<StringName>::Element *E2 = inheriting_classes.front(); E2; E2 = E2->next()) {
			if (ClassDB::can_instantiate(E2->get())) {
				default_value = ClassDB::class_get_default_property_value(E2->get(), p_property_name, &r_default_value_valid);
				if (r_default_value_valid) {
					break;
				}
			}
		}
	}

	return default_value;
}

void DocTools::generate(bool p_basic_types) {
	List<StringName> classes;
	ClassDB::get_class_list(&classes);
	classes.sort_custom<StringName::AlphCompare>();
	// Move ProjectSettings, so that other classes can register properties there.
	classes.move_to_back(classes.find("ProjectSettings"));

	bool skip_setter_getter_methods = true;

	while (classes.size()) {
		Set<StringName> setters_getters;

		String name = classes.front()->get();
		if (!ClassDB::is_class_exposed(name)) {
			print_verbose(vformat("Class '%s' is not exposed, skipping.", name));
			classes.pop_front();
			continue;
		}

		String cname = name;

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

		List<PropertyInfo> properties;
		List<PropertyInfo> own_properties;
		if (name == "ProjectSettings") {
			// Special case for project settings, so settings can be documented.
			ProjectSettings::get_singleton()->get_property_list(&properties);
			own_properties = properties;
		} else {
			ClassDB::get_property_list(name, &properties);
			ClassDB::get_property_list(name, &own_properties, true);
		}

		properties.sort();
		own_properties.sort();

		List<PropertyInfo>::Element *EO = own_properties.front();
		for (const PropertyInfo &E : properties) {
			bool inherited = true;
			if (EO && EO->get() == E) {
				inherited = false;
				EO = EO->next();
			}

			if (E.usage & PROPERTY_USAGE_GROUP || E.usage & PROPERTY_USAGE_SUBGROUP || E.usage & PROPERTY_USAGE_CATEGORY || E.usage & PROPERTY_USAGE_INTERNAL || (E.type == Variant::NIL && E.usage & PROPERTY_USAGE_ARRAY)) {
				continue;
			}

			DocData::PropertyDoc prop;
			prop.name = E.name;
			prop.overridden = inherited;

			if (inherited) {
				String parent = ClassDB::get_parent_class(c.name);
				while (!ClassDB::has_property(parent, prop.name, true)) {
					parent = ClassDB::get_parent_class(parent);
				}
				prop.overrides = parent;
			}

			bool default_value_valid = false;
			Variant default_value;

			if (name == "ProjectSettings") {
				// Special case for project settings, so that settings are not taken from the current project's settings
				if (E.name == "script" || !ProjectSettings::get_singleton()->is_builtin_setting(E.name)) {
					continue;
				}
				if (E.usage & PROPERTY_USAGE_EDITOR) {
					if (!ProjectSettings::get_singleton()->get_ignore_value_in_docs(E.name)) {
						default_value = ProjectSettings::get_singleton()->property_get_revert(E.name);
						default_value_valid = true;
					}
				}
			} else {
				default_value = get_documentation_default_value(name, E.name, default_value_valid);
				if (inherited) {
					bool base_default_value_valid = false;
					Variant base_default_value = get_documentation_default_value(ClassDB::get_parent_class(name), E.name, base_default_value_valid);
					if (!default_value_valid || !base_default_value_valid || default_value == base_default_value) {
						continue;
					}
				}
			}

			//used to track uninitialized values using valgrind
			//print_line("getting default value for " + String(name) + "." + String(E.name));
			if (default_value_valid && default_value.get_type() != Variant::OBJECT) {
				prop.default_value = default_value.get_construct_string().replace("\n", " ");
			}

			StringName setter = ClassDB::get_property_setter(name, E.name);
			StringName getter = ClassDB::get_property_getter(name, E.name);

			prop.setter = setter;
			prop.getter = getter;

			bool found_type = false;
			if (getter != StringName()) {
				MethodBind *mb = ClassDB::get_method(name, getter);
				if (mb) {
					PropertyInfo retinfo = mb->get_return_info();

					found_type = true;
					if (retinfo.type == Variant::INT && retinfo.usage & PROPERTY_USAGE_CLASS_IS_ENUM) {
						prop.enumeration = retinfo.class_name;
						prop.type = "int";
					} else if (retinfo.class_name != StringName()) {
						prop.type = retinfo.class_name;
					} else if (retinfo.type == Variant::ARRAY && retinfo.hint == PROPERTY_HINT_ARRAY_TYPE) {
						prop.type = retinfo.hint_string + "[]";
					} else if (retinfo.hint == PROPERTY_HINT_RESOURCE_TYPE) {
						prop.type = retinfo.hint_string;
					} else if (retinfo.type == Variant::NIL && retinfo.usage & PROPERTY_USAGE_NIL_IS_VARIANT) {
						prop.type = "Variant";
					} else if (retinfo.type == Variant::NIL) {
						prop.type = "void";
					} else {
						prop.type = Variant::get_type_name(retinfo.type);
					}
				}

				setters_getters.insert(getter);
			}

			if (setter != StringName()) {
				setters_getters.insert(setter);
			}

			if (!found_type) {
				if (E.type == Variant::OBJECT && E.hint == PROPERTY_HINT_RESOURCE_TYPE) {
					prop.type = E.hint_string;
				} else {
					prop.type = Variant::get_type_name(E.type);
				}
			}

			c.properties.push_back(prop);
		}

		List<MethodInfo> method_list;
		ClassDB::get_method_list(name, &method_list, true);
		method_list.sort();

		for (const MethodInfo &E : method_list) {
			if (E.name.is_empty() || (E.name[0] == '_' && !(E.flags & METHOD_FLAG_VIRTUAL))) {
				continue; //hidden, don't count
			}

			if (skip_setter_getter_methods && setters_getters.has(E.name)) {
				// Don't skip parametric setters and getters, i.e. method which require
				// one or more parameters to define what property should be set or retrieved.
				// E.g. CPUParticles3D::set_param(Parameter param, float value).
				if (E.arguments.size() == 0 /* getter */ || (E.arguments.size() == 1 && E.return_val.type == Variant::NIL /* setter */)) {
					continue;
				}
			}

			DocData::MethodDoc method;

			method.name = E.name;

			if (E.flags & METHOD_FLAG_VIRTUAL) {
				method.qualifiers = "virtual";
			}

			if (E.flags & METHOD_FLAG_CONST) {
				if (!method.qualifiers.is_empty()) {
					method.qualifiers += " ";
				}
				method.qualifiers += "const";
			}

			if (E.flags & METHOD_FLAG_VARARG) {
				if (!method.qualifiers.is_empty()) {
					method.qualifiers += " ";
				}
				method.qualifiers += "vararg";
			}

			if (E.flags & METHOD_FLAG_STATIC) {
				if (!method.qualifiers.is_empty()) {
					method.qualifiers += " ";
				}
				method.qualifiers += "static";
			}

			for (int i = -1; i < E.arguments.size(); i++) {
				if (i == -1) {
#ifdef DEBUG_METHODS_ENABLED
					DocData::return_doc_from_retinfo(method, E.return_val);
#endif
				} else {
					const PropertyInfo &arginfo = E.arguments[i];
					DocData::ArgumentDoc argument;
					DocData::argument_doc_from_arginfo(argument, arginfo);

					int darg_idx = i - (E.arguments.size() - E.default_arguments.size());
					if (darg_idx >= 0) {
						Variant default_arg = E.default_arguments[darg_idx];
						argument.default_value = default_arg.get_construct_string().replace("\n", " ");
					}

					method.arguments.push_back(argument);
				}
			}

			Vector<Error> errs = ClassDB::get_method_error_return_values(name, E.name);
			if (errs.size()) {
				if (!errs.has(OK)) {
					errs.insert(0, OK);
				}
				for (int i = 0; i < errs.size(); i++) {
					if (!method.errors_returned.has(errs[i])) {
						method.errors_returned.push_back(errs[i]);
					}
				}
			}

			c.methods.push_back(method);
		}

		List<MethodInfo> signal_list;
		ClassDB::get_signal_list(name, &signal_list, true);

		if (signal_list.size()) {
			for (List<MethodInfo>::Element *EV = signal_list.front(); EV; EV = EV->next()) {
				DocData::MethodDoc signal;
				signal.name = EV->get().name;
				for (int i = 0; i < EV->get().arguments.size(); i++) {
					const PropertyInfo &arginfo = EV->get().arguments[i];
					DocData::ArgumentDoc argument;
					DocData::argument_doc_from_arginfo(argument, arginfo);

					signal.arguments.push_back(argument);
				}

				c.signals.push_back(signal);
			}
		}

		List<String> constant_list;
		ClassDB::get_integer_constant_list(name, &constant_list, true);

		for (const String &E : constant_list) {
			DocData::ConstantDoc constant;
			constant.name = E;
			constant.value = itos(ClassDB::get_integer_constant(name, E));
			constant.is_value_valid = true;
			constant.enumeration = ClassDB::get_integer_constant_enum(name, E);
			c.constants.push_back(constant);
		}

		// Theme items.
		{
			List<StringName> l;

			Theme::get_default()->get_color_list(cname, &l);
			for (const StringName &E : l) {
				DocData::ThemeItemDoc tid;
				tid.name = E;
				tid.type = "Color";
				tid.data_type = "color";
				tid.default_value = Variant(Theme::get_default()->get_color(E, cname)).get_construct_string().replace("\n", " ");
				c.theme_properties.push_back(tid);
			}

			l.clear();
			Theme::get_default()->get_constant_list(cname, &l);
			for (const StringName &E : l) {
				DocData::ThemeItemDoc tid;
				tid.name = E;
				tid.type = "int";
				tid.data_type = "constant";
				tid.default_value = itos(Theme::get_default()->get_constant(E, cname));
				c.theme_properties.push_back(tid);
			}

			l.clear();
			Theme::get_default()->get_font_list(cname, &l);
			for (const StringName &E : l) {
				DocData::ThemeItemDoc tid;
				tid.name = E;
				tid.type = "Font";
				tid.data_type = "font";
				c.theme_properties.push_back(tid);
			}

			l.clear();
			Theme::get_default()->get_font_size_list(cname, &l);
			for (const StringName &E : l) {
				DocData::ThemeItemDoc tid;
				tid.name = E;
				tid.type = "int";
				tid.data_type = "font_size";
				c.theme_properties.push_back(tid);
			}

			l.clear();
			Theme::get_default()->get_icon_list(cname, &l);
			for (const StringName &E : l) {
				DocData::ThemeItemDoc tid;
				tid.name = E;
				tid.type = "Texture2D";
				tid.data_type = "icon";
				c.theme_properties.push_back(tid);
			}

			l.clear();
			Theme::get_default()->get_stylebox_list(cname, &l);
			for (const StringName &E : l) {
				DocData::ThemeItemDoc tid;
				tid.name = E;
				tid.type = "StyleBox";
				tid.data_type = "style";
				c.theme_properties.push_back(tid);
			}

			c.theme_properties.sort();
		}

		classes.pop_front();
	}

	{
		// So we can document the concept of Variant even if it's not a usable class per se.
		class_list["Variant"] = DocData::ClassDoc();
		class_list["Variant"].name = "Variant";
	}

	if (!p_basic_types) {
		return;
	}

	// Add Variant types.
	for (int i = 0; i < Variant::VARIANT_MAX; i++) {
		if (i == Variant::NIL) {
			continue; // Not exposed outside of 'null', should not be in class list.
		}
		if (i == Variant::OBJECT) {
			continue; // Use the core type instead.
		}

		String cname = Variant::get_type_name(Variant::Type(i));

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

		Callable::CallError cerror;
		Variant v;
		Variant::construct(Variant::Type(i), v, nullptr, 0, cerror);

		List<MethodInfo> method_list;
		v.get_method_list(&method_list);
		method_list.sort();
		Variant::get_constructor_list(Variant::Type(i), &method_list);

		for (int j = 0; j < Variant::OP_AND; j++) { // Showing above 'and' is pretty confusing and there are a lot of variations.
			for (int k = 0; k < Variant::VARIANT_MAX; k++) {
				Variant::Type rt = Variant::get_operator_return_type(Variant::Operator(j), Variant::Type(i), Variant::Type(k));
				if (rt != Variant::NIL) { // Has operator.
					// Skip String % operator as it's registered separately for each Variant arg type,
					// we'll add it manually below.
					if (i == Variant::STRING && Variant::Operator(j) == Variant::OP_MODULE) {
						continue;
					}
					MethodInfo mi;
					mi.name = "operator " + Variant::get_operator_name(Variant::Operator(j));
					mi.return_val.type = rt;
					if (k != Variant::NIL) {
						PropertyInfo arg;
						arg.name = "right";
						arg.type = Variant::Type(k);
						mi.arguments.push_back(arg);
					}
					method_list.push_back(mi);
				}
			}
		}

		if (i == Variant::STRING) {
			// We skipped % operator above, and we register it manually once for Variant arg type here.
			MethodInfo mi;
			mi.name = "operator %";
			mi.return_val.type = Variant::STRING;

			PropertyInfo arg;
			arg.name = "right";
			arg.type = Variant::NIL;
			arg.usage = PROPERTY_USAGE_NIL_IS_VARIANT;
			mi.arguments.push_back(arg);

			method_list.push_back(mi);
		}

		if (Variant::is_keyed(Variant::Type(i))) {
			MethodInfo mi;
			mi.name = "operator []";
			mi.return_val.type = Variant::NIL;
			mi.return_val.usage = PROPERTY_USAGE_NIL_IS_VARIANT;

			PropertyInfo arg;
			arg.name = "key";
			arg.type = Variant::NIL;
			arg.usage = PROPERTY_USAGE_NIL_IS_VARIANT;
			mi.arguments.push_back(arg);

			method_list.push_back(mi);
		} else if (Variant::has_indexing(Variant::Type(i))) {
			MethodInfo mi;
			mi.name = "operator []";
			mi.return_val.type = Variant::get_indexed_element_type(Variant::Type(i));
			PropertyInfo arg;
			arg.name = "index";
			arg.type = Variant::INT;
			mi.arguments.push_back(arg);

			method_list.push_back(mi);
		}

		for (const MethodInfo &mi : method_list) {
			DocData::MethodDoc method;

			method.name = mi.name;

			for (int j = 0; j < mi.arguments.size(); j++) {
				PropertyInfo arginfo = mi.arguments[j];
				DocData::ArgumentDoc ad;
				DocData::argument_doc_from_arginfo(ad, mi.arguments[j]);
				ad.name = arginfo.name;

				int darg_idx = mi.default_arguments.size() - mi.arguments.size() + j;
				if (darg_idx >= 0) {
					Variant default_arg = mi.default_arguments[darg_idx];
					ad.default_value = default_arg.get_construct_string().replace("\n", " ");
				}

				method.arguments.push_back(ad);
			}

			DocData::return_doc_from_retinfo(method, mi.return_val);

			if (mi.flags & METHOD_FLAG_VARARG) {
				if (!method.qualifiers.is_empty()) {
					method.qualifiers += " ";
				}
				method.qualifiers += "vararg";
			}

			if (mi.flags & METHOD_FLAG_CONST) {
				if (!method.qualifiers.is_empty()) {
					method.qualifiers += " ";
				}
				method.qualifiers += "const";
			}

			if (mi.flags & METHOD_FLAG_STATIC) {
				if (!method.qualifiers.is_empty()) {
					method.qualifiers += " ";
				}
				method.qualifiers += "static";
			}

			if (method.name == cname) {
				c.constructors.push_back(method);
			} else if (method.name.begins_with("operator")) {
				c.operators.push_back(method);
			} else {
				c.methods.push_back(method);
			}
		}

		List<PropertyInfo> properties;
		v.get_property_list(&properties);
		for (const PropertyInfo &pi : properties) {
			DocData::PropertyDoc property;
			property.name = pi.name;
			property.type = Variant::get_type_name(pi.type);
			property.default_value = v.get(pi.name).get_construct_string().replace("\n", " ");

			c.properties.push_back(property);
		}

		List<StringName> constants;
		Variant::get_constants_for_type(Variant::Type(i), &constants);

		for (const StringName &E : constants) {
			DocData::ConstantDoc constant;
			constant.name = E;
			Variant value = Variant::get_constant_value(Variant::Type(i), E);
			constant.value = value.get_type() == Variant::INT ? itos(value) : value.get_construct_string().replace("\n", " ");
			constant.is_value_valid = true;
			c.constants.push_back(constant);
		}
	}

	//built in constants and functions

	{
		String cname = "@GlobalScope";
		class_list[cname] = DocData::ClassDoc();
		DocData::ClassDoc &c = class_list[cname];
		c.name = cname;

		for (int i = 0; i < CoreConstants::get_global_constant_count(); i++) {
			DocData::ConstantDoc cd;
			cd.name = CoreConstants::get_global_constant_name(i);
			if (!CoreConstants::get_ignore_value_in_docs(i)) {
				cd.value = itos(CoreConstants::get_global_constant_value(i));
				cd.is_value_valid = true;
			} else {
				cd.is_value_valid = false;
			}
			cd.enumeration = CoreConstants::get_global_constant_enum(i);
			c.constants.push_back(cd);
		}

		List<Engine::Singleton> singletons;
		Engine::get_singleton()->get_singletons(&singletons);

		//servers (this is kind of hackish)
		for (const Engine::Singleton &s : singletons) {
			DocData::PropertyDoc pd;
			if (!s.ptr) {
				continue;
			}
			pd.name = s.name;
			pd.type = s.ptr->get_class();
			while (String(ClassDB::get_parent_class(pd.type)) != "Object") {
				pd.type = ClassDB::get_parent_class(pd.type);
			}
			c.properties.push_back(pd);
		}

		List<StringName> utility_functions;
		Variant::get_utility_function_list(&utility_functions);
		utility_functions.sort_custom<StringName::AlphCompare>();
		for (const StringName &E : utility_functions) {
			DocData::MethodDoc md;
			md.name = E;
			//return
			if (Variant::has_utility_function_return_value(E)) {
				PropertyInfo pi;
				pi.type = Variant::get_utility_function_return_type(E);
				if (pi.type == Variant::NIL) {
					pi.usage = PROPERTY_USAGE_NIL_IS_VARIANT;
				}
				DocData::ArgumentDoc ad;
				DocData::argument_doc_from_arginfo(ad, pi);
				md.return_type = ad.type;
			}

			if (Variant::is_utility_function_vararg(E)) {
				md.qualifiers = "vararg";
			} else {
				for (int i = 0; i < Variant::get_utility_function_argument_count(E); i++) {
					PropertyInfo pi;
					pi.type = Variant::get_utility_function_argument_type(E, i);
					pi.name = Variant::get_utility_function_argument_name(E, i);
					if (pi.type == Variant::NIL) {
						pi.usage = PROPERTY_USAGE_NIL_IS_VARIANT;
					}
					DocData::ArgumentDoc ad;
					DocData::argument_doc_from_arginfo(ad, pi);
					md.arguments.push_back(ad);
				}
			}

			c.methods.push_back(md);
		}
	}

	// Built-in script reference.
	// We only add a doc entry for languages which actually define any built-in
	// methods or constants.

	{
		for (int i = 0; i < ScriptServer::get_language_count(); i++) {
			ScriptLanguage *lang = ScriptServer::get_language(i);
			String cname = "@" + lang->get_name();
			DocData::ClassDoc c;
			c.name = cname;

			// Get functions.
			List<MethodInfo> minfo;
			lang->get_public_functions(&minfo);

			for (const MethodInfo &mi : minfo) {
				DocData::MethodDoc md;
				md.name = mi.name;

				if (mi.flags & METHOD_FLAG_VARARG) {
					if (!md.qualifiers.is_empty()) {
						md.qualifiers += " ";
					}
					md.qualifiers += "vararg";
				}

				DocData::return_doc_from_retinfo(md, mi.return_val);

				for (int j = 0; j < mi.arguments.size(); j++) {
					DocData::ArgumentDoc ad;
					DocData::argument_doc_from_arginfo(ad, mi.arguments[j]);

					int darg_idx = j - (mi.arguments.size() - mi.default_arguments.size());
					if (darg_idx >= 0) {
						Variant default_arg = mi.default_arguments[darg_idx];
						ad.default_value = default_arg.get_construct_string().replace("\n", " ");
					}

					md.arguments.push_back(ad);
				}

				c.methods.push_back(md);
			}

			// Get constants.
			List<Pair<String, Variant>> cinfo;
			lang->get_public_constants(&cinfo);

			for (const Pair<String, Variant> &E : cinfo) {
				DocData::ConstantDoc cd;
				cd.name = E.first;
				cd.value = E.second;
				cd.is_value_valid = true;
				c.constants.push_back(cd);
			}

			// Skip adding the lang if it doesn't expose anything (e.g. C#).
			if (c.methods.is_empty() && c.constants.is_empty()) {
				continue;
			}

			class_list[cname] = c;
		}
	}
}

static Error _parse_methods(Ref<XMLParser> &parser, Vector<DocData::MethodDoc> &methods) {
	String section = parser->get_node_name();
	String element = section.substr(0, section.length() - 1);

	while (parser->read() == OK) {
		if (parser->get_node_type() == XMLParser::NODE_ELEMENT) {
			if (parser->get_node_name() == element) {
				DocData::MethodDoc method;
				ERR_FAIL_COND_V(!parser->has_attribute("name"), ERR_FILE_CORRUPT);
				method.name = parser->get_attribute_value("name");
				if (parser->has_attribute("qualifiers")) {
					method.qualifiers = parser->get_attribute_value("qualifiers");
				}

				while (parser->read() == OK) {
					if (parser->get_node_type() == XMLParser::NODE_ELEMENT) {
						String name = parser->get_node_name();
						if (name == "return") {
							ERR_FAIL_COND_V(!parser->has_attribute("type"), ERR_FILE_CORRUPT);
							method.return_type = parser->get_attribute_value("type");
							if (parser->has_attribute("enum")) {
								method.return_enum = parser->get_attribute_value("enum");
							}
						} else if (name == "returns_error") {
							ERR_FAIL_COND_V(!parser->has_attribute("number"), ERR_FILE_CORRUPT);
							method.errors_returned.push_back(parser->get_attribute_value("number").to_int());
						} else if (name == "argument") {
							DocData::ArgumentDoc argument;
							ERR_FAIL_COND_V(!parser->has_attribute("name"), ERR_FILE_CORRUPT);
							argument.name = parser->get_attribute_value("name");
							ERR_FAIL_COND_V(!parser->has_attribute("type"), ERR_FILE_CORRUPT);
							argument.type = parser->get_attribute_value("type");
							if (parser->has_attribute("enum")) {
								argument.enumeration = parser->get_attribute_value("enum");
							}

							method.arguments.push_back(argument);

						} else if (name == "description") {
							parser->read();
							if (parser->get_node_type() == XMLParser::NODE_TEXT) {
								method.description = parser->get_node_data();
							}
						}

					} else if (parser->get_node_type() == XMLParser::NODE_ELEMENT_END && parser->get_node_name() == element) {
						break;
					}
				}

				methods.push_back(method);

			} else {
				ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, "Invalid tag in doc file: " + parser->get_node_name() + ", expected " + element + ".");
			}

		} else if (parser->get_node_type() == XMLParser::NODE_ELEMENT_END && parser->get_node_name() == section) {
			break;
		}
	}

	return OK;
}

Error DocTools::load_classes(const String &p_dir) {
	Error err;
	DirAccessRef da = DirAccess::open(p_dir, &err);
	if (!da) {
		return err;
	}

	da->list_dir_begin();
	String path;
	path = da->get_next();
	while (!path.is_empty()) {
		if (!da->current_is_dir() && path.ends_with("xml")) {
			Ref<XMLParser> parser = memnew(XMLParser);
			Error err2 = parser->open(p_dir.plus_file(path));
			if (err2) {
				return err2;
			}

			_load(parser);
		}
		path = da->get_next();
	}

	da->list_dir_end();

	return OK;
}

Error DocTools::erase_classes(const String &p_dir) {
	Error err;
	DirAccessRef da = DirAccess::open(p_dir, &err);
	if (!da) {
		return err;
	}

	List<String> to_erase;

	da->list_dir_begin();
	String path;
	path = da->get_next();
	while (!path.is_empty()) {
		if (!da->current_is_dir() && path.ends_with("xml")) {
			to_erase.push_back(path);
		}
		path = da->get_next();
	}
	da->list_dir_end();

	while (to_erase.size()) {
		da->remove(to_erase.front()->get());
		to_erase.pop_front();
	}

	return OK;
}

Error DocTools::_load(Ref<XMLParser> parser) {
	Error err = OK;

	while ((err = parser->read()) == OK) {
		if (parser->get_node_type() == XMLParser::NODE_ELEMENT && parser->get_node_name() == "?xml") {
			parser->skip_section();
		}

		if (parser->get_node_type() != XMLParser::NODE_ELEMENT) {
			continue; //no idea what this may be, but skipping anyway
		}

		ERR_FAIL_COND_V(parser->get_node_name() != "class", ERR_FILE_CORRUPT);

		ERR_FAIL_COND_V(!parser->has_attribute("name"), ERR_FILE_CORRUPT);
		String name = parser->get_attribute_value("name");
		class_list[name] = DocData::ClassDoc();
		DocData::ClassDoc &c = class_list[name];

		c.name = name;
		if (parser->has_attribute("inherits")) {
			c.inherits = parser->get_attribute_value("inherits");
		}

		while (parser->read() == OK) {
			if (parser->get_node_type() == XMLParser::NODE_ELEMENT) {
				String name2 = parser->get_node_name();

				if (name2 == "brief_description") {
					parser->read();
					if (parser->get_node_type() == XMLParser::NODE_TEXT) {
						c.brief_description = parser->get_node_data();
					}

				} else if (name2 == "description") {
					parser->read();
					if (parser->get_node_type() == XMLParser::NODE_TEXT) {
						c.description = parser->get_node_data();
					}
				} else if (name2 == "tutorials") {
					while (parser->read() == OK) {
						if (parser->get_node_type() == XMLParser::NODE_ELEMENT) {
							String name3 = parser->get_node_name();

							if (name3 == "link") {
								DocData::TutorialDoc tutorial;
								if (parser->has_attribute("title")) {
									tutorial.title = parser->get_attribute_value("title");
								}
								parser->read();
								if (parser->get_node_type() == XMLParser::NODE_TEXT) {
									tutorial.link = parser->get_node_data().strip_edges();
									c.tutorials.push_back(tutorial);
								}
							} else {
								ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, "Invalid tag in doc file: " + name3 + ".");
							}
						} else if (parser->get_node_type() == XMLParser::NODE_ELEMENT_END && parser->get_node_name() == "tutorials") {
							break; // End of <tutorials>.
						}
					}
				} else if (name2 == "constructors") {
					Error err2 = _parse_methods(parser, c.constructors);
					ERR_FAIL_COND_V(err2, err2);
				} else if (name2 == "methods") {
					Error err2 = _parse_methods(parser, c.methods);
					ERR_FAIL_COND_V(err2, err2);
				} else if (name2 == "operators") {
					Error err2 = _parse_methods(parser, c.operators);
					ERR_FAIL_COND_V(err2, err2);
				} else if (name2 == "signals") {
					Error err2 = _parse_methods(parser, c.signals);
					ERR_FAIL_COND_V(err2, err2);
				} else if (name2 == "members") {
					while (parser->read() == OK) {
						if (parser->get_node_type() == XMLParser::NODE_ELEMENT) {
							String name3 = parser->get_node_name();

							if (name3 == "member") {
								DocData::PropertyDoc prop2;

								ERR_FAIL_COND_V(!parser->has_attribute("name"), ERR_FILE_CORRUPT);
								prop2.name = parser->get_attribute_value("name");
								ERR_FAIL_COND_V(!parser->has_attribute("type"), ERR_FILE_CORRUPT);
								prop2.type = parser->get_attribute_value("type");
								if (parser->has_attribute("setter")) {
									prop2.setter = parser->get_attribute_value("setter");
								}
								if (parser->has_attribute("getter")) {
									prop2.getter = parser->get_attribute_value("getter");
								}
								if (parser->has_attribute("enum")) {
									prop2.enumeration = parser->get_attribute_value("enum");
								}
								if (!parser->is_empty()) {
									parser->read();
									if (parser->get_node_type() == XMLParser::NODE_TEXT) {
										prop2.description = parser->get_node_data();
									}
								}
								c.properties.push_back(prop2);
							} else {
								ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, "Invalid tag in doc file: " + name3 + ".");
							}

						} else if (parser->get_node_type() == XMLParser::NODE_ELEMENT_END && parser->get_node_name() == "members") {
							break; // End of <members>.
						}
					}

				} else if (name2 == "theme_items") {
					while (parser->read() == OK) {
						if (parser->get_node_type() == XMLParser::NODE_ELEMENT) {
							String name3 = parser->get_node_name();

							if (name3 == "theme_item") {
								DocData::ThemeItemDoc prop2;

								ERR_FAIL_COND_V(!parser->has_attribute("name"), ERR_FILE_CORRUPT);
								prop2.name = parser->get_attribute_value("name");
								ERR_FAIL_COND_V(!parser->has_attribute("type"), ERR_FILE_CORRUPT);
								prop2.type = parser->get_attribute_value("type");
								ERR_FAIL_COND_V(!parser->has_attribute("data_type"), ERR_FILE_CORRUPT);
								prop2.data_type = parser->get_attribute_value("data_type");
								if (!parser->is_empty()) {
									parser->read();
									if (parser->get_node_type() == XMLParser::NODE_TEXT) {
										prop2.description = parser->get_node_data();
									}
								}
								c.theme_properties.push_back(prop2);
							} else {
								ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, "Invalid tag in doc file: " + name3 + ".");
							}

						} else if (parser->get_node_type() == XMLParser::NODE_ELEMENT_END && parser->get_node_name() == "theme_items") {
							break; // End of <theme_items>.
						}
					}

				} else if (name2 == "constants") {
					while (parser->read() == OK) {
						if (parser->get_node_type() == XMLParser::NODE_ELEMENT) {
							String name3 = parser->get_node_name();

							if (name3 == "constant") {
								DocData::ConstantDoc constant2;
								ERR_FAIL_COND_V(!parser->has_attribute("name"), ERR_FILE_CORRUPT);
								constant2.name = parser->get_attribute_value("name");
								ERR_FAIL_COND_V(!parser->has_attribute("value"), ERR_FILE_CORRUPT);
								constant2.value = parser->get_attribute_value("value");
								constant2.is_value_valid = true;
								if (parser->has_attribute("enum")) {
									constant2.enumeration = parser->get_attribute_value("enum");
								}
								if (!parser->is_empty()) {
									parser->read();
									if (parser->get_node_type() == XMLParser::NODE_TEXT) {
										constant2.description = parser->get_node_data();
									}
								}
								c.constants.push_back(constant2);
							} else {
								ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, "Invalid tag in doc file: " + name3 + ".");
							}

						} else if (parser->get_node_type() == XMLParser::NODE_ELEMENT_END && parser->get_node_name() == "constants") {
							break; // End of <constants>.
						}
					}

				} else {
					ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, "Invalid tag in doc file: " + name2 + ".");
				}

			} else if (parser->get_node_type() == XMLParser::NODE_ELEMENT_END && parser->get_node_name() == "class") {
				break; // End of <class>.
			}
		}
	}

	return OK;
}

static void _write_string(FileAccess *f, int p_tablevel, const String &p_string) {
	if (p_string.is_empty()) {
		return;
	}
	String tab;
	for (int i = 0; i < p_tablevel; i++) {
		tab += "\t";
	}
	f->store_string(tab + p_string + "\n");
}

static void _write_method_doc(FileAccess *f, const String &p_name, Vector<DocData::MethodDoc> &p_method_docs) {
	if (!p_method_docs.is_empty()) {
		p_method_docs.sort();
		_write_string(f, 1, "<" + p_name + "s>");
		for (int i = 0; i < p_method_docs.size(); i++) {
			const DocData::MethodDoc &m = p_method_docs[i];

			String qualifiers;
			if (!m.qualifiers.is_empty()) {
				qualifiers += " qualifiers=\"" + m.qualifiers.xml_escape() + "\"";
			}

			_write_string(f, 2, "<" + p_name + " name=\"" + m.name.xml_escape() + "\"" + qualifiers + ">");

			if (!m.return_type.is_empty()) {
				String enum_text;
				if (!m.return_enum.is_empty()) {
					enum_text = " enum=\"" + m.return_enum + "\"";
				}
				_write_string(f, 3, "<return type=\"" + m.return_type + "\"" + enum_text + " />");
			}
			if (m.errors_returned.size() > 0) {
				for (int j = 0; j < m.errors_returned.size(); j++) {
					_write_string(f, 3, "<returns_error number=\"" + itos(m.errors_returned[j]) + "\"/>");
				}
			}

			for (int j = 0; j < m.arguments.size(); j++) {
				const DocData::ArgumentDoc &a = m.arguments[j];

				String enum_text;
				if (!a.enumeration.is_empty()) {
					enum_text = " enum=\"" + a.enumeration + "\"";
				}

				if (!a.default_value.is_empty()) {
					_write_string(f, 3, "<argument index=\"" + itos(j) + "\" name=\"" + a.name.xml_escape() + "\" type=\"" + a.type.xml_escape() + "\"" + enum_text + " default=\"" + a.default_value.xml_escape(true) + "\" />");
				} else {
					_write_string(f, 3, "<argument index=\"" + itos(j) + "\" name=\"" + a.name.xml_escape() + "\" type=\"" + a.type.xml_escape() + "\"" + enum_text + " />");
				}
			}

			_write_string(f, 3, "<description>");
			_write_string(f, 4, _translate_doc_string(m.description).strip_edges().xml_escape());
			_write_string(f, 3, "</description>");

			_write_string(f, 2, "</" + p_name + ">");
		}

		_write_string(f, 1, "</" + p_name + "s>");
	}
}

Error DocTools::save_classes(const String &p_default_path, const Map<String, String> &p_class_path) {
	for (KeyValue<String, DocData::ClassDoc> &E : class_list) {
		DocData::ClassDoc &c = E.value;

		String save_path;
		if (p_class_path.has(c.name)) {
			save_path = p_class_path[c.name];
		} else {
			save_path = p_default_path;
		}

		Error err;
		String save_file = save_path.plus_file(c.name + ".xml");
		FileAccessRef f = FileAccess::open(save_file, FileAccess::WRITE, &err);

		ERR_CONTINUE_MSG(err != OK, "Can't write doc file: " + save_file + ".");

		_write_string(f, 0, "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>");

		String header = "<class name=\"" + c.name + "\"";
		if (!c.inherits.is_empty()) {
			header += " inherits=\"" + c.inherits + "\"";
		}
		header += String(" version=\"") + VERSION_BRANCH + "\"";
		header += ">";
		_write_string(f, 0, header);

		_write_string(f, 1, "<brief_description>");
		_write_string(f, 2, _translate_doc_string(c.brief_description).strip_edges().xml_escape());
		_write_string(f, 1, "</brief_description>");

		_write_string(f, 1, "<description>");
		_write_string(f, 2, _translate_doc_string(c.description).strip_edges().xml_escape());
		_write_string(f, 1, "</description>");

		_write_string(f, 1, "<tutorials>");
		for (int i = 0; i < c.tutorials.size(); i++) {
			DocData::TutorialDoc tutorial = c.tutorials.get(i);
			String title_attribute = (!tutorial.title.is_empty()) ? " title=\"" + tutorial.title.xml_escape() + "\"" : "";
			_write_string(f, 2, "<link" + title_attribute + ">" + tutorial.link.xml_escape() + "</link>");
		}
		_write_string(f, 1, "</tutorials>");

		_write_method_doc(f, "constructor", c.constructors);

		_write_method_doc(f, "method", c.methods);

		if (!c.properties.is_empty()) {
			_write_string(f, 1, "<members>");

			c.properties.sort();

			for (int i = 0; i < c.properties.size(); i++) {
				String additional_attributes;
				if (!c.properties[i].enumeration.is_empty()) {
					additional_attributes += " enum=\"" + c.properties[i].enumeration + "\"";
				}
				if (!c.properties[i].default_value.is_empty()) {
					additional_attributes += " default=\"" + c.properties[i].default_value.xml_escape(true) + "\"";
				}

				const DocData::PropertyDoc &p = c.properties[i];

				if (c.properties[i].overridden) {
					_write_string(f, 2, "<member name=\"" + p.name + "\" type=\"" + p.type + "\" setter=\"" + p.setter + "\" getter=\"" + p.getter + "\" overrides=\"" + p.overrides + "\"" + additional_attributes + " />");
				} else {
					_write_string(f, 2, "<member name=\"" + p.name + "\" type=\"" + p.type + "\" setter=\"" + p.setter + "\" getter=\"" + p.getter + "\"" + additional_attributes + ">");
					_write_string(f, 3, _translate_doc_string(p.description).strip_edges().xml_escape());
					_write_string(f, 2, "</member>");
				}
			}
			_write_string(f, 1, "</members>");
		}

		_write_method_doc(f, "signal", c.signals);

		if (!c.constants.is_empty()) {
			_write_string(f, 1, "<constants>");
			for (int i = 0; i < c.constants.size(); i++) {
				const DocData::ConstantDoc &k = c.constants[i];
				if (k.is_value_valid) {
					if (!k.enumeration.is_empty()) {
						_write_string(f, 2, "<constant name=\"" + k.name + "\" value=\"" + k.value + "\" enum=\"" + k.enumeration + "\">");
					} else {
						_write_string(f, 2, "<constant name=\"" + k.name + "\" value=\"" + k.value + "\">");
					}
				} else {
					if (!k.enumeration.is_empty()) {
						_write_string(f, 2, "<constant name=\"" + k.name + "\" value=\"platform-dependent\" enum=\"" + k.enumeration + "\">");
					} else {
						_write_string(f, 2, "<constant name=\"" + k.name + "\" value=\"platform-dependent\">");
					}
				}
				_write_string(f, 3, _translate_doc_string(k.description).strip_edges().xml_escape());
				_write_string(f, 2, "</constant>");
			}

			_write_string(f, 1, "</constants>");
		}

		if (!c.theme_properties.is_empty()) {
			c.theme_properties.sort();

			_write_string(f, 1, "<theme_items>");
			for (int i = 0; i < c.theme_properties.size(); i++) {
				const DocData::ThemeItemDoc &ti = c.theme_properties[i];

				if (!ti.default_value.is_empty()) {
					_write_string(f, 2, "<theme_item name=\"" + ti.name + "\" data_type=\"" + ti.data_type + "\" type=\"" + ti.type + "\" default=\"" + ti.default_value.xml_escape(true) + "\">");
				} else {
					_write_string(f, 2, "<theme_item name=\"" + ti.name + "\" data_type=\"" + ti.data_type + "\" type=\"" + ti.type + "\">");
				}

				_write_string(f, 3, _translate_doc_string(ti.description).strip_edges().xml_escape());

				_write_string(f, 2, "</theme_item>");
			}
			_write_string(f, 1, "</theme_items>");
		}

		_write_method_doc(f, "operator", c.operators);

		_write_string(f, 0, "</class>");
	}

	return OK;
}

Error DocTools::load_compressed(const uint8_t *p_data, int p_compressed_size, int p_uncompressed_size) {
	Vector<uint8_t> data;
	data.resize(p_uncompressed_size);
	Compression::decompress(data.ptrw(), p_uncompressed_size, p_data, p_compressed_size, Compression::MODE_DEFLATE);
	class_list.clear();

	Ref<XMLParser> parser = memnew(XMLParser);
	Error err = parser->open_buffer(data);
	if (err) {
		return err;
	}

	_load(parser);

	return OK;
}


text:
. ./util.sh

P_UID=`id -u postgres`

if [ ${EUID} -ne ${P_UID} ] ; then
   log "You must run this script as user postgres."
   exit 1;
fi

createdb site ||
{
    log "Failed to create site database."
    exit 2;
}

createuser -P -R -D -S -e -l django_site ||
{
    log "Failed to create user"
    exit 3;
}

psql -c "grant all privileges on database site to django_site; "

redpajama_set_name: RedPajamaGithub


text:
package org.trustedanalytics.ingestion;

import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;

public class OnFeatureVectorArrived implements MqttCallback {

    private static final Logger LOGGER = LoggerFactory.getLogger(OnFeatureVectorArrived.class);

    private final Function<float[], Boolean> scoringEngine;
    private final Consumer<Float> scoringStore;

    public OnFeatureVectorArrived(Function<float[], Boolean> scoringEngine,
        Consumer<Float> scoringStore) {
        this.scoringEngine = scoringEngine;
        this.scoringStore = scoringStore;
    }

    @Override public void connectionLost(Throwable throwable) {
        LOGGER.error("Connection lost. " + throwable);
    }

    @Override public void messageArrived(String topic, MqttMessage mqttMessage)
        throws Exception {

        LOGGER.debug("message: {}", mqttMessage);

        final List<Float> dataVector = getDataVector(mqttMessage);
        if (dataVector.size() < 2) {
            LOGGER.warn(
                "Bad input data format: we're looking for at least 2 array elements, but got only {}",
                dataVector.size());
            return;
        }

        float score = dataVector.get(0);
        float[] featureArray = getFeatureArray(dataVector, score);

        if (!scoringEngine.apply(featureArray)) {
            LOGGER.debug("Anomaly detected - store info in Influx");
            scoringStore.accept(score);
        } else {
            LOGGER.debug("No anomaly detected");
        }
    }

    private List<Float> getDataVector(MqttMessage mqttMessage) {
        return Arrays.stream(mqttMessage.toString().split(","))
            .map(Float::parseFloat)
            .collect(Collectors.toList());
    }

    private float[] getFeatureArray(List<Float> dataVector, float score) {
        List<Float> featureVector = dataVector.subList(1, dataVector.size());
        LOGGER.debug("score: {}", score);
        LOGGER.debug("featureVector: {}", featureVector);

        float[] featureArray = new float[featureVector.size()];
        for (int i = 0; i < featureArray.length; ++i) {
            featureArray[i] = featureVector.get(i);
        }
        return featureArray;
    }

    @Override public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) {
        LOGGER.debug("deliveryComplete: " + iMqttDeliveryToken);
    }
}


text:
/*
 * DON'T INCLUDE THIS DIRECTLY.
 */

#ifndef NPY_NDARRAYOBJECT_H
#define NPY_NDARRAYOBJECT_H
#ifdef __cplusplus
#define CONFUSE_EMACS {
#define CONFUSE_EMACS2 }
extern "C" CONFUSE_EMACS
#undef CONFUSE_EMACS
#undef CONFUSE_EMACS2
/* ... otherwise a semi-smart identer (like emacs) tries to indent
       everything when you're typing */
#endif

#include <Python.h>
#include "ndarraytypes.h"

/* Includes the "function" C-API -- these are all stored in a
   list of pointers --- one for each file
   The two lists are concatenated into one in multiarray.

   They are available as import_array()
*/

#include "__multiarray_api.h"

/* C-API that requires previous API to be defined */

#define PyArray_DescrCheck(op) (((PyObject*)(op))->ob_type==&PyArrayDescr_Type)

#define PyArray_Check(op) PyObject_TypeCheck(op, &PyArray_Type)
#define PyArray_CheckExact(op) (((PyObject*)(op))->ob_type == &PyArray_Type)

#define PyArray_HasArrayInterfaceType(op, type, context, out)                 \
        ((((out)=PyArray_FromStructInterface(op)) != Py_NotImplemented) ||    \
         (((out)=PyArray_FromInterface(op)) != Py_NotImplemented) ||          \
         (((out)=PyArray_FromArrayAttr(op, type, context)) !=                 \
          Py_NotImplemented))

#define PyArray_HasArrayInterface(op, out)                                    \
        PyArray_HasArrayInterfaceType(op, NULL, NULL, out)

#define PyArray_IsZeroDim(op) (PyArray_Check(op) && \
                               (PyArray_NDIM((PyArrayObject *)op) == 0))

#define PyArray_IsScalar(obj, cls)                                            \
        (PyObject_TypeCheck(obj, &Py##cls##ArrType_Type))

#define PyArray_CheckScalar(m) (PyArray_IsScalar(m, Generic) ||               \
                                PyArray_IsZeroDim(m))
#if PY_MAJOR_VERSION >= 3
#define PyArray_IsPythonNumber(obj)                                           \
        (PyFloat_Check(obj) || PyComplex_Check(obj) ||                        \
         PyLong_Check(obj) || PyBool_Check(obj))
#define PyArray_IsIntegerScalar(obj) (PyLong_Check(obj)                       \
              || PyArray_IsScalar((obj), Integer))
#define PyArray_IsPythonScalar(obj)                                           \
        (PyArray_IsPythonNumber(obj) || PyBytes_Check(obj) ||                 \
         PyUnicode_Check(obj))
#else
#define PyArray_IsPythonNumber(obj)                                           \
        (PyInt_Check(obj) || PyFloat_Check(obj) || PyComplex_Check(obj) ||    \
         PyLong_Check(obj) || PyBool_Check(obj))
#define PyArray_IsIntegerScalar(obj) (PyInt_Check(obj)                        \
              || PyLong_Check(obj)                                            \
              || PyArray_IsScalar((obj), Integer))
#define PyArray_IsPythonScalar(obj)                                           \
        (PyArray_IsPythonNumber(obj) || PyString_Check(obj) ||                \
         PyUnicode_Check(obj))
#endif

#define PyArray_IsAnyScalar(obj)                                              \
        (PyArray_IsScalar(obj, Generic) || PyArray_IsPythonScalar(obj))

#define PyArray_CheckAnyScalar(obj) (PyArray_IsPythonScalar(obj) ||           \
                                     PyArray_CheckScalar(obj))

#define PyArray_GETCONTIGUOUS(m) (PyArray_ISCONTIGUOUS(m) ?                   \
                                  Py_INCREF(m), (m) :                         \
                                  (PyArrayObject *)(PyArray_Copy(m)))

#define PyArray_SAMESHAPE(a1,a2) ((PyArray_NDIM(a1) == PyArray_NDIM(a2)) &&   \
                                  PyArray_CompareLists(PyArray_DIMS(a1),      \
                                                       PyArray_DIMS(a2),      \
                                                       PyArray_NDIM(a1)))

#define PyArray_SIZE(m) PyArray_MultiplyList(PyArray_DIMS(m), PyArray_NDIM(m))
#define PyArray_NBYTES(m) (PyArray_ITEMSIZE(m) * PyArray_SIZE(m))
#define PyArray_FROM_O(m) PyArray_FromAny(m, NULL, 0, 0, 0, NULL)

#define PyArray_FROM_OF(m,flags) PyArray_CheckFromAny(m, NULL, 0, 0, flags,   \
                                                      NULL)

#define PyArray_FROM_OT(m,type) PyArray_FromAny(m,                            \
                                PyArray_DescrFromType(type), 0, 0, 0, NULL)

#define PyArray_FROM_OTF(m, type, flags) \
        PyArray_FromAny(m, PyArray_DescrFromType(type), 0, 0, \
                        (((flags) & NPY_ARRAY_ENSURECOPY) ? \
                         ((flags) | NPY_ARRAY_DEFAULT) : (flags)), NULL)

#define PyArray_FROMANY(m, type, min, max, flags) \
        PyArray_FromAny(m, PyArray_DescrFromType(type), min, max, \
                        (((flags) & NPY_ARRAY_ENSURECOPY) ? \
                         (flags) | NPY_ARRAY_DEFAULT : (flags)), NULL)

#define PyArray_ZEROS(m, dims, type, is_f_order) \
        PyArray_Zeros(m, dims, PyArray_DescrFromType(type), is_f_order)

#define PyArray_EMPTY(m, dims, type, is_f_order) \
        PyArray_Empty(m, dims, PyArray_DescrFromType(type), is_f_order)

#define PyArray_FILLWBYTE(obj, val) memset(PyArray_DATA(obj), val, \
                                           PyArray_NBYTES(obj))

#define PyArray_REFCOUNT(obj) (((PyObject *)(obj))->ob_refcnt)
#define NPY_REFCOUNT PyArray_REFCOUNT
#define NPY_MAX_ELSIZE (2 * NPY_SIZEOF_LONGDOUBLE)

#define PyArray_ContiguousFromAny(op, type, min_depth, max_depth) \
        PyArray_FromAny(op, PyArray_DescrFromType(type), min_depth, \
                              max_depth, NPY_ARRAY_DEFAULT, NULL)

#define PyArray_EquivArrTypes(a1, a2) \
        PyArray_EquivTypes(PyArray_DESCR(a1), PyArray_DESCR(a2))

#define PyArray_EquivByteorders(b1, b2) \
        (((b1) == (b2)) || (PyArray_ISNBO(b1) == PyArray_ISNBO(b2)))

#define PyArray_SimpleNew(nd, dims, typenum) \
        PyArray_New(&PyArray_Type, nd, dims, typenum, NULL, NULL, 0, 0, NULL)

#define PyArray_SimpleNewFromData(nd, dims, typenum, data) \
        PyArray_New(&PyArray_Type, nd, dims, typenum, NULL, \
                    data, 0, NPY_ARRAY_CARRAY, NULL)

#define PyArray_SimpleNewFromDescr(nd, dims, descr) \
        PyArray_NewFromDescr(&PyArray_Type, descr, nd, dims, \
                             NULL, NULL, 0, NULL)

#define PyArray_ToScalar(data, arr) \
        PyArray_Scalar(data, PyArray_DESCR(arr), (PyObject *)arr)

/* These might be faster without the dereferencing of obj
   going on inside -- of course an optimizing compiler should
   inline the constants inside a for loop making it a moot point
*/

#define PyArray_GETPTR1(obj, i) ((void *)(PyArray_BYTES(obj) + \
                                         (i)*PyArray_STRIDES(obj)[0]))

#define PyArray_GETPTR2(obj, i, j) ((void *)(PyArray_BYTES(obj) + \
                                            (i)*PyArray_STRIDES(obj)[0] + \
                                            (j)*PyArray_STRIDES(obj)[1]))

#define PyArray_GETPTR3(obj, i, j, k) ((void *)(PyArray_BYTES(obj) + \
                                            (i)*PyArray_STRIDES(obj)[0] + \
                                            (j)*PyArray_STRIDES(obj)[1] + \
                                            (k)*PyArray_STRIDES(obj)[2]))

#define PyArray_GETPTR4(obj, i, j, k, l) ((void *)(PyArray_BYTES(obj) + \
                                            (i)*PyArray_STRIDES(obj)[0] + \
                                            (j)*PyArray_STRIDES(obj)[1] + \
                                            (k)*PyArray_STRIDES(obj)[2] + \
                                            (l)*PyArray_STRIDES(obj)[3]))

static NPY_INLINE void
PyArray_XDECREF_ERR(PyArrayObject *arr)
{
    if (arr != NULL) {
        if (PyArray_FLAGS(arr) & NPY_ARRAY_UPDATEIFCOPY) {
            PyArrayObject *base = (PyArrayObject *)PyArray_BASE(arr);
            PyArray_ENABLEFLAGS(base, NPY_ARRAY_WRITEABLE);
            PyArray_CLEARFLAGS(arr, NPY_ARRAY_UPDATEIFCOPY);
        }
        Py_DECREF(arr);
    }
}

#define PyArray_DESCR_REPLACE(descr) do { \
                PyArray_Descr *_new_; \
                _new_ = PyArray_DescrNew(descr); \
                Py_XDECREF(descr); \
                descr = _new_; \
        } while(0)

/* Copy should always return contiguous array */
#define PyArray_Copy(obj) PyArray_NewCopy(obj, NPY_CORDER)

#define PyArray_FromObject(op, type, min_depth, max_depth) \
        PyArray_FromAny(op, PyArray_DescrFromType(type), min_depth, \
                              max_depth, NPY_ARRAY_BEHAVED | \
                                         NPY_ARRAY_ENSUREARRAY, NULL)

#define PyArray_ContiguousFromObject(op, type, min_depth, max_depth) \
        PyArray_FromAny(op, PyArray_DescrFromType(type), min_depth, \
                              max_depth, NPY_ARRAY_DEFAULT | \
                                         NPY_ARRAY_ENSUREARRAY, NULL)

#define PyArray_CopyFromObject(op, type, min_depth, max_depth) \
        PyArray_FromAny(op, PyArray_DescrFromType(type), min_depth, \
                        max_depth, NPY_ARRAY_ENSURECOPY | \
                                   NPY_ARRAY_DEFAULT | \
                                   NPY_ARRAY_ENSUREARRAY, NULL)

#define PyArray_Cast(mp, type_num)                                            \
        PyArray_CastToType(mp, PyArray_DescrFromType(type_num), 0)

#define PyArray_Take(ap, items, axis)                                         \
        PyArray_TakeFrom(ap, items, axis, NULL, NPY_RAISE)

#define PyArray_Put(ap, items, values)                                        \
        PyArray_PutTo(ap, items, values, NPY_RAISE)

/* Compatibility with old Numeric stuff -- don't use in new code */

#define PyArray_FromDimsAndData(nd, d, type, data)                            \
        PyArray_FromDimsAndDataAndDescr(nd, d, PyArray_DescrFromType(type),   \
                                        data)

/*
   Check to see if this key in the dictionary is the "title"
   entry of the tuple (i.e. a duplicate dictionary entry in the fields
   dict.
*/

#define NPY_TITLE_KEY(key, value) ((PyTuple_GET_SIZE((value))==3) && \
                                   (PyTuple_GET_ITEM((value), 2) == (key)))

#define DEPRECATE(msg) PyErr_WarnEx(PyExc_DeprecationWarning,msg,1)
#define DEPRECATE_FUTUREWARNING(msg) PyErr_WarnEx(PyExc_FutureWarning,msg,1)

#ifdef __cplusplus
}
#endif

#endif /* NPY_NDARRAYOBJECT_H */


text:
=pod

=head1 NAME

OSSL_TIME, OSSL_TIME_SECOND, OSSL_TIME_MS, OSSL_TIME_US,
ossl_time_infinite, ossl_time_zero, ossl_time_now,
ossl_ticks2time, ossl_time2ticks, ossl_seconds2time, ossl_time2seconds,
ossl_ms2time, ossl_us2time, ossl_time2ms, ossl_time2us,
ossl_time_to_timeval, ossl_time_from_timeval,
ossl_time_to_time_t, ossl_time_from_time_t,
ossl_time_compare, ossl_time_is_zero, ossl_time_is_infinite,
ossl_time_add, ossl_time_subtract,
ossl_time_multiply, ossl_time_divide, ossl_time_muldiv,
ossl_time_abs_difference, ossl_time_max,
ossl_time_min - times and durations

=head1 SYNOPSIS

 #include "internal/time.h"

 typedef struct OSSL_TIME;

 #define OSSL_TIME_SECOND   /* Ticks per second */
 #define OSSL_TIME_MS       /* Ticks per millisecond */
 #define OSSL_TIME_US       /* Ticks per microsecond */

 OSSL_TIME ossl_ticks2time(uint64_t);
 uint64_t ossl_time2ticks(OSSL_TIME t);
 OSSL_TIME ossl_seconds2time(uint64_t);
 uint64_t ossl_time2seconds(OSSL_TIME t);
 OSSL_TIME ossl_ms2time(uint64_t);
 uint64_t ossl_time2ms(OSSL_TIME t);
 OSSL_TIME ossl_us2time(uint64_t);
 uint64_t ossl_time2us(OSSL_TIME t);

 OSSL_TIME ossl_time_zero(void);
 OSSL_TIME ossl_time_infinite(void);
 OSSL_TIME ossl_time_now(void);

 struct timeval ossl_time_to_timeval(OSSL_TIME t);
 OSSL_TIME ossl_time_from_timeval(struct timeval tv);
 time_t ossl_time_to_time_t(OSSL_TIME t);
 OSSL_TIME ossl_time_from_time_t(time_t t);

 int ossl_time_compare(OSSL_TIME a, OSSL_TIME b);
 int ossl_time_is_zero(OSSL_TIME t);
 int ossl_time_is_infinite(OSSL_TIME t);

 OSSL_TIME ossl_time_add(OSSL_TIME a, OSSL_TIME b);
 OSSL_TIME ossl_time_subtract(OSSL_TIME a, OSSL_TIME b);
 OSSL_TIME ossl_time_multiply(OSSL_TIME a, uint64_t b);
 OSSL_TIME ossl_time_divide(OSSL_TIME a, uint64_t b);
 OSSL_TIME ossl_time_muldiv(OSSL_TIME a, uint64_t b, uint64_t c);
 OSSL_TIME ossl_time_abs_difference(OSSL_TIME a, OSSL_TIME b);
 OSSL_TIME ossl_time_max(OSSL_TIME a, OSSL_TIME b);
 OSSL_TIME ossl_time_min(OSSL_TIME a, OSSL_TIME b);

=head1 DESCRIPTION

These functions allow the current time to be obtained and for basic
arithmetic operations to be safely performed with times and durations.

B<OSSL_TIME> can represent a duration, or a point in time. Where it is
used to represent a point in time, it does so by expressing a duration
relative to some reference Epoch.  The OSSL_TIME structure itself does
not contain information about the Epoch used; thus, interpretation of
an OSSL_TIME requires that the Epoch it is to be interpreted relative
to is contextually understood.

B<OSSL_TIME_SECOND> is an integer that indicates the precision of an
B<OSSL_TIME>.  Specifically, it is the number of counts per second that
a time can represent.  The accuracy is independent of this and is system
dependent.

B<ossl_ticks2time> converts an integral number of counts to a time.

B<ossl_time2ticks> converts a time to an integral number of counts.

B<ossl_seconds2time>, B<ossl_ms2time> and B<ossl_us2time> convert an
integral number of seconds, milliseconds and microseconds respectively
to a time.  These functions are implemented as macros.

B<ossl_time2seconds>, B<ossl_time2ms> and B<ossl_time2us> convert a
time to an integral number of second, milliseconds and microseconds
respectively.  These functions truncates any fractional seconds and are
implemented as macros.

B<ossl_time_zero> returns the smallest representable B<OSSL_TIME>.
This value represents the time Epoch and it is returned when an underflow
would otherwise occur.

B<ossl_time_infinite> returns the largest representable B<OSSL_TIME>.
This value is returned when an overflow would otherwise occur.

B<ossl_time_now> returns the current time relative to an Epoch which
is undefined but unchanging for at least the duration of program
execution.  The time returned is monotonic and need not represent
wall-clock time.  The time returned by this function is useful for
scheduling timeouts, deadlines and recurring events, but due to its
undefined Epoch and monotonic nature, is not suitable for other uses.

B<ossl_time_to_timeval> converts a time to a I<struct timeval>.

B<ossl_time_from_timeval> converts a I<struct timeval> to a time.

B<ossl_time_to_time_t> converts a time to a I<time_t>.

B<ossl_time_from_time_t> converts a I<time_t> to a time.

B<ossl_time_compare> compares I<a> with I<b> and returns -1 if I<a>
is smaller than I<b>, 0 if they are equal and +1 if I<a> is
larger than I<b>.

B<ossl_time_is_zero> returns 1 if the time I<t> is zero and 0 otherwise.

B<ossl_time_is_infinite> returns 1 if the time I<t> is infinite and 0 otherwise.

B<ossl_time_add> performs a saturating addition of the two times,
returning I<a> + I<b>.
If the summation would overflow B<OSSL_TIME_INFINITY> is returned.

B<ossl_time_subtract> performs a saturating subtraction of the two items,
returning I<a> - I<b>.
If the difference would be negative,  B<0> is returned.

B<ossl_time_multiply> performs a saturating multiplication of a time value by a
given integer multiplier returning I<a> × I<b>.

B<ossl_time_divide> performs division of a time value by a given integer
divisor returning ⌊I<a> ÷ I<b>⌋.

B<ossl_time_muldiv> performs a fused multiplication and division operation.
The result is equal to ⌊I<a> × I<b> ÷ I<c>⌋.

B<ossl_time_abs_difference> returns the magnitude of the difference between two
time values.

B<ossl_time_min> returns the lesser of two time values.

B<ossl_time_max> returns the greater of two time values.

=head1 NOTES

The largest representable duration is guaranteed to be at least 500 years.

=head1 RETURN VALUES

B<ossl_time_now> returns the current time, or the time of the Epoch on error.

B<ossl_time_zero> returns the time of the Epoch.

B<ossl_time_infinite> returns the last representable time.

B<ossl_ticks2time>, B<ossl_seconds2time>, B<ossl_ms2time> and B<ossl_us2time>
return the duration specified in ticks, seconds, milliseconds and microseconds
respectively.

B<ossl_time2ticks>, B<ossl_time2seconds>, B<ossl_time2ms> and B<ossl_time2us>
return the number of ticks, seconds, microseconds and microseconds respectively
that the time object represents.

B<ossl_time_to_timeval>, B<ossl_time_from_timeval>, B<ossl_time_to_time_t> and
B<ossl_time_from_time_t> all return the converted time.

B<ossl_time_compare> returns -1, 0 or 1 depending on the comparison.

B<ossl_time_is_zero> and B<ossl_time_is_infinite> return 1 if the condition
is true and 0 otherwise.

B<ossl_time_add> returns the summation of the two times or
the last representable time on overflow.

B<ossl_time_subtract> returns the difference of the two times or the
time of the Epoch on underflow.

B<ossl_time_multiply> returns the result of multiplying the given time by the
given integral multiplier, or B<OSSL_TIME_INFINITY> on overflow.

B<ossl_time_divide> returns the result of dividing the given time by the given
integral divisor.

B<ossl_time_muldiv> returns the fused multiplication and division of the given
time and the two integral values.

B<ossl_time_abs_difference> returns the magnitude of the difference between the
input time values.

B<ossl_time_min> and B<ossl_time_max> choose and return one of the input values.

=head1 HISTORY

This functionality was added in OpenSSL 3.2.

=head1 COPYRIGHT

Copyright 2022 The OpenSSL Project Authors. All Rights Reserved.

Licensed under the Apache License 2.0 (the "License").  You may not use this
file except in compliance with the License.  You can obtain a copy in the file
LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.

=cut


text:
<?php

namespace Eftakhairul;

use PHPUnit\Framework\TestCase;

class RandomPasswordGeneratorTest extends TestCase
{
    /**
     * Checking password's characters count correct or not
     */
    public function testIsReturnCorrectStringCount()
    {
        //Create object
        $passwordGenerator =  new RandomPasswordGenerator();

        //checking password's characters count correct or not
        $this->assertEquals(9, strlen($passwordGenerator->useNumbers()->generatePassword(9) ));
    }

    /**
     * Checking number exists inside password string or not
     */
    public function testIsNumberContain()
    {
        //Create object
        $passwordGenerator = new RandomPasswordGenerator();
        $output            = preg_match("/[0-9]/i", $passwordGenerator->useNumbers(3)->generatePassword());

        //checking number exists inside password string or not
        $this->assertEquals(1, $output);
    }

    /**
     * Checking the password with the special chars
     */
    public function testUseSpecialChars()
    {
        //Create object
        $passwordGenerator = new RandomPasswordGenerator();
        $output            = preg_match("/[@#$%^]/i", $passwordGenerator->useSpecialChars()->generatePassword());

        //checking password's character has the special characters
        $this->assertEquals(1, $output);
    }
}


text:
//-----------------------------------------------------------------------
// <copyright file="FirmaMap.cs" company="Fubar Development Junker">
//     Copyright (c) Fubar Development Junker. All rights reserved.
// </copyright>
// <author>Mark Junker</author>
//-----------------------------------------------------------------------

using FluentNHibernate.Mapping;

namespace FubarDev.Lexware.Database.Global.Mappings
{
    /// <summary>
    /// Das Mapping für die Lexware-Firma
    /// </summary>
    public class FirmaMap : ClassMap<Firma>
    {
        /// <summary>
        /// Initialisiert eine neue Instanz der <see cref="FirmaMap"/> Klasse.
        /// </summary>
        public FirmaMap()
        {
            Schema("LEXGLOBAL");
            Table("LXG_FIRMA");
            Id(x => x.Id, "lID_Firma");
            Map(x => x.Name, "szName").Not.Nullable();
            Map(x => x.Owner, "szOwner").Not.Nullable();
            Map(x => x.Path, "szPath").Not.Nullable();

            Map(m => m.Created, "datErstelltAm");
            Map(m => m.CreatedBy, "szUserErstelltAm");
            Map(m => m.Updated, "datGeaendertAm");
            Map(m => m.UpdatedBy, "szUserGeaendertAm");
        }
    }
}


text:
<?php

namespace app\controllers;

use app\models as Model;
use Ocrend\Kernel\Router\RouterInterface;
use Ocrend\Kernel\Controllers\Controllers;
use Ocrend\Kernel\Controllers\ControllersInterface;

/**
 * Controlador error/
 *
 * @author Brayan Narváez <prinick@ocrend.com>
*/

class errorController extends Controllers implements ControllersInterface {

    public function __construct(RouterInterface $router) {
        parent::__construct($router);
        echo $this->template->render('error/error');
    }

}


text:
var mongoose = require('mongoose')
  , config = require('../config')
;

mongoose.connect(config.db.type + '://' + config.db.host + '/' + config.db.name);

mongoose.connection.on('open', function() {
  //console.log('Database connection opened.');
});

mongoose.connection.on('error', function(err) {
  console.error('Error connecting to database:', err);
});


text:
import * as ts from "../../_namespaces/ts";
import {
    createServerHost,
    File,
    libFile,
} from "../virtualFileSystemWithWatch";
import {
    checkNumberOfProjects,
    checkProjectActualFiles,
    checkProjectRootFiles,
    createProjectService,
    createSession,
    executeSessionRequest,
    executeSessionRequestNoResponse,
    openFilesForSession,
    verifyDynamic,
} from "./helpers";

function verifyPathRecognizedAsDynamic(path: string) {
    const file: File = {
        path,
        content: `/// <reference path="../../../../../../typings/@epic/Core.d.ts" />
/// <reference path="../../../../../../typings/@epic/Shell.d.ts" />
var x = 10;`
    };
    const host = createServerHost([libFile]);
    const projectService = createProjectService(host);
    projectService.openClientFile(file.path, file.content);
    verifyDynamic(projectService, projectService.toPath(file.path));

    projectService.checkNumberOfProjects({ inferredProjects: 1 });
    const project = projectService.inferredProjects[0];
    checkProjectRootFiles(project, [file.path]);
    checkProjectActualFiles(project, [file.path, libFile.path]);
}

describe("unittests:: tsserver:: dynamicFiles:: Untitled files", () => {
    const untitledFile = "untitled:^Untitled-1";
    it("Can convert positions to locations", () => {
        const aTs: File = { path: "/proj/a.ts", content: "" };
        const tsconfig: File = { path: "/proj/tsconfig.json", content: "{}" };
        const session = createSession(createServerHost([aTs, tsconfig]), { useInferredProjectPerProjectRoot: true });

        openFilesForSession([aTs], session);

        executeSessionRequestNoResponse<ts.server.protocol.OpenRequest>(session, ts.server.protocol.CommandTypes.Open, {
            file: untitledFile,
            fileContent: `/// <reference path="../../../../../../typings/@epic/Core.d.ts" />\nlet foo = 1;\nfooo/**/`,
            scriptKindName: "TS",
            projectRootPath: "/proj",
        });
        verifyDynamic(session.getProjectService(), `/proj/untitled:^untitled-1`);
        const response = executeSessionRequest<ts.server.protocol.CodeFixRequest, ts.server.protocol.CodeFixResponse>(session, ts.server.protocol.CommandTypes.GetCodeFixes, {
            file: untitledFile,
            startLine: 3,
            startOffset: 1,
            endLine: 3,
            endOffset: 5,
            errorCodes: [ts.Diagnostics.Cannot_find_name_0_Did_you_mean_1.code],
        });
        assert.deepEqual<readonly ts.server.protocol.CodeFixAction[] | undefined>(response, [
            {
                description: "Change spelling to 'foo'",
                fixName: "spelling",
                changes: [{
                    fileName: untitledFile,
                    textChanges: [{
                        start: { line: 3, offset: 1 },
                        end: { line: 3, offset: 5 },
                        newText: "foo",
                    }],
                }],
                commands: undefined,
                fixId: undefined,
                fixAllDescription: undefined
            },
        ]);
    });

    it("opening untitled files", () => {
        const config: File = {
            path: `/user/username/projects/myproject/tsconfig.json`,
            content: "{}"
        };
        const host = createServerHost([config, libFile], { useCaseSensitiveFileNames: true, currentDirectory: "/user/username/projects/myproject" });
        const service = createProjectService(host);
        service.openClientFile(untitledFile, "const x = 10;", /*scriptKind*/ undefined, "/user/username/projects/myproject");
        checkNumberOfProjects(service, { inferredProjects: 1 });
        checkProjectActualFiles(service.inferredProjects[0], [untitledFile, libFile.path]);
        verifyDynamic(service, `/user/username/projects/myproject/${untitledFile}`);

        const untitled: File = {
            path: `/user/username/projects/myproject/Untitled-1.ts`,
            content: "const x = 10;"
        };
        host.writeFile(untitled.path, untitled.content);
        host.checkTimeoutQueueLength(0);
        service.openClientFile(untitled.path, untitled.content, /*scriptKind*/ undefined, "/user/username/projects/myproject");
        checkNumberOfProjects(service, { configuredProjects: 1, inferredProjects: 1 });
        checkProjectActualFiles(service.configuredProjects.get(config.path)!, [untitled.path, libFile.path, config.path]);
        checkProjectActualFiles(service.inferredProjects[0], [untitledFile, libFile.path]);

        service.closeClientFile(untitledFile);
        checkProjectActualFiles(service.configuredProjects.get(config.path)!, [untitled.path, libFile.path, config.path]);
        checkProjectActualFiles(service.inferredProjects[0], [untitledFile, libFile.path]);

        service.openClientFile(untitledFile, "const x = 10;", /*scriptKind*/ undefined, "/user/username/projects/myproject");
        verifyDynamic(service, `/user/username/projects/myproject/${untitledFile}`);
        checkProjectActualFiles(service.configuredProjects.get(config.path)!, [untitled.path, libFile.path, config.path]);
        checkProjectActualFiles(service.inferredProjects[0], [untitledFile, libFile.path]);
    });

    it("opening and closing untitled files when projectRootPath is different from currentDirectory", () => {
        const config: File = {
            path: `/user/username/projects/myproject/tsconfig.json`,
            content: "{}"
        };
        const file: File = {
            path: `/user/username/projects/myproject/file.ts`,
            content: "const y = 10"
        };
        const host = createServerHost([config, file, libFile], { useCaseSensitiveFileNames: true });
        const service = createProjectService(host, { useInferredProjectPerProjectRoot: true });
        service.openClientFile(untitledFile, "const x = 10;", /*scriptKind*/ undefined, "/user/username/projects/myproject");
        checkNumberOfProjects(service, { inferredProjects: 1 });
        checkProjectActualFiles(service.inferredProjects[0], [untitledFile, libFile.path]);
        verifyDynamic(service, `/user/username/projects/myproject/${untitledFile}`);

        // Close untitled file
        service.closeClientFile(untitledFile);

        // Open file from configured project which should collect inferredProject
        service.openClientFile(file.path);
        checkNumberOfProjects(service, { configuredProjects: 1 });
    });

    it("when changing scriptKind of the untitled files", () => {
        const host = createServerHost([libFile], { useCaseSensitiveFileNames: true });
        const service = createProjectService(host, { useInferredProjectPerProjectRoot: true });
        service.openClientFile(untitledFile, "const x = 10;", ts.ScriptKind.TS, "/user/username/projects/myproject");
        checkNumberOfProjects(service, { inferredProjects: 1 });
        checkProjectActualFiles(service.inferredProjects[0], [untitledFile, libFile.path]);
        const program = service.inferredProjects[0].getCurrentProgram()!;
        const sourceFile = program.getSourceFile(untitledFile)!;

        // Close untitled file
        service.closeClientFile(untitledFile);

        // Open untitled file with different mode
        service.openClientFile(untitledFile, "const x = 10;", ts.ScriptKind.TSX, "/user/username/projects/myproject");
        checkNumberOfProjects(service, { inferredProjects: 1 });
        checkProjectActualFiles(service.inferredProjects[0], [untitledFile, libFile.path]);
        const newProgram = service.inferredProjects[0].getCurrentProgram()!;
        const newSourceFile = newProgram.getSourceFile(untitledFile)!;
        assert.notStrictEqual(newProgram, program);
        assert.notStrictEqual(newSourceFile, sourceFile);
    });
});

describe("unittests:: tsserver:: dynamicFiles:: ", () => {
    it("dynamic file without external project", () => {
        const file: File = {
            path: "^walkThroughSnippet:/Users/UserName/projects/someProject/out/someFile#1.js",
            content: "var x = 10;"
        };
        const host = createServerHost([libFile], { useCaseSensitiveFileNames: true });
        const projectService = createProjectService(host);
        projectService.setCompilerOptionsForInferredProjects({
            module: ts.ModuleKind.CommonJS,
            allowJs: true,
            allowSyntheticDefaultImports: true,
            allowNonTsExtensions: true
        });
        projectService.openClientFile(file.path, "var x = 10;");

        projectService.checkNumberOfProjects({ inferredProjects: 1 });
        const project = projectService.inferredProjects[0];
        checkProjectRootFiles(project, [file.path]);
        checkProjectActualFiles(project, [file.path, libFile.path]);
        verifyDynamic(projectService, `/${file.path}`);

        assert.strictEqual(projectService.ensureDefaultProjectForFile(ts.server.toNormalizedPath(file.path)), project);
        const indexOfX = file.content.indexOf("x");
        assert.deepEqual(project.getLanguageService(/*ensureSynchronized*/ true).getQuickInfoAtPosition(file.path, indexOfX), {
            kind: ts.ScriptElementKind.variableElement,
            kindModifiers: "",
            textSpan: { start: indexOfX, length: 1 },
            displayParts: [
                { text: "var", kind: "keyword" },
                { text: " ", kind: "space" },
                { text: "x", kind: "localName" },
                { text: ":", kind: "punctuation" },
                { text: " ", kind: "space" },
                { text: "number", kind: "keyword" }
            ],
            documentation: [],
            tags: undefined,
        });
    });

    it("dynamic file with reference paths without external project", () => {
        verifyPathRecognizedAsDynamic("^walkThroughSnippet:/Users/UserName/projects/someProject/out/someFile#1.js");
    });

    describe("dynamic file with projectRootPath", () => {
        const file: File = {
            path: "^walkThroughSnippet:/Users/UserName/projects/someProject/out/someFile#1.js",
            content: "var x = 10;"
        };
        const configFile: File = {
            path: `/user/username/projects/myproject/tsconfig.json`,
            content: "{}"
        };
        const configProjectFile: File = {
            path: `/user/username/projects/myproject/a.ts`,
            content: "let y = 10;"
        };
        it("with useInferredProjectPerProjectRoot", () => {
            const host = createServerHost([libFile, configFile, configProjectFile], { useCaseSensitiveFileNames: true });
            const session = createSession(host, { useInferredProjectPerProjectRoot: true });
            openFilesForSession([{ file: file.path, projectRootPath: "/user/username/projects/myproject" }], session);

            const projectService = session.getProjectService();
            checkNumberOfProjects(projectService, { inferredProjects: 1 });
            checkProjectActualFiles(projectService.inferredProjects[0], [file.path, libFile.path]);
            verifyDynamic(projectService, `/user/username/projects/myproject/${file.path}`);

            session.executeCommandSeq<ts.server.protocol.OutliningSpansRequest>({
                command: ts.server.protocol.CommandTypes.GetOutliningSpans,
                arguments: {
                    file: file.path
                }
            });

            // Without project root
            const file2Path = file.path.replace("#1", "#2");
            projectService.openClientFile(file2Path, file.content);
            checkNumberOfProjects(projectService, { inferredProjects: 2 });
            checkProjectActualFiles(projectService.inferredProjects[0], [file.path, libFile.path]);
            checkProjectActualFiles(projectService.inferredProjects[1], [file2Path, libFile.path]);
        });

        it("fails when useInferredProjectPerProjectRoot is false", () => {
            const host = createServerHost([libFile, configFile, configProjectFile], { useCaseSensitiveFileNames: true });
            const projectService = createProjectService(host);
            try {
                projectService.openClientFile(file.path, file.content, /*scriptKind*/ undefined, "/user/username/projects/myproject");
            }
            catch (e) {
                assert.strictEqual(
                    e.message.replace(/\r?\n/, "\n"),
                    `Debug Failure. False expression.\nVerbose Debug Information: {"fileName":"^walkThroughSnippet:/Users/UserName/projects/someProject/out/someFile#1.js","currentDirectory":"/user/username/projects/myproject","hostCurrentDirectory":"/","openKeys":[]}\nDynamic files must always be opened with service's current directory or service should support inferred project per projectRootPath.`
                );
            }
            const file2Path = file.path.replace("#1", "#2");
            projectService.openClientFile(file2Path, file.content);
            projectService.checkNumberOfProjects({ inferredProjects: 1 });
            checkProjectActualFiles(projectService.inferredProjects[0], [file2Path, libFile.path]);
        });
    });

    describe("verify accepts known schemas as dynamic file", () => {
        it("walkThroughSnippet", () => {
            verifyPathRecognizedAsDynamic("walkThroughSnippet:/usr/share/code/resources/app/out/vs/workbench/contrib/welcome/walkThrough/browser/editor/^vs_code_editor_walkthrough.md#1.ts");
        });

        it("untitled", () => {
            verifyPathRecognizedAsDynamic("untitled:/Users/matb/projects/san/^newFile.ts");
        });
    });
});


text:
require "httparty"
require "uri"

module Itebooks
  class Book
    # include HTTParty module so I can use its methods without referring to the HTTParty namespace all the time
    include HTTParty

    base_uri 'http://it-ebooks-api.info/v1/'

    def initialize attrs
      attrs.each do |name, val|
        # make all keys lowercase so they resemble class properties
        lowercase_name = name.downcase
        # dynamically generate instance variable on Book instance for every key and assign respective value to it
        instance_variable_set "@#{lowercase_name}", val
        # define getter method for every key in the response hash
        define_singleton_method(lowercase_name) {instance_variable_get "@#{lowercase_name}"}
      end
    end

    def self.search(query)
      # encode query in case the query contains whitespace or special characters
      encoded_query = URI.encode(query)
      #send the actual request to the it-ebooks-api
      response = get('/search/'+encoded_query)
      # if no books were found for the query, let the user know!
      if response.parsed_response['Total'] == "0"
        puts "No resulsts for: #{query}"
      # otherwise go over every book in the response and turn it into a Book instance
      else
        response['Books'].map { |b| self.new b }
      end
    end

    def self.find(id)
      # send to request
      response = get('/book/'+id.to_s)
      # extract the parsed response only
      attrs = response.parsed_response
      # instantiate a new Book and save all response attributes in instance variables
      self.new attrs
    end
  end
end


text:
var Trello = require('node-trello');
var oscar_conf = require('./conf').conf;

var trello_api = new Trello(oscar_conf['trello_app_key'], oscar_conf['trello_token']);

// Turns Trello into a DB.
function TrelloDB() {
  var _table_name_cache = {};

  // Returns a Trello list ID for the given table
  //
  // Passes the ID to the given callback.
  this._with_list_id = function(table_name, cb) {
    if (_table_name_cache[table_name] !== undefined) {
      cb(_table_name_cache[table_name]);
      return;
    }

    trello_api.get('1/board/' + oscar_conf['trello_db_board'] + '/lists', function(err, data) {
      var db_lists = data.filter(function(db_list) {return (db_list['name'] == table_name)});

      if (db_lists.length == 0) {
        console.log('No list named "' + table_name + '"');
        res.send(500, 'No list named "' + table_name + '"');
        return;
      }
      _table_name_cache[table_name] = db_lists[0]['id'];
      cb(_table_name_cache[table_name]);
    });
  }
}

// Returns all items in the given table for which the given callback returns true.
//
// If provided, `filter_callback` will be used to filter the result set.
// `result_callback(result_rows)` will be called when the lookup is complete.
TrelloDB.prototype.lookup = function(table, filter_callback, result_callback) {
  // Allow filter_callback to be omitted.
  if (result_callback === undefined) {
    result_callback = filter_callback;
    filter_callback = undefined;
  }

  this._with_list_id(table, function(list_id) {
    trello_api.get('1/list/' + list_id + '/cards/open', function(err, data) {
      var cards = data;
      var blobs = cards.map(function(card) { return card['name'] });
      var rows = blobs.map(function(blob) { return JSON.parse(blob) });

      if (filter_callback === undefined) { filter_callback = function(x) { return true } }
      result_callback(rows.filter(filter_callback));
    });
  });
}

// Adds the given item to the given table.
//
// callback() will be called when the insert is complete.
TrelloDB.prototype.insert = function(table, rule, callback) {
  this._with_list_id(table, function(list_id) {
    trello_api.post('1/list/' + list_id + '/cards', {name: JSON.stringify(rule)}, function(err) {
      if (err) { console.log(err); }
      callback();
    });
  });
}

exports.connect = function() { return new TrelloDB() };


text:
export function and () {
  const funs = Array.from(arguments)

  return function and () {
    const args = arguments
    const context = this

    let result

    funs.every(call)

    return result

    function call (fun) {
      return (result = fun.apply(context, args))
    }
  }
}


text:
import bFormCheckbox from './form-checkbox'
import bFormCheckboxGroup from './form-checkbox-group'
import { registerComponents, vueUse } from '../../utils/plugins'

const components = {
  bFormCheckbox,
  bCheckbox: bFormCheckbox,
  bCheck: bFormCheckbox,
  bFormCheckboxGroup,
  bCheckboxGroup: bFormCheckboxGroup,
  bCheckGroup: bFormCheckboxGroup
}

const VuePlugin = {
  install (Vue) {
    registerComponents(Vue, components)
  }
}

vueUse(VuePlugin)

export default VuePlugin


text:
<?php
/**
 * User: zach
 * Date: 6/20/13
 * Time: 9:07 AM
 */

namespace Elasticsearch\Tests\Serializers;

use Elasticsearch\Serializers\ArrayToJSONSerializer;
use PHPUnit_Framework_TestCase;
use Mockery as m;

/**
 * Class ArrayToJSONSerializerTest
 * @package Elasticsearch\Tests\Serializers
 */
class ArrayToJSONSerializerTest extends PHPUnit_Framework_TestCase
{
    public function tearDown()
    {
        m::close();
    }

    public function testSerializeArray()
    {
        $serializer = new ArrayToJSONSerializer();
        $body = array('value' => 'field');

        $ret = $serializer->serialize($body);

        $body = json_encode($body);
        $this->assertEquals($body, $ret);
    }

    public function testSerializeString()
    {
        $serializer = new ArrayToJSONSerializer();
        $body = 'abc';

        $ret = $serializer->serialize($body);

        $this->assertEquals($body, $ret);
    }

    public function testDeserializeJSON()
    {
        $serializer = new ArrayToJSONSerializer();
        $body = '{"field":"value"}';

        $ret = $serializer->deserialize($body);

        $body = json_decode($body, true);
        $this->assertEquals($body, $ret);
    }
}


text:
<?php

namespace ForkCMS\Modules\MediaLibrary\Backend\Ajax;

use ForkCMS\Core\Backend\Domain\Ajax\AjaxAction as BackendBaseAJAXAction;
use ForkCMS\Modules\Internationalisation\Backend\Domain\Translator\Language;
use ForkCMS\Modules\MediaLibrary\Domain\MediaFolder\Exception\MediaFolderNotFound;
use ForkCMS\Modules\MediaLibrary\Domain\MediaFolder\MediaFolder;
use ForkCMS\Modules\MediaLibrary\Domain\MediaFolder\MediaFolderRepository;
use ForkCMS\Modules\MediaLibrary\Domain\MediaGroup\Exception\MediaGroupNotFound;
use ForkCMS\Modules\MediaLibrary\Domain\MediaGroup\MediaGroup;
use ForkCMS\Modules\MediaLibrary\Domain\MediaGroup\MediaGroupRepository;
use ForkCMS\Modules\MediaLibrary\Domain\MediaItem\AspectRatio;
use ForkCMS\Modules\MediaLibrary\Domain\MediaItem\MediaItem;
use ForkCMS\Modules\MediaLibrary\Domain\MediaItem\MediaItemRepository;
use ForkCMS\Core\Common\Exception\AjaxExitException;
use Symfony\Component\HttpFoundation\Response;

/**
 * This AJAX-action will get all media items in a certain folder and from a gallery.
 */
class MediaItemFindAll extends BackendBaseAJAXAction
{
    /** @var string */
    protected $selectedTab = 'image';

    public function execute(): void
    {
        parent::execute();

        $mediaFolder = $this->getMediaFolderBasedOnMediaGroup();
        $aspectRatio = $this->getAspectRatio();
        $searchQuery = $this->getSearchQuery();

        // Output success message with variables
        $this->output(
            Response::HTTP_OK,
            [
                'media' => $this->loadMediaItems($mediaFolder, $aspectRatio, $searchQuery),
                'folder' => $mediaFolder !== null ? $mediaFolder->getId() : null,
                'tab' => $this->selectedTab,
            ]
        );
    }

    private function getAspectRatio(): ?AspectRatio
    {
        $aspectRatio = $this->getRequest()->request->get('aspect_ratio');

        if (empty($aspectRatio) || $aspectRatio === 'false') {
            return null;
        }

        return new AspectRatio($aspectRatio);
    }

    private function getSearchQuery(): ?string
    {
        $query = (string) $this->getRequest()->request->get('query');

        if (empty($query)) {
            return null;
        }

        return $query;
    }

    private function getMediaFolder(): ?MediaFolder
    {
        /** @var int $id */
        $id = $this->getRequest()->request->getInt('folder_id', 0);

        if ($id === 0) {
            return null;
        }

        try {
            /** @var MediaFolder */
            return $this->get(MediaFolderRepository::class)->findOneById($id);
        } catch (MediaFolderNotFound $mediaFolderNotFound) {
            throw new AjaxExitException(Language::err('NonExistingMediaFolder'));
        }
    }

    private function getMediaFolderBasedOnMediaGroup(): ?MediaFolder
    {
        /** @var MediaFolder|null $mediaFolder */
        $mediaFolder = $this->getMediaFolder();

        if ($mediaFolder !== null) {
            return $mediaFolder;
        }

        $mediaGroup = $this->getMediaGroup();

        if ($mediaGroup === null || $mediaGroup->getConnectedItems()->count() === 0) {
            if ($mediaFolder === null) {
                return $this->get(MediaFolderRepository::class)->findDefault();
            }

            return $mediaFolder;
        }

        /** @var MediaItem $mediaItem The first item of the gallery MediaGroup */
        $mediaItem = $mediaGroup->getConnectedItems()->first()->getItem();

        // Redefine tab
        $this->selectedTab = (string) $mediaItem->getType();

        // Redefine folder
        return $mediaItem->getFolder();
    }

    private function getMediaGroup(): ?MediaGroup
    {
        /** @var string $id */
        $id = $this->getRequest()->request->get('group_id', '');

        if ($id === '') {
            return null;
        }

        try {
            /** @var MediaGroup */
            return $this->get(MediaGroupRepository::class)->findOneById($id);
        } catch (MediaGroupNotFound $mediaGroupNotFound) {
            return null;
        }
    }

    private function loadMediaItems(?MediaFolder $mediaFolder, ?AspectRatio $aspectRatio, ?string $searchQuery): array
    {
        if ($mediaFolder === null) {
            return [];
        }

        if ($searchQuery) {
            return $this->get(MediaItemRepository::class)->findByFolderAndAspectRatioAndSearchQuery(
                $mediaFolder,
                $aspectRatio,
                $searchQuery
            );
        }

        return $this->get(MediaItemRepository::class)->findByFolderAndAspectRatio($mediaFolder, $aspectRatio);
    }
}


text:
class UploadList;

namespace crash_reporter {

// Mapping between a WebUI resource (identified by |name|) and a GRIT resource
// (identified by |resource_id|).
struct CrashesUILocalizedString {
  const char* name;
  int resource_id;
};

// List of localized strings that must be added to the WebUI.
extern const CrashesUILocalizedString kCrashesUILocalizedStrings[];
extern const size_t kCrashesUILocalizedStringsCount;

// Strings used by the WebUI resources.
// Must match the constants used in the resource files.
extern const char kCrashesUICrashesJS[];
extern const char kCrashesUICrashesCSS[];
extern const char kCrashesUISadTabSVG[];
extern const char kCrashesUIRequestCrashList[];
extern const char kCrashesUIRequestCrashUpload[];
extern const char kCrashesUIShortProductName[];
extern const char kCrashesUIUpdateCrashList[];
extern const char kCrashesUIRequestSingleCrashUpload[];

// Converts and appends the most recent uploads to |out_value|.
void UploadListToValue(UploadList* upload_list, base::Value::List* out_value);

}  // namespace crash_reporter

#endif  // COMPONENTS_CRASH_CORE_BROWSER_CRASHES_UI_UTIL_H_