aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/languageclient/progressmanager.cpp
blob: 8bb97afe7ee651e0ab4d8ddbd838de1a71c2a2d2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
// Copyright (C) 2021 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0

#include "progressmanager.h"

#include <coreplugin/progressmanager/futureprogress.h>
#include <coreplugin/progressmanager/progressmanager.h>
#include <languageserverprotocol/progresssupport.h>

using namespace LanguageServerProtocol;

namespace LanguageClient {

ProgressManager::ProgressManager()
{}

ProgressManager::~ProgressManager()
{
    reset();
}

void ProgressManager::handleProgress(const LanguageServerProtocol::ProgressParams &params)
{
    const ProgressToken &token = params.token();
    ProgressParams::ProgressType value = params.value();
    if (auto begin = std::get_if<WorkDoneProgressBegin>(&value))
        beginProgress(token, *begin);
    else if (auto report = std::get_if<WorkDoneProgressReport>(&value))
        reportProgress(token, *report);
    else if (auto end = std::get_if<WorkDoneProgressEnd>(&value))
        endProgress(token, *end);
}

void ProgressManager::setTitleForToken(const LanguageServerProtocol::ProgressToken &token,
                                         const QString &message)
{
    m_titles.insert(token, message);
}

void ProgressManager::reset()
{
    const QList<ProgressToken> &tokens = m_progress.keys();
    for (const ProgressToken &token : tokens)
        endProgress(token);
}

bool ProgressManager::isProgressEndMessage(const LanguageServerProtocol::ProgressParams &params)
{
    return std::holds_alternative<WorkDoneProgressEnd>(params.value());
}

Utils::Id languageClientProgressId(const ProgressToken &token)
{
    constexpr char k_LanguageClientProgressId[] = "LanguageClient.ProgressId.";
    auto toString = [](const ProgressToken &token){
        if (std::holds_alternative<int>(token))
            return QString::number(std::get<int>(token));
        return std::get<QString>(token);
    };
    return Utils::Id(k_LanguageClientProgressId).withSuffix(toString(token));
}

void ProgressManager::beginProgress(const ProgressToken &token, const WorkDoneProgressBegin &begin)
{
    auto interface = new QFutureInterface<void>();
    interface->reportStarted();
    interface->setProgressRange(0, 100); // LSP always reports percentage of the task
    const QString title = m_titles.value(token, begin.title());
    Core::FutureProgress *progress = Core::ProgressManager::addTask(
            interface->future(), title, languageClientProgressId(token));
    m_progress[token] = {progress, interface};
    reportProgress(token, begin);
}

void ProgressManager::reportProgress(const ProgressToken &token,
                                     const WorkDoneProgressReport &report)
{
    const LanguageClientProgress &progress = m_progress.value(token);
    if (progress.progressInterface) {
        const Utils::optional<QString> &message = report.message();
        if (message.has_value()) {
            progress.progressInterface->setSubtitle(*message);
            const bool showSubtitle = !message->isEmpty();
            progress.progressInterface->setSubtitleVisibleInStatusBar(showSubtitle);
        }
    }
    if (progress.futureInterface) {
        if (const Utils::optional<double> &percentage = report.percentage(); percentage.has_value())
            progress.futureInterface->setProgressValue(*percentage);
    }
}

void ProgressManager::endProgress(const ProgressToken &token, const WorkDoneProgressEnd &end)
{
    const LanguageClientProgress &progress = m_progress.value(token);
    const QString &message = end.message().value_or(QString());
    if (progress.progressInterface) {
        if (!message.isEmpty()) {
            progress.progressInterface->setKeepOnFinish(
                Core::FutureProgress::KeepOnFinishTillUserInteraction);
        }
        progress.progressInterface->setSubtitle(message);
        progress.progressInterface->setSubtitleVisibleInStatusBar(!message.isEmpty());
    }
    endProgress(token);
}

void ProgressManager::endProgress(const ProgressToken &token)
{
    const LanguageClientProgress &progress = m_progress.take(token);
    if (progress.futureInterface)
        progress.futureInterface->reportFinished();
    delete progress.futureInterface;
}

} // namespace LanguageClient