Source: core/find_in_cpp_class.js

/*
 * This file is part of PKM (Persistent Knowledge Monitor).
 * Copyright (c) 2020 Capgemini Group, Commissariat à l'énergie atomique et aux énergies alternatives,
 *                    OW2, Sysgo AG, Technikon, Tree Technology, Universitat Politècnica de València.
 * 
 * PKM is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License version 3 as published by
 * the Free Software Foundation.
 * 
 * PKM is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 * 
 * You should have received a copy of the GNU Affero General Public License
 * along with PKM.  If not, see <https://www.gnu.org/licenses/>.
 */

/**
 * find methods or fields in C++ class
 * 
 * @memberof PKM
 * @instance
 * @param {string} dbName - database name
 * @param {string} className - class name
 * @param {string} kind - either 'field' or 'method'
 * 
 * @return {Promise<Array.<Object>>} a promise that passes the result (an array) to resolve callback
 */
function find_in_cpp_class(dbName, className, kind)
{
	return new Promise(function(resolve, reject)
	{
		const debug = this.debug;
		
		function search_element(document, id)
		{
			if(document.hasOwnProperty('id') && (document.id === id))
			{
				return document;
			}
			
			if(document.hasOwnProperty('inner'))
			{
				for(let i = 0; i < document.inner.length; ++i)
				{
					const inner_element = document.inner[i];
					const found = search_element(inner_element, id)
					if(found) return found;
				}
			}
			
			return undefined;
		}
			
		function search(document, query)
		{
			let result = [];
			
			if(document.hasOwnProperty('manifest'))
			{
				document.manifest.forEach((manifest_item) =>
				{
					if(((query.id === undefined) || (query.id === manifest_item.id)) &&
					    ((query.kind === undefined) || ((typeof query.kind === 'string') && (query.kind === manifest_item.kind)) || ((query.kind instanceof RegExp) && query.kind.test(manifest_item.kind))) &&
					    ((query.path === undefined) || ((typeof query.path === 'string') && (query.path === manifest_item.path)) || ((query.path instanceof RegExp) && query.path.test(manifest_item.path))))
					{
						document.inner.forEach((inner_element) =>
						{
							const found = search_element(inner_element, manifest_item.id);
							if(found !== undefined)
							{
								result.push(found);
							}
						});
					}
				});
			}
				
				return result;
		}
		
		if((kind === 'field') || (kind === 'method'))
		{
			let get_doc_query =
			{
				$and :
				[
					{
						'manifest.path' : className
					},
					{
						$or :
						[
							{ 'manifest.kind' : 'class' },
							{ 'manifest.kind' : 'struct' },
							{ 'manifest.kind' : 'union' }
						]
					}
				]
			};

			this.get_documents(dbName, 'sourcecodeCPP', get_doc_query).then((documents) =>
			{
				let search_promises = documents.map((document) => new Promise((resolve, reject) =>
				{
					let result = [];
					
					let class_documents = search(document, { kind : new RegExp('^class$|^struct$|^union$'), path : className });
					
					const CppClass = require('../util/cpp_class');
					
					class_documents.map(class_document => new CppClass(class_document)).forEach((cpp_class) =>
					{
						if(cpp_class.hasOwnProperty(kind + 's'))
						{
							cpp_class[kind + 's'].forEach(({ id }) =>
							{
								let class_member = search_element(cpp_class, id);
								if(class_member !== undefined)
								{
									result.push(class_member);
								}
							});
						}
					});
					
					resolve(result);
				}));
				
				Promise.all(search_promises).then((results) =>
				{
					let result = results.reduce((acc, val) => acc.concat(val), []);
					resolve(result);
				});
			}).catch((err) =>
			{
				reject(this.Error(err));
			});
		}
		else
		{
			reject(this.BadRequest('bad kind'));
		}
	}.bind(this));
}

exports.find_in_cpp_class = find_in_cpp_class;