-
-
Notifications
You must be signed in to change notification settings - Fork 199
Refactor/lsp #175
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Refactor/lsp #175
Changes from all commits
7c6b06b
10dd37a
3f0890b
d2715e1
0a94c99
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,11 +1,13 @@ | ||||||||||||||||||||||||||||||||||||||||||||||
| #include "json_rpc.h" | ||||||||||||||||||||||||||||||||||||||||||||||
| #include "cJSON.h" | ||||||||||||||||||||||||||||||||||||||||||||||
| #include "lsp_project.h" | ||||||||||||||||||||||||||||||||||||||||||||||
| #include <assert.h> | ||||||||||||||||||||||||||||||||||||||||||||||
| #include <stdio.h> | ||||||||||||||||||||||||||||||||||||||||||||||
| #include <stdlib.h> | ||||||||||||||||||||||||||||||||||||||||||||||
| #include <string.h> | ||||||||||||||||||||||||||||||||||||||||||||||
| #include <stdbool.h> | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| void lsp_check_file(const char *uri, const char *src, int id); | ||||||||||||||||||||||||||||||||||||||||||||||
| void lsp_check_file(const char *uri, const char *src); | ||||||||||||||||||||||||||||||||||||||||||||||
| void lsp_goto_definition(const char *uri, int line, int col, int id); | ||||||||||||||||||||||||||||||||||||||||||||||
| void lsp_hover(const char *uri, int line, int col, int id); | ||||||||||||||||||||||||||||||||||||||||||||||
| void lsp_completion(const char *uri, int line, int col, int id); | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -48,6 +50,203 @@ static void get_params(cJSON *root, char **uri, int *line, int *col) | |||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| void send_lsp_message_json(const cJSON *json) | ||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||
| char *body; | ||||||||||||||||||||||||||||||||||||||||||||||
| size_t len; | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| assert(json); | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| body = cJSON_PrintUnformatted(json); | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| len = strlen(body); | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| fprintf(stdout, "Content-Length: %zu\r\n\r\n", len); | ||||||||||||||||||||||||||||||||||||||||||||||
| fwrite(body, 1, len, stdout); | ||||||||||||||||||||||||||||||||||||||||||||||
| fflush(stdout); | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| free(body); | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| cJSON *create_response(const cJSON *id_item, | ||||||||||||||||||||||||||||||||||||||||||||||
| const cJSON *result, | ||||||||||||||||||||||||||||||||||||||||||||||
| const cJSON *error) | ||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||
| cJSON *res; | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| assert(id_item || (error && !id_item)); | ||||||||||||||||||||||||||||||||||||||||||||||
| assert((result && !error) || (!result && error)); | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| res = cJSON_CreateObject(); | ||||||||||||||||||||||||||||||||||||||||||||||
| if (!res) { | ||||||||||||||||||||||||||||||||||||||||||||||
| return NULL; | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| cJSON_AddStringToObject(res, "jsonrpc", "2.0"); | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| cJSON_AddItemToObject(res, "id", cJSON_Duplicate(id_item, 1)); | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| if (result) | ||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||
| cJSON_AddItemToObject(res, "result", cJSON_Duplicate(result, 1)); | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
| else { | ||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+87
to
+93
|
||||||||||||||||||||||||||||||||||||||||||||||
| cJSON_AddItemToObject(res, "id", cJSON_Duplicate(id_item, 1)); | |
| if (result) | |
| { | |
| cJSON_AddItemToObject(res, "result", cJSON_Duplicate(result, 1)); | |
| } | |
| else { | |
| if (id_item) | |
| { | |
| cJSON_AddItemToObject(res, "id", cJSON_Duplicate(id_item, 1)); | |
| } | |
| else | |
| { | |
| cJSON_AddNullToObject(res, "id"); | |
| } | |
| if (result) | |
| { | |
| cJSON_AddItemToObject(res, "result", cJSON_Duplicate(result, 1)); | |
| } | |
| else | |
| { |
Copilot
AI
Feb 2, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
handle_initialize calls create_response(id_item, ...) without checking whether id_item is present. If initialize is sent as a notification (no id), this will hit the create_response assertions (or produce an invalid response). Guard this path: either treat missing id as a notification (initialize but do not respond), or return a JSON-RPC Invalid Request error with id: null.
| cJSON *response = create_response(id_item, result, NULL); | |
| send_lsp_message_json(response); | |
| cJSON_Delete(result); | |
| cJSON_Delete(response); | |
| if (id_item) | |
| { | |
| cJSON *response = create_response(id_item, result, NULL); | |
| send_lsp_message_json(response); | |
| cJSON_Delete(response); | |
| } | |
| cJSON_Delete(result); |
Copilot
AI
Feb 2, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The PR description mentions spec-compliant shutdown/exit handling, but handle_exit always exits with code 0 and still has TODOs. LSP requires exit code 0 only if a prior shutdown request was received; otherwise exit code 1. Track shutdown state and implement the correct exit code behavior.
Copilot
AI
Feb 2, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
contentChanges in textDocument/didChange is an array per LSP; using cJSON_GetObjectItem(changes, "text") will always return NULL and the change will be ignored. Extract the first array element (or iterate) and read its text field.
Copilot
AI
Feb 2, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This code accepts string IDs but still reads id_item->valueint and passes an int id to most handlers; for string IDs valueint becomes 0, causing responses with the wrong id. To be JSON-RPC compliant, propagate the original id_item (number or string) into responses (e.g., change handler signatures to take const cJSON *id_item, or convert to a string/variant) instead of truncating to int.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
send_lsp_message_jsonassumescJSON_PrintUnformattedalways succeeds; if it returns NULL (OOM),strlen(body)will dereference NULL and crash. Handle a NULL return (e.g., bail out or send an internal error) before callingstrlen/fwrite.