Add label_for_completion to extension API (#10175)

This PR adds the ability for extensions to implement
`label_for_completion` to customize completions coming back from the
language server.

We've used the Gleam extension as a motivating example, adding
`label_for_completion` support to it.

Release Notes:

- N/A

---------

Co-authored-by: Max <max@zed.dev>
Co-authored-by: Max Brunsfeld <maxbrunsfeld@gmail.com>
This commit is contained in:
Marshall Bowers 2024-04-04 13:56:04 -04:00 committed by GitHub
parent 0f1c2e6f2b
commit d306b531c7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
18 changed files with 1124 additions and 252 deletions

View file

@ -13,4 +13,5 @@ path = "src/gleam.rs"
crate-type = ["cdylib"]
[dependencies]
zed_extension_api = "0.0.4"
# zed_extension_api = "0.0.4"
zed_extension_api = { path = "../../crates/extension_api" }

View file

@ -7,6 +7,10 @@
(constant
name: (identifier) @constant)
; Variables
(identifier) @variable
(discard) @comment.unused
; Modules
(module) @module
(import alias: (identifier) @module)
@ -75,10 +79,6 @@
((identifier) @warning
(#match? @warning "^(auto|delegate|derive|else|implement|macro|test|echo)$"))
; Variables
(identifier) @variable
(discard) @comment.unused
; Keywords
[
(visibility_modifier) ; "pub"

View file

@ -1,4 +1,6 @@
use std::fs;
use zed::lsp::CompletionKind;
use zed::{CodeLabel, CodeLabelSpan, LanguageServerId};
use zed_extension_api::{self as zed, Result};
struct GleamExtension {
@ -8,7 +10,7 @@ struct GleamExtension {
impl GleamExtension {
fn language_server_binary_path(
&mut self,
config: zed::LanguageServerConfig,
language_server_id: &LanguageServerId,
worktree: &zed::Worktree,
) -> Result<String> {
if let Some(path) = &self.cached_binary_path {
@ -23,7 +25,7 @@ impl GleamExtension {
}
zed::set_language_server_installation_status(
&config.name,
&language_server_id,
&zed::LanguageServerInstallationStatus::CheckingForUpdate,
);
let release = zed::latest_github_release(
@ -61,7 +63,7 @@ impl GleamExtension {
if !fs::metadata(&binary_path).map_or(false, |stat| stat.is_file()) {
zed::set_language_server_installation_status(
&config.name,
&language_server_id,
&zed::LanguageServerInstallationStatus::Downloading,
);
@ -96,15 +98,51 @@ impl zed::Extension for GleamExtension {
fn language_server_command(
&mut self,
config: zed::LanguageServerConfig,
language_server_id: &LanguageServerId,
worktree: &zed::Worktree,
) -> Result<zed::Command> {
Ok(zed::Command {
command: self.language_server_binary_path(config, worktree)?,
command: self.language_server_binary_path(language_server_id, worktree)?,
args: vec!["lsp".to_string()],
env: Default::default(),
})
}
fn label_for_completion(
&self,
_language_server_id: &LanguageServerId,
completion: zed::lsp::Completion,
) -> Option<zed::CodeLabel> {
let name = &completion.label;
let ty = completion.detail?;
let let_binding = "let a";
let colon = ": ";
let assignment = " = ";
let call = match completion.kind? {
CompletionKind::Function | CompletionKind::Constructor => "()",
_ => "",
};
let code = format!("{let_binding}{colon}{ty}{assignment}{name}{call}");
Some(CodeLabel {
spans: vec![
CodeLabelSpan::code_range({
let start = let_binding.len() + colon.len() + ty.len() + assignment.len();
start..start + name.len()
}),
CodeLabelSpan::code_range({
let start = let_binding.len();
start..start + colon.len()
}),
CodeLabelSpan::code_range({
let start = let_binding.len() + colon.len();
start..start + ty.len()
}),
],
filter_range: (0..name.len()).into(),
code,
})
}
}
zed::register_extension!(GleamExtension);