summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpommicket <pommicket@gmail.com>2023-01-03 18:01:04 -0500
committerpommicket <pommicket@gmail.com>2023-01-03 18:01:04 -0500
commitc0397f1f4c80e73a2e4ccd1946703fe6a5bb405e (patch)
tree5b95649c140083e2af4332bb92260842436f22c9
parent87c8bd6eb27edb4bfc539967235c3a1e2f8d77e4 (diff)
go to type definition
-rw-r--r--README.md10
-rw-r--r--buffer.c5
-rw-r--r--command.c6
-rw-r--r--command.h1
-rw-r--r--ide-definitions.c15
-rw-r--r--lsp-parse.c19
-rw-r--r--lsp-write.c8
-rw-r--r--lsp.c8
-rw-r--r--lsp.h8
-rw-r--r--main.c8
-rw-r--r--ted.cfg3
-rw-r--r--ted.h2
-rw-r--r--test/lsp/multidef.cpp7
13 files changed, 87 insertions, 13 deletions
diff --git a/README.md b/README.md
index 83c037d..5c2982d 100644
--- a/README.md
+++ b/README.md
@@ -129,7 +129,15 @@ I would recommend trying out an LSP server if you're unsure about which one to u
ted has support for [LSPs](https://microsoft.github.io/language-server-protocol/)!
-You can Ctrl+Click on an identifier to go to its definition.
+You can Ctrl+Click on an identifier to go to its definition, or Ctrl+Shift+Click to go
+to its declaration, or Ctrl+Alt+Click to go to its type's definition.
+
+(clangd seems to sometimes go to the declaration even
+when the definition should be available, e.g.
+when Ctrl+clicking on the function declarations
+in `ted.h`. This is Not My Fault,
+and VSCode's clangd extension suffers from the same problem.)
+
You can also press Ctrl+D to get a searchable list of all functions/types where you can select one to go to
its definition.
diff --git a/buffer.c b/buffer.c
index 4645f75..0d372fc 100644
--- a/buffer.c
+++ b/buffer.c
@@ -2561,14 +2561,17 @@ bool buffer_handle_click(Ted *ted, TextBuffer *buffer, vec2 click, u8 times) {
// select to position
buffer_select_to_pos(buffer, buffer_pos);
break;
- case KEY_MODIFIER_CTRL:
+ case KEY_MODIFIER_CTRL:
case KEY_MODIFIER_CTRL | KEY_MODIFIER_SHIFT:
+ case KEY_MODIFIER_CTRL | KEY_MODIFIER_ALT:
if (!buffer->is_line_buffer) {
// go to definition/declaration
buffer_cursor_move_to_pos(buffer, buffer_pos);
GotoType type = GOTO_DEFINITION;
if (ted->key_modifier & KEY_MODIFIER_SHIFT)
type = GOTO_DECLARATION;
+ else if (ted->key_modifier & KEY_MODIFIER_ALT)
+ type = GOTO_TYPE_DEFINITION;
buffer_goto_word_at_cursor(buffer, type);
}
break;
diff --git a/command.c b/command.c
index bf26b3a..9ba6766 100644
--- a/command.c
+++ b/command.c
@@ -67,6 +67,7 @@ static CommandName const command_names[] = {
{"goto-definition", CMD_GOTO_DEFINITION},
{"goto-definition-at-cursor", CMD_GOTO_DEFINITION_AT_CURSOR},
{"goto-declaration-at-cursor", CMD_GOTO_DECLARATION_AT_CURSOR},
+ {"goto-type-definition-at-cursor", CMD_GOTO_TYPE_DEFINITION_AT_CURSOR},
{"find", CMD_FIND},
{"find-replace", CMD_FIND_REPLACE},
{"tab-close", CMD_TAB_CLOSE},
@@ -417,6 +418,11 @@ void command_execute(Ted *ted, Command c, i64 argument) {
buffer_goto_word_at_cursor(buffer, GOTO_DECLARATION);
}
} break;
+ case CMD_GOTO_TYPE_DEFINITION_AT_CURSOR: {
+ if (buffer && buffer_is_named_file(buffer)) {
+ buffer_goto_word_at_cursor(buffer, GOTO_TYPE_DEFINITION);
+ }
+ } break;
case CMD_FIND_USAGES:
usages_find(ted);
break;
diff --git a/command.h b/command.h
index 3f7d155..2713df8 100644
--- a/command.h
+++ b/command.h
@@ -76,6 +76,7 @@ ENUM_U16 {
CMD_GOTO_DEFINITION, // "go to definition of..." menu
CMD_GOTO_DEFINITION_AT_CURSOR,
CMD_GOTO_DECLARATION_AT_CURSOR,
+ CMD_GOTO_TYPE_DEFINITION_AT_CURSOR,
CMD_COPY,
CMD_CUT,
diff --git a/ide-definitions.c b/ide-definitions.c
index 7873630..7175e08 100644
--- a/ide-definitions.c
+++ b/ide-definitions.c
@@ -64,11 +64,22 @@ void definition_goto(Ted *ted, LSP *lsp, const char *name, LSPDocumentPosition p
case GOTO_DECLARATION:
request_type = LSP_REQUEST_DECLARATION;
break;
+ case GOTO_TYPE_DEFINITION:
+ request_type = LSP_REQUEST_TYPE_DEFINITION;
+ break;
+ case GOTO_IMPLEMENTATION:
+ request_type = LSP_REQUEST_IMPLEMENTATION;
+ break;
}
// send that request
LSPRequest request = {.type = request_type};
request.data.definition.position = position;
LSPRequestID id = lsp_send_request(lsp, &request);
+ if (id == 0 && request.type == LSP_REQUEST_IMPLEMENTATION) {
+ // if we can't go to the implementation, try going to the definition
+ request.type = LSP_REQUEST_DEFINITION;
+ id = lsp_send_request(lsp, &request);
+ }
defs->last_request_id = id;
defs->last_request_lsp = lsp->id;
defs->last_request_time = ted->frame_time;
@@ -142,7 +153,9 @@ void definitions_process_lsp_response(Ted *ted, LSP *lsp, const LSPResponse *res
switch (response->request.type) {
case LSP_REQUEST_DEFINITION:
- case LSP_REQUEST_DECLARATION: {
+ case LSP_REQUEST_DECLARATION:
+ case LSP_REQUEST_TYPE_DEFINITION:
+ case LSP_REQUEST_IMPLEMENTATION: {
// handle textDocument/definition or textDocument/declaration response
const LSPResponseDefinition *response_def = &response->data.definition;
diff --git a/lsp-parse.c b/lsp-parse.c
index 9c22fe4..42f2291 100644
--- a/lsp-parse.c
+++ b/lsp-parse.c
@@ -151,23 +151,34 @@ static void parse_capabilities(LSP *lsp, const JSON *json, JSONObject capabiliti
arr_add(lsp->signature_help_retrigger_chars, '>');
}
- // check for hover support
+ // check for textDocument/hover support
JSONValue hover_value = json_object_get(json, capabilities, "hoverProvider");
if (hover_value.type != JSON_UNDEFINED && hover_value.type != JSON_FALSE) {
cap->hover_support = true;
}
- // check for definition support
+ // check for textDocument/definition support
JSONValue definition_value = json_object_get(json, capabilities, "definitionProvider");
if (definition_value.type != JSON_UNDEFINED && definition_value.type != JSON_FALSE) {
cap->definition_support = true;
}
- // check for declaration support
+ // check for textDocument/declaration support
JSONValue declaration_value = json_object_get(json, capabilities, "declarationProvider");
if (declaration_value.type != JSON_UNDEFINED && declaration_value.type != JSON_FALSE) {
cap->declaration_support = true;
}
+ // check for textDocument/typeDefinition support
+ JSONValue type_definition_value = json_object_get(json, capabilities, "typeDefinitionProvider");
+ if (type_definition_value.type != JSON_UNDEFINED && type_definition_value.type != JSON_FALSE) {
+ cap->type_definition_support = true;
+ }
+
+ // check for textDocument/implementation support
+ JSONValue implementation_value = json_object_get(json, capabilities, "implementationProvider");
+ if (implementation_value.type != JSON_UNDEFINED && implementation_value.type != JSON_FALSE) {
+ cap->implementation_support = true;
+ }
// check for textDocument/documentHighlight support
JSONValue highlight_value = json_object_get(json, capabilities, "documentHighlightProvider");
@@ -890,6 +901,8 @@ void process_message(LSP *lsp, JSON *json) {
break;
case LSP_REQUEST_DEFINITION:
case LSP_REQUEST_DECLARATION:
+ case LSP_REQUEST_TYPE_DEFINITION:
+ case LSP_REQUEST_IMPLEMENTATION:
add_to_messages = parse_definition(lsp, json, &response);
break;
case LSP_REQUEST_HIGHLIGHT:
diff --git a/lsp-write.c b/lsp-write.c
index 691bcba..48229c8 100644
--- a/lsp-write.c
+++ b/lsp-write.c
@@ -281,6 +281,10 @@ static const char *lsp_request_method(LSPRequest *request) {
return "textDocument/definition";
case LSP_REQUEST_DECLARATION:
return "textDocument/declaration";
+ case LSP_REQUEST_TYPE_DEFINITION:
+ return "textDocument/typeDefinition";
+ case LSP_REQUEST_IMPLEMENTATION:
+ return "textDocument/implementation";
case LSP_REQUEST_HIGHLIGHT:
return "textDocument/documentHighlight";
case LSP_REQUEST_RENAME:
@@ -549,7 +553,9 @@ void write_request(LSP *lsp, LSPRequest *request) {
write_obj_end(o);
} break;
case LSP_REQUEST_DEFINITION:
- case LSP_REQUEST_DECLARATION: {
+ case LSP_REQUEST_DECLARATION:
+ case LSP_REQUEST_TYPE_DEFINITION:
+ case LSP_REQUEST_IMPLEMENTATION: {
const LSPRequestDefinition *def = &request->data.definition;
write_key_obj_start(o, "params");
write_document_position(o, def->position);
diff --git a/lsp.c b/lsp.c
index bd01bbd..3dc0fee 100644
--- a/lsp.c
+++ b/lsp.c
@@ -49,6 +49,8 @@ void lsp_request_free(LSPRequest *r) {
case LSP_REQUEST_HOVER:
case LSP_REQUEST_DEFINITION:
case LSP_REQUEST_DECLARATION:
+ case LSP_REQUEST_TYPE_DEFINITION:
+ case LSP_REQUEST_IMPLEMENTATION:
case LSP_REQUEST_REFERENCES:
case LSP_REQUEST_HIGHLIGHT:
case LSP_REQUEST_DID_CLOSE:
@@ -179,6 +181,10 @@ static bool lsp_supports_request(LSP *lsp, const LSPRequest *request) {
return cap->definition_support;
case LSP_REQUEST_DECLARATION:
return cap->declaration_support;
+ case LSP_REQUEST_TYPE_DEFINITION:
+ return cap->type_definition_support;
+ case LSP_REQUEST_IMPLEMENTATION:
+ return cap->implementation_support;
case LSP_REQUEST_WORKSPACE_SYMBOLS:
return cap->workspace_symbols_support;
case LSP_REQUEST_RENAME:
@@ -220,6 +226,8 @@ static bool request_type_is_notification(LSPRequestType type) {
case LSP_REQUEST_HOVER:
case LSP_REQUEST_DEFINITION:
case LSP_REQUEST_DECLARATION:
+ case LSP_REQUEST_TYPE_DEFINITION:
+ case LSP_REQUEST_IMPLEMENTATION:
case LSP_REQUEST_REFERENCES:
case LSP_REQUEST_RENAME:
case LSP_REQUEST_WORKSPACE_SYMBOLS:
diff --git a/lsp.h b/lsp.h
index f5404b1..c146a9b 100644
--- a/lsp.h
+++ b/lsp.h
@@ -66,6 +66,8 @@ typedef enum {
LSP_REQUEST_HOVER, // textDocument/hover
LSP_REQUEST_DEFINITION, // textDocument/definition
LSP_REQUEST_DECLARATION, // textDocument/declaration
+ LSP_REQUEST_TYPE_DEFINITION, // textDocument/typeDefinition
+ LSP_REQUEST_IMPLEMENTATION, // textDocument/implementation
LSP_REQUEST_HIGHLIGHT, // textDocument/documentHighlight
LSP_REQUEST_REFERENCES, // textDocument/references
LSP_REQUEST_RENAME, // textDocument/rename
@@ -201,7 +203,7 @@ typedef struct {
LSPRequestCompletion completion;
LSPRequestSignatureHelp signature_help;
LSPRequestHover hover;
- // LSP_REQUEST_DEFINITION, LSP_REQUEST_DECLARATION, or LSP_REQUEST_TYPE_DEFINITION
+ // LSP_REQUEST_DEFINITION, LSP_REQUEST_DECLARATION, LSP_REQUEST_TYPE_DEFINITION, or LSP_REQUEST_IMPLEMENTATION
LSPRequestDefinition definition;
LSPRequestHighlight highlight;
LSPRequestReferences references;
@@ -456,7 +458,7 @@ typedef struct {
LSPResponseCompletion completion;
LSPResponseSignatureHelp signature_help;
LSPResponseHover hover;
- // LSP_REQUEST_DEFINITION, LSP_REQUEST_DECLARATION, or LSP_REQUEST_TYPE_DEFINITION
+ // LSP_REQUEST_DEFINITION, LSP_REQUEST_DECLARATION, LSP_REQUEST_TYPE_DEFINITION, or LSP_REQUEST_IMPLEMENTATION
LSPResponseDefinition definition;
LSPResponseWorkspaceSymbols workspace_symbols;
LSPResponseRename rename;
@@ -484,6 +486,8 @@ typedef struct {
bool hover_support;
bool definition_support;
bool declaration_support;
+ bool implementation_support;
+ bool type_definition_support;
bool workspace_symbols_support;
bool highlight_support;
// support for multiple root folders
diff --git a/main.c b/main.c
index d4535a0..a49e6dd 100644
--- a/main.c
+++ b/main.c
@@ -1,8 +1,6 @@
/*
@TODO:
-- go to type definition
-- why does asking for a definition in ted.h send us to the wrong place?
- (vscode doesn't experience this problem)
+- fix problem where LSP_REQUEST_DEFINITION tag isn't being found
- ted.h documentation
- handle multiple symbols with same name in go-to-definition menu
- better non-error window/showMessage(Request)
@@ -28,8 +26,10 @@
- make buffer->path NULL for untitled buffers & fix resulting mess
- rust-analyzer bug reports:
- bad json can give "Unexpected error: client exited without proper shutdown sequence"
+- clangd bug report:
+ - textDocumemt/definition on ted.h declarations just gives you the declaration
FUTURE FEATURES:
-- add numlock as a key modifier? (but make sure "Ctrl+S" handles both "No NumLock+Ctrl+S" and "NumLock+Ctrl+S")
+- make go-to-definition/hover/highlight modifier key configurable
- return to previous location in buffer
- font setting & support for multiple fonts to cover more characters
- comment-start & comment-end settings
diff --git a/ted.cfg b/ted.cfg
index bca3276..4ab4aa7 100644
--- a/ted.cfg
+++ b/ted.cfg
@@ -265,7 +265,10 @@ Ctrl+t = :generate-tags
Ctrl+d = :goto-definition
# alternative to ctrl+click
Ctrl+' = :goto-definition-at-cursor
+# alternative to ctrl+shift+click
Ctrl+Shift+' = :goto-declaration-at-cursor
+# alternative to ctrl+alt+click
+Ctrl+Alt+' = :goto-type-definition-at-cursor
Ctrl+g = :goto-line
Ctrl+\ = :split-horizontal
diff --git a/ted.h b/ted.h
index 19a975c..6fb6754 100644
--- a/ted.h
+++ b/ted.h
@@ -467,6 +467,8 @@ typedef struct {
typedef enum {
GOTO_DECLARATION,
GOTO_DEFINITION,
+ GOTO_IMPLEMENTATION,
+ GOTO_TYPE_DEFINITION,
} GotoType;
typedef struct {
diff --git a/test/lsp/multidef.cpp b/test/lsp/multidef.cpp
new file mode 100644
index 0000000..eb5336d
--- /dev/null
+++ b/test/lsp/multidef.cpp
@@ -0,0 +1,7 @@
+
+void f(int x, int y) {
+}
+
+
+void f(int x) {
+}