summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpommicket <pommicket@gmail.com>2023-08-07 07:19:56 -0400
committerpommicket <pommicket@gmail.com>2023-08-07 07:19:56 -0400
commitb146279b48f6a4f4bea8946cb3f0f1f5cc5a9985 (patch)
tree70069f2f622f3b6190fa1effcfb9ce9e14d8f94b
parentbdbce6fe3c647616d22867bbc82e011c91231dd3 (diff)
handle more complicated renames
-rw-r--r--ide-rename-symbol.c132
-rw-r--r--lsp.h14
-rw-r--r--ted.c19
-rw-r--r--ted.h8
-rw-r--r--test/lsp/rust/src/foo.rs3
-rw-r--r--test/lsp/rust/src/main.rs4
6 files changed, 123 insertions, 57 deletions
diff --git a/ide-rename-symbol.c b/ide-rename-symbol.c
index 6f320ae..01f3106 100644
--- a/ide-rename-symbol.c
+++ b/ide-rename-symbol.c
@@ -120,72 +120,106 @@ void rename_symbol_process_lsp_response(Ted *ted, const LSPResponse *response) {
return;
}
+ if (response->error) {
+ ted_error(ted, "%s", response->error);
+ goto cleanup;
+
+ }
+
const LSPResponseRename *data = &response->data.rename;
LSP *lsp = ted_get_lsp_by_id(ted, rs->request_id.lsp);
if (!lsp) {
// LSP crashed or something
- return;
+ goto cleanup;
}
- bool perform_changes = true;
arr_foreach_ptr(data->changes, const LSPWorkspaceChange, change) {
- if (change->type != LSP_CHANGE_EDIT) {
- // TODO(eventually) : support these
- ted_error(ted, "rename is too complicated for ted to perform.");
- perform_changes = false;
+ if (change->type == LSP_CHANGE_DELETE && change->data.delete.recursive) {
+ ted_error(ted, "refusing to perform rename because it involves a recurisve deletion\n"
+ "I'm too scared to go through with this");
+ goto cleanup;
}
}
- if (perform_changes) {
-
- arr_foreach_ptr(data->changes, const LSPWorkspaceChange, change) {
- switch (change->type) {
- case LSP_CHANGE_EDIT: {
- const LSPWorkspaceChangeEdit *change_data = &change->data.edit;
- const char *path = lsp_document_path(lsp, change_data->document);
- if (!ted_open_file(ted, path)) goto done;
-
- TextBuffer *buffer = ted_get_buffer_with_file(ted, path);
- if (!buffer->will_chain_edits) {
- // chain all edits together so they can be undone with one ctrl+z
- buffer_start_edit_chain(buffer);
- }
-
- if (!buffer) {
- // this should never happen since we just
- // successfully opened it
- assert(0);
- goto done;
- }
-
-
- const LSPTextEdit *edit = &change_data->edit;
- BufferPos start = buffer_pos_from_lsp(buffer, edit->range.start);
- BufferPos end = buffer_pos_from_lsp(buffer, edit->range.end);
- buffer_delete_chars_between(buffer, start, end);
- buffer_insert_utf8_at_pos(buffer, start, lsp_response_string(response, edit->new_text));
-
- }
- break;
- case LSP_CHANGE_RENAME:
- case LSP_CHANGE_DELETE:
- case LSP_CHANGE_CREATE:
+ arr_foreach_ptr(data->changes, const LSPWorkspaceChange, change) {
+ switch (change->type) {
+ case LSP_CHANGE_EDIT: {
+ const LSPWorkspaceChangeEdit *change_data = &change->data.edit;
+ const char *path = lsp_document_path(lsp, change_data->document);
+ if (!ted_open_file(ted, path)) goto done;
+
+ TextBuffer *buffer = ted_get_buffer_with_file(ted, path);
+ if (!buffer->will_chain_edits) {
+ // chain all edits together so they can be undone with one ctrl+z
+ buffer_start_edit_chain(buffer);
+ }
+
+ if (!buffer) {
+ // this should never happen since we just
+ // successfully opened it
assert(0);
+ goto done;
+ }
+
+
+ const LSPTextEdit *edit = &change_data->edit;
+ BufferPos start = buffer_pos_from_lsp(buffer, edit->range.start);
+ BufferPos end = buffer_pos_from_lsp(buffer, edit->range.end);
+ buffer_delete_chars_between(buffer, start, end);
+ buffer_insert_utf8_at_pos(buffer, start, lsp_response_string(response, edit->new_text));
+
+ }
+ break;
+ case LSP_CHANGE_RENAME: {
+ const LSPWorkspaceChangeRename *rename = &change->data.rename;
+ const char *old = lsp_document_path(lsp, rename->old);
+ const char *new = lsp_document_path(lsp, rename->new);
+ FsType new_type = fs_path_type(new);
+ if (new_type == FS_DIRECTORY) {
+ ted_error(ted, "Aborting rename since it's asking to overwrite a directory.");
+ goto done;
+ }
+
+ if (rename->ignore_if_exists && new_type != FS_NON_EXISTENT) {
break;
}
- }
- done:
-
- // end all edit chains in all buffers
- // they're almost definitely all created by us
- for (u16 i = 0; i < TED_MAX_BUFFERS; ++i) {
- if (ted->buffers_used[i]) {
- TextBuffer *buffer = &ted->buffers[i];
- buffer_end_edit_chain(buffer);
+ if (!rename->overwrite && new_type != FS_NON_EXISTENT) {
+ ted_error(ted, "Aborting rename since it would overwrite a file.");
+ goto done;
}
+ os_rename_overwrite(old, new);
+ if (ted_close_buffer_with_file(ted, old))
+ ted_open_file(ted, new);
+ } break;
+ case LSP_CHANGE_DELETE: {
+ const LSPWorkspaceChangeDelete *delete = &change->data.delete;
+ const char *path = lsp_document_path(lsp, delete->document);
+ remove(path);
+ ted_close_buffer_with_file(ted, path);
+ } break;
+ case LSP_CHANGE_CREATE: {
+ const LSPWorkspaceChangeCreate *create = &change->data.create;
+ const char *path = lsp_document_path(lsp, create->document);
+ FILE *fp = fopen(path, create->overwrite ? "wb" : "ab");
+ if (fp) fclose(fp);
+ ted_open_file(ted, path);
+ } break;
}
}
+ done:
+
+ // end all edit chains in all buffers
+ // they're almost definitely all created by us
+ for (u16 i = 0; i < TED_MAX_BUFFERS; ++i) {
+ if (ted->buffers_used[i]) {
+ TextBuffer *buffer = &ted->buffers[i];
+ buffer_end_edit_chain(buffer);
+ }
+ }
+
+ ted_save_all(ted);
+ cleanup:
rename_symbol_clear(ted);
if (menu_is_open(ted, MENU_RENAME_SYMBOL))
menu_close(ted);
diff --git a/lsp.h b/lsp.h
index 4e5cf03..ab095f5 100644
--- a/lsp.h
+++ b/lsp.h
@@ -491,13 +491,15 @@ typedef struct {
} LSPResponseDocumentLink;
typedef struct {
- LSPRequest request; // the request which this is a response to
- char *error; // if not NULL, the data field will just be zeroed
- // LSP responses tend to have a lot of strings.
- // to avoid doing a ton of allocations+frees,
- // they're all stored here.
+ /// the request which this is a response to
+ LSPRequest request;
+ /// if not NULL, the data field will just be zeroed
+ char *error;
+ /// LSP responses tend to have a lot of strings.
+ /// to avoid doing a ton of allocations+frees,
+ /// they're all stored here.
char *string_data;
- // one of these is filled based on request.type
+ /// one of these is filled based on request.type
union {
LSPResponseCompletion completion;
LSPResponseSignatureHelp signature_help;
diff --git a/ted.c b/ted.c
index 14cc440..211a07b 100644
--- a/ted.c
+++ b/ted.c
@@ -575,6 +575,10 @@ static Status ted_open_buffer(Ted *ted, u16 *buffer_idx, u16 *tab) {
TextBuffer *ted_get_buffer_with_file(Ted *ted, const char *path) {
if (!path) return NULL;
+ if (!path_is_absolute(path)) {
+ assert(0);
+ return NULL;
+ }
bool *buffers_used = ted->buffers_used;
TextBuffer *buffers = ted->buffers;
@@ -879,3 +883,18 @@ void ted_remove_edit_notify(Ted *ted, EditNotifyID id) {
}
}
}
+
+void ted_close_buffer(Ted *ted, TextBuffer *buffer) {
+ if (!buffer) return;
+
+ u16 tab_idx=0;
+ Node *node = ted_buffer_location_in_node_tree(ted, buffer, &tab_idx);
+ node_tab_close(ted, node, tab_idx);
+}
+
+bool ted_close_buffer_with_file(Ted *ted, const char *path) {
+ TextBuffer *buffer = ted_get_buffer_with_file(ted, path);
+ if (!buffer) return false;
+ ted_close_buffer(ted, buffer);
+ return true;
+}
diff --git a/ted.h b/ted.h
index 0551eb2..4199767 100644
--- a/ted.h
+++ b/ted.h
@@ -973,8 +973,14 @@ void ted_path_full(Ted *ted, const char *relpath, char *abspath, size_t abspath_
void ted_reset_active_buffer(Ted *ted);
/// set ted's error message to the buffer's error.
void ted_error_from_buffer(Ted *ted, TextBuffer *buffer);
-/// Returns the buffer containing the file at `path`, or NULL if there is none.
+/// Returns the buffer containing the file at absolute path `path`, or NULL if there is none.
TextBuffer *ted_get_buffer_with_file(Ted *ted, const char *path);
+/// close this buffer, discarding unsaved changes.
+void ted_close_buffer(Ted *ted, TextBuffer *buffer);
+/// close buffer with this absolute path, discarding unsaved changes.
+///
+/// returns true if the buffer was actually present.
+bool ted_close_buffer_with_file(Ted *ted, const char *path);
/// save all buffers
bool ted_save_all(Ted *ted);
/// reload all buffers from their files
diff --git a/test/lsp/rust/src/foo.rs b/test/lsp/rust/src/foo.rs
new file mode 100644
index 0000000..08cbd24
--- /dev/null
+++ b/test/lsp/rust/src/foo.rs
@@ -0,0 +1,3 @@
+pub fn a() -> i32 {
+ 8
+}
diff --git a/test/lsp/rust/src/main.rs b/test/lsp/rust/src/main.rs
index e7a11a9..e71b6f7 100644
--- a/test/lsp/rust/src/main.rs
+++ b/test/lsp/rust/src/main.rs
@@ -1,3 +1,5 @@
+mod foo;
+
fn main() {
- println!("Hello, world!");
+ println!("Hello, world! {}", foo::a());
}