Skip to content

Commit

Permalink
Add package information in completions (posit-dev#616)
Browse files Browse the repository at this point in the history
And:
* Remove parameters from completion items entirely
* Add `::` details to namespace completions
  • Loading branch information
lionel- authored Nov 4, 2024
1 parent e3d0efc commit 4b4ab09
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 14 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@

## 2024-10

- Results from completions have been improved with extra details.
Package functions now display the package name (posit-dev/positron#5225)
and namespace completions now display `::` to hint at what is being
completed.

- The document symbol kind for assigned variables is now `VARIABLE` (@kv9898, posit-dev/positron#5071). This produces a clearer icon in the outline.

- Added support for outline headers in comments (@kv9898, posit-dev/positron#3822).
Expand Down
37 changes: 25 additions & 12 deletions crates/ark/src/lsp/completions/completion_item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ use harp::r_symbol;
use harp::utils::is_symbol_valid;
use harp::utils::r_env_binding_is_active;
use harp::utils::r_envir_name;
use harp::utils::r_formals;
use harp::utils::r_promise_force_with_rollback;
use harp::utils::r_promise_is_forced;
use harp::utils::r_promise_is_lazy_load_binding;
Expand All @@ -31,6 +30,7 @@ use stdext::*;
use tower_lsp::lsp_types::Command;
use tower_lsp::lsp_types::CompletionItem;
use tower_lsp::lsp_types::CompletionItemKind;
use tower_lsp::lsp_types::CompletionItemLabelDetails;
use tower_lsp::lsp_types::CompletionTextEdit;
use tower_lsp::lsp_types::Documentation;
use tower_lsp::lsp_types::InsertTextFormat;
Expand Down Expand Up @@ -148,6 +148,10 @@ pub(super) unsafe fn completion_item_from_package(
})?;

item.kind = Some(CompletionItemKind::MODULE);
item.label_details = Some(CompletionItemLabelDetails {
detail: Some(String::from("::")),
description: None,
});

if append_colons {
item.insert_text_format = Some(InsertTextFormat::SNIPPET);
Expand All @@ -162,10 +166,9 @@ pub(super) unsafe fn completion_item_from_package(
return Ok(item);
}

pub(super) fn completion_item_from_function<T: AsRef<str>>(
pub(super) fn completion_item_from_function(
name: &str,
package: Option<&str>,
parameters: &[T],
) -> Result<CompletionItem> {
let label = format!("{}", name);
let mut item = completion_item(label, CompletionData::Function {
Expand All @@ -175,8 +178,8 @@ pub(super) fn completion_item_from_function<T: AsRef<str>>(

item.kind = Some(CompletionItemKind::FUNCTION);

let detail = format!("{}({})", name, parameters.joined(", "));
item.detail = Some(detail);
let label_details = item_details(package);
item.label_details = Some(label_details);

let insert_text = sym_quote_invalid(name);
item.insert_text_format = Some(InsertTextFormat::SNIPPET);
Expand All @@ -192,6 +195,21 @@ pub(super) fn completion_item_from_function<T: AsRef<str>>(
return Ok(item);
}

fn item_details(package: Option<&str>) -> CompletionItemLabelDetails {
let description = package.map(|p| {
// Environments from the search path often have a "package:" prefix.
// Remove it from display. This creates some rare ambiguities but
// improves the display generally.
let p = p.strip_prefix("package:").unwrap_or(p);
format!("{{{p}}}")
});

CompletionItemLabelDetails {
detail: None,
description,
}
}

// TODO
pub(super) unsafe fn completion_item_from_dataset(name: &str) -> Result<CompletionItem> {
let mut item = completion_item(name.to_string(), CompletionData::Unknown)?;
Expand Down Expand Up @@ -238,19 +256,14 @@ pub(super) unsafe fn completion_item_from_object(
// In other words, when creating a completion item for these functions,
// we should also figure out where we can receive the help from.
if Rf_isFunction(object) != 0 {
let formals = r_formals(object)?;
let arguments = formals
.iter()
.map(|formal| formal.name.as_str())
.collect::<Vec<_>>();
return completion_item_from_function(name, package, &arguments);
return completion_item_from_function(name, package);
}

let mut item = completion_item(name, CompletionData::Object {
name: name.to_string(),
})?;

item.detail = Some("(Object)".to_string());
item.label_details = Some(item_details(package));
item.kind = Some(CompletionItemKind::STRUCT);

if !is_symbol_valid(name) {
Expand Down
4 changes: 2 additions & 2 deletions crates/ark/src/lsp/completions/sources/composite/workspace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,8 @@ pub(super) fn completions_from_workspace(
}

match &entry.data {
indexer::IndexEntryData::Function { name, arguments } => {
let mut completion = unwrap!(completion_item_from_function(name, None, arguments), Err(error) => {
indexer::IndexEntryData::Function { name, .. } => {
let mut completion = unwrap!(completion_item_from_function(name, None), Err(error) => {
error!("{:?}", error);
return;
});
Expand Down
4 changes: 4 additions & 0 deletions crates/ark/src/lsp/state_handlers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use anyhow::anyhow;
use serde_json::Value;
use struct_field_names_as_array::FieldNamesAsArray;
use tower_lsp::lsp_types::CompletionOptions;
use tower_lsp::lsp_types::CompletionOptionsCompletionItem;
use tower_lsp::lsp_types::ConfigurationItem;
use tower_lsp::lsp_types::DidChangeConfigurationParams;
use tower_lsp::lsp_types::DidChangeTextDocumentParams;
Expand Down Expand Up @@ -120,6 +121,9 @@ pub(crate) fn initialize(
trigger_characters: Some(vec!["$".to_string(), "@".to_string(), ":".to_string()]),
work_done_progress_options: Default::default(),
all_commit_characters: None,
completion_item: Some(CompletionOptionsCompletionItem {
label_details_support: Some(true),
}),
..Default::default()
}),
signature_help_provider: Some(SignatureHelpOptions {
Expand Down

0 comments on commit 4b4ab09

Please sign in to comment.