loom

Форк
0
/
SemanticTokens.cpp 
122 строки · 6.1 Кб
1
#include "script/ScriptDocumentOperation.h"
2
#include "script/ScriptSemanticTokenLegend.h"
3

4
using namespace simodo;
5

6
using SemanticTokenModifiers = variable::BitFlags<SemanticTokenModifier>;
7

8
/// \file
9
/// \see https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_semanticTokens
10

11
/// \todo Очень непонятно и очень некрасиво. Стоит переписать, чтобы было более понятно.
12
SemanticTokenType ScriptDocumentOperation::selectSemanticTokenType(const variable::Variable & var, const SemanticTokenType function_index) const {
13
    if (var.type() == variable::ValueType::Function)
14
        return function_index;
15

16
    const std::vector<std::u16string> & tokenTypes = _doc.server().server_capabilities().semanticTokensProvider.legend.tokenTypes;
17

18
    if (const variable::Value & spec_origin_value = var.spec().object()->find(variable::SPEC_ORIGIN); spec_origin_value.isString())
19
        for (size_t type_index = 0; type_index < tokenTypes.size(); ++type_index)
20
            if (spec_origin_value.getString() == tokenTypes[type_index])
21
                return static_cast<SemanticTokenType>(type_index);
22

23
    if (!var.spec().object()->variables().empty())
24
        return SemanticTokenType::BuiltInModule;  // \todo Проверить, тот ли тип?
25

26
    switch (var.type()) {
27
        case variable::ValueType::Object:
28
            return SemanticTokenType::Struct;  // \todo Проверить, тот ли тип?
29
        default:
30
            break;
31
    }
32
    return SemanticTokenType::Property;  // \todo Проверить, тот ли тип?
33
}
34

35
SemanticTokenModifiers makeSemanticTokenModifiers(const variable::Variable & var) {
36
    SemanticTokenModifiers modifiers;
37

38
    if (!var.spec().object()->find(variable::SPEC_READONLY).isNull())  modifiers.set(SemanticTokenModifier::Readonly);
39
    if (!var.spec().object()->find(variable::SPEC_PARAMETER).isNull()) modifiers.set(SemanticTokenModifier::Parameter);
40
    if (!var.spec().object()->find(variable::SPEC_INPUT).isNull())     modifiers.set(SemanticTokenModifier::Input);
41
    if (!var.spec().object()->find(variable::SPEC_OUTPUT).isNull())    modifiers.set(SemanticTokenModifier::Output);
42

43
    return modifiers;
44
}
45

46
struct TokenInfo { int64_t length, type, modifiers; };
47
struct PositionComp {
48
    bool operator() (const lsp::Position & x1, const lsp::Position & x2) const  { return x1 < x2; }
49
};
50

51
variable::Value ScriptDocumentOperation::produceSemanticTokensResponse() const
52
{
53
    std::map<lsp::Position, TokenInfo, PositionComp> tokens;
54
    const std::function insertToken =
55
            [&tokens](const inout::TokenLocation & loc, const SemanticTokenType type, const SemanticTokenModifiers & modifiers) 
56
            {
57
                const auto & range = loc.range();
58

59
                assert(range.start().line() == range.end().line());  // Предполагаем, что токен располагается на одной строке!
60
                const TokenInfo & tokenInfo = {
61
                        .length    = range.end().character() - range.start().character(),
62
                        .type      = static_cast<int64_t>(type),
63
                        .modifiers = modifiers.getRawValue(),
64
                };
65

66
                tokens.insert({ loc.range().start(), tokenInfo });
67
            };
68

69
    for(const variable::Variable & v : _semantic_data.declared())
70
        if (isInCurrentFile(v.location()) and not v.value().isError()) {
71
            insertToken(v.location(),
72
                        selectSemanticTokenType(v, SemanticTokenType::Function),             // \todo Проверить, тот ли тип?
73
                        makeSemanticTokenModifiers(v) | SemanticTokenModifier::Declaration); // \todo Проверить, тот ли модификатор?
74
        }
75

76
    for(const auto & [declared_variable, using_location] : _semantic_data.used())
77
        if (isInCurrentFile(using_location)) {
78
            SemanticTokenModifiers modifiers = makeSemanticTokenModifiers(declared_variable);
79

80
            if (declared_variable.location().range() != inout::Range {{0,0},{0,0}})
81
                modifiers.set(SemanticTokenModifier::Anchor);
82

83
            if (isRemoteFunctionLaunch(using_location))
84
                modifiers.set(SemanticTokenModifier::Remote);
85

86
            insertToken(using_location,
87
                        selectSemanticTokenType(declared_variable, SemanticTokenType::Method), // \todo Проверить, тот ли тип?
88
                        modifiers);                                                            // \todo Проверить, тот ли модификатор?
89
        }
90

91
    for(const auto & [t, ref] : _semantic_data.refs())
92
        if (isInCurrentFile(t.location())) {
93
            insertToken(t.location(),
94
                        SemanticTokenType::String,       // \todo Проверить, тот ли тип?
95
                        SemanticTokenModifier::Anchor);  // \todo Проверить, тот ли модификатор?
96
        }
97

98
    for(const inout::Token & t : _semantic_data.tokens())
99
        if (isInCurrentFile(t.location()) and t.qualification() == inout::TokenQualification::Keyword) {
100
            SemanticTokenType type;
101
            if (t.lexeme() == u"true" || t.lexeme() == u"false")
102
                type = SemanticTokenType::Boolean;  // \todo Проверить, тот ли тип?
103
            else if (t.lexeme() == u"undef" || t.lexeme() == u"null")
104
                type = SemanticTokenType::Number;   // \todo Проверить, тот ли тип?
105
            else
106
                type = SemanticTokenType::Keyword;  // \todo Проверить, тот ли тип?
107

108
            insertToken(t.location(), type, SemanticTokenModifiers::Empty);
109
        }
110

111
    std::vector<variable::Value> sem_tokens;
112

113
    for(const auto & [p, t] : tokens) {
114
        sem_tokens.emplace_back(static_cast<int64_t>(p.line()));
115
        sem_tokens.emplace_back(static_cast<int64_t>(p.character()));
116
        sem_tokens.emplace_back(t.length);
117
        sem_tokens.emplace_back(t.type);
118
        sem_tokens.emplace_back(t.modifiers);
119
    }
120

121
    return variable::Object{{{ u"data", sem_tokens }}};
122
}
123

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.