1
#include "script/ScriptDocumentOperation.h"
2
#include "simodo/lsp/LspEnums.h"
7
/// \see https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_documentSymbol
10
variable::Value makeDocumentSymbolsResponse(
11
const std::u16string & name,
12
const std::u16string & detail,
14
const lsp::Range & range,
15
const lsp::Range & selectionRange
17
return variable::Object{{
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) },
26
/// Проверка на то, принадлежит ли данная переменная этому модулю (файлу)
27
bool isDeclaredVariableInCurrentFile(const variable::Variable & var) {
28
const auto & spec_origin_value = var.spec().object()->find(variable::SPEC_PROPERTY);
30
return spec_origin_value.isBool() and spec_origin_value.getBool();
33
variable::Value ScriptDocumentOperation::produceDocumentSymbolsResponse() const
35
// \todo bug: дублируется результат в выпадающем списке,
36
// но, полагаю, проблема в дублирующихся перемеренных,
37
// которые получаются после семантического анализа
38
// (см. check/031-12-FunctionDefinition, check/031-14-FunctionDefinition)
40
std::vector<variable::Value> doc_symbols_response;
42
for (const auto & var : _semantic_data.declared()) {
43
if (not isInCurrentFile(var.location())) continue;
45
const bool isGlobal = isDeclaredVariableInCurrentFile(var);
48
case variable::ValueType::Function: {
49
const auto & body_range = getFunctionBodyRange(var);
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();
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()
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()
79
case variable::ValueType::Null:
80
case variable::ValueType::Object:
81
case variable::ValueType::Ref:
87
return doc_symbols_response;