/// <summary> /// Highlights the symbol node corresponding to the current caret position in the editor, expands/collapses nodes, then updates the UI. /// </summary> private async ValueTask HighlightExpandAndPresentItemsAsync(ImmutableSegmentedList <ExpansionOption> expansionOption, CancellationToken cancellationToken) { var model = await _filterAndSortDataModelQueue.WaitUntilCurrentBatchCompletesAsync().ConfigureAwait(false); if (model is null) { return; } // Switch to the UI thread to get the current caret point and latest active text view then create the UI model. await _threadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken); var activeTextView = GetLastActiveIWpfTextView(); if (activeTextView is null) { return; } var caretPoint = activeTextView.GetCaretPoint(activeTextView.TextBuffer); if (!caretPoint.HasValue) { return; } var documentSymbolUIItems = DocumentOutlineHelper.GetDocumentSymbolUIItems(model.DocumentSymbolData, _threadingContext); // Switch to the threadpool to determine which node to select (if applicable). await TaskScheduler.Default; var symbolToSelect = DocumentOutlineHelper.GetDocumentNodeToSelect(documentSymbolUIItems, model.OriginalSnapshot, caretPoint.Value); // Switch to the UI thread to update the view. await _threadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken); // Expand/collapse nodes based on the given Expansion Option. var expansion = expansionOption.Last(); if (expansion is not ExpansionOption.NoChange && SymbolTree.ItemsSource is not null) { DocumentOutlineHelper.SetIsExpanded(documentSymbolUIItems, (IEnumerable <DocumentSymbolUIItem>)SymbolTree.ItemsSource, expansion); } // Hightlight the selected node if it exists, otherwise unselect all nodes (required so that the view does not select a node by default). if (symbolToSelect is not null) { // Expand all ancestors first to ensure the selected node will be visible. DocumentOutlineHelper.ExpandAncestors(documentSymbolUIItems, symbolToSelect.RangeSpan); symbolToSelect.IsSelected = true; } else { // On Document Outline Control initialization, SymbolTree.ItemsSource is null if (SymbolTree.ItemsSource is not null) { DocumentOutlineHelper.UnselectAll((IEnumerable <DocumentSymbolUIItem>)SymbolTree.ItemsSource); } } SymbolTree.ItemsSource = documentSymbolUIItems; }