Compare commits

..
7 changed files with 28 additions and 143 deletions

View file

@ -18,7 +18,7 @@ SRCS= \
libraries/cJSON/cJSON.c \
src/json_rpc.c \
src/main.c \
src/pawn_ls.c
src/pawn_lsp.c
OBJS=$(addprefix $(BUILD_DIR)/,$(addsuffix .o,$(basename $(SRCS))))
DEPS=$(addprefix $(BUILD_DIR)/,$(addsuffix .d,$(basename $(SRCS))))

View file

@ -1,8 +1,8 @@
# Pawn Language Server
`pawn_ls` is a project to provide basic language server functionality for the
`pawn_lsp` is a project to provide basic LSP functionality for the
[Pawn scripting language](https://codeberg.org/compuphase/pawn).
`pawn_ls` is currently in development and has no releases, refer to the
`pawn_lsp` is currently in development and has no releases, refer to the
repository work items for development status.

View file

@ -6,12 +6,12 @@
#include "log.h"
#include "json_rpc.h"
#include "pawn_ls.h"
#include "pawn_lsp.h"
void sighandler(int signal);
static json_rpc_t jrpc;
static pawn_ls_t pawn;
static pawn_lsp_t pawn;
FILE *logger = NULL;
@ -22,11 +22,11 @@ main(int argc, char **argv)
struct termios term_new;
if (argc < 2) {
fprintf(stderr, "Usage: pawn_ls <pawncc> [...pawncc options]\r\n");
fprintf(stderr, "Usage: pawn_lsp <pawncc> [...pawncc options]\r\n");
return (-1);
}
logger = fopen("pawn_ls.log", "w");
logger = fopen("pawn_lsp.log", "w");
if (signal(SIGINT, sighandler) == SIG_ERR) {
log_error("Failed to intialize signal handling\r\n");
@ -45,13 +45,13 @@ main(int argc, char **argv)
return (-1);
}
if (pawn_ls_init(&pawn, &jrpc, argv[1], &argv[2], argc - 2)) {
if (pawn_lsp_init(&pawn, &jrpc, argv[1], &argv[2], argc - 2)) {
log_error("Failed to register Pawn language server\r\n");
return (-1);
}
json_rpc_run(&jrpc);
pawn_ls_deinit(&pawn);
pawn_lsp_deinit(&pawn);
if (logger) {
fclose(logger);

View file

View file

@ -1,59 +0,0 @@
#ifndef _PAWN_ENGINE_H_
#define _PAWN_ENGINE_H_
#include <stddef.h>
typedef struct str_struct {
/** Actual value of the string */
char *val;
/** Current length of the string in bytes */
size_t len;
/** Capacity of the string buffer */
size_t cap;
} str_t;
typedef struct file_position_struct {
/** Line number in the file (1-indexed) */
size_t line;
/** Column number in the file (1-indexed) */
size_t column;
} file_position_t;
typedef struct file_range_struct {
/** Start of the range, inclusive */
file_position_t start;
/** End of the range, inclusive */
file_position_t end;
} file_range_t;
typedef struct file_diagnostic_struct {
/** Message for the diagnostic */
str_t message;
/** Range of text the diagnostic applies to */
file_range_t range;
} file_diagnostic_t;
typedef struct pawn_diagnostics_struct {
/** Errors present in a Pawn script */
file_diagnostic_t *errors;
/** Number of errors */
size_t errors_len;
/** Warnings present in a Pawn script */
file_diagnostic_t *warnings;
/** Number of warnings */
size_t warnings_len;
} pawn_diagnostics_t;
typedef struct pawn_engine_settings_struct {
/** Path to the pawncc executable */
const char *pawncc;
/** Extra options to run pawncc with, not including the pawncc or script paths */
const char **argv;
/** Number of extra options */
int argc;
} pawn_engine_settings_t;
pawn_diagnostics_t *pawn_engine_compile(const char *path, pawn_engine_settings_t *settings);
#endif /* _PAWN_ENGINE_H_ */

View file

@ -4,10 +4,10 @@
#include "cJSON/cJSON.h"
#include "json_rpc.h"
#include "log.h"
#include "pawn_ls.h"
#include "pawn_lsp.h"
#define PAWN_LS_VESRION "v0.0.1"
#define PAWN_LS_NAME "pawn_ls"
#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);
@ -16,11 +16,10 @@ 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 _didopen_notf(json_rpc_request_t *req, void *arg);
static void _exit_notf(json_rpc_request_t *req, void *arg);
int
pawn_ls_init(pawn_ls_t *pawn,
pawn_lsp_init(pawn_lsp_t *pawn,
json_rpc_t *jrpc,
const char *pawncc,
char **pawn_args,
@ -46,7 +45,7 @@ pawn_ls_init(pawn_ls_t *pawn,
}
void
pawn_ls_deinit(pawn_ls_t *pawn)
pawn_lsp_deinit(pawn_lsp_t *pawn)
{
free(pawn->pawncc);
for (int i = 0; pawn->pawn_args[i] != NULL; i++) {
@ -80,9 +79,7 @@ _notify_handler(json_rpc_request_t *req, void *arg)
log_info("Handle notification \"%s\"\r\n", method);
if (!strcmp(method, "textDocument/didOpen")) {
_didopen_notf(req, arg);
} else if (!strcmp(method, "exit")) {
if (!strcmp(method, "exit")) {
_exit_notf(req, arg);
} else {
log_warn("Unrecognized notification method\r\n");
@ -93,54 +90,26 @@ _notify_handler(json_rpc_request_t *req, void *arg)
int
_initialize(json_rpc_request_t *req, cJSON **resp, void *arg)
{
cJSON *capabilities;
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_LS_NAME) == NULL) ||
(cJSON_AddStringToObject(val, "version", PAWN_LS_VESRION) == NULL)) {
return (-1);
}
/* All capabilities */
capabilities = cJSON_AddObjectToObject((*resp), "capabilities");
if (capabilities == NULL) {
return (-1);
}
/* utf-8 encoding only */
if (cJSON_AddStringToObject(capabilities, "positionEncoding", "utf-8") == NULL) {
return (-1);
}
/* TextDocumentSync */
val = cJSON_AddObjectToObject(capabilities, "textDocumentSync");
if (val == NULL) {
return (-1);
}
if ((cJSON_AddTrueToObject(val, "openClose") == NULL) ||
/* 1 = full content */
(cJSON_AddNumberToObject(val, "change", 1) == NULL)) {
return (-1);
}
/* Hover */
if (cJSON_AddTrueToObject(capabilities, "hoverProvider") == NULL) {
return (-1);
}
/* Go to's */
if ((cJSON_AddTrueToObject(capabilities, "declarationProvider") == NULL) ||
(cJSON_AddTrueToObject(capabilities, "definitionProvider") == NULL)) {
if ((cJSON_AddStringToObject(val, "name", PAWN_LSP_NAME) == NULL) ||
(cJSON_AddStringToObject(val, "version", PAWN_LSP_VESRION) == NULL)) {
return (-1);
}
@ -154,35 +123,10 @@ _shutdown(json_rpc_request_t *req, cJSON **resp, void *arg)
return (0);
}
static void
_didopen_notf(json_rpc_request_t *req, void *arg) {
cJSON *textdoc = cJSON_GetObjectItem(req->params, "textDocument");
cJSON *val;
if ((textdoc == NULL) || (!cJSON_IsObject(textdoc))) {
log_error("Invalid textDocument field\r\n");
return;
}
val = cJSON_GetObjectItem(textdoc, "uri");
if (val && cJSON_IsString(val)) {
log_info("textdoc uri: %s\r\n", val->valuestring);
} else {
log_warn("Invalid uri\r\n");
}
val = cJSON_GetObjectItem(textdoc, "text");
if (val && cJSON_IsString(val)) {
log_info("textdoc text: \"%s\"\r\n", val->valuestring);
} else {
log_warn("Invalid text\r\n");
}
}
static void
_exit_notf(json_rpc_request_t *req, void *arg)
{
pawn_ls_t *pawn = arg;
pawn_lsp_t *pawn = arg;
json_rpc_cancel(pawn->jrpc);
}

View file

@ -1,27 +1,27 @@
#ifndef _PAWN_LS_H_
#define _PAWN_LS_H_
#ifndef _PAWN_LSP_H_
#define _PAWN_LSP_H_
#include "json_rpc.h"
typedef struct pawn_ls_struct {
typedef struct pawn_lsp_struct {
/** Active JRPC instance */
json_rpc_t *jrpc;
/** Path to the pawncc compiler */
char *pawncc;
/** User provided args for pawncc */
char **pawn_args;
} pawn_ls_t;
} pawn_lsp_t;
/**
* @brief Register JSON RPC methods for the Pawn language server
*/
int pawn_ls_init(pawn_ls_t *pawn,
int pawn_lsp_init(pawn_lsp_t *pawn,
json_rpc_t *jrpc,
const char *pawncc,
char **pawn_argv,
int pawn_argc);
void pawn_ls_deinit(pawn_ls_t *pawn);
void pawn_lsp_deinit(pawn_lsp_t *pawn);
#endif /* _PAWN_LS_H_ */
#endif /* _PAWN_LSP_H_ */