loom

Форк
0
/
DocumentSymbols.cpp 
88 строк · 3.8 Кб
1
#include "script/ScriptDocumentOperation.h"
2
#include "simodo/lsp/LspEnums.h"
3

4
using namespace simodo;
5

6
/// \file
7
/// \see https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_documentSymbol
8

9

10
variable::Value makeDocumentSymbolsResponse(
11
        const std::u16string & name,
12
        const std::u16string & detail,
13
        lsp::SymbolKind        kind,
14
        const lsp::Range &     range,
15
        const lsp::Range &     selectionRange
16
) {
17
    return variable::Object{{
18
        { u"name",           name },
19
        { u"detail",         detail },
20
        { u"kind",           static_cast<int64_t>(kind) },
21
        { u"range",          lsp::DocumentContext::makeRange(range) },
22
        { u"selectionRange", lsp::DocumentContext::makeRange(selectionRange) },
23
}};
24
}
25

26
/// Проверка на то, принадлежит ли данная переменная этому модулю (файлу)
27
bool isDeclaredVariableInCurrentFile(const variable::Variable & var) {
28
    const auto & spec_origin_value = var.spec().object()->find(variable::SPEC_PROPERTY);
29

30
    return spec_origin_value.isBool() and spec_origin_value.getBool();
31
}
32

33
variable::Value ScriptDocumentOperation::produceDocumentSymbolsResponse() const
34
{
35
    // \todo bug: дублируется результат в выпадающем списке,
36
    //       но, полагаю, проблема в дублирующихся перемеренных,
37
    //       которые получаются после семантического анализа
38
    //       (см. check/031-12-FunctionDefinition, check/031-14-FunctionDefinition)
39

40
    std::vector<variable::Value> doc_symbols_response;
41

42
    for (const auto & var : _semantic_data.declared()) {
43
        if (not isInCurrentFile(var.location())) continue;
44

45
        const bool isGlobal = isDeclaredVariableInCurrentFile(var);
46

47
        switch (var.type()) {
48
            case variable::ValueType::Function: {
49
                    const auto & body_range = getFunctionBodyRange(var);
50

51
                    const auto & var_start  = var.location().range().start();
52
                    // если имя функции находится левее тела функции, то возьмём вместе с именем функции, иначе просто тело
53
                    const auto & start      = var_start <= body_range.start() ? var_start : body_range.start();
54
                    const auto & end        = body_range.end();
55

56
                    doc_symbols_response.push_back(makeDocumentSymbolsResponse(
57
                        /* name           = */ var.name(),
58
                        /* detail         = */ getVariableString(var),
59
                        /* kind           = */ lsp::SymbolKind::Function,
60
                        /* range          = */ { start, end },
61
                        /* selectionRange = */ var.location().range()
62
                    ));
63
                }
64
                break;
65
            case variable::ValueType::Bool:
66
            case variable::ValueType::Int:
67
            case variable::ValueType::Float:
68
            case variable::ValueType::String:
69
            case variable::ValueType::Array:
70
                if (not isGlobal) break;
71
                doc_symbols_response.push_back(makeDocumentSymbolsResponse(
72
                    /* name           = */ var.name(),
73
                    /* detail         = */ getVariableString(var),
74
                    /* kind           = */ lsp::SymbolKind::Variable,
75
                    /* range          = */ var.location().range(),
76
                    /* selectionRange = */ var.location().range()
77
                ));
78
                break;
79
            case variable::ValueType::Null:
80
            case variable::ValueType::Object:
81
            case variable::ValueType::Ref:
82
            default: break;
83
        }
84

85
    }
86

87
    return doc_symbols_response;
88
}
89

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

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

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

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