lspsemantichighlighting.cpp 3.68 KB
Newer Older
1
2
#include "lspsemantichighlighting.h"

3
4
#include <KTextEditor/MovingInterface>
#include <KTextEditor/View>
5

6
#include "semantic_tokens_legend.h"
7

8
9
10
void SemanticHighlighter::remove(const QUrl &url)
{
    m_docUrlToResultId.remove(url);
11
12
13
14
15
16
17

    auto it = m_docSemanticInfo.find(url);
    if (it == m_docSemanticInfo.end()) {
        return;
    }

    auto &movingRanges = it->movingRanges;
18
19
    for (auto mr : movingRanges) {
        delete mr;
Waqar Ahmed's avatar
Waqar Ahmed committed
20
        mr = nullptr;
21
    }
Waqar Ahmed's avatar
Waqar Ahmed committed
22
    movingRanges.clear();
23
    m_docSemanticInfo.remove(url);
24
}
25

26
void SemanticHighlighter::insert(const QUrl &url, const QString &resultId, const std::vector<uint32_t> &data)
27
{
28
29
30
    m_docUrlToResultId[url] = resultId;
    TokensData &tokensData = m_docSemanticInfo[url];
    tokensData.tokens = data;
31
32
}

33
34
35
36
/**
 * Handle semantic tokens edits
 */
void SemanticHighlighter::update(const QUrl &url, const QString &resultId, uint32_t start, uint32_t deleteCount, const std::vector<uint32_t> &data)
37
{
38
39
    auto toks = m_docSemanticInfo.find(url);
    if (toks == m_docSemanticInfo.end()) {
40
        return;
41
    }
42

43
    auto &existingTokens = toks->tokens;
44

45
46
47
    // replace
    if (deleteCount > 0) {
        existingTokens.erase(existingTokens.begin() + start, existingTokens.begin() + start + deleteCount);
48
    }
49
    existingTokens.insert(existingTokens.begin() + start, data.begin(), data.end());
50

51
52
53
    //     Update result Id
    m_docUrlToResultId[url] = resultId;
}
54

55
56
57
void SemanticHighlighter::highlight(const QUrl &url)
{
    Q_ASSERT(m_legend);
58

59
60
    if (!view || !m_legend) {
        return;
61
    }
62
63
64
65
66

    auto doc = view->document();
    if (!doc) {
        qWarning() << "View doesn't have doc!";
        return;
67
    }
68
69
70
71
72
73
74
75
76
77

    auto miface = qobject_cast<KTextEditor::MovingInterface *>(doc);

    TokensData &semanticData = m_docSemanticInfo[url];
    auto &movingRanges = semanticData.movingRanges;
    auto &data = semanticData.tokens;

    if (data.size() % 5 != 0) {
        qWarning() << "Bad data for doc: " << url << " skipping";
        return;
78
    }
79

80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
    int currentLine = 0;
    int start = 0;

    int reusedRanges = 0;
    int newRanges = 0;

    for (size_t i = 0; i < data.size(); i += 5) {
        int deltaLine = data.at(i);
        int deltaStart = data.at(i + 1);
        int len = data.at(i + 2);
        int type = data.at(i + 3);
        int mod = data.at(i + 4);
        (void)mod;

        currentLine += deltaLine;

        if (deltaLine == 0) {
            start += deltaStart;
        } else {
            start = deltaStart;
100
101
        }

102
103
        QString text = doc->line(currentLine);
        text = text.mid(start, len);
104

105
106
107
108
109
110
111
112
113
114
        KTextEditor::Range r(currentLine, start, currentLine, start + len);

        // Check if we have a moving ranges already available in the cache
        const auto index = i / 5;
        if (index < movingRanges.size()) {
            auto &range = movingRanges[index];
            range->setRange(r);
            range->setAttribute(m_legend->attrForIndex(type));
            reusedRanges++;
            continue;
115
        }
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133

        KTextEditor::MovingRange *mr = miface->newMovingRange(r);
        mr->setAttribute(m_legend->attrForIndex(type));
        movingRanges.push_back(mr);
        newRanges++;

        //         std::cout << "Token: " << text.toStdString() << " => " << m_types.at(type).toStdString() << ", Line: {" << currentLine << ", " << deltaLine
        //         << "}\n";
    }

    /**
     * Invalid all extra ranges
     */
    int totalCreatedRanges = reusedRanges + newRanges;
    if (totalCreatedRanges < (int)movingRanges.size()) {
        std::for_each(movingRanges.begin() + totalCreatedRanges, movingRanges.end(), [](KTextEditor::MovingRange *mr) {
            mr->setRange(KTextEditor::Range::invalid());
        });
134
135
    }
}