Skip to content

Commit

Permalink
Backport fixes from the geany-lsp project
Browse files Browse the repository at this point in the history
  • Loading branch information
techee committed Sep 17, 2024
1 parent 831c3ac commit 55232c5
Show file tree
Hide file tree
Showing 11 changed files with 192 additions and 50 deletions.
14 changes: 12 additions & 2 deletions lsp/data/lsp.conf
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,8 @@ autocomplete_window_max_entries=20
# Maximum number of autocompletion entries shown without scrolling (defining the
# actual height of the popup)
autocomplete_window_max_displayed=8
# The maximum width of the autocompletion popup in pixels
autocomplete_window_max_width=200
# The maximum width of the autocompletion popup in displayed characters
autocomplete_window_max_width=60
# Whether to automatically apply additional edits defined for the autocompletion
# entry. These are typically imports of the modules where the inserted symbol is
# defined
Expand Down Expand Up @@ -368,6 +368,16 @@ use_without_project=true
#show_server_stderr=true


[Nix]
cmd=nil
use_without_project=true
use_outside_project_dir=true
extra_identifier_characters=-'
#rpc_log=stdout
#rpc_log_full=true
#show_server_stderr=true


[PHP]
# Note: Server returns highlighting indices off by 1 and highlighting doesn't work
cmd=phpactor.phar language-server
Expand Down
71 changes: 62 additions & 9 deletions lsp/src/lsp-autocomplete.c
Original file line number Diff line number Diff line change
Expand Up @@ -94,9 +94,9 @@ static void free_autocomplete_symbol(gpointer data)
}


static const gchar *get_symbol_label(LspServer *server, LspAutocompleteSymbol *sym)
static const gchar *get_label(LspAutocompleteSymbol *sym, gboolean use_label)
{
if (server->config.autocomplete_use_label && sym->label)
if (use_label && sym->label)
return sym->label;

if (sym->text_edit && sym->text_edit->new_text)
Expand All @@ -110,6 +110,32 @@ static const gchar *get_symbol_label(LspServer *server, LspAutocompleteSymbol *s
}


static gchar *get_symbol_label(LspServer *server, LspAutocompleteSymbol *sym)
{
gchar *label = g_strdup(get_label(sym, server->config.autocomplete_use_label));
gchar *pos;

// remove stuff after newlines (we don't want them in the popup plus \n
// is used as the autocompletion list separator)
pos = strchr(label, '\n');
if (pos)
*pos = '\0';
pos = strchr(label, '\r');
if (pos)
*pos = '\0';

// ? used by Scintilla for icon specification
pos = strchr(label, '?');
if (pos)
*pos = ' ';
pos = strchr(label, '\t');
if (pos)
*pos = ' ';

return label;
}


static guint get_ident_prefixlen(const gchar *word_chars, GeanyDocument *doc, gint pos)
{
ScintillaObject *sci = doc->editor->sci;
Expand Down Expand Up @@ -150,9 +176,9 @@ void lsp_autocomplete_item_selected(LspServer *server, GeanyDocument *doc, guint
if (sel_num == 1 && sym->text_edit && sent_request_id == received_request_id)
{
if (server->config.autocomplete_apply_additional_edits && sym->additional_edits)
lsp_utils_apply_text_edits(sci, sym->text_edit, sym->additional_edits);
lsp_utils_apply_text_edits(sci, sym->text_edit, sym->additional_edits, sym->is_snippet);
else
lsp_utils_apply_text_edit(sci, sym->text_edit, TRUE);
lsp_utils_apply_text_edit(sci, sym->text_edit, sym->is_snippet);
}
else
{
Expand All @@ -172,7 +198,7 @@ void lsp_autocomplete_item_selected(LspServer *server, GeanyDocument *doc, guint
text_edit.range.start = lsp_utils_scintilla_pos_to_lsp(sci, pos - rootlen);
text_edit.range.end = lsp_utils_scintilla_pos_to_lsp(sci, pos);

lsp_utils_apply_text_edit(sci, &text_edit, sym->insert_text != NULL);
lsp_utils_apply_text_edit(sci, &text_edit, sym->is_snippet);
}
}

Expand Down Expand Up @@ -211,7 +237,7 @@ static void show_tags_list(LspServer *server, GeanyDocument *doc, GPtrArray *sym
ScintillaObject *sci = doc->editor->sci;
gint pos = sci_get_current_position(sci);
GString *words = g_string_sized_new(2000);
const gchar *label;
gchar *label;

for (i = 0; i < symbols->len; i++)
{
Expand All @@ -230,6 +256,8 @@ static void show_tags_list(LspServer *server, GeanyDocument *doc, GPtrArray *sym

sprintf(buf, "?%u", icon_id + 1);
g_string_append(words, buf);

g_free(label);
}

lsp_autocomplete_set_displayed_symbols(symbols);
Expand All @@ -242,6 +270,7 @@ static void show_tags_list(LspServer *server, GeanyDocument *doc, GPtrArray *sym
//make sure Scintilla selects the first item - see https://sourceforge.net/p/scintilla/bugs/2403/
label = get_symbol_label(server, symbols->pdata[0]);
SSM(sci, SCI_AUTOCSELECT, 0, (sptr_t)label);
g_free(label);
}
#endif

Expand Down Expand Up @@ -353,6 +382,27 @@ static gint sort_autocomplete_symbols(gconstpointer a, gconstpointer b, gpointer
}


static gboolean should_add(GPtrArray *symbols, const gchar *prefix)
{
LspAutocompleteSymbol *sym;
const gchar *label;

if (symbols->len == 0)
return FALSE;

if (symbols->len > 1)
return TRUE;

// don't single value with what's already typed unless it's a snippet
sym = symbols->pdata[0];
label = get_label(sym, FALSE);
if (g_strcmp0(label, prefix) != 0)
return TRUE;

return sym->is_snippet || sym->kind == LspCompletionKindSnippet;
}


static void process_response(LspServer *server, GVariant *response, GeanyDocument *doc)
{
//gboolean is_incomplete = FALSE;
Expand Down Expand Up @@ -440,14 +490,17 @@ static void process_response(LspServer *server, GVariant *response, GeanyDocumen
for (i = 0; i < symbols->len; i++)
{
LspAutocompleteSymbol *sym = symbols->pdata[i];
const gchar *display_label = get_symbol_label(server, sym);
gchar *display_label = get_symbol_label(server, sym);

if (g_hash_table_contains(entry_set, display_label))
{
free_autocomplete_symbol(sym);
g_free(display_label);
}
else
{
g_ptr_array_add(symbols_filtered, sym);
g_hash_table_insert(entry_set, g_strdup(display_label), NULL);
g_hash_table_insert(entry_set, display_label, NULL);
}
}

Expand All @@ -460,7 +513,7 @@ static void process_response(LspServer *server, GVariant *response, GeanyDocumen
/* sort with symbols matching the typed prefix first */
g_ptr_array_sort_with_data(symbols, sort_autocomplete_symbols, &sort_data);

if (symbols->len > 0)
if (should_add(symbols, sort_data.prefix))
show_tags_list(server, doc, symbols);
else
{
Expand Down
3 changes: 2 additions & 1 deletion lsp/src/lsp-extension.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ static void goto_cb(GVariant *return_value, GError *error, gpointer user_data)
{
gchar *fname = lsp_utils_get_real_path_from_uri_locale(str);

document_open_file(fname, FALSE, NULL, NULL);
if (fname)
document_open_file(fname, FALSE, NULL, NULL);
g_free(fname);
}
}
Expand Down
2 changes: 1 addition & 1 deletion lsp/src/lsp-format.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ static void format_cb(GVariant *return_value, GError *error, gpointer user_data)
edits = lsp_utils_parse_text_edits(&iter);

sci_start_undo_action(doc->editor->sci);
lsp_utils_apply_text_edits(doc->editor->sci, NULL, edits);
lsp_utils_apply_text_edits(doc->editor->sci, NULL, edits, FALSE);
sci_end_undo_action(doc->editor->sci);

g_ptr_array_free(edits, TRUE);
Expand Down
20 changes: 16 additions & 4 deletions lsp/src/lsp-goto.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,10 @@ GPtrArray *last_result;
static void goto_location(GeanyDocument *old_doc, LspLocation *loc)
{
gchar *fname = lsp_utils_get_real_path_from_uri_locale(loc->uri);
GeanyDocument *doc = document_open_file(fname, FALSE, NULL, NULL);
GeanyDocument *doc = NULL;

if (fname)
doc = document_open_file(fname, FALSE, NULL, NULL);

if (doc)
navqueue_goto_line(old_doc, doc, loc->range.start.line + 1);
Expand All @@ -70,13 +73,19 @@ static void filter_symbols(const gchar *filter)

static void show_in_msgwin(LspLocation *loc, GHashTable *sci_table)
{
gchar *fname = lsp_utils_get_real_path_from_uri_utf8(loc->uri);
gchar *base_path = lsp_utils_get_project_base_path();
GeanyDocument *doc = document_find_by_filename(fname);
ScintillaObject *sci = NULL;
gint lineno = loc->range.start.line;
gchar *fname, *base_path;
GeanyDocument *doc;
gchar *line_str;

fname = lsp_utils_get_real_path_from_uri_utf8(loc->uri);
if (!fname)
return;

doc = document_find_by_filename(fname);
base_path = lsp_utils_get_project_base_path();

if (doc)
sci = doc->editor->sci;
else
Expand Down Expand Up @@ -178,6 +187,9 @@ static void goto_cb(GVariant *return_value, GError *error, gpointer user_data)
LspSymbol *sym;

file_name = lsp_utils_get_real_path_from_uri_utf8(loc->uri);
if (!file_name)
continue;

name = g_path_get_basename(file_name);

sym = lsp_symbol_new(name, "", "", file_name, 0, 0, loc->range.start.line + 1, 0,
Expand Down
28 changes: 17 additions & 11 deletions lsp/src/lsp-rpc.c
Original file line number Diff line number Diff line change
Expand Up @@ -268,9 +268,12 @@ static GVariant *show_document(LspServer *srv, GVariant *params)
else if (g_str_has_prefix(uri, "file://"))
{
gchar *fname = lsp_utils_get_real_path_from_uri_locale(uri);
document_open_file(fname, FALSE, NULL, NULL);
g_free(fname);
success = TRUE;
if (fname)
{
document_open_file(fname, FALSE, NULL, NULL);
g_free(fname);
success = TRUE;
}
}
}

Expand Down Expand Up @@ -487,16 +490,19 @@ void lsp_rpc_notify(LspServer *srv, const gchar *method, GVariant *params,
method, params, NULL, NULL);

/* Two hacks in one:
* 1. gopls requires that the params member is present (jsonrpc-glib removes
* it when there are no parameters which is jsonrpc compliant)
* 2. haskell-language-server also requires params present _unless_ it's the
* "exit" notifications, where, if "params" present, it fails to
* terminate
* 1. some servers (e.g. gopls) require that the params member is present
* (jsonrpc-glib removes it when there are no parameters which is jsonrpc
* compliant)
* 2. haskell-language-server or nil require that the "exit" notification
* has no params member
*/
if (!params && !(srv->filetype == GEANY_FILETYPES_HASKELL && g_strcmp0(method, "exit") == 0))
if (!params && g_strcmp0(method, "exit") != 0)
{
params = JSONRPC_MESSAGE_NEW("gopls_bug_workarond",
JSONRPC_MESSAGE_PUT_STRING("https://github.com/golang/go/issues/57459"));
GVariantDict dict;

g_variant_dict_init(&dict, NULL);
params = g_variant_take_ref(g_variant_dict_end(&dict));

params_added = TRUE;
}

Expand Down
54 changes: 48 additions & 6 deletions lsp/src/lsp-server.c
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,52 @@ static gboolean use_incremental_sync(GVariant *node)
}


static gboolean send_did_save(GVariant *node)
{
gboolean val;
gboolean success = JSONRPC_MESSAGE_PARSE(node,
"capabilities", "{",
"textDocumentSync", "{",
"save", JSONRPC_MESSAGE_GET_BOOLEAN(&val),
"}",
"}");

if (!success)
{
GVariant *var = NULL;

JSONRPC_MESSAGE_PARSE(node,
"capabilities", "{",
"textDocumentSync", "{",
"save", JSONRPC_MESSAGE_GET_VARIANT(&var),
"}",
"}");

success = val = var != NULL;
if (var)
g_variant_unref(var);
}

return success && val;
}


static gboolean include_text_on_save(GVariant *node)
{
gboolean val;
gboolean success = JSONRPC_MESSAGE_PARSE(node,
"capabilities", "{",
"textDocumentSync", "{",
"save", "{",
"includeText", JSONRPC_MESSAGE_GET_BOOLEAN(&val),
"}",
"}",
"}");

return success && val;
}


static gboolean use_workspace_folders(GVariant *node)
{
gboolean change_notifications = FALSE;
Expand Down Expand Up @@ -492,6 +538,8 @@ static void initialize_cb(GVariant *return_value, GError *error, gpointer user_d
update_config(return_value, &s->supports_workspace_symbols, "workspaceSymbolProvider");

s->use_incremental_sync = use_incremental_sync(return_value);
s->send_did_save = send_did_save(return_value);
s->include_text_on_save = include_text_on_save(return_value);
s->use_workspace_folders = use_workspace_folders(return_value);

s->initialize_response = lsp_utils_json_pretty_print(return_value);
Expand Down Expand Up @@ -554,8 +602,6 @@ static void perform_initialize(LspServer *server)
"}",
"textDocument", "{",
"synchronization", "{",
"willSave", JSONRPC_MESSAGE_PUT_BOOLEAN(FALSE),
"willSaveWaitUntil", JSONRPC_MESSAGE_PUT_BOOLEAN(FALSE),
"didSave", JSONRPC_MESSAGE_PUT_BOOLEAN(TRUE),
"}",
"completion", "{",
Expand Down Expand Up @@ -587,7 +633,6 @@ static void perform_initialize(LspServer *server)
"}",
"semanticTokens", "{",
"requests", "{",
"range", JSONRPC_MESSAGE_PUT_BOOLEAN(FALSE),
"full", "{",
"delta", JSONRPC_MESSAGE_PUT_BOOLEAN(TRUE),
"}",
Expand Down Expand Up @@ -624,9 +669,6 @@ static void perform_initialize(LspServer *server)
"formats", "[",
"relative",
"]",
"overlappingTokenSupport", JSONRPC_MESSAGE_PUT_BOOLEAN(FALSE),
"multilineTokenSupport", JSONRPC_MESSAGE_PUT_BOOLEAN(FALSE),
"serverCancelSupport", JSONRPC_MESSAGE_PUT_BOOLEAN(FALSE),
"augmentsSyntaxTokens", JSONRPC_MESSAGE_PUT_BOOLEAN(TRUE),
"}",
"}",
Expand Down
2 changes: 2 additions & 0 deletions lsp/src/lsp-server.h
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,8 @@ typedef struct LspServer
gchar *signature_trigger_chars;
gchar *initialize_response;
gboolean use_incremental_sync;
gboolean send_did_save;
gboolean include_text_on_save;
gboolean use_workspace_folders;
gboolean supports_workspace_symbols;

Expand Down
Loading

0 comments on commit 55232c5

Please sign in to comment.