summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lsp-parse.c87
-rw-r--r--lsp.h39
-rw-r--r--main.c3
3 files changed, 110 insertions, 19 deletions
diff --git a/lsp-parse.c b/lsp-parse.c
index 1d84408..3834cd0 100644
--- a/lsp-parse.c
+++ b/lsp-parse.c
@@ -681,23 +681,84 @@ static bool parse_server2client_request(LSP *lsp, JSON *json, LSPRequest *reques
}
static bool parse_workspace_edit(LSP *lsp, LSPResponse *response, const JSON *json, JSONObject object, LSPWorkspaceEdit *edit) {
- JSONObject changes = json_object_get_object(json, object, "changes");
+ // the `changes` member is for changes to already-open documents
+ {
+ JSONObject changes = json_object_get_object(json, object, "changes");
+ for (u32 c = 0; c < changes.len; ++c) {
+ JSONValue uri = json_object_key(json, changes, c);
+ JSONArray edits = json_force_array(json_object_value(json, changes, c));
+ LSPDocumentID document = 0;
+ if (!parse_document_uri(lsp, json, uri, &document))
+ return false;
+ for (u32 e = 0; e < edits.len; ++e) {
+ LSPWorkspaceChange *change = arr_addp(edit->changes);
+ change->type = LSP_CHANGE_EDIT;
+ change->data.edit.document = document;
+ JSONValue text_edit = json_array_get(json, edits, e);
+ if (!parse_text_edit(lsp, response, json, text_edit, &change->data.edit.edit))
+ return false;
+ }
+ }
+ }
+ // the `documentChanges` member is for changes to other documents
+ JSONArray changes = json_object_get_array(json, object, "documentChanges");
for (u32 c = 0; c < changes.len; ++c) {
- JSONValue uri = json_object_key(json, changes, c);
- JSONArray edits = json_force_array(json_object_value(json, changes, c));
- LSPDocumentID document = 0;
- if (!parse_document_uri(lsp, json, uri, &document))
- return false;
- for (u32 e = 0; e < edits.len; ++e) {
- LSPWorkspaceChange *change = arr_addp(edit->changes);
- change->type = LSP_CHANGE_EDIT;
- change->data.edit.document = document;
- JSONValue text_edit = json_array_get(json, edits, e);
- if (!parse_text_edit(lsp, response, json, text_edit, &change->data.edit.edit))
+ JSONObject change = json_array_get_object(json, changes, c);
+ JSONValue kind = json_object_get(json, change, "kind");
+ if (kind.type == JSON_UNDEFINED) {
+ // change is a TextDocumentEdit
+ JSONObject text_document = json_object_get_object(json, change, "textDocument");
+ LSPDocumentID document=0;
+ if (!parse_document_uri(lsp, json, json_object_get(json, text_document, "uri"), &document))
return false;
+ JSONArray edits = json_object_get_array(json, change, "edits");
+ for (u32 e = 0; e < edits.len; ++e) {
+ LSPWorkspaceChange *out = arr_addp(edit->changes);
+ out->type = LSP_CHANGE_EDIT;
+ out->data.edit.document = document;
+ JSONValue text_edit = json_array_get(json, edits, e);
+ if (!parse_text_edit(lsp, response, json, text_edit, &out->data.edit.edit))
+ return false;
+ }
+ } else if (kind.type == JSON_STRING) {
+ char kind_str[32]={0};
+ json_string_get(json, kind.val.string, kind_str, sizeof kind_str);
+ LSPWorkspaceChange *out = arr_addp(edit->changes);
+ if (streq(kind_str, "create")) {
+ out->type = LSP_CHANGE_CREATE;
+ LSPWorkspaceChangeCreate *create = &out->data.create;
+ if (!parse_document_uri(lsp, json, json_object_get(json, change, "uri"), &create->document))
+ return false;
+ JSONObject options = json_object_get_object(json, change, "options");
+ create->ignore_if_exists = json_object_get_bool(json, options, "ignoreIfExists", false);
+ create->overwrite = json_object_get_bool(json, options, "overwrite", false);
+ } else if (streq(kind_str, "rename")) {
+ out->type = LSP_CHANGE_RENAME;
+ LSPWorkspaceChangeRename *rename = &out->data.rename;
+ if (!parse_document_uri(lsp, json, json_object_get(json, change, "oldUri"), &rename->old))
+ return false;
+ if (!parse_document_uri(lsp, json, json_object_get(json, change, "newUri"), &rename->new))
+ return false;
+ JSONObject options = json_object_get_object(json, change, "options");
+ rename->ignore_if_exists = json_object_get_bool(json, options, "ignoreIfExists", false);
+ rename->overwrite = json_object_get_bool(json, options, "overwrite", false);
+ } else if (streq(kind_str, "delete")) {
+ out->type = LSP_CHANGE_DELETE;
+ LSPWorkspaceChangeDelete *delete = &out->data.delete;
+ if (!parse_document_uri(lsp, json, json_object_get(json, change, "uri"), &delete->document))
+ return false;
+ JSONObject options = json_object_get_object(json, change, "options");
+ delete->ignore_if_not_exists = json_object_get_bool(json, options, "ignoreIfNotExists", false);
+ delete->recursive = json_object_get_bool(json, options, "recursive", false);
+ } else {
+ lsp_set_error(lsp, "Bad kind of workspace operation: '%s'", kind_str);
+ }
+ } else {
+ lsp_set_error(lsp, "Bad type for (TextDocumentEdit | CreateFile | RenameFile | DeleteFile).kind: %s",
+ json_type_to_str(kind.type));
}
}
- todo : the other thing
+
return true;
}
diff --git a/lsp.h b/lsp.h
index fa89792..41fc94c 100644
--- a/lsp.h
+++ b/lsp.h
@@ -346,16 +346,45 @@ typedef struct {
} LSPResponseWorkspaceSymbols;
typedef enum {
- LSP_CHANGE_EDIT = 1
+ LSP_CHANGE_EDIT = 1,
+ LSP_CHANGE_CREATE,
+ LSP_CHANGE_RENAME,
+ LSP_CHANGE_DELETE
} LSPWorkspaceChangeType;
typedef struct {
+ LSPDocumentID document;
+ LSPTextEdit edit;
+} LSPWorkspaceChangeEdit;
+
+typedef struct {
+ LSPDocumentID document;
+ bool overwrite;
+ bool ignore_if_exists;
+} LSPWorkspaceChangeCreate;
+
+typedef struct {
+ LSPDocumentID old;
+ LSPDocumentID new;
+ bool overwrite;
+ bool ignore_if_exists;
+} LSPWorkspaceChangeRename;
+
+typedef struct {
+ LSPDocumentID document;
+ bool recursive;
+ bool ignore_if_not_exists;
+} LSPWorkspaceChangeDelete;
+
+// this doesn't exist in the LSP spec. it represents
+// a single change from a WorkspaceEdit.
+typedef struct {
LSPWorkspaceChangeType type;
union {
- struct {
- LSPDocumentID document;
- LSPTextEdit edit;
- } edit;
+ LSPWorkspaceChangeEdit edit;
+ LSPWorkspaceChangeCreate create;
+ LSPWorkspaceChangeRename rename;
+ LSPWorkspaceChangeDelete delete;
} data;
} LSPWorkspaceChange;
diff --git a/main.c b/main.c
index 6613f2e..4c380ea 100644
--- a/main.c
+++ b/main.c
@@ -3,7 +3,6 @@
- more LSP stuff:
- document highlight (textDocument/documentHighlight)
- find usages (textDocument/references)
- - rename (textDocument/rename)
- handle multiple symbols with same name in go-to-definition menu
- :go-to-cursor-definition
- test full unicode position handling
@@ -39,6 +38,8 @@ FUTURE FEATURES:
- multiple files with command line arguments
- :set-build-command
- document links using LSP textDocument/documentLink request
+- rename using LSP (textDocument/rename)
+ - i'm putting this off for now since it seems hard to have undo support for it.
- add numlock as a key modifier? (but make sure "Ctrl+S" handles both "No NumLock+Ctrl+S" and "NumLock+Ctrl+S")
- better undo chaining (dechain on backspace?)
- allow multiple fonts (fonts directory?)