/***************************************************************************
lspclient.h - description
-------------------
begin : Wed Jan 20 2021
copyright : (C) 2002-2026 by Andre Simon
email : a.simon@mailbox.org
***************************************************************************/
/*
This file is part of Highlight.
Highlight is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Highlight is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Highlight. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef LSPCLIENT_H
#define LSPCLIENT_H
#ifdef _WIN32
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#else
#include <unistd.h>
#include <sys/wait.h>
#include <signal.h>
#if __linux__
#include <sys/prctl.h>
#endif
#endif
#include <vector>
#include <map>
#include <string>
#include "semantictoken.h"
#include "picojson/picojson.h"
namespace highlight
{
class LSPClient
{
private:
bool initialized{false};
bool hoverProvider{false};
bool semanticTokensProvider{false};
bool logRequests{false};
bool legacyProtocol{false};
std::string executable, workspace;
std::string serverName, serverVersion;
std::string triggerSyntax;
std::vector<std::string> options;
std::map<int, std::string> tokenTypes;
std::map<int, std::string> tokenModifiers;
std::map< std::tuple<int, int>, highlight::SemanticToken > tokenMap;
std::map< std::tuple<int, int>, highlight::SemanticToken > errorMap;
int initDelay{0};
#ifdef _WIN32
HANDLE g_hChildStd_IN_Rd ;
HANDLE g_hChildStd_IN_Wr ;
HANDLE g_hChildStd_OUT_Rd ;
HANDLE g_hChildStd_OUT_Wr ;
HANDLE hProcess;
#else
pid_t pid;
int inpipefd[2];
int outpipefd[2];
#endif
float msgId{1.0};
int lastErrorCode{0};
std::string lastErrorMessage;
std::string readBuffer; // Buffer to store leftover data between pipe reads
bool pipe_write_jsonrpc(const std::string &message);
std::string pipe_read_jsonrpc();
void runSimpleAction(const std::string action, int delay = 0);
bool checkErrorResponse(const picojson::value &json, const std::string& picoError);
void readNotification(const picojson::value &json);
bool isIdMatching(const picojson::value& jsonResponse, float myId);
void static signal_callback_handler(int signum);
public:
/** Constructor */
LSPClient();
~LSPClient();
void setExecutable ( const std::string& exec );
void setOptions (const std::vector<std::string>& o);
void setWorkspace ( const std::string& ws );
void setSyntax ( const std::string& syntax );
void setLegacyProtocol ( bool legacy );
bool connect();
bool runInitialize();
void runInitialized();
bool runDidOpen(const std::string &document, const std::string &syntax);
bool runDidClose(const std::string &document, const std::string &syntax);
std::string runHover(const std::string &document, int character, int line);
bool runSemanticTokensFull(const std::string &document);
void runShutdown();
void runExit();
void resetState();
bool isInitialized() const;
bool isHoverProvider() const;
bool isSemanticTokensProvider() const;
void setLogging(bool flag);
void setInitializeDelay(int ms);
std::string getServerName() const;
std::string getServerVersion() const;
std::string getErrorMessage() const;
bool tokenExists(unsigned int line, unsigned int col);
bool errorExists(unsigned int line, unsigned int col);
int getSemanticTokenCount() const;
highlight::SemanticToken getToken(unsigned int line, unsigned int col);
highlight::SemanticToken getError(unsigned int line, unsigned int col);
int getErrorCode() const;
};
}
#endif