function functionRecognizerInFile(filePath, functionName, isRecursive = true) {
    return new Promise(resolve => {
        fs.readFile(filePath, 'utf8', async function (err, data) {
            if (err) {
                return resolve(null);
            }

            /**
             * Removing express-async-handler function
             */
            let expressAsyncHandler = null;
            let imports = await getImportedFiles(data, filePath);
            let idx = imports.findIndex(e => e.fileName == 'express-async-handler');
            if (idx > -1) {
                if (!imports[idx].varFileName && imports[idx].exports.length > 0) {
                    expressAsyncHandler = imports[idx].exports[0].varName;
                } else {
                    expressAsyncHandler = imports[idx].varFileName;
                }
            }

            try {
                let cleanedData = data;
                cleanedData = await handleData.removeComments(cleanedData, true);
                if (expressAsyncHandler) {
                    cleanedData = cleanedData.split(new RegExp(`\\s*=\\s*${expressAsyncHandler}\\s*\\(`));
                    cleanedData = cleanedData.join(' = (');
                }
                cleanedData = cleanedData.replaceAll(' async ', ' ');
                cleanedData = cleanedData.split(new RegExp('\\=\\s*async\\s*\\('));
                cleanedData = cleanedData.join('= (');
                cleanedData = cleanedData.split(new RegExp('\\=\\s*function\\s*\\('));
                cleanedData = cleanedData.join('= (');
                cleanedData = cleanedData.split(new RegExp('\\:\\s*function\\s*\\('));
                cleanedData = cleanedData.join(': (');
                cleanedData = cleanedData.replaceAll(' function ', ' ');

                // REFACTOR: pass to function
                // adding '(' and ')' to arrow functions without '(' and ')', such as: ... async req => {
                if (cleanedData.split(new RegExp('\\s*\\n*\\t*=>\\s*\\n*\\t*').length > 1)) {
                    let params = cleanedData.trim().split(new RegExp('\\s*\\n*\\t*=>\\s*\\n*\\t*'));
                    for (let idx = 0; idx < params.length - 1; idx += 2) {
                        let param = params[idx];
                        if (param && param.slice(-1)[0] !== ')') {
                            let aux = param.split(new RegExp('\\s|\\n|\\t|\\='));
                            aux = aux.slice(-1)[0];
                            param = param.split(aux);
                            param.pop();
                            param = param.join(aux);
                            param += '(' + aux + ')';
                            params[idx] = param;
                        }
                    }
                    cleanedData = params.join(' => ');
                }

                cleanedData = cleanedData.split(new RegExp('=>\\s*\\n*\\t*=>'));
                cleanedData = cleanedData.join('=>');

                if (functionName) {
                    // When file has more than one exported function
                    let funcStr = await handleData.functionRecognizerInData(cleanedData, functionName, imports);

                    /**
                     * CASE: Referenced function, such as: module.exports = { foo: require('./fooFile').foo } in index file
                     * Issue: #29
                     */
                    if (!funcStr && cleanedData && isRecursive === true && filePath && filePath.split('/').length > 1 && filePath.split('/').slice(-1)[0].includes('index.')) {
                        let path = null;
                        let exports = cleanedData.split(new RegExp(`[\\s+|\\{|\\,]${functionName}\\s*\\:\\s*require\\s*\\(`));
                        if (exports.length > 1) {
                            let exp = exports[1].split(new RegExp('\\,|\\}'))[0];
                            exp = exp.split(new RegExp('\\s*\\)\\s*\\.\\s*'));
                            path = exp[0].replaceAll('"', '').replaceAll("'", '').replaceAll('`', '').replaceAll(' ', '');
                            if (exp.length > 1) {
                                functionName = exp[1]
                                    .trim()
                                    .split(/\(|\)|\{|\}|\[|\]|\/|\\|;|:|!|@|\$|#|=|\?|\+|,|\||&|\*|\t|\n| /)[0]
                                    .replaceAll(' ', '');
                            } else {
                                functionName = null;
                            }

                            let relativePath = filePath.split('/').slice(0, -1).join('/');
                            path = await resolvePathFile(path, relativePath);
                            if (path) {
                                let extension = await utils.getExtension(path);
                                if (path && path.split(new RegExp('\\.js$')).length > 1 && !fs.existsSync(path)) {
                                    path = path.replace(new RegExp('\\.js$'), '.ts');
                                }
                                funcStr = await functionRecognizerInFile(path + extension, functionName, false);
                            }
                        }
                    }
                    /* END CASE */

                    return resolve(funcStr);
                } else {
                    // When file has only one exported function
                    cleanedData = cleanedData.replaceAll('\n', ' ').replaceAll('  ', ' ').replaceAll('  ', ' ');
                    if (cleanedData.split(new RegExp('export\\s*\\t*default\\s*\\t*\\=*\\s*\\t*\\(.+\\).+\\{')).length > 1) {
                        let directPattern = cleanedData.split(new RegExp('export\\s*\\t*default\\s*\\t*\\=*\\s*\\t*\\(.+\\).+\\{'));
                        if (directPattern.length > 1) directPattern = true;
                        else directPattern = false;

                        if (directPattern) {
                            // Direct declaration in module.exports
                            let funcStr = await handleData.functionRecognizerInData(cleanedData, `export\\s*default`);
                            return resolve(funcStr);
                        } else {
                            // Indirect declaration in module.exports
                            let funcName = cleanedData.split(new RegExp('export\\s*\\n*\\t*default\\s*\\n*\\t*'));
                            if (funcName[1]) {
                                funcName = funcName[1].split(/\n|\s|\t|;|\{|\}|\(|\)|\[|\]/);
                            } else {
                                return resolve(null); // TODO: Verify 'null' case
                            }
                            let funcStr = await handleData.functionRecognizerInData(cleanedData, funcName[0]);
                            return resolve(funcStr);
                        }
                    } else {
                        let directPattern = cleanedData.split(new RegExp(`module\\s*\\n*\\t*\\.\\s*\\n*\\t*exports\\s*\\n*\\t*\\=*\\s*\\n*\\t*\\(.+\\).+\\{`));
                        if (directPattern.length > 1) {
                            directPattern = true;
                        } else {
                            directPattern = false;
                        }

                        if (directPattern) {
                            // Direct declaration in module.exports
                            let funcStr = await handleData.functionRecognizerInData(cleanedData, `module\\.exports`);
                            return resolve(funcStr);
                        } else {
                            // Indirect declaration in module.exports
                            let funcName = cleanedData.split(new RegExp('module\\s*\\n*\\t*\\.\\s*\\n*\\t*exports\\s*\\n*\\t*\\=\\s*\\n*\\t*'));
                            if (funcName[1]) {
                                funcName = funcName[1].split(/\n|\s|\t|;|\{|\}|\(|\)|\[|\]/);
                            } else {
                                return resolve(null); // TODO: Verify 'null' case
                            }
                            let funcStr = await handleData.functionRecognizerInData(cleanedData, funcName[0]);
                            return resolve(funcStr);
                        }
                    }
                }
            } catch (err) {
                return resolve(null);
            }
        });
    });
}
Recognize function in a file.
@param {*} filePath file's path.
@param {*} functionName
@param {*} isRecursive To avoid infinite loop in case of recursion.