Skip to content

Commit b463407

Browse files
authored
Eliminate the snippet source (#782)
* Delete snippets that I don't plan to handle in ark * Handle reserved word snippets in keyword source * Add tests for reserved word completions * Provide completion for `function` (as a reserved word) from keyword source * Use CompletionItem fields in the same way as other sources * Remove the snippet completion source * Delete the snippet file * Expand the completion item key Soon, several control flow elements will have both a bare and a snippet representation and we'll use the same `label` (but obviously differentiate elsewhere) * Represent certain keywords in both bare and snippet form Deal with reserved words in the order in which they appear in their help topic and be consistent everywhere
1 parent 9fe6ad1 commit b463407

File tree

5 files changed

+210
-356
lines changed

5 files changed

+210
-356
lines changed

crates/ark/resources/snippets/r.code-snippets

Lines changed: 0 additions & 181 deletions
This file was deleted.

crates/ark/src/lsp/completions/sources/composite.rs

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ mod document;
1010
mod keyword;
1111
pub(crate) mod pipe;
1212
mod search_path;
13-
mod snippets;
1413
mod subset;
1514
mod workspace;
1615

@@ -27,6 +26,23 @@ use crate::lsp::completions::sources::CompletionSource;
2726
use crate::treesitter::NodeType;
2827
use crate::treesitter::NodeTypeExt;
2928

29+
#[derive(Clone, Hash, PartialEq, Eq)]
30+
struct CompletionItemKey {
31+
label: String,
32+
kind_str: String,
33+
}
34+
35+
impl CompletionItemKey {
36+
fn new(item: &CompletionItem) -> Self {
37+
Self {
38+
label: item.label.clone(),
39+
kind_str: item
40+
.kind
41+
.map_or_else(|| "Text".to_string(), |k| format!("{:?}", k)),
42+
}
43+
}
44+
}
45+
3046
// Locally useful data structure for tracking completions and their source
3147
#[derive(Clone, Default)]
3248
struct CompletionItemWithSource {
@@ -60,12 +76,6 @@ pub(crate) fn get_completions(
6076
if is_identifier_like(completion_context.document_context.node) {
6177
push_completions(keyword::KeywordSource, completion_context, &mut completions)?;
6278

63-
push_completions(
64-
snippets::SnippetSource,
65-
completion_context,
66-
&mut completions,
67-
)?;
68-
6979
push_completions(
7080
search_path::SearchPathSource,
7181
completion_context,
@@ -94,7 +104,7 @@ pub(crate) fn get_completions(
94104
fn push_completions<S>(
95105
source: S,
96106
completion_context: &CompletionContext,
97-
completions: &mut HashMap<String, CompletionItemWithSource>,
107+
completions: &mut HashMap<CompletionItemKey, CompletionItemWithSource>,
98108
) -> anyhow::Result<()>
99109
where
100110
S: CompletionSource,
@@ -103,15 +113,17 @@ where
103113

104114
if let Some(source_completions) = collect_completions(source, completion_context)? {
105115
for item in source_completions {
106-
if let Some(existing) = completions.get(&item.label) {
116+
let key = CompletionItemKey::new(&item);
117+
if let Some(existing) = completions.get(&key) {
107118
log::trace!(
108-
"Completion with label '{}' already exists (first contributed by source: {}, now also from: {})",
109-
item.label,
119+
"Completion with label '{}' and kind '{:?}' already exists (first contributed by source: {}, now also from: {})",
120+
key.label,
121+
key.kind_str,
110122
existing.source,
111123
source_name
112124
);
113125
} else {
114-
completions.insert(item.label.clone(), CompletionItemWithSource {
126+
completions.insert(key, CompletionItemWithSource {
115127
item,
116128
source: source_name.to_string(),
117129
});
@@ -124,7 +136,7 @@ where
124136

125137
/// Produce plain old CompletionItems and sort them
126138
fn finalize_completions(
127-
completions: HashMap<String, CompletionItemWithSource>,
139+
completions: HashMap<CompletionItemKey, CompletionItemWithSource>,
128140
) -> Vec<CompletionItem> {
129141
let mut items: Vec<CompletionItem> = completions
130142
.into_values()
@@ -183,8 +195,7 @@ fn is_identifier_like(x: Node) -> bool {
183195
// non-`identifier` kinds. However, we do still want to provide completions
184196
// here, especially in two cases:
185197
// - `for<tab>` should provide completions for things like `forcats`
186-
// - `for<tab>` should provide snippet completions for the `for` snippet
187-
// The keywords here come from matching snippets in `r.code-snippets`.
198+
// - completions of certain reserved words from the keyword source
188199
if matches!(x.node_type(), NodeType::Anonymous(kind) if matches!(kind.as_str(), "if" | "for" | "while"))
189200
{
190201
return true;
@@ -208,7 +219,7 @@ mod tests {
208219
fn test_completions_on_anonymous_node_keywords() {
209220
r_task(|| {
210221
// `if`, `for`, and `while` in particular are both tree-sitter
211-
// anonymous nodes and snippet keywords, so they need to look like
222+
// anonymous nodes and keywords, so they need to look like
212223
// identifiers that we provide completions for
213224
for keyword in ["if", "for", "while"] {
214225
let point = Point { row: 0, column: 0 };

0 commit comments

Comments
 (0)