<commit_before><cfscript>
	/**
	 * Return the main documentation struct with an array of sections, and an array of functions
	 */
	struct function $returnInternalDocumentation(required array documentScope, required array ignore){
		local.rv["functions"] = $populateDocFunctionMeta(documentScope,ignore);
		local.rv["sections"]  = $populateDocSections(local.rv.functions);
		return local.rv;
	}

	/**
	 * For each type of cfc, i.e, model, controller, mapper, loop over the available functions and populate the
	 * function's metadata via getMetaData()
	 *
	 * @documentScope The Array of structs containing CFCs to introspect
	 * @ignore an array of function names to ignore. config() and init() are the usual ones.
	 */
	array function $populateDocFunctionMeta(required array documentScope, required array ignore){
		local.rv=[];
		for(local.doctype in arguments.documentScope){
			local.doctype["functions"]=listSort(StructKeyList(local.doctype.scope), "textnocase");
			// Populate A-Z function List
			for(local.functionName in listToArray(local.doctype.functions) ){
				local.meta={};
				local.hint="";
				// Check this is actually a function: dbmigrate stores a struct for instance
				// Don't display internal functions, duplicates or anything in the ignore list
				if(left(local.functionName, 1) != "$"
					&& !ArrayFindNoCase(arguments.ignore, local.functionName)
					&& isCustomFunction(local.doctype.scope[local.functionName])
				){
					// Get metadata
					local.meta=$parseMetaData(GetMetaData(local.doctype.scope[local.functionName]), local.doctype.name, local.functionName);
					local.hint=local.meta.hint;

					if(local.meta.name != "$pluginRunner"){

						// Look for identically named functions: just looking for name isn't enough, we need to compare the hint too
						local.match=arrayFind(local.rv, function(struct){
							return (struct.name == functionName && struct.hint == hint);
						});

						if(local.match){
							arrayAppend(local.rv[local.match]["availableIn"], local.doctype.name);
						} else {
							arrayAppend(local.rv, local.meta);
						}
					}
				}
			}
			local.rv = $arrayOfStructsSort(local.rv, "name");
		}
		return local.rv;
	}

	/**
	 * Look for [section:foo] style categories and build the categories array
	 *
	 * @docFunctions an array of function meta data as created by $populateDocFunctionMeta
	 */
	array function $populateDocSections(required array docFunctions){
		local.rv=[];
		for(local.doc in arguments.docFunctions){
			if(structKeyExists(local.doc.tags, "section") && len(local.doc.tags.section)){
				if( !ArrayFind(local.rv, function(struct){
					   return struct.name == doc.tags.section;
				})){
					arrayAppend(local.rv, {
						"name": local.doc.tags.section,
						"categories": []
					});
				}
				for(local.subsection in local.rv){
					if(local.subsection.name == local.doc.tags.section
						&& len(local.doc.tags.category)
						&& !arrayFind(local.subsection.categories, local.doc.tags.category)){
							arrayAppend(local.subsection.categories, local.doc.tags.category);
					}
					arraySort(local.subsection.categories, "textnocase");
				}
			}
		}
		local.rv = $arrayOfStructsSort(local.rv, "name");
		return local.rv;
	}

	/**
	* Take a metadata struct as from getMetaData() and get some additional info
	*
	* @meta metadata struct as returned from getMetaData()
	* @doctype ie. Controller || Model
	*/
	struct function $parseMetaData(required struct meta, required string doctype, required string functionName){
		local.m=arguments.meta;<commit_msg>Minor internal docs fix [ci skip]<commit_after><cfscript>
	/**
	 * Return the main documentation struct with an array of sections, and an array of functions
	 */
	struct function $returnInternalDocumentation(required array documentScope, required array ignore){
		local.rv["functions"] = $populateDocFunctionMeta(documentScope,ignore);
		local.rv["sections"]  = $populateDocSections(local.rv.functions);
		return local.rv;
	}

	/**
	 * For each type of cfc, i.e, model, controller, mapper, loop over the available functions and populate the
	 * function's metadata via getMetaData()
	 *
	 * @documentScope The Array of structs containing CFCs to introspect
	 * @ignore an array of function names to ignore. config() and init() are the usual ones.
	 */
	array function $populateDocFunctionMeta(required array documentScope, required array ignore){
		local.rv=[];
		for(local.doctype in arguments.documentScope){
			local.doctype["functions"]=listSort(StructKeyList(local.doctype.scope), "textnocase");
			// Populate A-Z function List
			for(local.functionName in listToArray(local.doctype.functions) ){
				local.meta={};
				local.hint="";
				// Check this is actually a function: dbmigrate stores a struct for instance
				// Don't display internal functions, duplicates or anything in the ignore list
				if(left(local.functionName, 1) != "$"
					&& !ArrayFindNoCase(arguments.ignore, local.functionName)
					&& isCustomFunction(local.doctype.scope[local.functionName])
				){
					// Get metadata
					local.meta=$parseMetaData(GetMetaData(local.doctype.scope[local.functionName]), local.doctype.name, local.functionName);
					local.hint=local.meta.hint;

					if(local.meta.name != "$pluginRunner"){

						// Look for identically named functions: just looking for name isn't enough, we need to compare the hint too
						local.match=arrayFind(local.rv, function(struct){
							return (struct.name == functionName && struct.hint == hint);
						});

						if(local.match){
							arrayAppend(local.rv[local.match]["availableIn"], local.doctype.name);
						} else {
							arrayAppend(local.rv, local.meta);
						}
					}
				}
			}
			local.rv = $arrayOfStructsSort(local.rv, "name");
		}
		return local.rv;
	}

	/**
	 * Look for [section:foo] style categories and build the categories array
	 *
	 * @docFunctions an array of function meta data as created by $populateDocFunctionMeta
	 */
	array function $populateDocSections(required array docFunctions){
		local.rv=[];
		for(local.doc in arguments.docFunctions){
			if(structKeyExists(local.doc.tags, "section") && len(local.doc.tags.section)){
				var section=local.doc.tags.section;
				if( !ArrayFind(local.rv, function(struct, section){
					   return struct.name == section;
				})){
					arrayAppend(local.rv, {
						"name": local.doc.tags.section,
						"categories": []
					});
				}
				for(local.subsection in local.rv){
					if(local.subsection.name == local.doc.tags.section
						&& len(local.doc.tags.category)
						&& !arrayFind(local.subsection.categories, local.doc.tags.category)){
							arrayAppend(local.subsection.categories, local.doc.tags.category);
					}
					arraySort(local.subsection.categories, "textnocase");
				}
			}
		}
		local.rv = $arrayOfStructsSort(local.rv, "name");
		return local.rv;
	}

	/**
	* Take a metadata struct as from getMetaData() and get some additional info
	*
	* @meta metadata struct as returned from getMetaData()
	* @doctype ie. Controller || Model
	*/
	struct function $parseMetaData(required struct meta, required string doctype, required string functionName){
		local.m=arguments.meta;
{'fraction_non_alphanumeric': 0.12391850404688809, 'fraction_numerical': 0.00027909572983533354, 'mean_word_length': 3.7843791722296394, 'pattern_counts': {'":': 4, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3376559', 'n_tokens_mistral': 2511, 'n_tokens_neox': 2079, 'n_words': 537}