source: tools/langserver/src/main.cpp

Last change on this file was ebe0f0d, checked in by Thierry Delisle <tdelisle@…>, 5 years ago

Added basic language server which now properly communicates with the client

  • Property mode set to 100644
File size: 2.7 KB
Line 
1#include <cstdio>
2
3#include <iostream>
4#include <string>
5#include <vector>
6
7#include <unistd.h>
8
9#include "json.hpp"
10#include "log.hpp"
11#include "server.hpp"
12
13static void request(std::vector<char> & buf);
14static void reply(const json::obj & );
15
16json::obj noop( const json::obj & ) {
17        return {};
18}
19
20std::unordered_map<std::string, json::obj (*)( const json::obj & )> actions {
21        { "initialize", server::init },
22        { "initialized", noop }
23};
24
25int main(int argc, char * argv[]) {
26        g_argc = argc;
27        g_argv = argv;
28
29        log() << "Language Server called with args:" << std::endl;
30        for(int i = 0; i < argc; i++) {
31                log() << "\t- " << argv[i] << std::endl;
32        }
33
34        // std::cout.setf(std::ios::unitbuf);
35
36        // char buff[1000];
37        // int r = 0;
38        // while(0 != (r = read(STDIN_FILENO, buff, 1000))) {
39        //      for(int i = 0; i < r; i++) {
40        //              log() << buff[i];
41        //      }
42        // }
43        // log() << std::endl;
44
45        // return 0;
46
47        std::vector<char> buffer;
48        while(true) {
49                request(buffer);
50                if(buffer.size() == 0) break;
51
52                auto top = json::parse(buffer);
53
54                auto action = actions.find( top["method"] );
55                if(action != actions.end()) {
56                        log() << "Executing request '" << action->first << "'" << std::endl;
57                        json::obj response = {
58                                {"id", top["id"] }
59                        };
60
61                        try{
62                                response["result"] = action->second( top["params"] );
63                        } catch( const json::obj & error ) {
64                                response["result"] = "";
65                                response["error"] = error;
66                        }
67
68                        reply(response);
69                }
70                else {
71                        log() << "WARNING no action for method '" << top["method"].dump(4) << "'" << std::endl;
72                }
73        }
74
75        log() << "Language Server closing after end of file" << std::endl;
76
77        return 0;
78}
79
80static void request(std::vector<char> & buffer) {
81        std::string lenstr;
82        std::getline( std::cin, lenstr );
83        if(std::cin.eof()) { buffer.clear(); return; };
84
85        if (lenstr.rfind("Content-Length: ", 0) != 0) {
86                log() << "Expected content length bug got '" << lenstr << "' instead " << std::endl;
87                std::exit(EXIT_FAILURE);
88        }
89
90        size_t idx = sizeof("Content-Length:");
91        size_t end;
92        size_t len = std::stoul(lenstr.substr(idx), &end);
93        if(lenstr.length() != (idx + end + 1)) {
94                log() << "Inconsistent size of integer in content length: " << lenstr.length() << " vs " << (idx + end) << std::endl;
95        }
96
97        log() << "New request of " << len << " bytes" << std::endl;
98        buffer.resize( len + 2 );
99        std::cin.read(buffer.data(), buffer.size());
100
101        for(char c : buffer) {
102                log() << c;
103        }
104        log() << std::endl;
105        return;
106}
107
108static void reply( const json::obj & response) {
109        if(response["result"].is_null()) {
110                log() << "No response needed" << std::endl;
111                return;
112        }
113
114        log() << "Responding with : " << response.dump(4) << std::endl;
115        const std::string & r = response.dump();
116        std::cout << "Content-Length: " << r.length() << "\r\n\r\n";
117        std::cout.flush();
118        std::cout  << r << "\r\n";
119        std::cout.flush();
120}
Note: See TracBrowser for help on using the repository browser.