Bash++
Bash++ compiler internal documentation
BashppServer.h
Go to the documentation of this file.
1
7#pragma once
8
9#include <iostream>
10#include <thread>
11#include <mutex>
12#include <chrono>
13#include <atomic>
14#include <memory>
15#include <unordered_map>
16#include <fstream>
17#include <nlohmann/json.hpp>
18#include <unistd.h>
19
20#include <frozen/string.h>
21#include <frozen/unordered_map.h>
22
23#include "ThreadPool.h"
24#include "ProgramPool.h"
25
26#include "static/Message.h"
27
28#include "generated/CompletionList.h"
29#include "generated/CompletionParams.h"
30
32#include <include/BashVersion.h>
33
34namespace bpp {
35
36using json = nlohmann::json;
37
38template<typename T>
39void printValue(std::ostream& os, const T& value) {
40 os << value;
41}
42
43template<typename... Ts>
44void printValue(std::ostream& os, const std::variant<Ts...>& v) {
45 std::visit([&os](auto&& arg) { os << arg; }, v);
46}
47
48
58 private:
59 pid_t pid = getpid();
60 std::atomic<bool> shutting_down = false;
61 // Resources
62 std::istream* input_stream = &std::cin; // Held as std::stream* for future extensions beyond stdio
63 std::ostream* output_stream = &std::cout;
64 ThreadPool thread_pool = ThreadPool(std::thread::hardware_concurrency());
65 ProgramPool program_pool = ProgramPool(10); // Maximum 10 programs in the pool
66 std::ofstream log_file;
67
68 // Debouncing didChange notifications
70 std::atomic<uint64_t> change_generation{0};
71 std::atomic<uint64_t> average_reparse_time_in_microseconds{50'000}; // 50ms initial guess
72 std::atomic<uint32_t> debounce_time_in_milliseconds{100}; // Start with 100ms
73 };
74
75 // Map: program main URI -> DebounceState
76 // Used for adaptive debouncing
78 private:
79 std::unordered_map<std::string, std::shared_ptr<DebounceState>> states;
81 std::mutex map_mutex;
82
83 void cleanup() {
84 for (auto it = states.begin(); it != states.end(); ) {
85 if (!pool->has_program(it->first)) {
86 it = states.erase(it);
87 } else {
88 it++;
89 }
90 }
91 }
92 public:
93 DebounceStateMap() = delete;
95 std::shared_ptr<DebounceState> get(const std::string& uri) {
96 std::lock_guard<std::mutex> lock(map_mutex);
97 cleanup(); // Clean up stale entries on every access
98 auto it = states.find(uri);
99 if (it != states.end()) return it->second;
100 auto new_state = std::make_shared<DebounceState>();
101 states[uri] = new_state;
102 return new_state;
103 }
104 };
106 std::atomic<bool> processing_didChange{false};
107
108 static std::string readHeaderLine(std::streambuf* buffer);
109
110 void _sendMessage(const std::string& message);
111
112 static std::mutex output_mutex; // Mutex for thread-safe output
113 static std::mutex log_mutex; // Mutex for thread-safe logging
114
115 static GenericResponseMessage invalidRequestHandler(const GenericRequestMessage& request);
116 static void invalidNotificationHandler(const GenericNotificationMessage& request);
117
118 void processRequest(const GenericRequestMessage& request);
119 void processNotification(const GenericNotificationMessage& notification);
120
122 public:
123 BashppServer();
124 ~BashppServer() = default;
125
126 BashppServer(const BashppServer& other) = delete; // Non-copyable
127 BashppServer& operator=(const BashppServer& other) = delete;
128 BashppServer(BashppServer&& other) noexcept = delete; // Non-movable
129 BashppServer& operator=(BashppServer&& other) noexcept = delete;
130
131 void mainLoop();
132
133 void setLogFile(const std::string& path);
134 void setTargetBashVersion(const BashVersion& version);
135
136 GenericResponseMessage shutdown(const GenericRequestMessage& request);
137 void cleanup();
138
139 void processMessage(const std::string& message);
140
141 // Request-Response handlers
142 GenericResponseMessage handleInitialize(const GenericRequestMessage& request);
143 GenericResponseMessage handleDefinition(const GenericRequestMessage& request);
144 GenericResponseMessage handleHover(const GenericRequestMessage& request);
145 GenericResponseMessage handleDocumentSymbol(const GenericRequestMessage& request);
146 GenericResponseMessage handleRename(const GenericRequestMessage& request);
147 GenericResponseMessage handleReferences(const GenericRequestMessage& request);
148 GenericResponseMessage handleCompletion(const GenericRequestMessage& request);
149
150 CompletionList handleATCompletion(const CompletionParams& params);
151 CompletionList handleDOTCompletion(const CompletionParams& params);
152
153 // Notification handlers
154 void handleDidOpen(const GenericNotificationMessage& request);
155 void handleDidChange(const GenericNotificationMessage& request);
156 void handleDidChangeWatchedFiles(const GenericNotificationMessage& request);
157 void handleDidClose(const GenericNotificationMessage& request);
158
159 void sendResponse(const GenericResponseMessage& response);
160 void sendNotification(const GenericNotificationMessage& notification);
161
162 void publishDiagnostics(std::shared_ptr<bpp::bpp_program> program);
163
164 void add_include_path(const std::string& path);
165 void set_suppress_warnings(bool suppress);
166
167 template <typename... Args>
168 void log(Args&&... args) {
169 if (!log_file.is_open()) return; // Not logging
170
171 std::lock_guard<std::mutex> lock(log_mutex);
172 auto now = std::chrono::system_clock::now();
173 auto now_time_t = std::chrono::system_clock::to_time_t(now);
174 std::tm tm_buf{};
175 localtime_r(&now_time_t, &tm_buf);
176 log_file << "[" << std::put_time(&tm_buf, "%Y-%m-%d %H:%M:%S") << "] ";
177 log_file << "[" << std::to_string(pid) << "] ";
178 ((printValue(log_file, std::forward<Args>(args))), ...);
179 log_file << std::endl;
180 }
181
182 private:
183 using RequestHandler = GenericResponseMessage (BashppServer::*)(const GenericRequestMessage&);
184 using NotificationHandler = void (BashppServer::*)(const GenericNotificationMessage&);
185
190 static constexpr frozen::unordered_map<frozen::string, RequestHandler, 8> request_handlers = {
191 {"initialize", &BashppServer::handleInitialize},
192 {"textDocument/definition", &BashppServer::handleDefinition},
193 {"textDocument/completion", &BashppServer::handleCompletion},
194 {"textDocument/hover", &BashppServer::handleHover},
195 {"textDocument/documentSymbol", &BashppServer::handleDocumentSymbol},
196 {"textDocument/rename", &BashppServer::handleRename},
197 {"textDocument/references", &BashppServer::handleReferences},
198 {"shutdown", &BashppServer::shutdown}
199 };
200
205 static constexpr frozen::unordered_map<frozen::string, NotificationHandler, 4> notification_handlers = {
206 {"textDocument/didOpen", &BashppServer::handleDidOpen},
207 {"textDocument/didChange", &BashppServer::handleDidChange},
208 {"workspace/didChangeWatchedFiles", &BashppServer::handleDidChangeWatchedFiles},
209 {"textDocument/didClose", &BashppServer::handleDidClose}
210 };
211};
212
213} // namespace bpp
Manages a pool of bpp_program objects for efficient reuse and access.
Definition ProgramPool.h:36
bool has_program(const std::string &file_path)
Check if a program for the given file path exists in the pool.
Definition ProgramPool.cpp:234
A thread pool implementation that manages a pool of worker threads to execute tasks concurrently.
Definition ThreadPool.h:24
Definition BashppServer.h:77
ProgramPool * pool
Definition BashppServer.h:80
void cleanup()
Definition BashppServer.h:83
std::shared_ptr< DebounceState > get(const std::string &uri)
Definition BashppServer.h:95
DebounceStateMap(ProgramPool *program_pool)
Definition BashppServer.h:94
std::unordered_map< std::string, std::shared_ptr< DebounceState > > states
Definition BashppServer.h:79
std::mutex map_mutex
Definition BashppServer.h:81
The main server class for handling LSP requests and notifications.
Definition BashppServer.h:57
void publishDiagnostics(std::shared_ptr< bpp::bpp_program > program)
Definition BashppServer.cpp:310
GenericResponseMessage handleHover(const GenericRequestMessage &request)
Definition handleHover.cpp:12
void(BashppServer::*)(const GenericNotificationMessage &) NotificationHandler
Definition BashppServer.h:184
void processNotification(const GenericNotificationMessage &notification)
Definition BashppServer.cpp:256
static std::string readHeaderLine(std::streambuf *buffer)
Definition BashppServer.cpp:141
std::ostream * output_stream
Definition BashppServer.h:63
void mainLoop()
Definition BashppServer.cpp:156
static std::mutex log_mutex
Definition BashppServer.h:113
DebounceStateMap debounce_states
Definition BashppServer.h:105
GenericResponseMessage handleRename(const GenericRequestMessage &request)
Definition handleRename.cpp:13
pid_t pid
Definition BashppServer.h:59
void sendNotification(const GenericNotificationMessage &notification)
Definition BashppServer.cpp:226
void processRequest(const GenericRequestMessage &request)
Definition BashppServer.cpp:232
GenericResponseMessage handleDocumentSymbol(const GenericRequestMessage &request)
Definition handleDocumentSymbol.cpp:10
static constexpr frozen::unordered_map< frozen::string, RequestHandler, 8 > request_handlers
Maps request types to the functions that handle them.
Definition BashppServer.h:190
ProgramPool program_pool
Definition BashppServer.h:65
void handleDidClose(const GenericNotificationMessage &request)
Definition handledDidClose.cpp:11
GenericResponseMessage(BashppServer::*)(const GenericRequestMessage &) RequestHandler
Definition BashppServer.h:183
void sendResponse(const GenericResponseMessage &response)
Definition BashppServer.cpp:220
std::atomic< bool > processing_didChange
Definition BashppServer.h:106
ThreadPool thread_pool
Definition BashppServer.h:64
static GenericResponseMessage invalidRequestHandler(const GenericRequestMessage &request)
Definition BashppServer.cpp:206
std::atomic< bool > shutting_down
Definition BashppServer.h:60
static constexpr frozen::unordered_map< frozen::string, NotificationHandler, 4 > notification_handlers
Maps notification types to the functions that handle them.
Definition BashppServer.h:205
~BashppServer()=default
BashppServer & operator=(const BashppServer &other)=delete
BashppServer(const BashppServer &other)=delete
GenericResponseMessage shutdown(const GenericRequestMessage &request)
Definition BashppServer.cpp:302
GenericResponseMessage handleReferences(const GenericRequestMessage &request)
Definition handleReference.cpp:13
BashppServer & operator=(BashppServer &&other) noexcept=delete
static void invalidNotificationHandler(const GenericNotificationMessage &request)
Definition BashppServer.cpp:210
std::istream * input_stream
Definition BashppServer.h:62
void handleDidChange(const GenericNotificationMessage &request)
Definition handleDidChange.cpp:11
void processMessage(const std::string &message)
Definition BashppServer.cpp:272
void handleDidOpen(const GenericNotificationMessage &request)
Definition handleDidOpen.cpp:11
void log(Args &&... args)
Definition BashppServer.h:168
BashppServer()
Definition BashppServer.cpp:17
GenericResponseMessage handleInitialize(const GenericRequestMessage &request)
Definition handleInitialize.cpp:12
std::ofstream log_file
Definition BashppServer.h:66
GenericResponseMessage handleDefinition(const GenericRequestMessage &request)
Definition handleDefinition.cpp:13
CompletionList handleDOTCompletion(const CompletionParams &params)
Definition handleCompletion.cpp:118
void setLogFile(const std::string &path)
Definition BashppServer.cpp:122
CompletionList handleATCompletion(const CompletionParams &params)
Definition handleCompletion.cpp:76
void handleDidChangeWatchedFiles(const GenericNotificationMessage &request)
Definition handleDidChangeWatchedFiles.cpp:11
void add_include_path(const std::string &path)
Definition BashppServer.cpp:356
BashppServer(BashppServer &&other) noexcept=delete
void cleanup()
Definition BashppServer.cpp:131
CompletionList default_completion_list
Definition BashppServer.h:121
static std::mutex output_mutex
Definition BashppServer.h:112
void setTargetBashVersion(const BashVersion &version)
Definition BashppServer.cpp:127
void _sendMessage(const std::string &message)
Definition BashppServer.cpp:214
GenericResponseMessage handleCompletion(const GenericRequestMessage &request)
Definition handleCompletion.cpp:12
void set_suppress_warnings(bool suppress)
Definition BashppServer.cpp:360
Definition bash_case.cpp:9
void printValue(std::ostream &os, const T &value)
Definition BashppServer.h:39
nlohmann::json json
Definition BashppServer.h:36
Represents a Bash version to target for code generation.
Definition BashVersion.h:22
Definition BashppServer.h:69
std::atomic< uint32_t > debounce_time_in_milliseconds
Definition BashppServer.h:72
std::atomic< uint64_t > change_generation
Definition BashppServer.h:70
std::atomic< uint64_t > average_reparse_time_in_microseconds
Definition BashppServer.h:71