/// <summary>
        /// Inventory required functions from file
        /// </summary>
        public void InventoryRequiredFunctionsFromTextFile(string filePath, Functions.Functions functions, List <string> functionsNotFound)
        {
            string t = hoReverse.hoUtils.HoUtil.ReadAllText(filePath);

            if (t == "")
            {
                return;
            }
            string s = HoService.DeleteComment(t);

            Regex rgx   = new Regex(@"(\w+)\(", RegexOptions.Multiline);
            Match match = rgx.Match(s);

            while (match.Success)
            {
                string       functionCode = match.Groups[1].Value;
                FunctionItem functionItem;
                if (functions.FunctionList.TryGetValue(functionCode, out functionItem))
                {
                    // function found
                    RequiredFunctionAdd(functionItem);
                }
                else
                {
                    // function not found
                    if (!functionsNotFound.Contains(functionCode))
                    {
                        functionsNotFound.Add($@"{functionCode}");
                    }
                    //MessageBox.Show($"Function: '{functionCode}' not found in file\r\n'{filePath}'", "Function not find");
                }
                match = match.NextMatch();
            }
            return;
        }
        /// <summary>
        /// Generate provided Interface. All functions called from not component modules
        /// -
        /// </summary>
        /// <param name="db"></param>
        /// <param name="folderNameOfClass"></param>
        /// <param name="fileNamesOfClassTree"></param>
        /// <param name="allCompImplementations"></param>
        /// <returns></returns>
        private static DataTable ShowProvidedInterface(BROWSEVCDB db,
                                                       string folderNameOfClass,
                                                       IQueryable <string> fileNamesOfClassTree,
                                                       IEnumerable <ImplFunctionItem> allCompImplementations)
        {
            var compImplementations = (from f in allCompImplementations
                                       where f.FilePath.StartsWith(folderNameOfClass) || f.FilePath == ""
                                       select new
            {
                Imp = new ImplFunctionItem(f.Interface, f.Implementation, f.FilePath, "", f.LineStart),
                // Rx to find a call to function, should be fast, later detailed test
                // 'function('
                RxImplementation = new Regex($@"\b{f.Implementation}\s*\("),
                RxInterface = new Regex($@"\b{f.Interface}\s*\(")
            }).ToArray();

            // over all files except Class/Component Tree (files not part of component/class/sub folder)
            IQueryable <string> fileNamesCalledImplementation = (from f in db.Files
                                                                 where !fileNamesOfClassTree.Any(x => x == f.Name) &&
                                                                 (f.LeafName.ToLower().EndsWith(".c") || f.LeafName.ToLower().EndsWith(".cpp"))
                                                                 select f.Name).Distinct();

            foreach (var fileName in fileNamesCalledImplementation)
            {
                if (!File.Exists(fileName))
                {
                    MessageBox.Show($@"File:{Environment.NewLine}'{fileName}'{Environment.NewLine}{Environment.NewLine}Root:{Environment.NewLine}{_folderRoot}",
                                    @"Can't open implementation of provided interface, skip!!!");
                    continue;
                }
                // only files in implementation
                if (fileName.ToLower().Contains(_folderRoot.ToLower()))
                {
                    string code = HoService.DeleteComment(HoUtil.ReadAllText(fileName));
                    foreach (var f1 in compImplementations)
                    {
                        if (f1.RxImplementation.IsMatch(code) || f1.RxInterface.IsMatch(code))
                        {
                            Regex rx = f1.Imp.Implementation == f1.Imp.Interface
                                ? new Regex($@"^.*\b{f1.Imp.Implementation}\s*\([^}}{{;]*;", RegexOptions.Multiline)
                                : new Regex($@"^.*\b({f1.Imp.Implementation}|{f1.Imp.Interface})\s*\([^}}{{;]*;", RegexOptions.Multiline);

                            Match match = rx.Match(code);
                            while (match.Success)
                            {
                                // That's not an call to a function
                                if (match.Value.Trim().StartsWith("FUNC(") || match.Value.Trim().StartsWith("void ") || match.Value.Trim().StartsWith("static ") || match.Value.Trim().StartsWith("extern "))
                                {
                                    match = match.NextMatch();
                                    continue;
                                }

                                f1.Imp.FilePathCallee = fileName;
                                break;
                            }

                            //f1.Imp.FilePathCallee = fileName;
                        }
                    }
                }
            }
            // Sort: Function, FileName
            var outputList = (from f in compImplementations
                              orderby f.Imp.Interface, f.Imp.Implementation
                              select new
            {
                Interface = f.Imp.Interface,
                Implementation = f.Imp.Implementation == f.Imp.Interface ? "" : f.Imp.Implementation,
                FileName = f.Imp.FileName,
                FileNameCallee = f.Imp.FileNameCallee,
                // no root path
                FilePath = f.Imp.FilePath.Length > _folderRoot.Length ? f.Imp.FilePath.Substring(_folderRoot.Length) : "",
                FilePathCallee = f.Imp.FilePathCallee.Length > _folderRoot.Length ? f.Imp.FilePathCallee.Substring(_folderRoot.Length) : "",
                isCalled = f.Imp.IsCalled,
                LineStart = f.Imp.LineStart
            }).Distinct();

            return(outputList.ToDataTable());
        }
        /// <summary>
        /// Get all required Interfaces of Component (root folder of component)
        /// </summary>
        /// <param name="db"></param>
        /// <param name="folderNameOfClass"></param>
        /// <param name="filesPathOfClassTree"></param>
        /// <param name="allImplementations"></param>
        /// <returns></returns>
        private static DataTable ShowRequiredInterface(BROWSEVCDB db,
                                                       string folderNameOfClass,
                                                       IQueryable <string> filesPathOfClassTree,
                                                       IEnumerable <ImplFunctionItem> allImplementations)
        {
            // Estimate all possible function calls of passed files
            Regex rx = new Regex(@"(\b[A-Z]\w*_\w*)\s*\(", RegexOptions.IgnoreCase);
            List <CallFunctionItem> lFunctionCalls = new List <CallFunctionItem>();

            foreach (var file in filesPathOfClassTree)
            {
                // only files that are in source folder, no library files.
                if (file.ToLower().Contains(_folderRoot.ToLower()))
                {
                    string code  = HoService.DeleteComment(HoUtil.ReadAllText(file));
                    Match  match = rx.Match(code);
                    while (match.Success)
                    {
                        lFunctionCalls.Add(new CallFunctionItem(match.Groups[1].Value, file));
                        match = match.NextMatch();
                    }
                }
            }


            // ignore the following function names (beginning)
            string[] ignoreList =
            {
                "Rte_Read",     "Rte_Write",     "Rte_Invalidate",
                "L2A_Rte_Read", "L2A_Rte_Write", "L2A_Rte_Invalidate",
                "L2B_Rte_Read", "L2B_Rte_Write", "L2B_Rte_Invalidate",
                "L2C_Rte_Read", "L2C_Rte_Write", "L2C_Rte_Invalidate"
            };

            // filter only function implementation
            // - not current folder/subfolder (current component, required)
            // - not to ignore according to ignore list
            var filteredFunctions = (from f in lFunctionCalls
                                     join fAll in allImplementations on f.Function equals fAll.Implementation
                                     where (!fAll.FilePath.StartsWith(folderNameOfClass)) &&
                                     ignoreList.All(l => !f.Function.StartsWith(l)) // handle ignore list
                                     orderby fAll.Implementation
                                     select new
            {
                Interface = fAll.Interface,
                Implementation = fAll.Implementation,
                FilePathImplementation = fAll.FilePath,
                FilePathCallee = f.FilePath,     // no implementation available yet
                isCalled = false,
                LineStart = fAll.LineStart,
                LineEnd = fAll.LineEnd,
                ColumnEnd = fAll.ColumnEnd
            }).Distinct();


            // check if filtered functions are implemented
            List <ImplFunctionItem> filteredImplemtedFunctions = new List <ImplFunctionItem>();

            foreach (var f in filteredFunctions)
            {
                if (!File.Exists(f.FilePathImplementation))
                {
                    MessageBox.Show($"File:\r\n'{f.FilePathImplementation}'\r\n\r\nRoot:\r\n{_folderRoot}",
                                    "Can't open implementation of required interface, skip interface!!!");
                    continue;
                }
                string[] codeLines = File.ReadAllLines(f.FilePathImplementation);
                // declaration ends with ';'
                // implementation ends with '}'
                //codeLines[f.Line - 1].Dump();
                if (f.LineEnd > 0 && f.ColumnEnd > 0)
                {
                    string line = codeLines[f.LineEnd - 1];
                    if (line.Length > 0)
                    {
                        if (line.Substring(f.ColumnEnd - 1, 1) != ";")
                        {
                            filteredImplemtedFunctions.Add(new ImplFunctionItem(
                                                               f.Interface,
                                                               f.Interface == f.Implementation ? "" : f.Implementation,
                                                               // no root path
                                                               f.FilePathImplementation.Length > _folderRoot.Length ? f.FilePathImplementation.Substring(_folderRoot.Length) : "",
                                                               f.FilePathCallee.Length > _folderRoot.Length ? f.FilePathCallee.Substring(_folderRoot.Length): "",
                                                               f.LineStart));
                        }
                    }
                }
            }
            return(filteredImplemtedFunctions.ToDataTable());
        }