The *Code Explorer* is a dockable toolwindow that displays a *TreeView* that shows all opened VBA projects and their respective modules, but unlike the "native" *Project Explorer*, Rubberduck's explorer also drills down to individual module members, and allows quickly navigating them:

![Rubberduck 1.3 Code Explorer](https://i.stack.imgur.com/rhRX9.png)

While it *looks* pretty, the code behind it is among the most painful code in the project - clearly, it needs to be refactored and optimized. I'm particularly interested in ways to improve the `async void RefreshExplorerTreeView()` method and the whole node-generation code.

```
namespace Rubberduck.UI.CodeExplorer
{
    public class CodeExplorerDockablePresenter : DockablePresenterBase
    {
        private readonly IRubberduckParser _parser;
        private CodeExplorerWindow Control { get { return UserControl as CodeExplorerWindow; } }

        public CodeExplorerDockablePresenter(IRubberduckParser parser, VBE vbe, AddIn addIn, CodeExplorerWindow view)
            : base(vbe, addIn, view)
        {
            _parser = parser;
            RegisterControlEvents();
        }

        public override void Show()
        {
            base.Show();
            Task.Run(() => RefreshExplorerTreeView()); 
        }

        private void RegisterControlEvents()
        {
            if (Control == null)
            {
                return;
            }

            Control.RefreshTreeView += RefreshExplorerTreeView;
            Control.NavigateTreeNode += NavigateExplorerTreeNode;
            Control.AddComponent += AddComponent;
            Control.AddTestModule += AddTestModule;
            Control.ToggleFolders += ToggleFolders;
            Control.ShowDesigner += ShowDesigner;
            Control.DisplayStyleChanged += DisplayStyleChanged;
            Control.RunAllTests += ContextMenuRunAllTests;
            Control.RunInspections += ContextMenuRunInspections;
            Control.SelectionChanged += SelectionChanged;
            Control.Rename += RenameSelection;
            Control.FindAllReferences += FindAllReferencesForSelection;
        }

        public event EventHandler<NavigateCodeEventArgs> FindAllReferences;
        private void FindAllReferencesForSelection(object sender, NavigateCodeEventArgs e)
        {
            var handler = FindAllReferences;
            if (handler != null)
            {
                handler(sender, e);
            }
        }

        public event EventHandler<TreeNodeNavigateCodeEventArgs> Rename;
        private void RenameSelection(object sender, TreeNodeNavigateCodeEventArgs e)
        {
            if (e.Node == null || e.Selection.Equals(default(Selection)) && e.QualifiedName == default(QualifiedModuleName))
            {
                return;
            }

            var handler = Rename;
            if (handler != null)
            {
                handler(this, e);
                RefreshExplorerTreeView();
                e.Node.EnsureVisible();
            }
        }

        private void SelectionChanged(object sender, TreeNodeNavigateCodeEventArgs e)
        {
            if (e.Node == null || e.Node.Tag == null)
            {
                return;
            }

            try
            {
                VBE.ActiveVBProject = e.QualifiedName.Project;
            }
            catch (COMException)
            {
                // swallow "catastrophic failure"
            }
        }

        public event EventHandler RunInspections;
        private void ContextMenuRunInspections(object sender, EventArgs e)
        {
            var handler = RunInspections;
            if (handler != null)
            {
                handler(this, EventArgs.Empty);
            }
        }

        public event EventHandler RunAllTests;
        private void ContextMenuRunAllTests(object sender, EventArgs e)
        {
            var handler = RunAllTests;
            if (handler != null)
            {
                handler(this, EventArgs.Empty);
            }
        }

        private void DisplayStyleChanged(object sender, EventArgs e)
        {
            RefreshExplorerTreeView();
        }

        private void AddTestModule(object sender, EventArgs e)
        {
            NewUnitTestModuleCommand.NewUnitTestModule(VBE);
            RefreshExplorerTreeView();
        }

        private void ShowDesigner(object sender, EventArgs e)
        {
            var node = Control.SolutionTree.SelectedNode;
            if (node != null && node.Tag != null)
            {
                var selection = (Declaration)node.Tag;
                var module = selection.QualifiedName.QualifiedModuleName.Component.CodeModule;
                if (module == null)
                {
                    return;
                }

                try
                {
                    module.Parent.DesignerWindow().Visible = true;
                }
                catch
                {
                    Control.ShowDesignerButton.Enabled = false;
                }
            }
        }

        private bool _showFolders = true;
        private void ToggleFolders(object sender, EventArgs e)
        {
            _showFolders = !_showFolders;
            RefreshExplorerTreeView();
        }

        private void AddComponent(object sender, AddComponentEventArgs e)
        {
            var project = VBE.ActiveVBProject;
            if (project == null)
            {
                return;
            }

            project.VBComponents.Add(e.ComponentType);
            RefreshExplorerTreeView();
        }

        private void NavigateExplorerTreeNode(object sender, TreeNodeNavigateCodeEventArgs e)
        {
            var declaration = e.Declaration;
            if (declaration != null)
            {
                VBE.SetSelection(new QualifiedSelection(declaration.QualifiedName.QualifiedModuleName, declaration.Selection));
            }
        }

        private void RefreshExplorerTreeView(object sender, EventArgs e)
        {
            Task.Run(() => RefreshExplorerTreeView());
        }

        private async void RefreshExplorerTreeView()
        {
            Control.Invoke((MethodInvoker) delegate
            {
                Control.SolutionTree.Nodes.Clear();
                Control.ShowDesignerButton.Enabled = false;
            });

            var projects = VBE.VBProjects.Cast<VBProject>();
            foreach (var vbProject in projects)
            {
                var project = vbProject;
                await Task.Run(() =>
                {
                    var node = new TreeNode(project.Name + " (parsing...)");
                    node.ImageKey = "Hourglass";
                    node.SelectedImageKey = node.ImageKey;

                    Control.Invoke((MethodInvoker)delegate
                    {
                        Control.SolutionTree.Nodes.Add(node);
                        Control.SolutionTree.Refresh();
                        AddProjectNodes(project, node);
                    });
                });
            }
        }

        private void AddProjectNodes(VBProject project, TreeNode root)
        {
            Control.Invoke((MethodInvoker)async delegate
            {
                if (project.Protection == vbext_ProjectProtection.vbext_pp_locked)
                {
                    root.ImageKey = "Locked";
                }
                else
                {
                    var nodes = (await CreateModuleNodesAsync(project)).ToArray();
                    AddProjectFolders(project, root, nodes);
                    root.ImageKey = "ClosedFolder";
                    root.Expand();
                }

                root.Text = project.Name;
            });
        }

        private static readonly IDictionary<vbext_ComponentType, string> ComponentTypeIcons =
            new Dictionary<vbext_ComponentType, string>
            {
                { vbext_ComponentType.vbext_ct_StdModule, "StandardModule"},
                { vbext_ComponentType.vbext_ct_ClassModule, "ClassModule"},
                { vbext_ComponentType.vbext_ct_Document, "OfficeDocument"},
                { vbext_ComponentType.vbext_ct_ActiveXDesigner, "ClassModule"},
                { vbext_ComponentType.vbext_ct_MSForm, "Form"}
            };

        private void AddProjectFolders(VBProject project, TreeNode root, TreeNode[] components)
        {
            var documentNodes = components.Where(node => node.ImageKey == "OfficeDocument")
                                          .OrderBy(node => node.Text)
                                          .ToArray();
            if (project.VBComponents.Cast<VBComponent>()
                       .Any(component => component.Type == vbext_ComponentType.vbext_ct_Document))
            {
                AddFolderNode(root, "Documents", "ClosedFolder", documentNodes);
            }

            var formsNodes = components.Where(node => node.ImageKey == "Form")
                                       .OrderBy(node => node.Text)
                                       .ToArray();
            if (project.VBComponents.Cast<VBComponent>()
                       .Any(component => component.Type == vbext_ComponentType.vbext_ct_MSForm))
            {
                AddFolderNode(root, "Forms", "ClosedFolder", formsNodes);
            }

            var stdModulesNodes = components.Where(node => node.ImageKey == "StandardModule")
                                            .OrderBy(node => node.Text)
                                            .ToArray();
            if (project.VBComponents.Cast<VBComponent>()
                       .Any(component => component.Type == vbext_ComponentType.vbext_ct_StdModule))
            {
                AddFolderNode(root, "Standard Modules", "ClosedFolder", stdModulesNodes);
            }

            var classModulesNodes = components.Where(node => node.ImageKey == "ClassModule")
                                              .OrderBy(node => node.Text)
                                              .ToArray();
            if (project.VBComponents.Cast<VBComponent>()
                       .Any(component => component.Type == vbext_ComponentType.vbext_ct_ClassModule
                                      || component.Type == vbext_ComponentType.vbext_ct_ActiveXDesigner))
            {
                AddFolderNode(root, "Class Modules", "ClosedFolder", classModulesNodes);
            }
        }

        private void AddFolderNode(TreeNode root, string text, string imageKey, TreeNode[] nodes)
        {
            if (_showFolders)
            {
                var node = root.Nodes.Add(text);
                node.ImageKey = imageKey;
                node.SelectedImageKey = imageKey;
                node.Nodes.AddRange(nodes);
                node.Expand();
            }
            else
            {
                root.Nodes.AddRange(nodes);
            }
        }

        private async Task<IEnumerable<TreeNode>> CreateModuleNodesAsync(VBProject project)
        {
            var result = new List<TreeNode>();
            var parseResult = _parser.Parse(project);
            foreach (var componentParseResult in parseResult.ComponentParseResults)
            {
                var component = componentParseResult.Component;
                var members = parseResult.Declarations.Items
                    .Where(declaration => declaration.ParentScope == component.Collection.Parent.Name + "." + component.Name
                        && declaration.DeclarationType != DeclarationType.Control
                        && declaration.DeclarationType != DeclarationType.ModuleOption);

                var node = new TreeNode(component.Name);
                node.ImageKey = ComponentTypeIcons[component.Type];
                node.SelectedImageKey = node.ImageKey;
                node.Tag = parseResult.Declarations.Items.SingleOrDefault(item => 
                    item.IdentifierName == component.Name 
                    && item.Project == component.Collection.Parent
                    && (item.DeclarationType == DeclarationType.Class || item.DeclarationType == DeclarationType.Module));

                foreach (var declaration in members)
                {
                    if (declaration.DeclarationType == DeclarationType.UserDefinedTypeMember
                        || declaration.DeclarationType == DeclarationType.EnumerationMember)
                    {
                        // these ones are handled by their respective parent
                        continue;
                    }

                    var text = GetNodeText(declaration);
                    var child = new TreeNode(text);
                    child.ImageKey = GetImageKeyForDeclaration(declaration);
                    child.SelectedImageKey = child.ImageKey;
                    child.Tag = declaration;

                    if (declaration.DeclarationType == DeclarationType.UserDefinedType
                        || declaration.DeclarationType == DeclarationType.Enumeration)
                    {
                        var subDeclaration = declaration;
                        var subMembers = parseResult.Declarations.Items.Where(item => 
                            (item.DeclarationType == DeclarationType.EnumerationMember || item.DeclarationType == DeclarationType.UserDefinedTypeMember)
                            && item.Context != null && subDeclaration.Context.Equals(item.Context.Parent));

                        foreach (var subMember in subMembers)
                        {
                            var subChild = new TreeNode(subMember.IdentifierName);
                            subChild.ImageKey = GetImageKeyForDeclaration(subMember);
                            subChild.SelectedImageKey = subChild.ImageKey;
                            subChild.Tag = subMember;
                            child.Nodes.Add(subChild);
                        }
                    }

                    node.Nodes.Add(child);
                }

                result.Add(node);
            }

            return result;
        }

        private string GetNodeText(Declaration declaration)
        {
            if (Control.DisplayStyle == TreeViewDisplayStyle.MemberNames)
            {
                var result = declaration.IdentifierName;
                if (declaration.DeclarationType == DeclarationType.PropertyGet)
                {
                    result += " (" + Tokens.Get + ")";
                }
                else if (declaration.DeclarationType == DeclarationType.PropertyLet)
                {
                    result += " (" + Tokens.Let + ")";
                }
                else if (declaration.DeclarationType == DeclarationType.PropertySet)
                {
                    result += " (" + Tokens.Set + ")";
                }

                return result;
            }

            if (declaration.DeclarationType == DeclarationType.Procedure)
            {
                return ((VBAParser.SubStmtContext) declaration.Context).Signature();
            }

            if (declaration.DeclarationType == DeclarationType.Function)
            {
                return ((VBAParser.FunctionStmtContext)declaration.Context).Signature();
            }

            if (declaration.DeclarationType == DeclarationType.PropertyGet)
            {
                return ((VBAParser.PropertyGetStmtContext)declaration.Context).Signature();
            }

            if (declaration.DeclarationType == DeclarationType.PropertyLet)
            {
                return ((VBAParser.PropertyLetStmtContext)declaration.Context).Signature();
            }

            if (declaration.DeclarationType == DeclarationType.PropertySet)
            {
                return ((VBAParser.PropertySetStmtContext)declaration.Context).Signature();
            }

            return declaration.IdentifierName;
        }

        private string GetImageKeyForDeclaration(Declaration declaration)
        {
            var result = string.Empty;
            switch (declaration.DeclarationType)
            {
                case DeclarationType.Module:
                    break;
                case DeclarationType.Class:
                    break;
                case DeclarationType.Procedure:
                case DeclarationType.Function:
                    if (declaration.Accessibility == Accessibility.Private)
                    {
                        result = "PrivateMethod";
                        break;
                    }
                    if (declaration.Accessibility == Accessibility.Friend)
                    {
                        result = "FriendMethod";
                        break;
                    }
                    result = "PublicMethod";
                    break;

                case DeclarationType.PropertyGet:
                case DeclarationType.PropertyLet:
                case DeclarationType.PropertySet:
                    if (declaration.Accessibility == Accessibility.Private)
                    {
                        result = "PrivateProperty";
                        break;
                    }
                    if (declaration.Accessibility == Accessibility.Friend)
                    {
                        result = "FriendProperty";
                        break;
                    }
                    result = "PublicProperty";
                    break;

                case DeclarationType.Parameter:
                    break;
                case DeclarationType.Variable:
                    if (declaration.Accessibility == Accessibility.Private)
                    {
                        result = "PrivateField";
                        break;
                    }
                    if (declaration.Accessibility == Accessibility.Friend)
                    {
                        result = "FriendField";
                        break;
                    }
                    result = "PublicField";
                    break;

                case DeclarationType.Constant:
                    if (declaration.Accessibility == Accessibility.Private)
                    {
                        result = "PrivateConst";
                        break;
                    }
                    if (declaration.Accessibility == Accessibility.Friend)
                    {
                        result = "FriendConst";
                        break;
                    }
                    result = "PublicConst";
                    break;

                case DeclarationType.Enumeration:
                    if (declaration.Accessibility == Accessibility.Private)
                    {
                        result = "PrivateEnum";
                        break;
                    }
                    if (declaration.Accessibility == Accessibility.Friend)
                    {
                        result = "FriendEnum";
                        break;
                    }
                    result = "PublicEnum";
                    break;

                case DeclarationType.EnumerationMember:
                    result = "EnumItem";
                    break;

                case DeclarationType.Event:
                    if (declaration.Accessibility == Accessibility.Private)
                    {
                        result = "PrivateEvent";
                        break;
                    }
                    if (declaration.Accessibility == Accessibility.Friend)
                    {
                        result = "FriendEvent";
                        break;
                    }
                    result = "PublicEvent";
                    break;

                case DeclarationType.UserDefinedType:
                    if (declaration.Accessibility == Accessibility.Private)
                    {
                        result = "PrivateType";
                        break;
                    }
                    if (declaration.Accessibility == Accessibility.Friend)
                    {
                        result = "FriendType";
                        break;
                    }
                    result = "PublicType";
                    break;

                case DeclarationType.UserDefinedTypeMember:
                    result = "PublicField";
                    break;

                case DeclarationType.LibraryProcedure:
                case DeclarationType.LibraryFunction:
                    result = "Identifier";
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
            }

            return result;
        }
    }
}

```

One thing that bothers me above all, is the fact that this presenter is calling into the parser - which means the parse results can only be used in this class... but there are *many* other features that would love to know the VBA code has just been re-parsed. Part of me is starting to accept the idea that maybe perhaps a *Singleton* might be in order here. Is there another way?