editor: Fix function completion expansion in string contexts and call expressions (#30351)
Closes #27582 Now, when accepting function completion, it doesn't expand with parentheses and arguments in the following cases: 1. If it's in a string (like `type Foo = MyClass["sayHello"]` instead of `type Foo = MyClass["sayHello(name)"]`) 2. If it's in a call expression (like `useRef<HTMLDivElement>(null)` over `useRef(initialValue)<HTMLDivElement>(null)`) This is a follow-up to https://github.com/zed-industries/zed/pull/30312, more like cleaner version of it. Release Notes: - Fixed an issue where accepting a method as an object string in JavaScript would incorrectly expand. E.g. `MyClass["sayHello(name)"]` instead of `MyClass["sayHello"]`.
This commit is contained in:
parent
851ab13f94
commit
b88ba44b32
6 changed files with 39 additions and 21 deletions
|
@ -5051,27 +5051,19 @@ impl Editor {
|
||||||
let snippet;
|
let snippet;
|
||||||
let new_text;
|
let new_text;
|
||||||
if completion.is_snippet() {
|
if completion.is_snippet() {
|
||||||
// lsp returns function definition with placeholders in "new_text"
|
let mut snippet_source = completion.new_text.clone();
|
||||||
// when configured from language server, even when renaming a function
|
if let Some(scope) = snapshot.language_scope_at(newest_anchor.head()) {
|
||||||
//
|
if scope.prefers_label_for_snippet_in_completion() {
|
||||||
// in such cases, we use the label instead
|
if let Some(label) = completion.label() {
|
||||||
// https://github.com/zed-industries/zed/issues/29982
|
if matches!(
|
||||||
let snippet_source = completion
|
completion.kind(),
|
||||||
.label()
|
Some(CompletionItemKind::FUNCTION) | Some(CompletionItemKind::METHOD)
|
||||||
.filter(|label| {
|
) {
|
||||||
completion.kind() == Some(CompletionItemKind::FUNCTION)
|
snippet_source = label;
|
||||||
&& label != &completion.new_text
|
}
|
||||||
})
|
}
|
||||||
.and_then(|label| {
|
}
|
||||||
let cursor_offset = newest_anchor.head().to_offset(&snapshot);
|
}
|
||||||
let next_char_is_not_whitespace = snapshot
|
|
||||||
.chars_at(cursor_offset)
|
|
||||||
.next()
|
|
||||||
.map_or(true, |ch| !ch.is_whitespace());
|
|
||||||
next_char_is_not_whitespace.then_some(label)
|
|
||||||
})
|
|
||||||
.unwrap_or(completion.new_text.clone());
|
|
||||||
|
|
||||||
snippet = Some(Snippet::parse(&snippet_source).log_err()?);
|
snippet = Some(Snippet::parse(&snippet_source).log_err()?);
|
||||||
new_text = snippet.as_ref().unwrap().text.clone();
|
new_text = snippet.as_ref().unwrap().text.clone();
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -828,6 +828,8 @@ pub struct LanguageConfigOverride {
|
||||||
pub completion_query_characters: Override<HashSet<char>>,
|
pub completion_query_characters: Override<HashSet<char>>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub opt_into_language_servers: Vec<LanguageServerName>,
|
pub opt_into_language_servers: Vec<LanguageServerName>,
|
||||||
|
#[serde(default)]
|
||||||
|
pub prefer_label_for_snippet: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, Debug, Serialize, JsonSchema)]
|
#[derive(Clone, Deserialize, Debug, Serialize, JsonSchema)]
|
||||||
|
@ -1788,6 +1790,18 @@ impl LanguageScope {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns whether to prefer snippet `label` over `new_text` to replace text when
|
||||||
|
/// completion is accepted.
|
||||||
|
///
|
||||||
|
/// In cases like when cursor is in string or renaming existing function,
|
||||||
|
/// you don't want to expand function signature instead just want function name
|
||||||
|
/// to replace existing one.
|
||||||
|
pub fn prefers_label_for_snippet_in_completion(&self) -> bool {
|
||||||
|
self.config_override()
|
||||||
|
.and_then(|o| o.prefer_label_for_snippet)
|
||||||
|
.unwrap_or(false)
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns a list of bracket pairs for a given language with an additional
|
/// Returns a list of bracket pairs for a given language with an additional
|
||||||
/// piece of information about whether the particular bracket pair is currently active for a given language.
|
/// piece of information about whether the particular bracket pair is currently active for a given language.
|
||||||
pub fn brackets(&self) -> impl Iterator<Item = (&BracketPair, bool)> {
|
pub fn brackets(&self) -> impl Iterator<Item = (&BracketPair, bool)> {
|
||||||
|
|
|
@ -34,3 +34,7 @@ opt_into_language_servers = ["emmet-language-server"]
|
||||||
[overrides.string]
|
[overrides.string]
|
||||||
completion_query_characters = ["-", "."]
|
completion_query_characters = ["-", "."]
|
||||||
opt_into_language_servers = ["tailwindcss-language-server"]
|
opt_into_language_servers = ["tailwindcss-language-server"]
|
||||||
|
prefer_label_for_snippet = true
|
||||||
|
|
||||||
|
[overrides.call_expression]
|
||||||
|
prefer_label_for_snippet = true
|
||||||
|
|
|
@ -13,3 +13,5 @@
|
||||||
(jsx_self_closing_element)
|
(jsx_self_closing_element)
|
||||||
(jsx_expression)
|
(jsx_expression)
|
||||||
] @default
|
] @default
|
||||||
|
|
||||||
|
(_ value: (call_expression) @call_expression)
|
||||||
|
|
|
@ -21,3 +21,7 @@ debuggers = ["JavaScript"]
|
||||||
|
|
||||||
[overrides.string]
|
[overrides.string]
|
||||||
completion_query_characters = ["."]
|
completion_query_characters = ["."]
|
||||||
|
prefer_label_for_snippet = true
|
||||||
|
|
||||||
|
[overrides.call_expression]
|
||||||
|
prefer_label_for_snippet = true
|
||||||
|
|
|
@ -1,2 +1,4 @@
|
||||||
(comment) @comment.inclusive
|
(comment) @comment.inclusive
|
||||||
(string) @string
|
(string) @string
|
||||||
|
|
||||||
|
(_ value: (call_expression) @call_expression)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue