source: tools/langserver/src/main.cpp@ ef1da0e2

ADT ast-experimental pthread-emulation
Last change on this file since ef1da0e2 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.