Build tree view by the recursion method

47 views Asked by At

I am a software development novice and I am currently working on an apprenticeship project to develop a tool for analyzing complex log files.
I am working with the technology.NET/C#/WPF. I am having trouble building a tree using recursion, particularly the tree's structure. Recursion is recommended, but I am having trouble with performance for large files.

It is necessary to obtain this tree structure.

****** FICHIER DE TRACE ******
      Function1 (start and end)
                       Function2 (start and end)
                        Function3 (start and end)
                Function11 (start and end)
                     Function4 (start and end)
            Function5 (start and end)
****** FICHIER DE TRACE ******
    Function10 (start and end)

My class is :

public class LogFunctionInfo
    {
        #region Fields
        private readonly LogData _logData;
        #endregion


        #region Properties
        public string? FunctionName { get; private set; }
        public int StartIndex { get; private set; }
        public int EndIndex { get; private set; }
        public List<LogFunctionInfo> SubFunctions { get; private set; }
        #endregion


        #region Constructors
        public LogFunctionInfo(LogData logData, int startIndex, int endIndex)
        {
            _logData = logData;
            StartIndex = startIndex; 
            EndIndex = endIndex;
            SubFunctions = new List<LogFunctionInfo>();
        }
        #endregion


        #region Methods
        // Identifies the boundaries of functions within the log data recursively.
        public void IdentifyFunctionBoundaries(LogData logData, int startIndex, int endIndex)
        {
            try
            {
                StartIndex = startIndex;
                FunctionName = logData.LogList[startIndex].FunctionName;
                EndIndex = FindFunctionEnd(logData, startIndex, endIndex);

                // Create a LogFunctionInfo object for the current function
                LogFunctionInfo currentFunction = new LogFunctionInfo(logData, StartIndex, EndIndex)
                {
                    FunctionName = FunctionName
                };

                // Add the current function to the SubFunctions list
                SubFunctions.Add(currentFunction);

                // Recursively identify functions within the current function's scope
                if (EndIndex <= endIndex && startIndex + 1 < endIndex)
                {
                    currentFunction.IdentifyFunctionBoundaries(logData, StartIndex + 1, EndIndex);
                }
            }
            catch (IndexOutOfRangeException e)
            {
                Console.WriteLine($"Index out of range: {e.Message}");
            }
            catch (Exception e)
            {
                Console.WriteLine($"Error identifying function boundaries: {e.Message}");
            }
        }

        // Finds the end index of the current function within the log data.
        private int FindFunctionEnd(LogData logData, int startIndex, int endIndex)
        {
            var logList = logData.LogList;
            int tempFunctionEndIndex = startIndex;

            // Iterate through log entries starting from the startIndex
            for (int index = startIndex; index < endIndex; index++)
            {
                // Check if the current entry's function name matches the start entry's function name
                // and if the current entry's code line number is greater than the start entry's code line number and their RowNumber
                // This indicates the end of the function
                if (logList[index].FunctionName == logList[startIndex].FunctionName &&
                    (logList[index].CodeLineNumber >= logList[tempFunctionEndIndex].CodeLineNumber))
                {
                    tempFunctionEndIndex = index;
                }
            }

            return tempFunctionEndIndex; // If the end of the function is not found
        }
        #endregion
    }

After unit testing, the expected result is not satisfactory. Although it provides me with structure, it is not able to identify all the children of the same parent.

****** FICHIER DE TRACE ******
      Function1 (start and end)
                       Function2 (start and end)
                        Function3 (start and end)
                Function11 (start and end)
1

There are 1 answers

0
Andrey Chernenkov On

The SubFunctions list is only appended once per recursion, therefore the IdentifyFunctionBoundaries can not detect siblings in the tree. Try returning the last index of each nested function and iterate through the logs until the last index of the current function.
Something like this should work:

// ...

        public int IdentifyFunctionBoundaries(LogData logData, int startIndex, int endIndex)
        {
            try
            {
                StartIndex = startIndex;
                FunctionName = logData.LogList[startIndex].FunctionName;
                EndIndex = FindFunctionEnd(logData, startIndex, endIndex);

                // Create a LogFunctionInfo object for the current function
                LogFunctionInfo currentFunction = new LogFunctionInfo(logData, StartIndex, EndIndex)
                {
                    FunctionName = FunctionName
                };

                // Add the current function to the SubFunctions list
                SubFunctions.Add(currentFunction);

                if (EndIndex <= endIndex && startIndex + 1 < endIndex)
                {
                    int currentIndex = startIndex + 1;
                    while (currentIndex < endIndex) 
                    {
                        // Recursively identify functions within the current function's scope
                        currentIndex = currentFunction.IdentifyFunctionBoundaries(logData, currentIndex, EndIndex) + 1;
                    }
                }
            }
            catch (IndexOutOfRangeException e)
            {
                Console.WriteLine($"Index out of range: {e.Message}");
            }
            catch (Exception e)
            {
                Console.WriteLine($"Error identifying function boundaries: {e.Message}");
            }
            finally
            {
                return EndIndex;
            }
        }

// ...