Inheritance: TaskRunnerNode
        private ITaskRunnerNode LoadHierarchy(string configPath)
        {
            var cliCommandName = GetCliCommandName(configPath);
            SetRootNodeIcon(cliCommandName);
            bool isNpm = (cliCommandName == Constants.NPM_CLI_COMMAND);

            ITaskRunnerNode root = new TaskNode(Vsix.Name, false, isNpm);

            var scripts = TaskParser.LoadTasks(configPath, cliCommandName);
            var hierarchy = GetHierarchy(scripts.Keys);

            IEnumerable<string> allDefaultTasks = (isNpm
                ? Constants.NPM_ALL_DEFAULT_TASKS
                : Constants.YARN_ALL_DEFAULT_TASKS);
            var defaults = hierarchy.Where(h => allDefaultTasks.Contains(h.Key));

            TaskNode defaultTasks = new TaskNode("Defaults", false, isNpm);
            defaultTasks.Description = $"Default predefined {cliCommandName} commands.";
            root.Children.Add(defaultTasks);
            AddCommands(configPath, scripts, defaults, defaultTasks, isNpm);

            if (hierarchy.Count != defaults.Count())
            {
                var customs = hierarchy.Except(defaults);

                TaskNode customTasks = new TaskNode("Custom", false, isNpm);
                customTasks.Description = $"Custom {cliCommandName} commands.";
                root.Children.Add(customTasks);

                AddCommands(configPath, scripts, customs, customTasks, isNpm);
            }

            return root;
        }
        private void AddCommands(string configPath, SortedList<string, string> scripts, IEnumerable<KeyValuePair<string, IEnumerable<string>>> commands, TaskNode tasks, bool isNpm)
        {
            string cwd = Path.GetDirectoryName(configPath);

            foreach (var parent in commands)
            {
                TaskNode parentTask = CreateTask(cwd, parent.Key, scripts[parent.Key], isNpm);

                foreach (var child in parent.Value)
                {
                    TaskNode childTask = CreateTask(cwd, child, scripts[child], isNpm);
                    parentTask.Children.Add(childTask);
                }

                tasks.Children.Add(parentTask);
            }
        }
        private void AddCommands(string configPath, SortedList <string, string> scripts, IEnumerable <KeyValuePair <string, IEnumerable <string> > > commands, TaskNode tasks, bool isNpm)
        {
            string cwd = Path.GetDirectoryName(configPath);

            foreach (var parent in commands)
            {
                TaskNode parentTask = CreateTask(cwd, parent.Key, scripts[parent.Key], isNpm);

                foreach (var child in parent.Value)
                {
                    TaskNode childTask = CreateTask(cwd, child, scripts[child], isNpm);
                    parentTask.Children.Add(childTask);
                }

                tasks.Children.Add(parentTask);
            }
        }
        private ITaskRunnerNode LoadHierarchy(string configPath)
        {
            var cliCommandName = GetCliCommandName(configPath);

            SetRootNodeIcon(cliCommandName);
            bool isNpm = (cliCommandName == Constants.NPM_CLI_COMMAND);

            ITaskRunnerNode root = new TaskNode(Vsix.Name, false, isNpm);

            var scripts   = TaskParser.LoadTasks(configPath, cliCommandName);
            var hierarchy = GetHierarchy(scripts.Keys);

            IEnumerable <string> allDefaultTasks = (isNpm
                ? Constants.NPM_ALL_DEFAULT_TASKS
                : Constants.YARN_ALL_DEFAULT_TASKS);
            var defaults = hierarchy.Where(h => allDefaultTasks.Contains(h.Key));

            TaskNode defaultTasks = new TaskNode("Defaults", false, isNpm);

            defaultTasks.Description = $"Default predefined {cliCommandName} commands.";
            root.Children.Add(defaultTasks);
            AddCommands(configPath, scripts, defaults, defaultTasks, isNpm);

            if (hierarchy.Count != defaults.Count())
            {
                var customs = hierarchy.Except(defaults);

                TaskNode customTasks = new TaskNode("Custom", false, isNpm);
                customTasks.Description = $"Custom {cliCommandName} commands.";
                root.Children.Add(customTasks);

                AddCommands(configPath, scripts, customs, customTasks, isNpm);
            }

            return(root);
        }