Repository: microsoft/terminal
File: src/cascadia/TerminalApp/TabManagement.cpp (C++)

Code before:
    }

    // Method Description:
    // - Removes the tab (both TerminalControl and XAML) after prompting for approval
    // Arguments:
    // - tab: the tab to remove
    winrt::Windows::Foundation::IAsyncAction TerminalPage::_HandleCloseTabRequested(winrt::TerminalApp::TabBase tab)
    {
        if (tab.ReadOnly())
        {
            ContentDialogResult warningResult = co_await _ShowCloseReadOnlyDialog();

            // If the user didn't explicitly click on close tab - leave
            if (warningResult != ContentDialogResult::Primary)
            {
                co_return;
            }
        }

        if (const auto terminalTab = _GetTerminalTabImpl(tab))
        {
            auto actions = terminalTab->BuildStartupActions();

            _AddPreviouslyClosedPaneOrTab(std::move(actions));
        }
        else if (tab.try_as<SettingsTab>())
        {
            ActionAndArgs action;
            action.Action(ShortcutAction::OpenSettings);
            OpenSettingsArgs args{ SettingsTarget::SettingsUI };
            action.Args(args);

            _AddPreviouslyClosedPaneOrTab(std::vector{ std::move(action) });
        }

        _RemoveTab(tab);
    }

    // Method Description:
    // - Removes the tab (both TerminalControl and XAML)
    // Arguments:
    // - tab: the tab to remove
    void TerminalPage::_RemoveTab(const winrt::TerminalApp::TabBase& tab)
    {
        uint32_t tabIndex{};
        if (!_tabs.IndexOf(tab, tabIndex))
        {
            // The tab is already removed
            return;
        }


Review comment (suggestion):
this almost seems like `TabBase` should have a virtual method like `BuildStartupActions` that both `TerminalTab` and `SettingsTab` override with their specific implementations...

Code after:
    }

    // Method Description:
    // - Removes the tab (both TerminalControl and XAML) after prompting for approval
    // Arguments:
    // - tab: the tab to remove
    winrt::Windows::Foundation::IAsyncAction TerminalPage::_HandleCloseTabRequested(winrt::TerminalApp::TabBase tab)
    {
        if (tab.ReadOnly())
        {
            ContentDialogResult warningResult = co_await _ShowCloseReadOnlyDialog();

            // If the user didn't explicitly click on close tab - leave
            if (warningResult != ContentDialogResult::Primary)
            {
                co_return;
            }
        }

        auto t = winrt::get_self<implementation::TabBase>(tab);
        auto actions = t->BuildStartupActions();
        _AddPreviouslyClosedPaneOrTab(std::move(actions));

        _RemoveTab(tab);
    }

    // Method Description:
    // - Removes the tab (both TerminalControl and XAML)
    // Arguments:
    // - tab: the tab to remove
    void TerminalPage::_RemoveTab(const winrt::TerminalApp::TabBase& tab)
    {
        uint32_t tabIndex{};
        if (!_tabs.IndexOf(tab, tabIndex))
        {
            // The tab is already removed
            return;
        }

        // We use _removing flag to suppress _OnTabSelectionChanged events
        // that might get triggered while removing
        _removing = true;
        auto unsetRemoving = wil::scope_exit([&]() noexcept { _removing = false; });

        const auto focusedTabIndex{ _GetFocusedTabIndex() };

        // Removing the tab from the collection should destroy its control and disconnect its connection,
        // but it doesn't always do so. The UI tree may still be holding the control and preventing its destruction.
        tab.Shutdown();

        uint32_t mruIndex{};