与语言服务器通信(Languager服务器协议)



我想在一个简单的自行编写的文本编辑器中测试语言服务器协议。但我不太确定我是否正确地理解了如何向服务器写入和从中读取。我想用C++来完成这项工作。

为了测试的目的,我在这个例子中使用了Qt。但如果你使用另一个图书馆,这也可以。作为一个服务器,我安装了ccls(它正在运行,就像我用atom测试它一样)。

所以这是我的总体想法:1.将服务器作为进程启动2.根据规范定义初始化的json文件3.将其转换为字符串并发送给客户端3.等待响应(应该是InitializeResult)

#include <QCoreApplication>
#include <QProcess>
#include <iostream>
#include <QFile>
int main(int argc, char* argv[]) {
QCoreApplication app(argc, argv);
QFile file {"src/initializeRequest.json"};
file.open(QIODevice::ReadOnly);
QProcess* myProcess = new QProcess(&app);
myProcess->start("ccls", QStringList {});
std::cout << myProcess->write(file.readAll()) << 'n';
std::cout << myProcess->readAll().toStdString();
file.close();
return app.exec();
}

但实际上,我甚至不确定这些消息(didOpen、initializeRequest等)是否真的是作为文件发送的。根据语言服务器协议,他们是描述json文件的接口。。。但我没有发现他们是如何发送的

因此,如果有人能告诉我我是否走在了正确的轨道上(我尝试发送实际文件),以及是否有人能向我展示与服务器的最简单的通信,我将不胜感激,这样我就真的得到了回应(看看它是否有效)。

我做了很多实验,并创建了一个最小的工作示例。在这个例子中,我向ccls(它是一个C++语言服务器)发送一个初始化请求并读取响应。我使用QProcess启动服务器(但当然可以使用不同的东西)和rapidjson(https://github.com/Tencent/rapidjson)用于构造json文件。

#include <QCoreApplication>
#include <QProcess>
#include <iostream>
#include <sstream>
#include "rapidjson/stringbuffer.h"
#include "rapidjson/writer.h"
int main(int argc, char* argv[]) {
QCoreApplication app {argc, argv};
//Start server as a QProcess
QProcess* server = new QProcess {&app};
server->start("ccls", QStringList {"-log-file=/tmp/ccls2.log", "-init={}"});
server->waitForStarted(-1);
std::cout << "Server started" << 'n';
//Construct json Request
rapidjson::StringBuffer output {};
rapidjson::Writer<rapidjson::StringBuffer> writer {output};
writer.StartObject();
writer.Key("jsonrpc");
writer.String("2.0");
writer.Key("id");
writer.Int(0);
writer.Key("method");
writer.String("initialize");
writer.Key("params");
writer.StartObject();
writer.Key("processId");
writer.Int(0);
writer.Key("rootUri");
writer.String("home");
writer.Key("capabilities");
writer.StartObject();
writer.EndObject();
writer.EndObject();
writer.EndObject();
std::string content = output.GetString();
std::ostringstream oss;
oss << "Content-Length: " << content.length() << "rn" << "rn";
std::string header = oss.str();
std::cout << header << content << 'n';
//Send request to server
server->write(header.c_str());
server->write(content.c_str());
//Wait for response and read it
server->waitForReadyRead(-1);
std::cout << "Server has sent response" << 'n';
std::cout << server->readAll().toStdString() << 'n';
return app.exec();
}

输出:

Server started
Content-Length: 106
{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":0,"rootUri":"home","capabilities":{}}}
Server has sent response
Content-Length: 1046
{"jsonrpc":"2.0","id":0,"result":{"capabilities":{"textDocumentSync":{"openClose":true,"change":2,"willSave":false,"willSaveWaitUntil":false,"
save":{"includeText":false}},"hoverProvider":true,"completionProvider":{"resolveProvider":false,"triggerCharacters":[".",":",">","#","<",""",
"/"]},"signatureHelpProvider":{"triggerCharacters":["(",","]},"definitionProvider":true,"implementationProvider":true,"typeDefinitionProvider"
:true,"referencesProvider":true,"documentHighlightProvider":true,"documentSymbolProvider":true,"workspaceSymbolProvider":true,"codeActionProvi
der":{"codeActionKinds":["quickfix"]},"codeLensProvider":{"resolveProvider":false},"documentFormattingProvider":true,"documentRangeFormattingP
rovider":true,"documentOnTypeFormattingProvider":{"firstTriggerCharacter":"}","moreTriggerCharacter":[]},"renameProvider":true,"documentLinkPr
ovider":{"resolveProvider":true},"foldingRangeProvider":true,"executeCommandProvider":{"commands":["ccls.xref"]},"workspace":{"workspaceFolder
s":{"supported":true,"changeNotifications":true}}}}}

正如我所说,我想向所有有同样问题的人展示一个最简单的例子。当然,为请求等创建结构是有意义的

最新更新