Notification support

This commit is contained in:
Aaron Cook 2026-05-24 21:17:10 -05:00
commit 297c8f800e
7 changed files with 286 additions and 102 deletions

132
src/pawn_lsp.c Normal file
View file

@ -0,0 +1,132 @@
#include <stdlib.h>
#include <string.h>
#include "cJSON/cJSON.h"
#include "json_rpc.h"
#include "log.h"
#include "pawn_lsp.h"
#define PAWN_LSP_VESRION "v0.0.1"
#define PAWN_LSP_NAME "pawn_lsp"
static int _request_handler(json_rpc_request_t *req, cJSON **resp, void *arg);
static void _notify_handler(json_rpc_request_t *req, void *arg);
static int _initialize(json_rpc_request_t *req, cJSON **resp, void *arg);
static int _shutdown(json_rpc_request_t *req, cJSON **resp, void *arg);
static void _exit_notf(json_rpc_request_t *req, void *arg);
int
pawn_lsp_init(pawn_lsp_t *pawn,
json_rpc_t *jrpc,
const char *pawncc,
char **pawn_args,
int pawn_argc)
{
pawn->jrpc = jrpc;
pawn->pawncc = strdup(pawncc);
/* execv(pawncc <filename> -d0 -v=2 -o/tmp/... [...args] <NULL>)*/
pawn->pawn_args = calloc(pawn_argc + 5, sizeof(char *));
/* pawn->pawn_args[0] = <filename>, set when compiling */
pawn->pawn_args[1] = strdup("-d0");
pawn->pawn_args[2] = strdup("-v=2");
/* pawn->pawn_args[3] = -o/tmp/..., set when compiling */
for (int i = 0; i < pawn_argc; i++) {
pawn->pawn_args[i + 4] = strdup(pawn_args[i]);
}
json_rpc_set_request_handler(jrpc, _request_handler, &pawn);
json_rpc_set_notify_handler(jrpc, _notify_handler, &pawn);
return (0);
}
void
pawn_lsp_deinit(pawn_lsp_t *pawn)
{
free(pawn->pawncc);
for (int i = 0; pawn->pawn_args[i] != NULL; i++) {
free(pawn->pawn_args[i]);
}
free(pawn->pawn_args);
}
static int
_request_handler(json_rpc_request_t *req, cJSON **resp, void *arg)
{
char *method = req->method->valuestring;
log_info("Handle request \"%s\"\r\n", method);
if (!strcmp(method, "initialize")) {
return _initialize(req, resp, arg);
} else if (!strcmp(method, "shutdown")) {
return _shutdown(req, resp, arg);
} else {
log_warn("Unrecognized request method\r\n");
(*resp) = cJSON_CreateNull();
return (-1);
}
}
static void
_notify_handler(json_rpc_request_t *req, void *arg)
{
char *method = req->method->valuestring;
log_info("Handle notification \"%s\"\r\n", method);
if (!strcmp(method, "exit")) {
_exit_notf(req, arg);
} else {
log_warn("Unrecognized notification method\r\n");
}
}
int
_initialize(json_rpc_request_t *req, cJSON **resp, void *arg)
{
cJSON *val;
(*resp) = cJSON_CreateObject();
val = cJSON_AddObjectToObject((*resp), "capabilities");
if (val == NULL) {
return (-1);
}
if (cJSON_AddStringToObject(val, "positionEncoding", "utf-8") == NULL) {
return (-1);
}
val = cJSON_AddObjectToObject((*resp), "serverInfo");
if (val == NULL) {
return (-1);
}
if ((cJSON_AddStringToObject(val, "name", PAWN_LSP_NAME) == NULL) ||
(cJSON_AddStringToObject(val, "version", PAWN_LSP_VESRION) == NULL)) {
return (-1);
}
return (0);
}
static int
_shutdown(json_rpc_request_t *req, cJSON **resp, void *arg)
{
(*resp) = cJSON_CreateNull();
return (0);
}
static void
_exit_notf(json_rpc_request_t *req, void *arg)
{
pawn_lsp_t *pawn = arg;
json_rpc_cancel(pawn->jrpc);
}