loom

Форк
0
/
main.cpp 
238 строк · 8.4 Кб
1
/*
2
MIT License
3

4
Copyright (c) 2021 МГТУ им. Н.Э. Баумана, кафедра ИУ-6, Михаил Фетисов,
5

6
https://bmstu.codes/lsx/simodo
7
*/
8

9
/*! \file Утилита тестирования средств работы с JSON библиотеки SIMODO core. Проект SIMODO.
10
 */
11

12
#include "simodo/lsp-server/ServerContext.h"
13
#include "simodo/lsp-server/DocumentContext.h"
14

15
#include "simodo/lsp-client/LspEnums.h"
16

17
#include "simodo/variable/json/parser/JsonRdp.h"
18
#include "simodo/variable/json/parser/Json5Rdp.h"
19
#include "simodo/variable/json/parser/JsonLspBuilder.h"
20
#include "simodo/inout/log/Logger.h"
21
#include "simodo/inout/token/RefBufferStream.h"
22
#include "simodo/inout/convert/functions.h"
23
#include "simodo/variable/json/Serialization.h"
24

25
#include <vector>
26
#include <memory>
27
#include <algorithm>
28
#include <exception>
29

30
using namespace simodo;
31

32
class JsonDocumentOperation : public lsp::DocumentOperation_interface
33
{
34
    lsp::DocumentContext &              _doc;
35

36
    std::vector<inout::Token>           _const_variable_set;
37
    std::vector<std::pair<inout::Token,inout::Token>>
38
                                        _group_set;
39

40
public:
41
    JsonDocumentOperation(lsp::DocumentContext &doc) : _doc(doc) {}
42

43
    virtual bool analyze(const std::u16string & text, inout::Reporter_abstract & m) override
44
    {
45
        if (_doc.file_name().empty())
46
            return false;
47

48
        std::vector<inout::Token>   const_variable_set;
49
        std::vector<std::pair<inout::Token,inout::Token>>
50
                                    group_set;
51
        variable::JsonLspBuilder    builder(const_variable_set, group_set);
52
        inout::RefBufferStream      buffer_stream(text.data());
53
        std::unique_ptr<inout::Parser_interface>   
54
                                    parser;
55
        variable::Value             value;
56
        bool                        ok = false;
57

58
        if (_doc.file_name()[_doc.file_name().size()-1] == '5')
59
            parser = std::make_unique<variable::Json5Rdp>(m, builder, _doc.file_name(), value);
60
        else
61
            parser = std::make_unique<variable::JsonRdp>(m, builder, _doc.file_name(), value);
62

63
        try
64
        {
65
            ok = parser->parse(buffer_stream);
66
        }
67
        catch(const std::exception & ex)
68
        {
69
            m.reportFatal(ex.what());
70
        }
71

72
        if (ok || const_variable_set.size() >= _const_variable_set.size()) {
73
            std::sort(group_set.begin(), 
74
                    group_set.end(), 
75
                    [](const std::pair<inout::Token,inout::Token> & a, const std::pair<inout::Token,inout::Token> & b)
76
                    {
77
                        return a.first.location().range().start() < b.first.location().range().start();
78
                    });
79

80
            _const_variable_set.swap(const_variable_set);
81
            _group_set.swap(group_set);
82
        }
83

84
        return true;
85
    }
86

87
    virtual bool checkDependency(const std::string & /*uri*/) const override
88
    {
89
        return false;
90
    }
91

92
    virtual variable::Value produceHoverResponse(const lsp::Position & /*pos*/) const override
93
    {
94
        return {};
95
    }
96

97
    virtual variable::Value produceGotoDeclarationResponse(const lsp::Position & /*pos*/) const override
98
    {
99
        return {};
100
    }
101

102
    virtual variable::Value produceGotoDefinitionResponse(const lsp::Position & /*pos*/) const override
103
    {
104
        return {};
105
    }
106

107
    virtual variable::Value produceCompletionResponse(const lsp::CompletionParams & /*completionParams*/) const override
108
    {
109
        return {};
110
    }
111

112
    virtual variable::Value produceSemanticTokensResponse() const override
113
    {
114
        struct TokenInfo { int64_t length, type, modifiers; };
115
        struct TokenComp {
116
            bool operator() (const std::pair<int64_t,int64_t> & x1, const std::pair<int64_t,int64_t> & x2) const {
117
                return x1.first < x2.first || (x1.first == x2.first && x1.second < x2.second);
118
            }
119
        };    
120

121
        std::map<std::pair<int64_t,int64_t>, TokenInfo, TokenComp> tokens;
122

123
        for(const inout::Token & t : _const_variable_set) 
124
            if (t.type() == inout::LexemeType::Id) {
125
                int64_t line      = static_cast<int64_t>(t.location().range().start().line());
126
                int64_t character = static_cast<int64_t>(t.location().range().start().character());
127
                int64_t length    = static_cast<int64_t>(t.location().range().end().character()-character);
128
                int64_t modifiers = static_cast<int64_t>(0);
129
                tokens.insert({ {line, character}, {length, 0, modifiers}});
130
            }
131

132
        std::vector<variable::Value> sem_tokens;
133

134
        for(const auto & [p,t] : tokens) {
135
            sem_tokens.emplace_back(p.first);
136
            sem_tokens.emplace_back(p.second);
137
            sem_tokens.emplace_back(t.length);
138
            sem_tokens.emplace_back(t.type);
139
            sem_tokens.emplace_back(t.modifiers);
140
        }
141
        
142
        return variable::Object {{{u"data", sem_tokens}}};
143
    }
144

145
    virtual variable::Value produceDocumentSymbolsResponse() const override
146
    {
147
        std::vector<variable::Value> doc_symbols;
148

149
        for(const inout::Token & t : _const_variable_set)
150
            if (t.type() == inout::LexemeType::Id) {
151
                    doc_symbols.emplace_back(variable::Object {{
152
                        {u"name",           t.token()},
153
                        {u"detail",         t.token()
154
                                            + u" [" + inout::toU16(std::to_string(t.location().range().start().line()+1))
155
                                            + u","  + inout::toU16(std::to_string(t.location().range().start().character()+1))
156
                                            + u"]"},
157
                        {u"kind",           int64_t(lsp::SymbolKind::Variable)},
158
                        {u"range",          _doc.makeRange({t.location().range().start(), t.location().range().end()})},
159
                        {u"selectionRange", _doc.makeRange(t.location().range())},
160
                    }});
161
                }
162

163
        return doc_symbols;
164
    }
165

166
    virtual variable::Value produceSimodoCommandResponse(const std::u16string & /*command_name*/, std::u16string /*text*/) const override
167
    {
168
        return {};
169
    }
170
};
171

172
class DocumentOperationFactory : public lsp::DocumentOperationFactory_interface
173
{
174
public:
175
    virtual std::unique_ptr<lsp::DocumentOperation_interface> create(lsp::DocumentContext &doc, const std::string & /*languageId*/)
176
    {
177
        return std::make_unique<JsonDocumentOperation>(doc);
178
    }
179
};
180

181
int main(int argc, char *argv[])
182
{
183
    inout::Logger::SeverityLevel  log_level = inout::Logger::SeverityLevel::Info;
184
    bool                          save_mode = false;
185
    std::unique_ptr<std::ostream> log_stream;
186
    std::unique_ptr<std::istream> in;
187

188
    if (argc > 1)
189
        log_stream = std::make_unique<std::ofstream>(argv[1]);
190

191
    if (argc > 2)
192
    {
193
        if (std::string(argv[2]) == "Debug")
194
            log_level = inout::Logger::SeverityLevel::Debug;
195
        else if (std::string(argv[2]) == "Info")
196
            log_level = inout::Logger::SeverityLevel::Info;
197
        else if (std::string(argv[2]) == "Warning")
198
            log_level = inout::Logger::SeverityLevel::Warning;
199
        else if (std::string(argv[2]) == "Error")
200
            log_level = inout::Logger::SeverityLevel::Error;
201
        else if (std::string(argv[2]) == "Critical")
202
            log_level = inout::Logger::SeverityLevel::Critical;
203
    }
204

205
    if (argc > 3)
206
        save_mode = std::string(argv[3]) == "save";
207

208
    if (argc > 4)
209
#ifdef CROSS_WIN
210
        in = std::make_unique<std::ifstream>(simodo::inout::fromUtf8CharToWChar(argv[4]).c_str());
211
#else
212
        in = std::make_unique<std::ifstream>(argv[4]);
213
#endif
214
    inout::Logger log(log_stream ? *log_stream.get() : std::cerr, 
215
                    "SIMODO-LSP-JSON", 
216
                    log_level);
217

218
    lsp::ServerCapabilities server_capabilities;
219

220
    server_capabilities.hoverProvider = false;
221
    server_capabilities.documentSymbolProvider = true;
222
    server_capabilities.semanticTokensProvider.legend.tokenTypes = {u"property"};
223

224
    DocumentOperationFactory factory;
225

226
    lsp::ServerContext server(u"JSON",
227
                              server_capabilities,
228
                              lsp::SimodoCapabilities(),
229
                              factory,
230
                              log,
231
                              in ? *in.get() : std::cin,
232
                              std::cout,
233
                              save_mode);
234

235
    server.run();
236

237
    return 0;
238
}
239

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

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

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

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